Commit 8688bd2d by eguven Committed by Oliver Woodman

Rename DownloadState to Download

PiperOrigin-RevId: 242839480
parent f0cd144b
Showing with 767 additions and 818 deletions
......@@ -16,9 +16,9 @@
package com.google.android.exoplayer2.demo;
import android.app.Notification;
import com.google.android.exoplayer2.offline.Download;
import com.google.android.exoplayer2.offline.DownloadManager;
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.ui.DownloadNotificationHelper;
import com.google.android.exoplayer2.util.NotificationUtil;
......@@ -61,26 +61,26 @@ public class DemoDownloadService extends DownloadService {
}
@Override
protected Notification getForegroundNotification(DownloadState[] downloadStates) {
protected Notification getForegroundNotification(Download[] downloads) {
return notificationHelper.buildProgressNotification(
R.drawable.ic_download, /* contentIntent= */ null, /* message= */ null, downloadStates);
R.drawable.ic_download, /* contentIntent= */ null, /* message= */ null, downloads);
}
@Override
protected void onDownloadStateChanged(DownloadState downloadState) {
protected void onDownloadChanged(Download download) {
Notification notification;
if (downloadState.state == DownloadState.STATE_COMPLETED) {
if (download.state == Download.STATE_COMPLETED) {
notification =
notificationHelper.buildDownloadCompletedNotification(
R.drawable.ic_download_done,
/* contentIntent= */ null,
Util.fromUtf8Bytes(downloadState.action.data));
} else if (downloadState.state == DownloadState.STATE_FAILED) {
Util.fromUtf8Bytes(download.action.data));
} else if (download.state == Download.STATE_FAILED) {
notification =
notificationHelper.buildDownloadFailedNotification(
R.drawable.ic_download_done,
/* contentIntent= */ null,
Util.fromUtf8Bytes(downloadState.action.data));
Util.fromUtf8Bytes(download.action.data));
} else {
return;
}
......
......@@ -25,12 +25,12 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.offline.ActionFile;
import com.google.android.exoplayer2.offline.DefaultDownloadIndex;
import com.google.android.exoplayer2.offline.Download;
import com.google.android.exoplayer2.offline.DownloadAction;
import com.google.android.exoplayer2.offline.DownloadCursor;
import com.google.android.exoplayer2.offline.DownloadHelper;
import com.google.android.exoplayer2.offline.DownloadManager;
import com.google.android.exoplayer2.offline.DownloadService;
import com.google.android.exoplayer2.offline.DownloadState;
import com.google.android.exoplayer2.offline.DownloadStateCursor;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.upstream.DataSource;
......@@ -63,7 +63,7 @@ public class DownloadTracker implements DownloadManager.Listener {
private final Context context;
private final DataSource.Factory dataSourceFactory;
private final CopyOnWriteArraySet<Listener> listeners;
private final HashMap<Uri, DownloadState> downloadStates;
private final HashMap<Uri, Download> downloads;
private final DefaultDownloadIndex downloadIndex;
@Nullable private StartDownloadDialogHelper startDownloadDialogHelper;
......@@ -74,7 +74,7 @@ public class DownloadTracker implements DownloadManager.Listener {
this.dataSourceFactory = dataSourceFactory;
this.downloadIndex = downloadIndex;
listeners = new CopyOnWriteArraySet<>();
downloadStates = new HashMap<>();
downloads = new HashMap<>();
loadDownloads();
}
......@@ -87,15 +87,15 @@ public class DownloadTracker implements DownloadManager.Listener {
}
public boolean isDownloaded(Uri uri) {
DownloadState downloadState = downloadStates.get(uri);
return downloadState != null && downloadState.state != DownloadState.STATE_FAILED;
Download download = downloads.get(uri);
return download != null && download.state != Download.STATE_FAILED;
}
@SuppressWarnings("unchecked")
public List<StreamKey> getOfflineStreamKeys(Uri uri) {
DownloadState downloadState = downloadStates.get(uri);
return downloadState != null && downloadState.state != DownloadState.STATE_FAILED
? downloadState.action.streamKeys
Download download = downloads.get(uri);
return download != null && download.state != Download.STATE_FAILED
? download.action.streamKeys
: Collections.emptyList();
}
......@@ -105,10 +105,10 @@ public class DownloadTracker implements DownloadManager.Listener {
Uri uri,
String extension,
RenderersFactory renderersFactory) {
DownloadState downloadState = downloadStates.get(uri);
if (downloadState != null) {
Download download = downloads.get(uri);
if (download != null) {
DownloadService.startWithRemoveDownload(
context, DemoDownloadService.class, downloadState.action.id, /* foreground= */ false);
context, DemoDownloadService.class, download.action.id, /* foreground= */ false);
} else {
if (startDownloadDialogHelper != null) {
startDownloadDialogHelper.release();
......@@ -122,16 +122,16 @@ public class DownloadTracker implements DownloadManager.Listener {
// DownloadManager.Listener
@Override
public void onDownloadStateChanged(DownloadManager downloadManager, DownloadState downloadState) {
downloadStates.put(downloadState.action.uri, downloadState);
public void onDownloadChanged(DownloadManager downloadManager, Download download) {
downloads.put(download.action.uri, download);
for (Listener listener : listeners) {
listener.onDownloadsChanged();
}
}
@Override
public void onDownloadRemoved(DownloadManager downloadManager, DownloadState downloadState) {
downloadStates.remove(downloadState.action.uri);
public void onDownloadRemoved(DownloadManager downloadManager, Download download) {
downloads.remove(download.action.uri);
for (Listener listener : listeners) {
listener.onDownloadsChanged();
}
......@@ -140,10 +140,10 @@ public class DownloadTracker implements DownloadManager.Listener {
// Internal methods
private void loadDownloads() {
try (DownloadStateCursor loadedDownloadStates = downloadIndex.getDownloadStates()) {
while (loadedDownloadStates.moveToNext()) {
DownloadState downloadState = loadedDownloadStates.getDownloadState();
downloadStates.put(downloadState.action.uri, downloadState);
try (DownloadCursor loadedDownloads = downloadIndex.getDownloads()) {
while (loadedDownloads.moveToNext()) {
Download download = loadedDownloads.getDownload();
downloads.put(download.action.uri, download);
}
} catch (IOException e) {
Log.w(TAG, "Failed to query download states", e);
......
......@@ -33,7 +33,7 @@ import java.util.ArrayList;
import java.util.List;
/**
* A {@link DownloadIndex} which uses SQLite to persist {@link DownloadState}s.
* A {@link DownloadIndex} which uses SQLite to persist {@link Download}s.
*
* <p class="caution">Database access may take a long time, do not call methods of this class from
* the application main thread.
......@@ -88,7 +88,7 @@ public final class DefaultDownloadIndex implements DownloadIndex {
private static final String WHERE_ID_EQUALS = COLUMN_ID + " = ?";
private static final String WHERE_STATE_TERMINAL =
getStateQuery(DownloadState.STATE_COMPLETED, DownloadState.STATE_FAILED);
getStateQuery(Download.STATE_COMPLETED, Download.STATE_FAILED);
private static final String[] COLUMNS =
new String[] {
......@@ -153,8 +153,8 @@ public final class DefaultDownloadIndex implements DownloadIndex {
private boolean initialized;
/**
* Creates a DefaultDownloadIndex which stores the {@link DownloadState}s on a SQLite database
* provided by {@code databaseProvider}.
* Creates a DefaultDownloadIndex which stores the {@link Download}s on a SQLite database provided
* by {@code databaseProvider}.
*
* @param databaseProvider A DatabaseProvider which provides the database which will be used to
* store DownloadStatus table.
......@@ -165,52 +165,51 @@ public final class DefaultDownloadIndex implements DownloadIndex {
@Override
@Nullable
public DownloadState getDownloadState(String id) throws DatabaseIOException {
public Download getDownload(String id) throws DatabaseIOException {
ensureInitialized();
try (Cursor cursor = getCursor(WHERE_ID_EQUALS, new String[] {id})) {
if (cursor.getCount() == 0) {
return null;
}
cursor.moveToNext();
return getDownloadStateForCurrentRow(cursor);
return getDownloadForCurrentRow(cursor);
} catch (SQLiteException e) {
throw new DatabaseIOException(e);
}
}
@Override
public DownloadStateCursor getDownloadStates(@DownloadState.State int... states)
throws DatabaseIOException {
public DownloadCursor getDownloads(@Download.State int... states) throws DatabaseIOException {
ensureInitialized();
Cursor cursor = getCursor(getStateQuery(states), /* selectionArgs= */ null);
return new DownloadStateCursorImpl(cursor);
return new DownloadCursorImpl(cursor);
}
/**
* Adds or replaces a {@link DownloadState}.
* Adds or replaces a {@link Download}.
*
* @param downloadState The {@link DownloadState} to be added.
* @param download The {@link Download} to be added.
* @throws DatabaseIOException If an error occurs setting the state.
*/
public void putDownloadState(DownloadState downloadState) throws DatabaseIOException {
public void putDownload(Download download) throws DatabaseIOException {
ensureInitialized();
ContentValues values = new ContentValues();
values.put(COLUMN_ID, downloadState.action.id);
values.put(COLUMN_TYPE, downloadState.action.type);
values.put(COLUMN_URI, downloadState.action.uri.toString());
values.put(COLUMN_STREAM_KEYS, encodeStreamKeys(downloadState.action.streamKeys));
values.put(COLUMN_CUSTOM_CACHE_KEY, downloadState.action.customCacheKey);
values.put(COLUMN_DATA, downloadState.action.data);
values.put(COLUMN_STATE, downloadState.state);
values.put(COLUMN_DOWNLOAD_PERCENTAGE, downloadState.getDownloadPercentage());
values.put(COLUMN_DOWNLOADED_BYTES, downloadState.getDownloadedBytes());
values.put(COLUMN_TOTAL_BYTES, downloadState.getTotalBytes());
values.put(COLUMN_FAILURE_REASON, downloadState.failureReason);
values.put(COLUMN_ID, download.action.id);
values.put(COLUMN_TYPE, download.action.type);
values.put(COLUMN_URI, download.action.uri.toString());
values.put(COLUMN_STREAM_KEYS, encodeStreamKeys(download.action.streamKeys));
values.put(COLUMN_CUSTOM_CACHE_KEY, download.action.customCacheKey);
values.put(COLUMN_DATA, download.action.data);
values.put(COLUMN_STATE, download.state);
values.put(COLUMN_DOWNLOAD_PERCENTAGE, download.getDownloadPercentage());
values.put(COLUMN_DOWNLOADED_BYTES, download.getDownloadedBytes());
values.put(COLUMN_TOTAL_BYTES, download.getTotalBytes());
values.put(COLUMN_FAILURE_REASON, download.failureReason);
values.put(COLUMN_STOP_FLAGS, 0);
values.put(COLUMN_NOT_MET_REQUIREMENTS, 0);
values.put(COLUMN_MANUAL_STOP_REASON, downloadState.manualStopReason);
values.put(COLUMN_START_TIME_MS, downloadState.startTimeMs);
values.put(COLUMN_UPDATE_TIME_MS, downloadState.updateTimeMs);
values.put(COLUMN_MANUAL_STOP_REASON, download.manualStopReason);
values.put(COLUMN_START_TIME_MS, download.startTimeMs);
values.put(COLUMN_UPDATE_TIME_MS, download.updateTimeMs);
try {
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
writableDatabase.replaceOrThrow(TABLE_NAME, /* nullColumnHack= */ null, values);
......@@ -220,12 +219,12 @@ public final class DefaultDownloadIndex implements DownloadIndex {
}
/**
* Removes the {@link DownloadState} with the given {@code id}.
* Removes the {@link Download} with the given {@code id}.
*
* @param id ID of a {@link DownloadState}.
* @param id ID of a {@link Download}.
* @throws DatabaseIOException If an error occurs removing the state.
*/
public void removeDownloadState(String id) throws DatabaseIOException {
public void removeDownload(String id) throws DatabaseIOException {
ensureInitialized();
try {
databaseProvider.getWritableDatabase().delete(TABLE_NAME, WHERE_ID_EQUALS, new String[] {id});
......@@ -236,7 +235,7 @@ public final class DefaultDownloadIndex implements DownloadIndex {
/**
* Sets the manual stop reason of the downloads in a terminal state ({@link
* DownloadState#STATE_COMPLETED}, {@link DownloadState#STATE_FAILED}).
* Download#STATE_COMPLETED}, {@link Download#STATE_FAILED}).
*
* @param manualStopReason The manual stop reason.
* @throws DatabaseIOException If an error occurs updating the state.
......@@ -255,12 +254,12 @@ public final class DefaultDownloadIndex implements DownloadIndex {
/**
* Sets the manual stop reason of the download with the given {@code id} in a terminal state
* ({@link DownloadState#STATE_COMPLETED}, {@link DownloadState#STATE_FAILED}).
* ({@link Download#STATE_COMPLETED}, {@link Download#STATE_FAILED}).
*
* <p>If there's no {@link DownloadState} with the given {@code id} or it isn't in a terminal
* state, then nothing happens.
* <p>If there's no {@link Download} with the given {@code id} or it isn't in a terminal state,
* then nothing happens.
*
* @param id ID of a {@link DownloadState}.
* @param id ID of a {@link Download}.
* @param manualStopReason The manual stop reason.
* @throws DatabaseIOException If an error occurs updating the state.
*/
......@@ -326,7 +325,7 @@ public final class DefaultDownloadIndex implements DownloadIndex {
}
}
private static String getStateQuery(@DownloadState.State int... states) {
private static String getStateQuery(@Download.State int... states) {
if (states.length == 0) {
return TRUE;
}
......@@ -342,7 +341,7 @@ public final class DefaultDownloadIndex implements DownloadIndex {
return selectionBuilder.toString();
}
private static DownloadState getDownloadStateForCurrentRow(Cursor cursor) {
private static Download getDownloadForCurrentRow(Cursor cursor) {
DownloadAction action =
new DownloadAction(
cursor.getString(COLUMN_INDEX_ID),
......@@ -355,7 +354,7 @@ public final class DefaultDownloadIndex implements DownloadIndex {
cachingCounters.alreadyCachedBytes = cursor.getLong(COLUMN_INDEX_DOWNLOADED_BYTES);
cachingCounters.contentLength = cursor.getLong(COLUMN_INDEX_TOTAL_BYTES);
cachingCounters.percentage = cursor.getFloat(COLUMN_INDEX_DOWNLOAD_PERCENTAGE);
return new DownloadState(
return new Download(
action,
cursor.getInt(COLUMN_INDEX_STATE),
cursor.getInt(COLUMN_INDEX_FAILURE_REASON),
......@@ -401,17 +400,17 @@ public final class DefaultDownloadIndex implements DownloadIndex {
return streamKeys;
}
private static final class DownloadStateCursorImpl implements DownloadStateCursor {
private static final class DownloadCursorImpl implements DownloadCursor {
private final Cursor cursor;
private DownloadStateCursorImpl(Cursor cursor) {
private DownloadCursorImpl(Cursor cursor) {
this.cursor = cursor;
}
@Override
public DownloadState getDownloadState() {
return getDownloadStateForCurrentRow(cursor);
public Download getDownload() {
return getDownloadForCurrentRow(cursor);
}
@Override
......
......@@ -24,7 +24,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** Represents state of a download. */
public final class DownloadState {
public final class Download {
/**
* Download states. One of {@link #STATE_QUEUED}, {@link #STATE_STOPPED}, {@link
......@@ -128,15 +128,15 @@ public final class DownloadState {
/*package*/ CachingCounters counters;
/**
* Creates a {@link DownloadState} using a {@link DownloadAction}.
* Creates a {@link Download} using a {@link DownloadAction}.
*
* @param action The {@link DownloadAction}.
*/
public DownloadState(DownloadAction action) {
public Download(DownloadAction action) {
this(action, System.currentTimeMillis());
}
private DownloadState(DownloadAction action, long currentTimeMs) {
private Download(DownloadAction action, long currentTimeMs) {
this(
action,
/* state= */ STATE_QUEUED,
......@@ -147,7 +147,7 @@ public final class DownloadState {
new CachingCounters());
}
/* package */ DownloadState(
/* package */ Download(
DownloadAction action,
@State int state,
@FailureReason int failureReason,
......@@ -170,15 +170,15 @@ public final class DownloadState {
}
/**
* Merges the given {@link DownloadAction} and creates a new {@link DownloadState}. The action
* must have the same id and type.
* Merges the given {@link DownloadAction} and creates a new {@link Download}. The action must
* have the same id and type.
*
* @param newAction The {@link DownloadAction} to be merged.
* @param canStart Whether the download is eligible to be started.
* @return A new {@link DownloadState}.
* @return A new {@link Download}.
*/
public DownloadState copyWithMergedAction(DownloadAction newAction, boolean canStart) {
return new DownloadState(
public Download copyWithMergedAction(DownloadAction newAction, boolean canStart) {
return new Download(
action.copyWithMergedAction(newAction),
getNextState(state, canStart && manualStopReason == 0),
FAILURE_REASON_NONE,
......@@ -193,8 +193,8 @@ public final class DownloadState {
*
* @param state The {@link State}.
*/
public DownloadState copyWithState(@State int state) {
return new DownloadState(
public Download copyWithState(@State int state) {
return new Download(
action,
state,
FAILURE_REASON_NONE,
......
......@@ -18,19 +18,19 @@ package com.google.android.exoplayer2.offline;
import java.io.Closeable;
/** Provides random read-write access to the result set returned by a database query. */
public interface DownloadStateCursor extends Closeable {
public interface DownloadCursor extends Closeable {
/** Returns the DownloadState at the current position. */
DownloadState getDownloadState();
/** Returns the download at the current position. */
Download getDownload();
/** Returns the numbers of DownloadStates in the cursor. */
/** Returns the numbers of downloads in the cursor. */
int getCount();
/**
* Returns the current position of the cursor in the DownloadState set. The value is zero-based.
* When the DownloadState set is first returned the cursor will be at positon -1, which is before
* the first DownloadState. After the last DownloadState is returned another call to next() will
* leave the cursor past the last entry, at a position of count().
* Returns the current position of the cursor in the download set. The value is zero-based. When
* the download set is first returned the cursor will be at positon -1, which is before the first
* download. After the last download is returned another call to next() will leave the cursor past
* the last entry, at a position of count().
*
* @return the current cursor position.
*/
......@@ -49,7 +49,7 @@ public interface DownloadStateCursor extends Closeable {
boolean moveToPosition(int position);
/**
* Move the cursor to the first DownloadState.
* Move the cursor to the first download.
*
* <p>This method will return false if the cursor is empty.
*
......@@ -60,7 +60,7 @@ public interface DownloadStateCursor extends Closeable {
}
/**
* Move the cursor to the last DownloadState.
* Move the cursor to the last download.
*
* <p>This method will return false if the cursor is empty.
*
......@@ -71,7 +71,7 @@ public interface DownloadStateCursor extends Closeable {
}
/**
* Move the cursor to the next DownloadState.
* Move the cursor to the next download.
*
* <p>This method will return false if the cursor is already past the last entry in the result
* set.
......@@ -83,7 +83,7 @@ public interface DownloadStateCursor extends Closeable {
}
/**
* Move the cursor to the previous DownloadState.
* Move the cursor to the previous download.
*
* <p>This method will return false if the cursor is already before the first entry in the result
* set.
......@@ -94,18 +94,18 @@ public interface DownloadStateCursor extends Closeable {
return moveToPosition(getPosition() - 1);
}
/** Returns whether the cursor is pointing to the first DownloadState. */
/** Returns whether the cursor is pointing to the first download. */
default boolean isFirst() {
return getPosition() == 0 && getCount() != 0;
}
/** Returns whether the cursor is pointing to the last DownloadState. */
/** Returns whether the cursor is pointing to the last download. */
default boolean isLast() {
int count = getCount();
return getPosition() == (count - 1) && count != 0;
}
/** Returns whether the cursor is pointing to the position before the first DownloadState. */
/** Returns whether the cursor is pointing to the position before the first download. */
default boolean isBeforeFirst() {
if (getCount() == 0) {
return true;
......@@ -113,7 +113,7 @@ public interface DownloadStateCursor extends Closeable {
return getPosition() == -1;
}
/** Returns whether the cursor is pointing to the position after the last DownloadState. */
/** Returns whether the cursor is pointing to the position after the last download. */
default boolean isAfterLast() {
if (getCount() == 0) {
return true;
......
......@@ -18,27 +18,26 @@ package com.google.android.exoplayer2.offline;
import androidx.annotation.Nullable;
import java.io.IOException;
/** Persists {@link DownloadState}s. */
/** Persists {@link Download}s. */
public interface DownloadIndex {
/**
* Returns the {@link DownloadState} with the given {@code id}, or null.
* Returns the {@link Download} with the given {@code id}, or null.
*
* @param id ID of a {@link DownloadState}.
* @return The {@link DownloadState} with the given {@code id}, or null if a download state with
* this id doesn't exist.
* @param id ID of a {@link Download}.
* @return The {@link Download} with the given {@code id}, or null if a download state with this
* id doesn't exist.
* @throws IOException If an error occurs reading the state.
*/
@Nullable
DownloadState getDownloadState(String id) throws IOException;
Download getDownload(String id) throws IOException;
/**
* Returns a {@link DownloadStateCursor} to {@link DownloadState}s with the given {@code states}.
* Returns a {@link DownloadCursor} to {@link Download}s with the given {@code states}.
*
* @param states Returns only the {@link DownloadState}s with this states. If empty, returns all.
* @return A cursor to {@link DownloadState}s with the given {@code states}.
* @param states Returns only the {@link Download}s with this states. If empty, returns all.
* @return A cursor to {@link Download}s with the given {@code states}.
* @throws IOException If an error occurs reading the state.
*/
DownloadStateCursor getDownloadStates(@DownloadState.State int... states) throws IOException;
DownloadCursor getDownloads(@Download.State int... states) throws IOException;
}
......@@ -69,12 +69,12 @@ public final class DownloadIndexUtil {
*/
/* package */ static void mergeAction(DownloadAction action, DefaultDownloadIndex downloadIndex)
throws IOException {
DownloadState downloadState = downloadIndex.getDownloadState(action.id);
if (downloadState != null) {
downloadState = downloadState.copyWithMergedAction(action, /* canStart= */ true);
Download download = downloadIndex.getDownload(action.id);
if (download != null) {
download = download.copyWithMergedAction(action, /* canStart= */ true);
} else {
downloadState = new DownloadState(action);
download = new Download(action);
}
downloadIndex.putDownloadState(downloadState);
downloadIndex.putDownload(download);
}
}
......@@ -15,17 +15,17 @@
*/
package com.google.android.exoplayer2.offline;
import static com.google.android.exoplayer2.offline.DownloadState.FAILURE_REASON_NONE;
import static com.google.android.exoplayer2.offline.DownloadState.FAILURE_REASON_UNKNOWN;
import static com.google.android.exoplayer2.offline.DownloadState.MANUAL_STOP_REASON_NONE;
import static com.google.android.exoplayer2.offline.DownloadState.MANUAL_STOP_REASON_UNDEFINED;
import static com.google.android.exoplayer2.offline.DownloadState.STATE_COMPLETED;
import static com.google.android.exoplayer2.offline.DownloadState.STATE_DOWNLOADING;
import static com.google.android.exoplayer2.offline.DownloadState.STATE_FAILED;
import static com.google.android.exoplayer2.offline.DownloadState.STATE_QUEUED;
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.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;
import static com.google.android.exoplayer2.offline.Download.STATE_QUEUED;
import static com.google.android.exoplayer2.offline.Download.STATE_REMOVING;
import static com.google.android.exoplayer2.offline.Download.STATE_RESTARTING;
import static com.google.android.exoplayer2.offline.Download.STATE_STOPPED;
import android.content.Context;
import android.os.Handler;
......@@ -74,18 +74,17 @@ public final class DownloadManager {
* Called when the state of a download changes.
*
* @param downloadManager The reporting instance.
* @param downloadState The state of the download.
* @param download The state of the download.
*/
default void onDownloadStateChanged(
DownloadManager downloadManager, DownloadState downloadState) {}
default void onDownloadChanged(DownloadManager downloadManager, Download download) {}
/**
* Called when a download is removed.
*
* @param downloadManager The reporting instance.
* @param downloadState The last state of the download before it was removed.
* @param download The last state of the download before it was removed.
*/
default void onDownloadRemoved(DownloadManager downloadManager, DownloadState downloadState) {}
default void onDownloadRemoved(DownloadManager downloadManager, Download download) {}
/**
* Called when there is no active download left.
......@@ -160,11 +159,11 @@ public final class DownloadManager {
// Collections that are accessed on the main thread.
private final CopyOnWriteArraySet<Listener> listeners;
private final ArrayList<DownloadState> downloadStates;
private final ArrayList<Download> downloads;
// Collections that are accessed on the internal thread.
private final ArrayList<Download> downloads;
private final HashMap<Download, DownloadThread> activeDownloads;
private final ArrayList<DownloadInternal> downloadInternals;
private final HashMap<DownloadInternal, DownloadThread> activeDownloads;
// Mutable fields that are accessed on the main thread.
private int pendingMessages;
......@@ -246,8 +245,8 @@ public final class DownloadManager {
this.minRetryCount = minRetryCount;
manualStopReason = MANUAL_STOP_REASON_UNDEFINED;
downloadInternals = new ArrayList<>();
downloads = new ArrayList<>();
downloadStates = new ArrayList<>();
activeDownloads = new HashMap<>();
listeners = new CopyOnWriteArraySet<>();
releaseLock = new Object();
......@@ -285,12 +284,12 @@ public final class DownloadManager {
/** Returns the number of downloads. */
public int getDownloadCount() {
return downloadStates.size();
return downloads.size();
}
/** Returns the states of all current downloads. */
public DownloadState[] getAllDownloadStates() {
return downloadStates.toArray(new DownloadState[0]);
public Download[] getAllDownloads() {
return downloads.toArray(new Download[0]);
}
/** Returns the requirements needed to be met to start downloads. */
......@@ -347,9 +346,9 @@ public final class DownloadManager {
* Sets a manual stop reason for all downloads.
*
* @param manualStopReason An application defined stop reason. Value {@value
* DownloadState#MANUAL_STOP_REASON_NONE} is not allowed and value {@value
* DownloadState#MANUAL_STOP_REASON_UNDEFINED} is reserved for {@link
* DownloadState#MANUAL_STOP_REASON_UNDEFINED}.
* 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 stopDownloads(int manualStopReason) {
Assertions.checkArgument(manualStopReason != MANUAL_STOP_REASON_NONE);
......@@ -382,9 +381,9 @@ public final class DownloadManager {
*
* @param id The unique content id of the download to be stopped.
* @param manualStopReason An application defined stop reason. Value {@value
* DownloadState#MANUAL_STOP_REASON_NONE} is not allowed and value {@value
* DownloadState#MANUAL_STOP_REASON_UNDEFINED} is reserved for {@link
* DownloadState#MANUAL_STOP_REASON_UNDEFINED}.
* 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);
......@@ -439,7 +438,7 @@ public final class DownloadManager {
pendingMessages = 0;
activeDownloadCount = 0;
initialized = false;
downloadStates.clear();
downloads.clear();
}
}
......@@ -469,15 +468,15 @@ public final class DownloadManager {
private boolean handleMainMessage(Message message) {
switch (message.what) {
case MSG_INITIALIZED:
List<DownloadState> downloadStates = (List<DownloadState>) message.obj;
onInitialized(downloadStates);
List<Download> downloads = (List<Download>) message.obj;
onInitialized(downloads);
break;
case MSG_DOWNLOAD_STATE_CHANGED:
DownloadState state = (DownloadState) message.obj;
onDownloadStateChanged(state);
Download state = (Download) message.obj;
onDownloadChanged(state);
break;
case MSG_DOWNLOAD_REMOVED:
state = (DownloadState) message.obj;
state = (Download) message.obj;
onDownloadRemoved(state);
break;
case MSG_PROCESSED:
......@@ -493,34 +492,34 @@ public final class DownloadManager {
// TODO: Merge these three events into a single MSG_STATE_CHANGE that can carry all updates. This
// allows updating idle at the same point as the downloads that can be queried changes.
private void onInitialized(List<DownloadState> downloadStates) {
private void onInitialized(List<Download> downloads) {
initialized = true;
this.downloadStates.addAll(downloadStates);
this.downloads.addAll(downloads);
for (Listener listener : listeners) {
listener.onInitialized(DownloadManager.this);
}
}
private void onDownloadStateChanged(DownloadState downloadState) {
int downloadStateIndex = getDownloadStateIndex(downloadState.action.id);
if (downloadState.state == STATE_COMPLETED || downloadState.state == STATE_FAILED) {
if (downloadStateIndex != C.INDEX_UNSET) {
downloadStates.remove(downloadStateIndex);
private void onDownloadChanged(Download download) {
int downloadIndex = getDownloadIndex(download.action.id);
if (download.state == STATE_COMPLETED || download.state == STATE_FAILED) {
if (downloadIndex != C.INDEX_UNSET) {
downloads.remove(downloadIndex);
}
} else if (downloadStateIndex != C.INDEX_UNSET) {
downloadStates.set(downloadStateIndex, downloadState);
} else if (downloadIndex != C.INDEX_UNSET) {
downloads.set(downloadIndex, download);
} else {
downloadStates.add(downloadState);
downloads.add(download);
}
for (Listener listener : listeners) {
listener.onDownloadStateChanged(this, downloadState);
listener.onDownloadChanged(this, download);
}
}
private void onDownloadRemoved(DownloadState downloadState) {
downloadStates.remove(getDownloadStateIndex(downloadState.action.id));
private void onDownloadRemoved(Download download) {
downloads.remove(getDownloadIndex(download.action.id));
for (Listener listener : listeners) {
listener.onDownloadRemoved(this, downloadState);
listener.onDownloadRemoved(this, download);
}
}
......@@ -534,9 +533,9 @@ public final class DownloadManager {
}
}
private int getDownloadStateIndex(String id) {
for (int i = 0; i < downloadStates.size(); i++) {
if (downloadStates.get(i).action.id.equals(id)) {
private int getDownloadIndex(String id) {
for (int i = 0; i < downloads.size(); i++) {
if (downloads.get(i).action.id.equals(id)) {
return i;
}
}
......@@ -588,16 +587,16 @@ public final class DownloadManager {
private void setManualStopReasonInternal(@Nullable String id, int manualStopReason) {
if (id != null) {
Download download = getDownload(id);
if (download != null) {
logd("download manual stop reason is set to : " + manualStopReason, download);
download.setManualStopReason(manualStopReason);
DownloadInternal downloadInternal = getDownload(id);
if (downloadInternal != null) {
logd("download manual stop reason is set to : " + manualStopReason, downloadInternal);
downloadInternal.setManualStopReason(manualStopReason);
return;
}
} else {
this.manualStopReason = manualStopReason;
for (int i = 0; i < downloads.size(); i++) {
downloads.get(i).setManualStopReason(manualStopReason);
for (int i = 0; i < downloadInternals.size(); i++) {
downloadInternals.get(i).setManualStopReason(manualStopReason);
}
}
try {
......@@ -612,60 +611,59 @@ public final class DownloadManager {
}
private void addDownloadInternal(DownloadAction action) {
Download download = getDownload(action.id);
if (download != null) {
download.addAction(action);
logd("Action is added to existing download", download);
DownloadInternal downloadInternal = getDownload(action.id);
if (downloadInternal != null) {
downloadInternal.addAction(action);
logd("Action is added to existing download", downloadInternal);
} else {
DownloadState downloadState = loadDownloadState(action.id);
if (downloadState == null) {
downloadState = new DownloadState(action);
Download download = loadDownload(action.id);
if (download == null) {
download = new Download(action);
logd("Download state is created for " + action.id);
} else {
downloadState =
downloadState.copyWithMergedAction(action, /* canStart= */ notMetRequirements == 0);
download = download.copyWithMergedAction(action, /* canStart= */ notMetRequirements == 0);
logd("Download state is loaded for " + action.id);
}
addDownloadForState(downloadState);
addDownloadForState(download);
}
}
private void removeDownloadInternal(String id) {
Download download = getDownload(id);
if (download != null) {
download.remove();
DownloadInternal downloadInternal = getDownload(id);
if (downloadInternal != null) {
downloadInternal.remove();
} else {
DownloadState downloadState = loadDownloadState(id);
if (downloadState != null) {
addDownloadForState(downloadState.copyWithState(STATE_REMOVING));
Download download = loadDownload(id);
if (download != null) {
addDownloadForState(download.copyWithState(STATE_REMOVING));
} else {
logd("Can't remove download. No download with id: " + id);
}
}
}
private void onDownloadStateChangedInternal(Download download, DownloadState downloadState) {
logd("Download state is changed", download);
private void onDownloadChangedInternal(DownloadInternal downloadInternal, Download download) {
logd("Download state is changed", downloadInternal);
try {
downloadIndex.putDownloadState(downloadState);
downloadIndex.putDownload(download);
} catch (DatabaseIOException e) {
Log.e(TAG, "Failed to update index", e);
}
if (download.state == STATE_COMPLETED || download.state == STATE_FAILED) {
downloads.remove(download);
if (downloadInternal.state == STATE_COMPLETED || downloadInternal.state == STATE_FAILED) {
downloadInternals.remove(downloadInternal);
}
mainHandler.obtainMessage(MSG_DOWNLOAD_STATE_CHANGED, downloadState).sendToTarget();
mainHandler.obtainMessage(MSG_DOWNLOAD_STATE_CHANGED, download).sendToTarget();
}
private void onDownloadRemovedInternal(Download download, DownloadState downloadState) {
logd("Download is removed", download);
private void onDownloadRemovedInternal(DownloadInternal downloadInternal, Download download) {
logd("Download is removed", downloadInternal);
try {
downloadIndex.removeDownloadState(downloadState.action.id);
downloadIndex.removeDownload(download.action.id);
} catch (DatabaseIOException e) {
Log.e(TAG, "Failed to remove from index", e);
}
downloads.remove(download);
mainHandler.obtainMessage(MSG_DOWNLOAD_REMOVED, downloadState).sendToTarget();
downloadInternals.remove(downloadInternal);
mainHandler.obtainMessage(MSG_DOWNLOAD_REMOVED, download).sendToTarget();
}
private void setNotMetRequirementsInternal(
......@@ -675,25 +673,25 @@ public final class DownloadManager {
}
this.notMetRequirements = notMetRequirements;
logdFlags("Not met requirements are changed", notMetRequirements);
for (int i = 0; i < downloads.size(); i++) {
downloads.get(i).setNotMetRequirements(notMetRequirements);
for (int i = 0; i < downloadInternals.size(); i++) {
downloadInternals.get(i).setNotMetRequirements(notMetRequirements);
}
}
@Nullable
private Download getDownload(String id) {
for (int i = 0; i < downloads.size(); i++) {
Download download = downloads.get(i);
if (download.getId().equals(id)) {
return download;
private DownloadInternal getDownload(String id) {
for (int i = 0; i < downloadInternals.size(); i++) {
DownloadInternal downloadInternal = downloadInternals.get(i);
if (downloadInternal.getId().equals(id)) {
return downloadInternal;
}
}
return null;
}
private DownloadState loadDownloadState(String id) {
private Download loadDownload(String id) {
try {
return downloadIndex.getDownloadState(id);
return downloadIndex.getDownload(id);
} catch (DatabaseIOException e) {
Log.e(TAG, "loadDownload failed", e);
}
......@@ -702,33 +700,34 @@ public final class DownloadManager {
private void initializeInternal(int notMetRequirements) {
this.notMetRequirements = notMetRequirements;
ArrayList<DownloadState> loadedStates = new ArrayList<>();
try (DownloadStateCursor cursor =
downloadIndex.getDownloadStates(
ArrayList<Download> loadedStates = new ArrayList<>();
try (DownloadCursor cursor =
downloadIndex.getDownloads(
STATE_QUEUED, STATE_STOPPED, STATE_DOWNLOADING, STATE_REMOVING, STATE_RESTARTING)) {
while (cursor.moveToNext()) {
loadedStates.add(cursor.getDownloadState());
loadedStates.add(cursor.getDownload());
}
logd("Download states are loaded.");
} catch (Throwable e) {
Log.e(TAG, "Download state loading failed.", e);
loadedStates.clear();
}
for (DownloadState downloadState : loadedStates) {
addDownloadForState(downloadState);
for (Download download : loadedStates) {
addDownloadForState(download);
}
logd("Downloads are created.");
mainHandler.obtainMessage(MSG_INITIALIZED, loadedStates).sendToTarget();
for (int i = 0; i < downloads.size(); i++) {
downloads.get(i).start();
for (int i = 0; i < downloadInternals.size(); i++) {
downloadInternals.get(i).start();
}
}
private void addDownloadForState(DownloadState downloadState) {
Download download = new Download(this, downloadState, notMetRequirements, manualStopReason);
downloads.add(download);
logd("Download is added", download);
download.initialize();
private void addDownloadForState(Download download) {
DownloadInternal downloadInternal =
new DownloadInternal(this, download, notMetRequirements, manualStopReason);
downloadInternals.add(downloadInternal);
logd("Download is added", downloadInternal);
downloadInternal.initialize();
}
private static void logd(String message) {
......@@ -737,9 +736,9 @@ public final class DownloadManager {
}
}
private static void logd(String message, Download download) {
private static void logd(String message, DownloadInternal downloadInternal) {
if (DEBUG) {
logd(message + ": " + download);
logd(message + ": " + downloadInternal);
}
}
......@@ -750,39 +749,39 @@ public final class DownloadManager {
}
@StartThreadResults
private int startDownloadThread(Download download) {
if (activeDownloads.containsKey(download)) {
if (stopDownloadThread(download)) {
private int startDownloadThread(DownloadInternal downloadInternal) {
if (activeDownloads.containsKey(downloadInternal)) {
if (stopDownloadThread(downloadInternal)) {
return START_THREAD_WAIT_DOWNLOAD_CANCELLATION;
}
return START_THREAD_WAIT_REMOVAL_TO_FINISH;
}
if (!download.isInRemoveState()) {
if (!downloadInternal.isInRemoveState()) {
if (simultaneousDownloads == maxSimultaneousDownloads) {
return START_THREAD_TOO_MANY_DOWNLOADS;
}
simultaneousDownloads++;
}
DownloadThread downloadThread = new DownloadThread(download);
activeDownloads.put(download, downloadThread);
download.setCounters(downloadThread.downloader.getCounters());
logd("Download is started", download);
DownloadThread downloadThread = new DownloadThread(downloadInternal);
activeDownloads.put(downloadInternal, downloadThread);
downloadInternal.setCounters(downloadThread.downloader.getCounters());
logd("Download is started", downloadInternal);
return START_THREAD_SUCCEEDED;
}
private boolean stopDownloadThread(Download download) {
DownloadThread downloadThread = activeDownloads.get(download);
private boolean stopDownloadThread(DownloadInternal downloadInternal) {
DownloadThread downloadThread = activeDownloads.get(downloadInternal);
if (downloadThread != null && !downloadThread.isRemoveThread) {
downloadThread.cancel();
logd("Download is cancelled", download);
logd("Download is cancelled", downloadInternal);
return true;
}
return false;
}
private void releaseInternal() {
for (Download download : activeDownloads.keySet()) {
stopDownloadThread(download);
for (DownloadInternal downloadInternal : activeDownloads.keySet()) {
stopDownloadThread(downloadInternal);
}
internalThread.quit();
synchronized (releaseLock) {
......@@ -792,56 +791,55 @@ public final class DownloadManager {
}
private void onDownloadThreadStoppedInternal(DownloadThread downloadThread) {
Download download = downloadThread.download;
logd("Download is stopped", download);
activeDownloads.remove(download);
DownloadInternal downloadInternal = downloadThread.downloadInternal;
logd("Download is stopped", downloadInternal);
activeDownloads.remove(downloadInternal);
boolean tryToStartDownloads = false;
if (!downloadThread.isRemoveThread) {
// If maxSimultaneousDownloads was hit, there might be a download waiting for a slot.
tryToStartDownloads = simultaneousDownloads == maxSimultaneousDownloads;
simultaneousDownloads--;
}
download.onDownloadThreadStopped(downloadThread.isCanceled, downloadThread.finalError);
downloadInternal.onDownloadThreadStopped(downloadThread.isCanceled, downloadThread.finalError);
if (tryToStartDownloads) {
for (int i = 0;
simultaneousDownloads < maxSimultaneousDownloads && i < downloads.size();
simultaneousDownloads < maxSimultaneousDownloads && i < downloadInternals.size();
i++) {
downloads.get(i).start();
downloadInternals.get(i).start();
}
}
}
private static final class Download {
private static final class DownloadInternal {
private final DownloadManager downloadManager;
private DownloadState downloadState;
@DownloadState.State private int state;
@MonotonicNonNull @DownloadState.FailureReason private int failureReason;
private Download download;
@Download.State private int state;
@MonotonicNonNull @Download.FailureReason private int failureReason;
@Requirements.RequirementFlags private int notMetRequirements;
private int manualStopReason;
private Download(
private DownloadInternal(
DownloadManager downloadManager,
DownloadState downloadState,
Download download,
@Requirements.RequirementFlags int notMetRequirements,
int manualStopReason) {
this.downloadManager = downloadManager;
this.downloadState = downloadState;
this.download = download;
this.notMetRequirements = notMetRequirements;
this.manualStopReason = manualStopReason;
}
private void initialize() {
initialize(downloadState.state);
initialize(download.state);
}
public String getId() {
return downloadState.action.id;
return download.action.id;
}
public void addAction(DownloadAction newAction) {
downloadState =
downloadState.copyWithMergedAction(newAction, /* canStart= */ notMetRequirements == 0);
download = download.copyWithMergedAction(newAction, /* canStart= */ notMetRequirements == 0);
initialize();
}
......@@ -849,17 +847,17 @@ public final class DownloadManager {
initialize(STATE_REMOVING);
}
public DownloadState getUpdatedDownloadState() {
downloadState =
new DownloadState(
downloadState.action,
public Download getUpdatedDownload() {
download =
new Download(
download.action,
state,
state != STATE_FAILED ? FAILURE_REASON_NONE : failureReason,
manualStopReason,
downloadState.startTimeMs,
download.startTimeMs,
/* updateTimeMs= */ System.currentTimeMillis(),
downloadState.counters);
return downloadState;
download.counters);
return download;
}
public boolean isIdle() {
......@@ -868,7 +866,7 @@ public final class DownloadManager {
@Override
public String toString() {
return getId() + ' ' + DownloadState.getStateString(state);
return getId() + ' ' + Download.getStateString(state);
}
public void start() {
......@@ -894,11 +892,11 @@ public final class DownloadManager {
}
public void setCounters(CachingCounters counters) {
downloadState.setCounters(counters);
download.setCounters(counters);
}
private void updateStopState() {
DownloadState oldDownloadState = downloadState;
Download oldDownload = download;
if (canStart()) {
if (state == STATE_STOPPED) {
startOrQueue();
......@@ -909,8 +907,8 @@ public final class DownloadManager {
setState(STATE_STOPPED);
}
}
if (oldDownloadState == downloadState) {
downloadManager.onDownloadStateChangedInternal(this, getUpdatedDownloadState());
if (oldDownload == download) {
downloadManager.onDownloadChangedInternal(this, getUpdatedDownload());
}
}
......@@ -926,7 +924,7 @@ public final class DownloadManager {
setState(STATE_STOPPED);
}
if (state == initialState) {
downloadManager.onDownloadStateChangedInternal(this, getUpdatedDownloadState());
downloadManager.onDownloadChangedInternal(this, getUpdatedDownload());
}
}
......@@ -945,10 +943,10 @@ public final class DownloadManager {
}
}
private void setState(@DownloadState.State int newState) {
private void setState(@Download.State int newState) {
if (state != newState) {
state = newState;
downloadManager.onDownloadStateChangedInternal(this, getUpdatedDownloadState());
downloadManager.onDownloadChangedInternal(this, getUpdatedDownload());
}
}
......@@ -959,12 +957,12 @@ public final class DownloadManager {
if (isCanceled) {
downloadManager.startDownloadThread(this);
} else if (state == STATE_REMOVING) {
downloadManager.onDownloadRemovedInternal(this, getUpdatedDownloadState());
downloadManager.onDownloadRemovedInternal(this, getUpdatedDownload());
} else if (state == STATE_RESTARTING) {
initialize(STATE_QUEUED);
} else { // STATE_DOWNLOADING
if (error != null) {
Log.e(TAG, "Download failed: " + downloadState.action.id, error);
Log.e(TAG, "Download failed: " + download.action.id, error);
failureReason = FAILURE_REASON_UNKNOWN;
setState(STATE_FAILED);
} else {
......@@ -976,17 +974,17 @@ public final class DownloadManager {
private class DownloadThread extends Thread {
private final Download download;
private final DownloadInternal downloadInternal;
private final Downloader downloader;
private final boolean isRemoveThread;
private volatile boolean isCanceled;
private Throwable finalError;
private DownloadThread(Download download) {
this.download = download;
this.downloader = downloaderFactory.createDownloader(download.downloadState.action);
this.isRemoveThread = download.isInRemoveState();
private DownloadThread(DownloadInternal downloadInternal) {
this.downloadInternal = downloadInternal;
this.downloader = downloaderFactory.createDownloader(downloadInternal.download.action);
this.isRemoveThread = downloadInternal.isInRemoveState();
start();
}
......@@ -1000,7 +998,7 @@ public final class DownloadManager {
@Override
public void run() {
logd("Download started", download);
logd("Download started", downloadInternal);
try {
if (isRemoveThread) {
downloader.remove();
......@@ -1015,14 +1013,14 @@ public final class DownloadManager {
if (!isCanceled) {
long downloadedBytes = downloader.getDownloadedBytes();
if (downloadedBytes != errorPosition) {
logd("Reset error count. downloadedBytes = " + downloadedBytes, download);
logd("Reset error count. downloadedBytes = " + downloadedBytes, downloadInternal);
errorPosition = downloadedBytes;
errorCount = 0;
}
if (++errorCount > minRetryCount) {
throw e;
}
logd("Download error. Retry " + errorCount, download);
logd("Download error. Retry " + errorCount, downloadInternal);
Thread.sleep(getRetryDelayMillis(errorCount));
}
}
......
......@@ -79,8 +79,8 @@ public abstract class DownloadService extends Service {
* <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 DownloadState#MANUAL_STOP_REASON_NONE}. If omitted, the
* stop reason will be {@link DownloadState#MANUAL_STOP_REASON_UNDEFINED}.
* 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>
*/
......@@ -405,8 +405,7 @@ public abstract class DownloadService extends Service {
break;
case ACTION_STOP:
contentId = intent.getStringExtra(KEY_CONTENT_ID);
int stopReason =
intent.getIntExtra(KEY_STOP_REASON, DownloadState.MANUAL_STOP_REASON_UNDEFINED);
int stopReason = intent.getIntExtra(KEY_STOP_REASON, Download.MANUAL_STOP_REASON_UNDEFINED);
if (contentId == null) {
downloadManager.stopDownloads(stopReason);
} else {
......@@ -477,7 +476,7 @@ public abstract class DownloadService extends Service {
* 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 downloadStates} array. The returned notification is used to satisfy system
* with an empty {@code downloads} array. The returned notification is used to satisfy system
* requirements for foreground services.
*
* <p>Download services that do not wish to run in the foreground should be created by setting the
......@@ -485,35 +484,35 @@ public abstract class DownloadService extends Service {
* #FOREGROUND_NOTIFICATION_ID_NONE}. This method will not be called in this case, meaning it can
* be implemented to throw {@link UnsupportedOperationException}.
*
* @param downloadStates The states of all current downloads.
* @param downloads The states of all current downloads.
* @return The foreground notification to display.
*/
protected abstract Notification getForegroundNotification(DownloadState[] downloadStates);
protected abstract Notification getForegroundNotification(Download[] downloads);
/**
* Called when the state of a download changes. The default implementation is a no-op.
*
* @param downloadState The new state of the download.
* @param download The new state of the download.
*/
protected void onDownloadStateChanged(DownloadState downloadState) {
protected void onDownloadChanged(Download download) {
// Do nothing.
}
/**
* Called when a download is removed. The default implementation is a no-op.
*
* @param downloadState The last state of the download before it was removed.
* @param download The last state of the download before it was removed.
*/
protected void onDownloadRemoved(DownloadState downloadState) {
protected void onDownloadRemoved(Download download) {
// Do nothing.
}
private void notifyDownloadStateChange(DownloadState downloadState) {
onDownloadStateChanged(downloadState);
private void notifyDownloadChange(Download download) {
onDownloadChanged(download);
if (foregroundNotificationUpdater != null) {
if (downloadState.state == DownloadState.STATE_DOWNLOADING
|| downloadState.state == DownloadState.STATE_REMOVING
|| downloadState.state == DownloadState.STATE_RESTARTING) {
if (download.state == Download.STATE_DOWNLOADING
|| download.state == Download.STATE_REMOVING
|| download.state == Download.STATE_RESTARTING) {
foregroundNotificationUpdater.startPeriodicUpdates();
} else {
foregroundNotificationUpdater.update();
......@@ -521,8 +520,8 @@ public abstract class DownloadService extends Service {
}
}
private void notifyDownloadRemoved(DownloadState downloadState) {
onDownloadRemoved(downloadState);
private void notifyDownloadRemoved(Download download) {
onDownloadRemoved(download);
if (foregroundNotificationUpdater != null) {
foregroundNotificationUpdater.update();
}
......@@ -582,8 +581,8 @@ public abstract class DownloadService extends Service {
}
public void update() {
DownloadState[] downloadStates = downloadManager.getAllDownloadStates();
startForeground(notificationId, getForegroundNotification(downloadStates));
Download[] downloads = downloadManager.getAllDownloads();
startForeground(notificationId, getForegroundNotification(downloads));
notificationDisplayed = true;
if (periodicUpdatesStarted) {
handler.removeCallbacks(this);
......@@ -641,17 +640,16 @@ public abstract class DownloadService extends Service {
}
@Override
public void onDownloadStateChanged(
DownloadManager downloadManager, DownloadState downloadState) {
public void onDownloadChanged(DownloadManager downloadManager, Download download) {
if (downloadService != null) {
downloadService.notifyDownloadStateChange(downloadState);
downloadService.notifyDownloadChange(download);
}
}
@Override
public void onDownloadRemoved(DownloadManager downloadManager, DownloadState downloadState) {
public void onDownloadRemoved(DownloadManager downloadManager, Download download) {
if (downloadService != null) {
downloadService.notifyDownloadRemoved(downloadState);
downloadService.notifyDownloadRemoved(download);
}
}
......
......@@ -48,39 +48,37 @@ public class DefaultDownloadIndexTest {
}
@Test
public void getDownloadState_nonExistingId_returnsNull() throws DatabaseIOException {
assertThat(downloadIndex.getDownloadState("non existing id")).isNull();
public void getDownload_nonExistingId_returnsNull() throws DatabaseIOException {
assertThat(downloadIndex.getDownload("non existing id")).isNull();
}
@Test
public void addAndGetDownloadState_nonExistingId_returnsTheSameDownloadState()
throws DatabaseIOException {
public void addAndGetDownload_nonExistingId_returnsTheSameDownload() throws DatabaseIOException {
String id = "id";
DownloadState downloadState = new DownloadStateBuilder(id).build();
Download download = new DownloadBuilder(id).build();
downloadIndex.putDownloadState(downloadState);
DownloadState readDownloadState = downloadIndex.getDownloadState(id);
downloadIndex.putDownload(download);
Download readDownload = downloadIndex.getDownload(id);
DownloadStateTest.assertEqual(readDownloadState, downloadState);
DownloadTest.assertEqual(readDownload, download);
}
@Test
public void addAndGetDownloadState_existingId_returnsUpdatedDownloadState()
throws DatabaseIOException {
public void addAndGetDownload_existingId_returnsUpdatedDownload() throws DatabaseIOException {
String id = "id";
DownloadStateBuilder downloadStateBuilder = new DownloadStateBuilder(id);
downloadIndex.putDownloadState(downloadStateBuilder.build());
DownloadBuilder downloadBuilder = new DownloadBuilder(id);
downloadIndex.putDownload(downloadBuilder.build());
DownloadState downloadState =
downloadStateBuilder
Download download =
downloadBuilder
.setType("different type")
.setUri("different uri")
.setCacheKey("different cacheKey")
.setState(DownloadState.STATE_FAILED)
.setState(Download.STATE_FAILED)
.setDownloadPercentage(50)
.setDownloadedBytes(200)
.setTotalBytes(400)
.setFailureReason(DownloadState.FAILURE_REASON_UNKNOWN)
.setFailureReason(Download.FAILURE_REASON_UNKNOWN)
.setManualStopReason(0x12345678)
.setStartTimeMs(10)
.setUpdateTimeMs(20)
......@@ -89,108 +87,94 @@ public class DefaultDownloadIndexTest {
new StreamKey(/* periodIndex= */ 3, /* groupIndex= */ 4, /* trackIndex= */ 5))
.setCustomMetadata(new byte[] {0, 1, 2, 3, 7, 8, 9, 10})
.build();
downloadIndex.putDownloadState(downloadState);
DownloadState readDownloadState = downloadIndex.getDownloadState(id);
downloadIndex.putDownload(download);
Download readDownload = downloadIndex.getDownload(id);
assertThat(readDownloadState).isNotNull();
DownloadStateTest.assertEqual(readDownloadState, downloadState);
assertThat(readDownload).isNotNull();
DownloadTest.assertEqual(readDownload, download);
}
@Test
public void releaseAndRecreateDownloadIndex_returnsTheSameDownloadState()
throws DatabaseIOException {
public void releaseAndRecreateDownloadIndex_returnsTheSameDownload() throws DatabaseIOException {
String id = "id";
DownloadState downloadState = new DownloadStateBuilder(id).build();
downloadIndex.putDownloadState(downloadState);
Download download = new DownloadBuilder(id).build();
downloadIndex.putDownload(download);
downloadIndex = new DefaultDownloadIndex(databaseProvider);
DownloadState readDownloadState = downloadIndex.getDownloadState(id);
assertThat(readDownloadState).isNotNull();
DownloadStateTest.assertEqual(readDownloadState, downloadState);
Download readDownload = downloadIndex.getDownload(id);
assertThat(readDownload).isNotNull();
DownloadTest.assertEqual(readDownload, download);
}
@Test
public void removeDownloadState_nonExistingId_doesNotFail() throws DatabaseIOException {
downloadIndex.removeDownloadState("non existing id");
public void removeDownload_nonExistingId_doesNotFail() throws DatabaseIOException {
downloadIndex.removeDownload("non existing id");
}
@Test
public void removeDownloadState_existingId_getDownloadStateReturnsNull()
throws DatabaseIOException {
public void removeDownload_existingId_getDownloadReturnsNull() throws DatabaseIOException {
String id = "id";
DownloadState downloadState = new DownloadStateBuilder(id).build();
downloadIndex.putDownloadState(downloadState);
downloadIndex.removeDownloadState(id);
Download download = new DownloadBuilder(id).build();
downloadIndex.putDownload(download);
downloadIndex.removeDownload(id);
DownloadState readDownloadState = downloadIndex.getDownloadState(id);
assertThat(readDownloadState).isNull();
Download readDownload = downloadIndex.getDownload(id);
assertThat(readDownload).isNull();
}
@Test
public void getDownloadStates_emptyDownloadIndex_returnsEmptyArray() throws DatabaseIOException {
assertThat(downloadIndex.getDownloadStates().getCount()).isEqualTo(0);
public void getDownloads_emptyDownloadIndex_returnsEmptyArray() throws DatabaseIOException {
assertThat(downloadIndex.getDownloads().getCount()).isEqualTo(0);
}
@Test
public void getDownloadStates_noState_returnsAllDownloadStatusSortedByStartTime()
public void getDownloads_noState_returnsAllDownloadStatusSortedByStartTime()
throws DatabaseIOException {
DownloadState downloadState1 = new DownloadStateBuilder("id1").setStartTimeMs(1).build();
downloadIndex.putDownloadState(downloadState1);
DownloadState downloadState2 = new DownloadStateBuilder("id2").setStartTimeMs(0).build();
downloadIndex.putDownloadState(downloadState2);
DownloadStateCursor cursor = downloadIndex.getDownloadStates();
Download download1 = new DownloadBuilder("id1").setStartTimeMs(1).build();
downloadIndex.putDownload(download1);
Download download2 = new DownloadBuilder("id2").setStartTimeMs(0).build();
downloadIndex.putDownload(download2);
try (DownloadCursor cursor = downloadIndex.getDownloads()) {
assertThat(cursor.getCount()).isEqualTo(2);
cursor.moveToNext();
DownloadStateTest.assertEqual(cursor.getDownloadState(), downloadState2);
DownloadTest.assertEqual(cursor.getDownload(), download2);
cursor.moveToNext();
DownloadStateTest.assertEqual(cursor.getDownloadState(), downloadState1);
cursor.close();
DownloadTest.assertEqual(cursor.getDownload(), download1);
}
}
@Test
public void getDownloadStates_withStates_returnsAllDownloadStatusWithTheSameStates()
public void getDownloads_withStates_returnsAllDownloadStatusWithTheSameStates()
throws DatabaseIOException {
DownloadState downloadState1 =
new DownloadStateBuilder("id1")
.setStartTimeMs(0)
.setState(DownloadState.STATE_REMOVING)
.build();
downloadIndex.putDownloadState(downloadState1);
DownloadState downloadState2 =
new DownloadStateBuilder("id2")
.setStartTimeMs(1)
.setState(DownloadState.STATE_STOPPED)
.build();
downloadIndex.putDownloadState(downloadState2);
DownloadState downloadState3 =
new DownloadStateBuilder("id3")
.setStartTimeMs(2)
.setState(DownloadState.STATE_COMPLETED)
.build();
downloadIndex.putDownloadState(downloadState3);
DownloadStateCursor cursor =
downloadIndex.getDownloadStates(
DownloadState.STATE_REMOVING, DownloadState.STATE_COMPLETED);
Download download1 =
new DownloadBuilder("id1").setStartTimeMs(0).setState(Download.STATE_REMOVING).build();
downloadIndex.putDownload(download1);
Download download2 =
new DownloadBuilder("id2").setStartTimeMs(1).setState(Download.STATE_STOPPED).build();
downloadIndex.putDownload(download2);
Download download3 =
new DownloadBuilder("id3").setStartTimeMs(2).setState(Download.STATE_COMPLETED).build();
downloadIndex.putDownload(download3);
try (DownloadCursor cursor =
downloadIndex.getDownloads(Download.STATE_REMOVING, Download.STATE_COMPLETED)) {
assertThat(cursor.getCount()).isEqualTo(2);
cursor.moveToNext();
DownloadStateTest.assertEqual(cursor.getDownloadState(), downloadState1);
DownloadTest.assertEqual(cursor.getDownload(), download1);
cursor.moveToNext();
DownloadStateTest.assertEqual(cursor.getDownloadState(), downloadState3);
cursor.close();
DownloadTest.assertEqual(cursor.getDownload(), download3);
}
}
@Test
public void putDownloadState_setsVersion() throws DatabaseIOException {
public void putDownload_setsVersion() throws DatabaseIOException {
SQLiteDatabase readableDatabase = databaseProvider.getReadableDatabase();
assertThat(
VersionTable.getVersion(readableDatabase, VersionTable.FEATURE_OFFLINE, INSTANCE_UID))
.isEqualTo(VersionTable.VERSION_UNSET);
downloadIndex.putDownloadState(new DownloadStateBuilder("id1").build());
downloadIndex.putDownload(new DownloadBuilder("id1").build());
assertThat(
VersionTable.getVersion(readableDatabase, VersionTable.FEATURE_OFFLINE, INSTANCE_UID))
......@@ -199,9 +183,9 @@ public class DefaultDownloadIndexTest {
@Test
public void downloadIndex_versionDowngradeWipesData() throws DatabaseIOException {
DownloadState downloadState1 = new DownloadStateBuilder("id1").build();
downloadIndex.putDownloadState(downloadState1);
DownloadStateCursor cursor = downloadIndex.getDownloadStates();
Download download1 = new DownloadBuilder("id1").build();
downloadIndex.putDownload(download1);
DownloadCursor cursor = downloadIndex.getDownloads();
assertThat(cursor.getCount()).isEqualTo(1);
cursor.close();
......@@ -211,7 +195,7 @@ public class DefaultDownloadIndexTest {
downloadIndex = new DefaultDownloadIndex(databaseProvider);
cursor = downloadIndex.getDownloadStates();
cursor = downloadIndex.getDownloads();
assertThat(cursor.getCount()).isEqualTo(0);
cursor.close();
assertThat(
......@@ -222,105 +206,97 @@ public class DefaultDownloadIndexTest {
@Test
public void setManualStopReason_setReasonToNone() throws Exception {
String id = "id";
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(id)
.setState(DownloadState.STATE_COMPLETED)
.setManualStopReason(0x12345678);
DownloadState downloadState = downloadStateBuilder.build();
downloadIndex.putDownloadState(downloadState);
downloadIndex.setManualStopReason(DownloadState.MANUAL_STOP_REASON_NONE);
DownloadState readDownloadState = downloadIndex.getDownloadState(id);
DownloadState expectedDownloadState =
downloadStateBuilder.setManualStopReason(DownloadState.MANUAL_STOP_REASON_NONE).build();
DownloadStateTest.assertEqual(readDownloadState, expectedDownloadState);
DownloadBuilder downloadBuilder =
new DownloadBuilder(id).setState(Download.STATE_COMPLETED).setManualStopReason(0x12345678);
Download download = downloadBuilder.build();
downloadIndex.putDownload(download);
downloadIndex.setManualStopReason(Download.MANUAL_STOP_REASON_NONE);
Download readDownload = downloadIndex.getDownload(id);
Download expectedDownload =
downloadBuilder.setManualStopReason(Download.MANUAL_STOP_REASON_NONE).build();
DownloadTest.assertEqual(readDownload, expectedDownload);
}
@Test
public void setManualStopReason_setReason() throws Exception {
String id = "id";
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(id)
.setState(DownloadState.STATE_FAILED)
.setFailureReason(DownloadState.FAILURE_REASON_UNKNOWN);
DownloadState downloadState = downloadStateBuilder.build();
downloadIndex.putDownloadState(downloadState);
DownloadBuilder downloadBuilder =
new DownloadBuilder(id)
.setState(Download.STATE_FAILED)
.setFailureReason(Download.FAILURE_REASON_UNKNOWN);
Download download = downloadBuilder.build();
downloadIndex.putDownload(download);
int manualStopReason = 0x12345678;
downloadIndex.setManualStopReason(manualStopReason);
DownloadState readDownloadState = downloadIndex.getDownloadState(id);
DownloadState expectedDownloadState =
downloadStateBuilder.setManualStopReason(manualStopReason).build();
DownloadStateTest.assertEqual(readDownloadState, expectedDownloadState);
Download readDownload = downloadIndex.getDownload(id);
Download expectedDownload = downloadBuilder.setManualStopReason(manualStopReason).build();
DownloadTest.assertEqual(readDownload, expectedDownload);
}
@Test
public void setManualStopReason_notTerminalState_doesNotSetManualStopReason() throws Exception {
String id = "id";
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(id).setState(DownloadState.STATE_DOWNLOADING);
DownloadState downloadState = downloadStateBuilder.build();
downloadIndex.putDownloadState(downloadState);
DownloadBuilder downloadBuilder = new DownloadBuilder(id).setState(Download.STATE_DOWNLOADING);
Download download = downloadBuilder.build();
downloadIndex.putDownload(download);
int notMetRequirements = 0x12345678;
downloadIndex.setManualStopReason(notMetRequirements);
DownloadState readDownloadState = downloadIndex.getDownloadState(id);
DownloadStateTest.assertEqual(readDownloadState, downloadState);
Download readDownload = downloadIndex.getDownload(id);
DownloadTest.assertEqual(readDownload, download);
}
@Test
public void setSingleDownloadManualStopReason_setReasonToNone() throws Exception {
String id = "id";
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(id)
.setState(DownloadState.STATE_COMPLETED)
.setManualStopReason(0x12345678);
DownloadState downloadState = downloadStateBuilder.build();
downloadIndex.putDownloadState(downloadState);
downloadIndex.setManualStopReason(id, DownloadState.MANUAL_STOP_REASON_NONE);
DownloadState readDownloadState = downloadIndex.getDownloadState(id);
DownloadState expectedDownloadState =
downloadStateBuilder.setManualStopReason(DownloadState.MANUAL_STOP_REASON_NONE).build();
DownloadStateTest.assertEqual(readDownloadState, expectedDownloadState);
DownloadBuilder downloadBuilder =
new DownloadBuilder(id).setState(Download.STATE_COMPLETED).setManualStopReason(0x12345678);
Download download = downloadBuilder.build();
downloadIndex.putDownload(download);
downloadIndex.setManualStopReason(id, Download.MANUAL_STOP_REASON_NONE);
Download readDownload = downloadIndex.getDownload(id);
Download expectedDownload =
downloadBuilder.setManualStopReason(Download.MANUAL_STOP_REASON_NONE).build();
DownloadTest.assertEqual(readDownload, expectedDownload);
}
@Test
public void setSingleDownloadManualStopReason_setReason() throws Exception {
String id = "id";
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(id)
.setState(DownloadState.STATE_FAILED)
.setFailureReason(DownloadState.FAILURE_REASON_UNKNOWN);
DownloadState downloadState = downloadStateBuilder.build();
downloadIndex.putDownloadState(downloadState);
DownloadBuilder downloadBuilder =
new DownloadBuilder(id)
.setState(Download.STATE_FAILED)
.setFailureReason(Download.FAILURE_REASON_UNKNOWN);
Download download = downloadBuilder.build();
downloadIndex.putDownload(download);
int manualStopReason = 0x12345678;
downloadIndex.setManualStopReason(id, manualStopReason);
DownloadState readDownloadState = downloadIndex.getDownloadState(id);
DownloadState expectedDownloadState =
downloadStateBuilder.setManualStopReason(manualStopReason).build();
DownloadStateTest.assertEqual(readDownloadState, expectedDownloadState);
Download readDownload = downloadIndex.getDownload(id);
Download expectedDownload = downloadBuilder.setManualStopReason(manualStopReason).build();
DownloadTest.assertEqual(readDownload, expectedDownload);
}
@Test
public void setSingleDownloadManualStopReason_notTerminalState_doesNotSetManualStopReason()
throws Exception {
String id = "id";
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(id).setState(DownloadState.STATE_DOWNLOADING);
DownloadState downloadState = downloadStateBuilder.build();
downloadIndex.putDownloadState(downloadState);
DownloadBuilder downloadBuilder = new DownloadBuilder(id).setState(Download.STATE_DOWNLOADING);
Download download = downloadBuilder.build();
downloadIndex.putDownload(download);
int notMetRequirements = 0x12345678;
downloadIndex.setManualStopReason(id, notMetRequirements);
DownloadState readDownloadState = downloadIndex.getDownloadState(id);
DownloadStateTest.assertEqual(readDownloadState, downloadState);
Download readDownload = downloadIndex.getDownload(id);
DownloadTest.assertEqual(readDownload, download);
}
}
......@@ -23,13 +23,13 @@ import java.util.Collections;
import java.util.List;
/**
* Builder for DownloadState.
* Builder for {@link Download}.
*
* <p>Defines default values for each field (except {@code id}) to facilitate DownloadState creation
* for tests. Tests must avoid depending on the default values but explicitly set tested parameters
* during test initialization.
* <p>Defines default values for each field (except {@code id}) to facilitate {@link Download}
* creation for tests. Tests must avoid depending on the default values but explicitly set tested
* parameters during test initialization.
*/
class DownloadStateBuilder {
class DownloadBuilder {
private final CachingCounters counters;
private String id;
private String type;
......@@ -43,15 +43,15 @@ class DownloadStateBuilder {
private List<StreamKey> streamKeys;
private byte[] customMetadata;
DownloadStateBuilder(String id) {
DownloadBuilder(String id) {
this(id, "type", Uri.parse("uri"), /* cacheKey= */ null, new byte[0], Collections.emptyList());
}
DownloadStateBuilder(DownloadAction action) {
DownloadBuilder(DownloadAction action) {
this(action.id, action.type, action.uri, action.customCacheKey, action.data, action.streamKeys);
}
DownloadStateBuilder(
DownloadBuilder(
String id,
String type,
Uri uri,
......@@ -62,8 +62,8 @@ class DownloadStateBuilder {
this.type = type;
this.uri = uri;
this.cacheKey = cacheKey;
this.state = DownloadState.STATE_QUEUED;
this.failureReason = DownloadState.FAILURE_REASON_NONE;
this.state = Download.STATE_QUEUED;
this.failureReason = Download.FAILURE_REASON_NONE;
this.startTimeMs = (long) 0;
this.updateTimeMs = (long) 0;
this.streamKeys = streamKeys;
......@@ -71,90 +71,84 @@ class DownloadStateBuilder {
this.counters = new CachingCounters();
}
public DownloadStateBuilder setId(String id) {
public DownloadBuilder setId(String id) {
this.id = id;
return this;
}
public DownloadStateBuilder setType(String type) {
public DownloadBuilder setType(String type) {
this.type = type;
return this;
}
public DownloadStateBuilder setUri(String uri) {
public DownloadBuilder setUri(String uri) {
this.uri = Uri.parse(uri);
return this;
}
public DownloadStateBuilder setUri(Uri uri) {
public DownloadBuilder setUri(Uri uri) {
this.uri = uri;
return this;
}
public DownloadStateBuilder setCacheKey(@Nullable String cacheKey) {
public DownloadBuilder setCacheKey(@Nullable String cacheKey) {
this.cacheKey = cacheKey;
return this;
}
public DownloadStateBuilder setState(int state) {
public DownloadBuilder setState(int state) {
this.state = state;
return this;
}
public DownloadStateBuilder setDownloadPercentage(float downloadPercentage) {
public DownloadBuilder setDownloadPercentage(float downloadPercentage) {
counters.percentage = downloadPercentage;
return this;
}
public DownloadStateBuilder setDownloadedBytes(long downloadedBytes) {
public DownloadBuilder setDownloadedBytes(long downloadedBytes) {
counters.alreadyCachedBytes = downloadedBytes;
return this;
}
public DownloadStateBuilder setTotalBytes(long totalBytes) {
public DownloadBuilder setTotalBytes(long totalBytes) {
counters.contentLength = totalBytes;
return this;
}
public DownloadStateBuilder setFailureReason(int failureReason) {
public DownloadBuilder setFailureReason(int failureReason) {
this.failureReason = failureReason;
return this;
}
public DownloadStateBuilder setManualStopReason(int manualStopReason) {
public DownloadBuilder setManualStopReason(int manualStopReason) {
this.manualStopReason = manualStopReason;
return this;
}
public DownloadStateBuilder setStartTimeMs(long startTimeMs) {
public DownloadBuilder setStartTimeMs(long startTimeMs) {
this.startTimeMs = startTimeMs;
return this;
}
public DownloadStateBuilder setUpdateTimeMs(long updateTimeMs) {
public DownloadBuilder setUpdateTimeMs(long updateTimeMs) {
this.updateTimeMs = updateTimeMs;
return this;
}
public DownloadStateBuilder setStreamKeys(StreamKey... streamKeys) {
public DownloadBuilder setStreamKeys(StreamKey... streamKeys) {
this.streamKeys = Arrays.asList(streamKeys);
return this;
}
public DownloadStateBuilder setCustomMetadata(byte[] customMetadata) {
public DownloadBuilder setCustomMetadata(byte[] customMetadata) {
this.customMetadata = customMetadata;
return this;
}
public DownloadState build() {
public Download build() {
DownloadAction action = new DownloadAction(id, type, uri, streamKeys, cacheKey, customMetadata);
return new DownloadState(
action,
state,
failureReason,
manualStopReason,
startTimeMs,
updateTimeMs,
counters);
return new Download(
action, state, failureReason, manualStopReason, startTimeMs, updateTimeMs, counters);
}
}
......@@ -56,7 +56,7 @@ public class DownloadIndexUtilTest {
}
@Test
public void addAction_nonExistingDownloadState_createsNewDownloadState() throws IOException {
public void addAction_nonExistingDownload_createsNewDownload() throws IOException {
byte[] data = new byte[] {1, 2, 3, 4};
DownloadAction action =
new DownloadAction(
......@@ -71,11 +71,11 @@ public class DownloadIndexUtilTest {
DownloadIndexUtil.mergeAction(action, downloadIndex);
assertDownloadIndexContainsAction(action, DownloadState.STATE_QUEUED);
assertDownloadIndexContainsAction(action, Download.STATE_QUEUED);
}
@Test
public void addAction_existingDownloadState_createsMergedDownloadState() throws IOException {
public void addAction_existingDownload_createsMergedDownload() throws IOException {
StreamKey streamKey1 =
new StreamKey(/* periodIndex= */ 3, /* groupIndex= */ 4, /* trackIndex= */ 5);
StreamKey streamKey2 =
......@@ -100,18 +100,18 @@ public class DownloadIndexUtilTest {
DownloadIndexUtil.mergeAction(action2, downloadIndex);
DownloadState downloadState = downloadIndex.getDownloadState(action2.id);
assertThat(downloadState).isNotNull();
assertThat(downloadState.action.type).isEqualTo(action2.type);
assertThat(downloadState.action.customCacheKey).isEqualTo(action2.customCacheKey);
assertThat(downloadState.action.data).isEqualTo(action2.data);
assertThat(downloadState.action.uri).isEqualTo(action2.uri);
assertThat(downloadState.action.streamKeys).containsExactly(streamKey1, streamKey2);
assertThat(downloadState.state).isEqualTo(DownloadState.STATE_QUEUED);
Download download = downloadIndex.getDownload(action2.id);
assertThat(download).isNotNull();
assertThat(download.action.type).isEqualTo(action2.type);
assertThat(download.action.customCacheKey).isEqualTo(action2.customCacheKey);
assertThat(download.action.data).isEqualTo(action2.data);
assertThat(download.action.uri).isEqualTo(action2.uri);
assertThat(download.action.streamKeys).containsExactly(streamKey1, streamKey2);
assertThat(download.state).isEqualTo(Download.STATE_QUEUED);
}
@Test
public void upgradeActionFile_createsDownloadStates() throws IOException {
public void upgradeActionFile_createsDownloads() throws IOException {
// Copy the test asset to a file.
byte[] actionFileBytes =
TestUtil.getByteArray(
......@@ -144,15 +144,15 @@ public class DownloadIndexUtilTest {
ActionFile actionFile = new ActionFile(tempFile);
DownloadIndexUtil.mergeActionFile(actionFile, /* downloadIdProvider= */ null, downloadIndex);
assertDownloadIndexContainsAction(expectedAction1, DownloadState.STATE_QUEUED);
assertDownloadIndexContainsAction(expectedAction2, DownloadState.STATE_QUEUED);
assertDownloadIndexContainsAction(expectedAction1, Download.STATE_QUEUED);
assertDownloadIndexContainsAction(expectedAction2, Download.STATE_QUEUED);
}
private void assertDownloadIndexContainsAction(DownloadAction action, int state)
throws IOException {
DownloadState downloadState = downloadIndex.getDownloadState(action.id);
assertThat(downloadState.action).isEqualTo(action);
assertThat(downloadState.state).isEqualTo(state);
Download download = downloadIndex.getDownload(action.id);
assertThat(download.action).isEqualTo(action);
assertThat(download.state).isEqualTo(state);
}
@SuppressWarnings("unchecked")
......
......@@ -20,7 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.offline.DownloadState.State;
import com.google.android.exoplayer2.offline.Download.State;
import com.google.android.exoplayer2.scheduler.Requirements;
import com.google.android.exoplayer2.testutil.DummyMainThread;
import com.google.android.exoplayer2.testutil.DummyMainThread.TestRunnable;
......@@ -343,7 +343,7 @@ public class DownloadManagerTest {
TaskWrapper task3 = new DownloadRunner(uri3).postDownloadAction().postRemoveAction().getTask();
task3.assertRemoving();
DownloadState[] states = downloadManager.getAllDownloadStates();
Download[] states = downloadManager.getAllDownloads();
assertThat(states).hasLength(3);
String[] taskIds = {task1.taskId, task2.taskId, task3.taskId};
......@@ -554,27 +554,27 @@ public class DownloadManagerTest {
}
private TaskWrapper assertDownloading() {
return assertState(DownloadState.STATE_DOWNLOADING);
return assertState(Download.STATE_DOWNLOADING);
}
private TaskWrapper assertCompleted() {
return assertState(DownloadState.STATE_COMPLETED);
return assertState(Download.STATE_COMPLETED);
}
private TaskWrapper assertRemoving() {
return assertState(DownloadState.STATE_REMOVING);
return assertState(Download.STATE_REMOVING);
}
private TaskWrapper assertFailed() {
return assertState(DownloadState.STATE_FAILED);
return assertState(Download.STATE_FAILED);
}
private TaskWrapper assertQueued() {
return assertState(DownloadState.STATE_QUEUED);
return assertState(Download.STATE_QUEUED);
}
private TaskWrapper assertStopped() {
return assertState(DownloadState.STATE_STOPPED);
return assertState(Download.STATE_STOPPED);
}
private TaskWrapper assertState(@State int expectedState) {
......
/*
* Copyright (C) 2019 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 static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import android.net.Uri;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/** Unit tests for {@link DownloadState}. */
@RunWith(AndroidJUnit4.class)
public class DownloadStateTest {
private Uri testUri;
@Before
public void setUp() throws Exception {
testUri = Uri.parse("https://www.test.com/download1");
}
@Test
public void mergeAction_actionHaveDifferentType_throwsException() {
DownloadAction downloadAction = createDownloadAction();
DownloadState downloadState =
new DownloadStateBuilder(downloadAction)
.setType(downloadAction.type + "_different")
.setState(DownloadState.STATE_QUEUED)
.build();
try {
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
fail();
} catch (Exception e) {
// Expected.
}
}
@Test
public void mergeAction_actionHaveDifferentId_throwsException() {
DownloadAction downloadAction = createDownloadAction();
DownloadState downloadState =
new DownloadStateBuilder(downloadAction)
.setId(downloadAction.id + "_different")
.setState(DownloadState.STATE_QUEUED)
.build();
try {
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
fail();
} catch (Exception e) {
// Expected.
}
}
@Test
public void mergeAction_actionsWithSameIdAndType_doesNotFail() {
DownloadAction downloadAction = createDownloadAction();
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(downloadAction).setState(DownloadState.STATE_QUEUED);
DownloadState downloadState = downloadStateBuilder.build();
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
}
@Test
public void mergeAction_actionHaveDifferentUri_downloadStateUriIsUpdated() {
DownloadAction downloadAction = createDownloadAction();
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(downloadAction)
.setUri(downloadAction.uri + "_different")
.setState(DownloadState.STATE_QUEUED);
DownloadState downloadState = downloadStateBuilder.build();
DownloadState mergedDownloadState =
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
DownloadState expectedDownloadState = downloadStateBuilder.setUri(downloadAction.uri).build();
assertEqual(mergedDownloadState, expectedDownloadState);
}
@Test
public void mergeAction_actionHaveDifferentData_downloadStateDataIsUpdated() {
DownloadAction downloadAction =
new DownloadAction(
"id",
DownloadAction.TYPE_DASH,
testUri,
Collections.emptyList(),
/* customCacheKey= */ null,
/* data= */ new byte[] {1, 2, 3, 4});
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(downloadAction)
.setState(DownloadState.STATE_QUEUED)
.setCustomMetadata(new byte[0]);
DownloadState downloadState = downloadStateBuilder.build();
DownloadState mergedDownloadState =
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
DownloadState expectedDownloadState =
downloadStateBuilder.setCustomMetadata(downloadAction.data).build();
assertEqual(mergedDownloadState, expectedDownloadState);
}
@Test
public void mergeAction_removingDownloadDownloadAction_stateBecomesRestarting() {
DownloadAction downloadAction = createDownloadAction();
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(downloadAction).setState(DownloadState.STATE_REMOVING);
DownloadState downloadState = downloadStateBuilder.build();
DownloadState mergedDownloadState =
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
DownloadState expectedDownloadState =
downloadStateBuilder.setState(DownloadState.STATE_RESTARTING).build();
assertEqual(mergedDownloadState, expectedDownloadState);
}
@Test
public void mergeAction_failedDownloadDownloadAction_stateBecomesQueued() {
DownloadAction downloadAction = createDownloadAction();
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(downloadAction)
.setState(DownloadState.STATE_FAILED)
.setFailureReason(DownloadState.FAILURE_REASON_UNKNOWN);
DownloadState downloadState = downloadStateBuilder.build();
DownloadState mergedDownloadState =
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
DownloadState expectedDownloadState =
downloadStateBuilder
.setState(DownloadState.STATE_QUEUED)
.setFailureReason(DownloadState.FAILURE_REASON_NONE)
.build();
assertEqual(mergedDownloadState, expectedDownloadState);
}
@Test
public void mergeAction_stoppedDownloadDownloadAction_stateStaysStopped() {
DownloadAction downloadAction = createDownloadAction();
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(downloadAction)
.setState(DownloadState.STATE_STOPPED)
.setManualStopReason(DownloadState.MANUAL_STOP_REASON_UNDEFINED);
DownloadState downloadState = downloadStateBuilder.build();
DownloadState mergedDownloadState =
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
assertEqual(mergedDownloadState, downloadState);
}
@Test
public void mergeAction_manualStopReasonSetButNotInStoppedState_stateBecomesStopped() {
DownloadAction downloadAction = createDownloadAction();
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(downloadAction)
.setState(DownloadState.STATE_COMPLETED)
.setManualStopReason(DownloadState.MANUAL_STOP_REASON_UNDEFINED);
DownloadState downloadState = downloadStateBuilder.build();
DownloadState mergedDownloadState =
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
DownloadState expectedDownloadState =
downloadStateBuilder.setState(DownloadState.STATE_STOPPED).build();
assertEqual(mergedDownloadState, expectedDownloadState);
}
@Test
public void mergeAction_returnsMergedKeys() {
StreamKey streamKey1 = new StreamKey(/* groupIndex= */ 0, /* trackIndex= */ 0);
StreamKey streamKey2 = new StreamKey(/* groupIndex= */ 1, /* trackIndex= */ 1);
StreamKey[] keys1 = new StreamKey[] {streamKey1};
StreamKey[] keys2 = new StreamKey[] {streamKey2};
StreamKey[] expectedKeys = new StreamKey[] {streamKey1, streamKey2};
doTestMergeActionReturnsMergedKeys(keys1, keys2, expectedKeys);
}
@Test
public void mergeAction_returnsUniqueKeys() {
StreamKey streamKey1 = new StreamKey(/* groupIndex= */ 0, /* trackIndex= */ 0);
StreamKey streamKey1Copy = new StreamKey(/* groupIndex= */ 0, /* trackIndex= */ 0);
StreamKey streamKey2 = new StreamKey(/* groupIndex= */ 1, /* trackIndex= */ 1);
StreamKey[] keys1 = new StreamKey[] {streamKey1};
StreamKey[] keys2 = new StreamKey[] {streamKey2, streamKey1Copy};
StreamKey[] expectedKeys = new StreamKey[] {streamKey1, streamKey2};
doTestMergeActionReturnsMergedKeys(keys1, keys2, expectedKeys);
}
@Test
public void mergeAction_ifFirstActionKeysEmpty_returnsEmptyKeys() {
StreamKey streamKey1 = new StreamKey(/* groupIndex= */ 0, /* trackIndex= */ 0);
StreamKey streamKey2 = new StreamKey(/* groupIndex= */ 1, /* trackIndex= */ 1);
StreamKey[] keys1 = new StreamKey[] {};
StreamKey[] keys2 = new StreamKey[] {streamKey2, streamKey1};
StreamKey[] expectedKeys = new StreamKey[] {};
doTestMergeActionReturnsMergedKeys(keys1, keys2, expectedKeys);
}
@Test
public void mergeAction_ifNotFirstActionKeysEmpty_returnsEmptyKeys() {
StreamKey streamKey1 = new StreamKey(/* groupIndex= */ 0, /* trackIndex= */ 0);
StreamKey streamKey2 = new StreamKey(/* groupIndex= */ 1, /* trackIndex= */ 1);
StreamKey[] keys1 = new StreamKey[] {streamKey2, streamKey1};
StreamKey[] keys2 = new StreamKey[] {};
StreamKey[] expectedKeys = new StreamKey[] {};
doTestMergeActionReturnsMergedKeys(keys1, keys2, expectedKeys);
}
private void doTestMergeActionReturnsMergedKeys(
StreamKey[] keys1, StreamKey[] keys2, StreamKey[] expectedKeys) {
DownloadAction downloadAction =
new DownloadAction(
"id",
DownloadAction.TYPE_DASH,
testUri,
Arrays.asList(keys2),
/* customCacheKey= */ null,
/* data= */ null);
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(downloadAction)
.setState(DownloadState.STATE_QUEUED)
.setStreamKeys(keys1);
DownloadState downloadState = downloadStateBuilder.build();
DownloadState mergedDownloadState =
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
DownloadState expectedDownloadState = downloadStateBuilder.setStreamKeys(expectedKeys).build();
assertEqual(mergedDownloadState, expectedDownloadState);
}
static void assertEqual(DownloadState downloadState, DownloadState expected) {
assertEqual(downloadState, expected, false);
}
static void assertEqual(
DownloadState downloadState, DownloadState that, boolean compareTimeFields) {
assertThat(downloadState.action).isEqualTo(that.action);
assertThat(downloadState.state).isEqualTo(that.state);
assertThat(downloadState.getDownloadPercentage()).isEqualTo(that.getDownloadPercentage());
assertThat(downloadState.getDownloadedBytes()).isEqualTo(that.getDownloadedBytes());
assertThat(downloadState.getTotalBytes()).isEqualTo(that.getTotalBytes());
if (compareTimeFields) {
assertThat(downloadState.startTimeMs).isEqualTo(that.startTimeMs);
assertThat(downloadState.updateTimeMs).isEqualTo(that.updateTimeMs);
}
assertThat(downloadState.failureReason).isEqualTo(that.failureReason);
assertThat(downloadState.manualStopReason).isEqualTo(that.manualStopReason);
}
private DownloadAction createDownloadAction() {
return new DownloadAction(
"id",
DownloadAction.TYPE_DASH,
testUri,
Collections.emptyList(),
/* customCacheKey= */ null,
/* data= */ null);
}
}
/*
* Copyright (C) 2019 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 static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import android.net.Uri;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/** Unit tests for {@link Download}. */
@RunWith(AndroidJUnit4.class)
public class DownloadTest {
private Uri testUri;
@Before
public void setUp() throws Exception {
testUri = Uri.parse("https://www.test.com/download1");
}
@Test
public void mergeAction_actionHaveDifferentType_throwsException() {
DownloadAction downloadAction = createDownloadAction();
Download download =
new DownloadBuilder(downloadAction)
.setType(downloadAction.type + "_different")
.setState(Download.STATE_QUEUED)
.build();
try {
download.copyWithMergedAction(downloadAction, /* canStart= */ true);
fail();
} catch (Exception e) {
// Expected.
}
}
@Test
public void mergeAction_actionHaveDifferentId_throwsException() {
DownloadAction downloadAction = createDownloadAction();
Download download =
new DownloadBuilder(downloadAction)
.setId(downloadAction.id + "_different")
.setState(Download.STATE_QUEUED)
.build();
try {
download.copyWithMergedAction(downloadAction, /* canStart= */ true);
fail();
} catch (Exception e) {
// Expected.
}
}
@Test
public void mergeAction_actionsWithSameIdAndType_doesNotFail() {
DownloadAction downloadAction = createDownloadAction();
DownloadBuilder downloadBuilder =
new DownloadBuilder(downloadAction).setState(Download.STATE_QUEUED);
Download download = downloadBuilder.build();
download.copyWithMergedAction(downloadAction, /* canStart= */ true);
}
@Test
public void mergeAction_actionHaveDifferentUri_downloadUriIsUpdated() {
DownloadAction downloadAction = createDownloadAction();
DownloadBuilder downloadBuilder =
new DownloadBuilder(downloadAction)
.setUri(downloadAction.uri + "_different")
.setState(Download.STATE_QUEUED);
Download download = downloadBuilder.build();
Download mergedDownload = download.copyWithMergedAction(downloadAction, /* canStart= */ true);
Download expectedDownload = downloadBuilder.setUri(downloadAction.uri).build();
assertEqual(mergedDownload, expectedDownload);
}
@Test
public void mergeAction_actionHaveDifferentData_downloadDataIsUpdated() {
DownloadAction downloadAction =
new DownloadAction(
"id",
DownloadAction.TYPE_DASH,
testUri,
Collections.emptyList(),
/* customCacheKey= */ null,
/* data= */ new byte[] {1, 2, 3, 4});
DownloadBuilder downloadBuilder =
new DownloadBuilder(downloadAction)
.setState(Download.STATE_QUEUED)
.setCustomMetadata(new byte[0]);
Download download = downloadBuilder.build();
Download mergedDownload = download.copyWithMergedAction(downloadAction, /* canStart= */ true);
Download expectedDownload = downloadBuilder.setCustomMetadata(downloadAction.data).build();
assertEqual(mergedDownload, expectedDownload);
}
@Test
public void mergeAction_removingDownloadDownloadAction_stateBecomesRestarting() {
DownloadAction downloadAction = createDownloadAction();
DownloadBuilder downloadBuilder =
new DownloadBuilder(downloadAction).setState(Download.STATE_REMOVING);
Download download = downloadBuilder.build();
Download mergedDownload = download.copyWithMergedAction(downloadAction, /* canStart= */ true);
Download expectedDownload = downloadBuilder.setState(Download.STATE_RESTARTING).build();
assertEqual(mergedDownload, expectedDownload);
}
@Test
public void mergeAction_failedDownloadDownloadAction_stateBecomesQueued() {
DownloadAction downloadAction = createDownloadAction();
DownloadBuilder downloadBuilder =
new DownloadBuilder(downloadAction)
.setState(Download.STATE_FAILED)
.setFailureReason(Download.FAILURE_REASON_UNKNOWN);
Download download = downloadBuilder.build();
Download mergedDownload = download.copyWithMergedAction(downloadAction, /* canStart= */ true);
Download expectedDownload =
downloadBuilder
.setState(Download.STATE_QUEUED)
.setFailureReason(Download.FAILURE_REASON_NONE)
.build();
assertEqual(mergedDownload, expectedDownload);
}
@Test
public void mergeAction_stoppedDownloadDownloadAction_stateStaysStopped() {
DownloadAction downloadAction = createDownloadAction();
DownloadBuilder downloadBuilder =
new DownloadBuilder(downloadAction)
.setState(Download.STATE_STOPPED)
.setManualStopReason(Download.MANUAL_STOP_REASON_UNDEFINED);
Download download = downloadBuilder.build();
Download mergedDownload = download.copyWithMergedAction(downloadAction, /* canStart= */ true);
assertEqual(mergedDownload, download);
}
@Test
public void mergeAction_manualStopReasonSetButNotInStoppedState_stateBecomesStopped() {
DownloadAction downloadAction = createDownloadAction();
DownloadBuilder downloadBuilder =
new DownloadBuilder(downloadAction)
.setState(Download.STATE_COMPLETED)
.setManualStopReason(Download.MANUAL_STOP_REASON_UNDEFINED);
Download download = downloadBuilder.build();
Download mergedDownload = download.copyWithMergedAction(downloadAction, /* canStart= */ true);
Download expectedDownload = downloadBuilder.setState(Download.STATE_STOPPED).build();
assertEqual(mergedDownload, expectedDownload);
}
@Test
public void mergeAction_returnsMergedKeys() {
StreamKey streamKey1 = new StreamKey(/* groupIndex= */ 0, /* trackIndex= */ 0);
StreamKey streamKey2 = new StreamKey(/* groupIndex= */ 1, /* trackIndex= */ 1);
StreamKey[] keys1 = new StreamKey[] {streamKey1};
StreamKey[] keys2 = new StreamKey[] {streamKey2};
StreamKey[] expectedKeys = new StreamKey[] {streamKey1, streamKey2};
doTestMergeActionReturnsMergedKeys(keys1, keys2, expectedKeys);
}
@Test
public void mergeAction_returnsUniqueKeys() {
StreamKey streamKey1 = new StreamKey(/* groupIndex= */ 0, /* trackIndex= */ 0);
StreamKey streamKey1Copy = new StreamKey(/* groupIndex= */ 0, /* trackIndex= */ 0);
StreamKey streamKey2 = new StreamKey(/* groupIndex= */ 1, /* trackIndex= */ 1);
StreamKey[] keys1 = new StreamKey[] {streamKey1};
StreamKey[] keys2 = new StreamKey[] {streamKey2, streamKey1Copy};
StreamKey[] expectedKeys = new StreamKey[] {streamKey1, streamKey2};
doTestMergeActionReturnsMergedKeys(keys1, keys2, expectedKeys);
}
@Test
public void mergeAction_ifFirstActionKeysEmpty_returnsEmptyKeys() {
StreamKey streamKey1 = new StreamKey(/* groupIndex= */ 0, /* trackIndex= */ 0);
StreamKey streamKey2 = new StreamKey(/* groupIndex= */ 1, /* trackIndex= */ 1);
StreamKey[] keys1 = new StreamKey[] {};
StreamKey[] keys2 = new StreamKey[] {streamKey2, streamKey1};
StreamKey[] expectedKeys = new StreamKey[] {};
doTestMergeActionReturnsMergedKeys(keys1, keys2, expectedKeys);
}
@Test
public void mergeAction_ifNotFirstActionKeysEmpty_returnsEmptyKeys() {
StreamKey streamKey1 = new StreamKey(/* groupIndex= */ 0, /* trackIndex= */ 0);
StreamKey streamKey2 = new StreamKey(/* groupIndex= */ 1, /* trackIndex= */ 1);
StreamKey[] keys1 = new StreamKey[] {streamKey2, streamKey1};
StreamKey[] keys2 = new StreamKey[] {};
StreamKey[] expectedKeys = new StreamKey[] {};
doTestMergeActionReturnsMergedKeys(keys1, keys2, expectedKeys);
}
private void doTestMergeActionReturnsMergedKeys(
StreamKey[] keys1, StreamKey[] keys2, StreamKey[] expectedKeys) {
DownloadAction downloadAction =
new DownloadAction(
"id",
DownloadAction.TYPE_DASH,
testUri,
Arrays.asList(keys2),
/* customCacheKey= */ null,
/* data= */ null);
DownloadBuilder downloadBuilder =
new DownloadBuilder(downloadAction).setState(Download.STATE_QUEUED).setStreamKeys(keys1);
Download download = downloadBuilder.build();
Download mergedDownload = download.copyWithMergedAction(downloadAction, /* canStart= */ true);
Download expectedDownload = downloadBuilder.setStreamKeys(expectedKeys).build();
assertEqual(mergedDownload, expectedDownload);
}
static void assertEqual(Download download, Download expected) {
assertEqual(download, expected, false);
}
static void assertEqual(Download download, Download that, boolean compareTimeFields) {
assertThat(download.action).isEqualTo(that.action);
assertThat(download.state).isEqualTo(that.state);
assertThat(download.getDownloadPercentage()).isEqualTo(that.getDownloadPercentage());
assertThat(download.getDownloadedBytes()).isEqualTo(that.getDownloadedBytes());
assertThat(download.getTotalBytes()).isEqualTo(that.getTotalBytes());
if (compareTimeFields) {
assertThat(download.startTimeMs).isEqualTo(that.startTimeMs);
assertThat(download.updateTimeMs).isEqualTo(that.updateTimeMs);
}
assertThat(download.failureReason).isEqualTo(that.failureReason);
assertThat(download.manualStopReason).isEqualTo(that.manualStopReason);
}
private DownloadAction createDownloadAction() {
return new DownloadAction(
"id",
DownloadAction.TYPE_DASH,
testUri,
Collections.emptyList(),
/* customCacheKey= */ null,
/* data= */ null);
}
}
......@@ -29,10 +29,10 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.offline.DefaultDownloadIndex;
import com.google.android.exoplayer2.offline.DefaultDownloaderFactory;
import com.google.android.exoplayer2.offline.Download;
import com.google.android.exoplayer2.offline.DownloadAction;
import com.google.android.exoplayer2.offline.DownloadManager;
import com.google.android.exoplayer2.offline.DownloadService;
import com.google.android.exoplayer2.offline.DownloadState;
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.scheduler.Requirements;
......@@ -141,7 +141,7 @@ public class DownloadServiceDashTest {
}
@Override
protected Notification getForegroundNotification(DownloadState[] downloadStates) {
protected Notification getForegroundNotification(Download[] downloads) {
throw new UnsupportedOperationException();
}
};
......
......@@ -23,7 +23,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.offline.DownloadState;
import com.google.android.exoplayer2.offline.Download;
/** Helper for creating download notifications. */
public final class DownloadNotificationHelper {
......@@ -49,37 +49,37 @@ public final class DownloadNotificationHelper {
* @param smallIcon A small icon for the notification.
* @param contentIntent An optional content intent to send when the notification is clicked.
* @param message An optional message to display on the notification.
* @param downloadStates The download states.
* @param downloads The download states.
* @return The notification.
*/
public Notification buildProgressNotification(
@DrawableRes int smallIcon,
@Nullable PendingIntent contentIntent,
@Nullable String message,
DownloadState[] downloadStates) {
Download[] downloads) {
float totalPercentage = 0;
int downloadTaskCount = 0;
boolean allDownloadPercentagesUnknown = true;
boolean haveDownloadedBytes = false;
boolean haveDownloadTasks = false;
boolean haveRemoveTasks = false;
for (DownloadState downloadState : downloadStates) {
if (downloadState.state == DownloadState.STATE_REMOVING
|| downloadState.state == DownloadState.STATE_RESTARTING) {
for (Download download : downloads) {
if (download.state == Download.STATE_REMOVING
|| download.state == Download.STATE_RESTARTING) {
haveRemoveTasks = true;
continue;
}
if (downloadState.state != DownloadState.STATE_DOWNLOADING
&& downloadState.state != DownloadState.STATE_COMPLETED) {
if (download.state != Download.STATE_DOWNLOADING
&& download.state != Download.STATE_COMPLETED) {
continue;
}
haveDownloadTasks = true;
float downloadPercentage = downloadState.getDownloadPercentage();
float downloadPercentage = download.getDownloadPercentage();
if (downloadPercentage != C.PERCENTAGE_UNSET) {
allDownloadPercentagesUnknown = false;
totalPercentage += downloadPercentage;
}
haveDownloadedBytes |= downloadState.getDownloadedBytes() > 0;
haveDownloadedBytes |= download.getDownloadedBytes() > 0;
downloadTaskCount++;
}
......
......@@ -20,7 +20,7 @@ import android.app.PendingIntent;
import android.content.Context;
import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.offline.DownloadState;
import com.google.android.exoplayer2.offline.Download;
import com.google.android.exoplayer2.util.Util;
/**
......@@ -40,7 +40,7 @@ public final class DownloadNotificationUtil {
* @param channelId The id of the notification channel to use.
* @param contentIntent An optional content intent to send when the notification is clicked.
* @param message An optional message to display on the notification.
* @param downloadStates The download states.
* @param downloads The download states.
* @return The notification.
*/
public static Notification buildProgressNotification(
......@@ -49,9 +49,9 @@ public final class DownloadNotificationUtil {
String channelId,
@Nullable PendingIntent contentIntent,
@Nullable String message,
DownloadState[] downloadStates) {
Download[] downloads) {
return new DownloadNotificationHelper(context, channelId)
.buildProgressNotification(smallIcon, contentIntent, message, downloadStates);
.buildProgressNotification(smallIcon, contentIntent, message, downloads);
}
/**
......
......@@ -19,9 +19,9 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import android.os.ConditionVariable;
import com.google.android.exoplayer2.offline.Download;
import com.google.android.exoplayer2.offline.Download.State;
import com.google.android.exoplayer2.offline.DownloadManager;
import com.google.android.exoplayer2.offline.DownloadState;
import com.google.android.exoplayer2.offline.DownloadState.State;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
......@@ -42,7 +42,7 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
private final ConditionVariable initializedCondition;
private CountDownLatch downloadFinishedCondition;
@DownloadState.FailureReason private int failureReason;
@Download.FailureReason private int failureReason;
public TestDownloadManagerListener(
DownloadManager downloadManager, DummyMainThread dummyMainThread) {
......@@ -69,16 +69,16 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
}
@Override
public void onDownloadStateChanged(DownloadManager downloadManager, DownloadState downloadState) {
if (downloadState.state == DownloadState.STATE_FAILED) {
failureReason = downloadState.failureReason;
public void onDownloadChanged(DownloadManager downloadManager, Download download) {
if (download.state == Download.STATE_FAILED) {
failureReason = download.failureReason;
}
getStateQueue(downloadState.action.id).add(downloadState.state);
getStateQueue(download.action.id).add(download.state);
}
@Override
public void onDownloadRemoved(DownloadManager downloadManager, DownloadState downloadState) {
getStateQueue(downloadState.action.id).add(STATE_REMOVED);
public void onDownloadRemoved(DownloadManager downloadManager, Download download) {
getStateQueue(download.action.id).add(STATE_REMOVED);
}
@Override
......@@ -94,8 +94,8 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
*/
public void blockUntilTasksCompleteAndThrowAnyDownloadError() throws Throwable {
blockUntilTasksComplete();
if (failureReason != DownloadState.FAILURE_REASON_NONE) {
throw new Exception("Failure reason: " + DownloadState.getFailureString(failureReason));
if (failureReason != Download.FAILURE_REASON_NONE) {
throw new Exception("Failure reason: " + Download.getFailureString(failureReason));
}
}
......@@ -152,9 +152,7 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
}
int receivedState = receivedStates.get(i);
String receivedStateString =
receivedState == STATE_REMOVED
? "REMOVED"
: DownloadState.getStateString(receivedState);
receivedState == STATE_REMOVED ? "REMOVED" : Download.getStateString(receivedState);
sb.append(receivedStateString);
}
fail(
......@@ -162,7 +160,7 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
Locale.US,
"for download (%s) expected:<%s> but was:<%s>",
taskId,
DownloadState.getStateString(expectedState),
Download.getStateString(expectedState),
sb));
}
}
......
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