mirror of
https://github.com/samsonjs/media.git
synced 2026-04-26 14:57:47 +00:00
Move download state transitions into DownloadManager
Non-trivial download state transitions are currently split across DownloadManager and Download. These transitions are part of the same state machine, so it's clearer if they're all in the same place (i.e. DownloadManager, since this is the component that transitions downloads between states). PiperOrigin-RevId: 243249915
This commit is contained in:
parent
f623a9dea0
commit
a588717b46
7 changed files with 244 additions and 412 deletions
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.offline;
|
||||
|
||||
import static com.google.android.exoplayer2.offline.Download.STATE_QUEUED;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
|
@ -88,9 +90,17 @@ public final class ActionFileUpgradeUtil {
|
|||
throws IOException {
|
||||
Download download = downloadIndex.getDownload(action.id);
|
||||
if (download != null) {
|
||||
download = download.copyWithMergedAction(action, /* canStart= */ true);
|
||||
download = DownloadManager.mergeAction(download, action, download.manualStopReason);
|
||||
} else {
|
||||
download = new Download(action);
|
||||
long nowMs = System.currentTimeMillis();
|
||||
download =
|
||||
new Download(
|
||||
action,
|
||||
STATE_QUEUED,
|
||||
Download.FAILURE_REASON_NONE,
|
||||
Download.MANUAL_STOP_REASON_NONE,
|
||||
/* startTimeMs= */ nowMs,
|
||||
/* updateTimeMs= */ nowMs);
|
||||
}
|
||||
downloadIndex.putDownload(download);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,25 +111,22 @@ public final class Download {
|
|||
/** The reason the download is manually stopped, or {@link #MANUAL_STOP_REASON_NONE}. */
|
||||
public final int manualStopReason;
|
||||
|
||||
/*package*/ CachingCounters counters;
|
||||
/* package */ CachingCounters counters;
|
||||
|
||||
/**
|
||||
* Creates a {@link Download} using a {@link DownloadAction}.
|
||||
*
|
||||
* @param action The {@link DownloadAction}.
|
||||
*/
|
||||
public Download(DownloadAction action) {
|
||||
this(action, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
private Download(DownloadAction action, long currentTimeMs) {
|
||||
/* package */ Download(
|
||||
DownloadAction action,
|
||||
@State int state,
|
||||
@FailureReason int failureReason,
|
||||
int manualStopReason,
|
||||
long startTimeMs,
|
||||
long updateTimeMs) {
|
||||
this(
|
||||
action,
|
||||
/* state= */ STATE_QUEUED,
|
||||
FAILURE_REASON_NONE,
|
||||
/* manualStopReason= */ 0,
|
||||
/* startTimeMs= */ currentTimeMs,
|
||||
/* updateTimeMs= */ currentTimeMs,
|
||||
state,
|
||||
failureReason,
|
||||
manualStopReason,
|
||||
startTimeMs,
|
||||
updateTimeMs,
|
||||
new CachingCounters());
|
||||
}
|
||||
|
||||
|
|
@ -155,39 +152,9 @@ public final class Download {
|
|||
this.counters = counters;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Download}.
|
||||
*/
|
||||
public Download copyWithMergedAction(DownloadAction newAction, boolean canStart) {
|
||||
return new Download(
|
||||
action.copyWithMergedAction(newAction),
|
||||
getNextState(state, canStart && manualStopReason == 0),
|
||||
FAILURE_REASON_NONE,
|
||||
manualStopReason,
|
||||
startTimeMs,
|
||||
/* updateTimeMs= */ System.currentTimeMillis(),
|
||||
counters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy with the specified state, clearing {@link #failureReason}.
|
||||
*
|
||||
* @param state The {@link State}.
|
||||
*/
|
||||
public Download copyWithState(@State int state) {
|
||||
return new Download(
|
||||
action,
|
||||
state,
|
||||
FAILURE_REASON_NONE,
|
||||
manualStopReason,
|
||||
startTimeMs,
|
||||
/* updateTimeMs= */ System.currentTimeMillis(),
|
||||
counters);
|
||||
/** Returns whether the download is completed or failed. These are terminal states. */
|
||||
public boolean isTerminalState() {
|
||||
return state == STATE_COMPLETED || state == STATE_FAILED;
|
||||
}
|
||||
|
||||
/** Returns the total number of downloaded bytes. */
|
||||
|
|
@ -217,14 +184,4 @@ public final class Download {
|
|||
Assertions.checkNotNull(counters);
|
||||
this.counters = counters;
|
||||
}
|
||||
|
||||
private static int getNextState(@State int currentState, boolean canStart) {
|
||||
if (currentState == STATE_REMOVING || currentState == STATE_RESTARTING) {
|
||||
return STATE_RESTARTING;
|
||||
} else if (canStart) {
|
||||
return STATE_QUEUED;
|
||||
} else {
|
||||
return STATE_STOPPED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ public final class DownloadManager {
|
|||
|
||||
/** Listener for {@link DownloadManager} events. */
|
||||
public interface Listener {
|
||||
|
||||
/**
|
||||
* Called when all actions have been restored.
|
||||
*
|
||||
|
|
@ -485,7 +486,7 @@ public final class DownloadManager {
|
|||
|
||||
private void onDownloadChanged(Download download) {
|
||||
int downloadIndex = getDownloadIndex(download.action.id);
|
||||
if (download.state == STATE_COMPLETED || download.state == STATE_FAILED) {
|
||||
if (download.isTerminalState()) {
|
||||
if (downloadIndex != C.INDEX_UNSET) {
|
||||
downloads.remove(downloadIndex);
|
||||
}
|
||||
|
|
@ -643,19 +644,26 @@ public final class DownloadManager {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Use manualStopReason.
|
||||
private void addDownloadInternal(DownloadAction action, int manualStopReason) {
|
||||
DownloadInternal downloadInternal = getDownload(action.id);
|
||||
if (downloadInternal != null) {
|
||||
downloadInternal.addAction(action);
|
||||
downloadInternal.addAction(action, manualStopReason);
|
||||
logd("Action is added to existing download", downloadInternal);
|
||||
} else {
|
||||
Download download = loadDownload(action.id);
|
||||
if (download == null) {
|
||||
download = new Download(action);
|
||||
long nowMs = System.currentTimeMillis();
|
||||
download =
|
||||
new Download(
|
||||
action,
|
||||
manualStopReason != Download.MANUAL_STOP_REASON_NONE ? STATE_STOPPED : STATE_QUEUED,
|
||||
Download.FAILURE_REASON_NONE,
|
||||
manualStopReason,
|
||||
/* startTimeMs= */ nowMs,
|
||||
/* updateTimeMs= */ nowMs);
|
||||
logd("Download state is created for " + action.id);
|
||||
} else {
|
||||
download = download.copyWithMergedAction(action, /* canStart= */ canStartDownloads());
|
||||
download = mergeAction(download, action, manualStopReason);
|
||||
logd("Download state is loaded for " + action.id);
|
||||
}
|
||||
addDownloadForState(download);
|
||||
|
|
@ -669,7 +677,7 @@ public final class DownloadManager {
|
|||
} else {
|
||||
Download download = loadDownload(id);
|
||||
if (download != null) {
|
||||
addDownloadForState(download.copyWithState(STATE_REMOVING));
|
||||
addDownloadForState(copyWithState(download, STATE_REMOVING));
|
||||
} else {
|
||||
logd("Can't remove download. No download with id: " + id);
|
||||
}
|
||||
|
|
@ -798,6 +806,39 @@ public final class DownloadManager {
|
|||
return downloadsStarted && notMetRequirements == 0;
|
||||
}
|
||||
|
||||
/* package */ static Download mergeAction(
|
||||
Download download, DownloadAction action, int manualStopReason) {
|
||||
@Download.State int state = download.state;
|
||||
if (state == STATE_REMOVING || state == STATE_RESTARTING) {
|
||||
state = STATE_RESTARTING;
|
||||
} else if (manualStopReason != MANUAL_STOP_REASON_NONE) {
|
||||
state = STATE_STOPPED;
|
||||
} else {
|
||||
state = STATE_QUEUED;
|
||||
}
|
||||
long nowMs = System.currentTimeMillis();
|
||||
long startTimeMs = download.isTerminalState() ? nowMs : download.startTimeMs;
|
||||
return new Download(
|
||||
download.action.copyWithMergedAction(action),
|
||||
state,
|
||||
FAILURE_REASON_NONE,
|
||||
manualStopReason,
|
||||
startTimeMs,
|
||||
/* updateTimeMs= */ nowMs,
|
||||
download.counters);
|
||||
}
|
||||
|
||||
private static Download copyWithState(Download download, @Download.State int state) {
|
||||
return new Download(
|
||||
download.action,
|
||||
state,
|
||||
FAILURE_REASON_NONE,
|
||||
download.manualStopReason,
|
||||
download.startTimeMs,
|
||||
/* updateTimeMs= */ System.currentTimeMillis(),
|
||||
download.counters);
|
||||
}
|
||||
|
||||
private static void logd(String message) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, message);
|
||||
|
|
@ -841,8 +882,8 @@ public final class DownloadManager {
|
|||
initialize(download.state);
|
||||
}
|
||||
|
||||
public void addAction(DownloadAction newAction) {
|
||||
download = download.copyWithMergedAction(newAction, downloadManager.canStartDownloads());
|
||||
public void addAction(DownloadAction newAction, int manualStopReason) {
|
||||
download = mergeAction(download, newAction, manualStopReason);
|
||||
initialize();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,62 +56,7 @@ public class ActionFileUpgradeUtilTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void addAction_nonExistingDownload_createsNewDownload() throws IOException {
|
||||
byte[] data = new byte[] {1, 2, 3, 4};
|
||||
DownloadAction action =
|
||||
new DownloadAction(
|
||||
"id",
|
||||
TYPE_DASH,
|
||||
Uri.parse("https://www.test.com/download"),
|
||||
asList(
|
||||
new StreamKey(/* periodIndex= */ 0, /* groupIndex= */ 1, /* trackIndex= */ 2),
|
||||
new StreamKey(/* periodIndex= */ 3, /* groupIndex= */ 4, /* trackIndex= */ 5)),
|
||||
/* customCacheKey= */ "key123",
|
||||
data);
|
||||
|
||||
ActionFileUpgradeUtil.mergeAction(action, downloadIndex);
|
||||
|
||||
assertDownloadIndexContainsAction(action, Download.STATE_QUEUED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addAction_existingDownload_createsMergedDownload() throws IOException {
|
||||
StreamKey streamKey1 =
|
||||
new StreamKey(/* periodIndex= */ 3, /* groupIndex= */ 4, /* trackIndex= */ 5);
|
||||
StreamKey streamKey2 =
|
||||
new StreamKey(/* periodIndex= */ 0, /* groupIndex= */ 1, /* trackIndex= */ 2);
|
||||
DownloadAction action1 =
|
||||
new DownloadAction(
|
||||
"id",
|
||||
TYPE_DASH,
|
||||
Uri.parse("https://www.test.com/download1"),
|
||||
asList(streamKey1),
|
||||
/* customCacheKey= */ "key123",
|
||||
new byte[] {1, 2, 3, 4});
|
||||
DownloadAction action2 =
|
||||
new DownloadAction(
|
||||
"id",
|
||||
TYPE_DASH,
|
||||
Uri.parse("https://www.test.com/download2"),
|
||||
asList(streamKey2),
|
||||
/* customCacheKey= */ "key123",
|
||||
new byte[] {5, 4, 3, 2, 1});
|
||||
ActionFileUpgradeUtil.mergeAction(action1, downloadIndex);
|
||||
|
||||
ActionFileUpgradeUtil.mergeAction(action2, downloadIndex);
|
||||
|
||||
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_createsDownloads() throws IOException {
|
||||
public void upgradeAndDelete_createsDownloads() throws IOException {
|
||||
// Copy the test asset to a file.
|
||||
byte[] actionFileBytes =
|
||||
TestUtil.getByteArray(
|
||||
|
|
@ -144,10 +89,65 @@ public class ActionFileUpgradeUtilTest {
|
|||
|
||||
ActionFileUpgradeUtil.upgradeAndDelete(
|
||||
tempFile, /* downloadIdProvider= */ null, downloadIndex, /* deleteOnFailure= */ true);
|
||||
|
||||
assertDownloadIndexContainsAction(expectedAction1, Download.STATE_QUEUED);
|
||||
assertDownloadIndexContainsAction(expectedAction2, Download.STATE_QUEUED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeAction_nonExistingDownload_createsNewDownload() throws IOException {
|
||||
byte[] data = new byte[] {1, 2, 3, 4};
|
||||
DownloadAction action =
|
||||
new DownloadAction(
|
||||
"id",
|
||||
TYPE_DASH,
|
||||
Uri.parse("https://www.test.com/download"),
|
||||
asList(
|
||||
new StreamKey(/* periodIndex= */ 0, /* groupIndex= */ 1, /* trackIndex= */ 2),
|
||||
new StreamKey(/* periodIndex= */ 3, /* groupIndex= */ 4, /* trackIndex= */ 5)),
|
||||
/* customCacheKey= */ "key123",
|
||||
data);
|
||||
|
||||
ActionFileUpgradeUtil.mergeAction(action, downloadIndex);
|
||||
|
||||
assertDownloadIndexContainsAction(action, Download.STATE_QUEUED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeAction_existingDownload_createsMergedDownload() throws IOException {
|
||||
StreamKey streamKey1 =
|
||||
new StreamKey(/* periodIndex= */ 3, /* groupIndex= */ 4, /* trackIndex= */ 5);
|
||||
StreamKey streamKey2 =
|
||||
new StreamKey(/* periodIndex= */ 0, /* groupIndex= */ 1, /* trackIndex= */ 2);
|
||||
DownloadAction action1 =
|
||||
new DownloadAction(
|
||||
"id",
|
||||
TYPE_DASH,
|
||||
Uri.parse("https://www.test.com/download1"),
|
||||
asList(streamKey1),
|
||||
/* customCacheKey= */ "key123",
|
||||
new byte[] {1, 2, 3, 4});
|
||||
DownloadAction action2 =
|
||||
new DownloadAction(
|
||||
"id",
|
||||
TYPE_DASH,
|
||||
Uri.parse("https://www.test.com/download2"),
|
||||
asList(streamKey2),
|
||||
/* customCacheKey= */ "key123",
|
||||
new byte[] {5, 4, 3, 2, 1});
|
||||
ActionFileUpgradeUtil.mergeAction(action1, downloadIndex);
|
||||
ActionFileUpgradeUtil.mergeAction(action2, downloadIndex);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private void assertDownloadIndexContainsAction(DownloadAction action, int state)
|
||||
throws IOException {
|
||||
Download download = downloadIndex.getDownload(action.id);
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public class DefaultDownloadIndexTest {
|
|||
downloadIndex.putDownload(download);
|
||||
Download readDownload = downloadIndex.getDownload(id);
|
||||
|
||||
DownloadTest.assertEqual(readDownload, download);
|
||||
assertEqual(readDownload, download);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -91,7 +91,7 @@ public class DefaultDownloadIndexTest {
|
|||
Download readDownload = downloadIndex.getDownload(id);
|
||||
|
||||
assertThat(readDownload).isNotNull();
|
||||
DownloadTest.assertEqual(readDownload, download);
|
||||
assertEqual(readDownload, download);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -103,7 +103,7 @@ public class DefaultDownloadIndexTest {
|
|||
downloadIndex = new DefaultDownloadIndex(databaseProvider);
|
||||
Download readDownload = downloadIndex.getDownload(id);
|
||||
assertThat(readDownload).isNotNull();
|
||||
DownloadTest.assertEqual(readDownload, download);
|
||||
assertEqual(readDownload, download);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -138,9 +138,9 @@ public class DefaultDownloadIndexTest {
|
|||
try (DownloadCursor cursor = downloadIndex.getDownloads()) {
|
||||
assertThat(cursor.getCount()).isEqualTo(2);
|
||||
cursor.moveToNext();
|
||||
DownloadTest.assertEqual(cursor.getDownload(), download2);
|
||||
assertEqual(cursor.getDownload(), download2);
|
||||
cursor.moveToNext();
|
||||
DownloadTest.assertEqual(cursor.getDownload(), download1);
|
||||
assertEqual(cursor.getDownload(), download1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -161,9 +161,9 @@ public class DefaultDownloadIndexTest {
|
|||
downloadIndex.getDownloads(Download.STATE_REMOVING, Download.STATE_COMPLETED)) {
|
||||
assertThat(cursor.getCount()).isEqualTo(2);
|
||||
cursor.moveToNext();
|
||||
DownloadTest.assertEqual(cursor.getDownload(), download1);
|
||||
assertEqual(cursor.getDownload(), download1);
|
||||
cursor.moveToNext();
|
||||
DownloadTest.assertEqual(cursor.getDownload(), download3);
|
||||
assertEqual(cursor.getDownload(), download3);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ public class DefaultDownloadIndexTest {
|
|||
Download readDownload = downloadIndex.getDownload(id);
|
||||
Download expectedDownload =
|
||||
downloadBuilder.setManualStopReason(Download.MANUAL_STOP_REASON_NONE).build();
|
||||
DownloadTest.assertEqual(readDownload, expectedDownload);
|
||||
assertEqual(readDownload, expectedDownload);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -234,7 +234,7 @@ public class DefaultDownloadIndexTest {
|
|||
|
||||
Download readDownload = downloadIndex.getDownload(id);
|
||||
Download expectedDownload = downloadBuilder.setManualStopReason(manualStopReason).build();
|
||||
DownloadTest.assertEqual(readDownload, expectedDownload);
|
||||
assertEqual(readDownload, expectedDownload);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -248,7 +248,7 @@ public class DefaultDownloadIndexTest {
|
|||
downloadIndex.setManualStopReason(notMetRequirements);
|
||||
|
||||
Download readDownload = downloadIndex.getDownload(id);
|
||||
DownloadTest.assertEqual(readDownload, download);
|
||||
assertEqual(readDownload, download);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -264,7 +264,7 @@ public class DefaultDownloadIndexTest {
|
|||
Download readDownload = downloadIndex.getDownload(id);
|
||||
Download expectedDownload =
|
||||
downloadBuilder.setManualStopReason(Download.MANUAL_STOP_REASON_NONE).build();
|
||||
DownloadTest.assertEqual(readDownload, expectedDownload);
|
||||
assertEqual(readDownload, expectedDownload);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -282,7 +282,7 @@ public class DefaultDownloadIndexTest {
|
|||
|
||||
Download readDownload = downloadIndex.getDownload(id);
|
||||
Download expectedDownload = downloadBuilder.setManualStopReason(manualStopReason).build();
|
||||
DownloadTest.assertEqual(readDownload, expectedDownload);
|
||||
assertEqual(readDownload, expectedDownload);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -297,6 +297,18 @@ public class DefaultDownloadIndexTest {
|
|||
downloadIndex.setManualStopReason(id, notMetRequirements);
|
||||
|
||||
Download readDownload = downloadIndex.getDownload(id);
|
||||
DownloadTest.assertEqual(readDownload, download);
|
||||
assertEqual(readDownload, download);
|
||||
}
|
||||
|
||||
private static void assertEqual(Download download, Download that) {
|
||||
assertThat(download.action).isEqualTo(that.action);
|
||||
assertThat(download.state).isEqualTo(that.state);
|
||||
assertThat(download.startTimeMs).isEqualTo(that.startTimeMs);
|
||||
assertThat(download.updateTimeMs).isEqualTo(that.updateTimeMs);
|
||||
assertThat(download.failureReason).isEqualTo(that.failureReason);
|
||||
assertThat(download.manualStopReason).isEqualTo(that.manualStopReason);
|
||||
assertThat(download.getDownloadPercentage()).isEqualTo(that.getDownloadPercentage());
|
||||
assertThat(download.getDownloadedBytes()).isEqualTo(that.getDownloadedBytes());
|
||||
assertThat(download.getTotalBytes()).isEqualTo(that.getTotalBytes());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import com.google.android.exoplayer2.upstream.cache.CacheUtil.CachingCounters;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
|
@ -449,6 +450,71 @@ public class DownloadManagerTest {
|
|||
downloadManagerListener.blockUntilTasksCompleteAndThrowAnyDownloadError();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeAction_removingDownload_becomesRestarting() {
|
||||
DownloadAction downloadAction = createDownloadAction();
|
||||
DownloadBuilder downloadBuilder =
|
||||
new DownloadBuilder(downloadAction).setState(Download.STATE_REMOVING);
|
||||
Download download = downloadBuilder.build();
|
||||
|
||||
Download mergedDownload =
|
||||
DownloadManager.mergeAction(download, downloadAction, download.manualStopReason);
|
||||
|
||||
Download expectedDownload = downloadBuilder.setState(Download.STATE_RESTARTING).build();
|
||||
assertEqualIgnoringTimeFields(mergedDownload, expectedDownload);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeAction_failedDownload_becomesQueued() {
|
||||
DownloadAction downloadAction = createDownloadAction();
|
||||
DownloadBuilder downloadBuilder =
|
||||
new DownloadBuilder(downloadAction)
|
||||
.setState(Download.STATE_FAILED)
|
||||
.setFailureReason(Download.FAILURE_REASON_UNKNOWN);
|
||||
Download download = downloadBuilder.build();
|
||||
|
||||
Download mergedDownload =
|
||||
DownloadManager.mergeAction(download, downloadAction, download.manualStopReason);
|
||||
|
||||
Download expectedDownload =
|
||||
downloadBuilder
|
||||
.setState(Download.STATE_QUEUED)
|
||||
.setFailureReason(Download.FAILURE_REASON_NONE)
|
||||
.build();
|
||||
assertEqualIgnoringTimeFields(mergedDownload, expectedDownload);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeAction_stoppedDownload_staysStopped() {
|
||||
DownloadAction downloadAction = createDownloadAction();
|
||||
DownloadBuilder downloadBuilder =
|
||||
new DownloadBuilder(downloadAction)
|
||||
.setState(Download.STATE_STOPPED)
|
||||
.setManualStopReason(/* manualStopReason= */ 1);
|
||||
Download download = downloadBuilder.build();
|
||||
|
||||
Download mergedDownload =
|
||||
DownloadManager.mergeAction(download, downloadAction, download.manualStopReason);
|
||||
|
||||
assertEqualIgnoringTimeFields(mergedDownload, download);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeAction_manualStopReasonSetButNotStopped_becomesStopped() {
|
||||
DownloadAction downloadAction = createDownloadAction();
|
||||
DownloadBuilder downloadBuilder =
|
||||
new DownloadBuilder(downloadAction)
|
||||
.setState(Download.STATE_COMPLETED)
|
||||
.setManualStopReason(/* manualStopReason= */ 1);
|
||||
Download download = downloadBuilder.build();
|
||||
|
||||
Download mergedDownload =
|
||||
DownloadManager.mergeAction(download, downloadAction, download.manualStopReason);
|
||||
|
||||
Download expectedDownload = downloadBuilder.setState(Download.STATE_STOPPED).build();
|
||||
assertEqualIgnoringTimeFields(mergedDownload, expectedDownload);
|
||||
}
|
||||
|
||||
private void setUpDownloadManager(final int maxActiveDownloadTasks) throws Exception {
|
||||
if (downloadManager != null) {
|
||||
releaseDownloadManager();
|
||||
|
|
@ -486,6 +552,26 @@ public class DownloadManagerTest {
|
|||
dummyMainThread.runTestOnMainThread(r);
|
||||
}
|
||||
|
||||
private static void assertEqualIgnoringTimeFields(Download download, Download that) {
|
||||
assertThat(download.action).isEqualTo(that.action);
|
||||
assertThat(download.state).isEqualTo(that.state);
|
||||
assertThat(download.failureReason).isEqualTo(that.failureReason);
|
||||
assertThat(download.manualStopReason).isEqualTo(that.manualStopReason);
|
||||
assertThat(download.getDownloadPercentage()).isEqualTo(that.getDownloadPercentage());
|
||||
assertThat(download.getDownloadedBytes()).isEqualTo(that.getDownloadedBytes());
|
||||
assertThat(download.getTotalBytes()).isEqualTo(that.getTotalBytes());
|
||||
}
|
||||
|
||||
private static DownloadAction createDownloadAction() {
|
||||
return new DownloadAction(
|
||||
"id",
|
||||
DownloadAction.TYPE_DASH,
|
||||
Uri.parse("https://www.test.com/download"),
|
||||
Collections.emptyList(),
|
||||
/* customCacheKey= */ null,
|
||||
/* data= */ null);
|
||||
}
|
||||
|
||||
private final class DownloadRunner {
|
||||
|
||||
private final Uri uri;
|
||||
|
|
|
|||
|
|
@ -1,274 +0,0 @@
|
|||
/*
|
||||
* 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(/* manualStopReason= */ 1);
|
||||
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(/* manualStopReason= */ 1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue