Commit facd32e6 by eguven Committed by Toni

Remove DownloadAction.createRemoveAction

PiperOrigin-RevId: 240557315
parent d4f5c9c7
......@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.offline;
import com.google.android.exoplayer2.offline.DownloadAction.UnsupportedActionException;
import com.google.android.exoplayer2.util.AtomicFile;
import com.google.android.exoplayer2.util.Util;
import java.io.DataInputStream;
......@@ -22,12 +23,14 @@ import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
/**
* Stores and loads {@link DownloadAction}s to/from a file.
*/
public final class ActionFile {
private static final String TAG = "ActionFile";
/* package */ static final int VERSION = 0;
private final AtomicFile atomicFile;
......@@ -58,11 +61,15 @@ public final class ActionFile {
throw new IOException("Unsupported action file version: " + version);
}
int actionCount = dataInputStream.readInt();
DownloadAction[] actions = new DownloadAction[actionCount];
ArrayList<DownloadAction> actions = new ArrayList<>();
for (int i = 0; i < actionCount; i++) {
actions[i] = DownloadAction.deserializeFromStream(dataInputStream);
try {
actions.add(DownloadAction.deserializeFromStream(dataInputStream));
} catch (UnsupportedActionException e) {
// remove DownloadAction is not supported. Ignore the exception and continue loading rest.
}
}
return actions;
return actions.toArray(new DownloadAction[0]);
} finally {
Util.closeQuietly(inputStream);
}
......
......@@ -17,7 +17,6 @@ package com.google.android.exoplayer2.offline;
import android.net.Uri;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
......@@ -31,9 +30,12 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/** Contains the necessary parameters for a download or remove action. */
/** Contains the necessary parameters for a download action. */
public final class DownloadAction {
/** Thrown when the encoded action data belongs to an unsupported DownloadAction type. */
public static class UnsupportedActionException extends IOException {}
/** Type for progressive downloads. */
public static final String TYPE_PROGRESSIVE = "progressive";
/** Type for DASH downloads. */
......@@ -51,6 +53,8 @@ public final class DownloadAction {
* @param data The action data to deserialize.
* @return The deserialized action.
* @throws IOException If the data could not be deserialized.
* @throws UnsupportedActionException If the data belongs to an unsupported {@link DownloadAction}
* type. Input read position is set to the end of the data.
*/
public static DownloadAction fromByteArray(byte[] data) throws IOException {
ByteArrayInputStream input = new ByteArrayInputStream(data);
......@@ -67,6 +71,8 @@ public final class DownloadAction {
* @return The deserialized action.
* @throws IOException If there is an IO error reading from {@code input}, or if the data could
* not be deserialized.
* @throws UnsupportedActionException If the data belongs to an unsupported {@link DownloadAction}
* type. Input read position is set to the end of the data.
*/
public static DownloadAction deserializeFromStream(InputStream input) throws IOException {
return readFromStream(new DataInputStream(input));
......@@ -108,41 +114,16 @@ public final class DownloadAction {
List<StreamKey> keys,
@Nullable String customCacheKey,
@Nullable byte[] data) {
return new DownloadAction(
id, type, uri, /* isRemoveAction= */ false, keys, customCacheKey, data);
}
/**
* Creates a DASH remove action.
*
* @param type The type of the action.
* @param uri The URI of the media to be removed.
* @param customCacheKey A custom key for cache indexing, or null.
*/
public static DownloadAction createRemoveAction(
String type, Uri uri, @Nullable String customCacheKey) {
return new DownloadAction(
generateId(uri, customCacheKey),
type,
uri,
/* isRemoveAction= */ true,
Collections.emptyList(),
customCacheKey,
/* data= */ null);
return new DownloadAction(id, type, uri, keys, customCacheKey, data);
}
/** The unique content id. */
public final String id;
/** The type of the action. */
public final String type;
/** The uri being downloaded or removed. */
/** The uri being downloaded. */
public final Uri uri;
/** Whether this is a remove action. If false, this is a download action. */
public final boolean isRemoveAction;
/**
* Keys of streams to be downloaded. If empty, all streams will be downloaded. Empty if this
* action is a remove action.
*/
/** Keys of streams to be downloaded. If empty, all streams will be downloaded. */
public final List<StreamKey> keys;
/** A custom key for cache indexing, or null. */
@Nullable public final String customCacheKey;
......@@ -152,37 +133,26 @@ public final class DownloadAction {
/**
* @param id The content id.
* @param type The type of the action.
* @param uri The uri being downloaded or removed.
* @param isRemoveAction Whether this is a remove action. If false, this is a download action.
* @param keys Keys of streams to be downloaded. If empty, all streams will be downloaded. Empty
* if this action is a remove action.
* @param uri The uri being downloaded.
* @param keys Keys of streams to be downloaded. If empty, all streams will be downloaded.
* @param customCacheKey A custom key for cache indexing, or null.
* @param data Custom data for this action. Null if this action is a remove action.
* @param data Custom data for this action.
*/
private DownloadAction(
String id,
String type,
Uri uri,
boolean isRemoveAction,
List<StreamKey> keys,
@Nullable String customCacheKey,
@Nullable byte[] data) {
this.id = id;
this.type = type;
this.uri = uri;
this.isRemoveAction = isRemoveAction;
this.customCacheKey = customCacheKey;
if (isRemoveAction) {
Assertions.checkArgument(keys.isEmpty());
Assertions.checkArgument(data == null);
this.keys = Collections.emptyList();
this.data = Util.EMPTY_BYTE_ARRAY;
} else {
ArrayList<StreamKey> mutableKeys = new ArrayList<>(keys);
Collections.sort(mutableKeys);
this.keys = Collections.unmodifiableList(mutableKeys);
this.data = data != null ? Arrays.copyOf(data, data.length) : Util.EMPTY_BYTE_ARRAY;
}
ArrayList<StreamKey> mutableKeys = new ArrayList<>(keys);
Collections.sort(mutableKeys);
this.keys = Collections.unmodifiableList(mutableKeys);
this.data = data != null ? Arrays.copyOf(data, data.length) : Util.EMPTY_BYTE_ARRAY;
}
/** Serializes itself into a byte array. */
......@@ -211,7 +181,6 @@ public final class DownloadAction {
return id.equals(that.id)
&& type.equals(that.type)
&& uri.equals(that.uri)
&& isRemoveAction == that.isRemoveAction
&& keys.equals(that.keys)
&& Util.areEqual(customCacheKey, that.customCacheKey)
&& Arrays.equals(data, that.data);
......@@ -222,7 +191,6 @@ public final class DownloadAction {
int result = type.hashCode();
result = 31 * result + id.hashCode();
result = 31 * result + uri.hashCode();
result = 31 * result + (isRemoveAction ? 1 : 0);
result = 31 * result + keys.hashCode();
result = 31 * result + (customCacheKey != null ? customCacheKey.hashCode() : 0);
result = 31 * result + Arrays.hashCode(data);
......@@ -242,7 +210,7 @@ public final class DownloadAction {
dataOutputStream.writeUTF(type);
dataOutputStream.writeInt(VERSION);
dataOutputStream.writeUTF(uri.toString());
dataOutputStream.writeBoolean(isRemoveAction);
dataOutputStream.writeBoolean(false);
dataOutputStream.writeInt(data.length);
dataOutputStream.write(data);
dataOutputStream.writeInt(keys.size());
......@@ -271,10 +239,6 @@ public final class DownloadAction {
if (dataLength != 0) {
data = new byte[dataLength];
input.readFully(data);
if (isRemoveAction) {
// Remove actions are no longer permitted to have data.
data = null;
}
} else {
data = null;
}
......@@ -297,8 +261,12 @@ public final class DownloadAction {
customCacheKey = input.readBoolean() ? input.readUTF() : null;
}
if (isRemoveAction) {
// Remove actions are not supported anymore.
throw new UnsupportedActionException();
}
return new DownloadAction(
generateId(uri, customCacheKey), type, uri, isRemoveAction, keys, customCacheKey, data);
generateId(uri, customCacheKey), type, uri, keys, customCacheKey, data);
}
private static String generateId(Uri uri, @Nullable String customCacheKey) {
......
......@@ -342,11 +342,11 @@ public final class DownloadManager {
}
/**
* Handles the given action.
* Adds a download defined by the given action.
*
* @param action The action to be executed.
* @param action The download action.
*/
public void handleAction(DownloadAction action) {
public void addDownload(DownloadAction action) {
Assertions.checkState(!released);
dowloadUpdateQueue.add(
new DownloadUpdater(action.id) {
......@@ -392,6 +392,8 @@ public final class DownloadManager {
DownloadState onLoad(@Nullable DownloadState downloadState) {
if (downloadState != null) {
downloadState = downloadState.setRemoveState();
} else {
logd("Can't remove download. No download with id: " + id);
}
return downloadState;
}
......@@ -541,15 +543,14 @@ public final class DownloadManager {
}
private void processDownloadUpdateQueue() {
if (loadingDownload || dowloadUpdateQueue.isEmpty()) {
return;
}
DownloadUpdater downloadUpdater = dowloadUpdateQueue.remove();
Download download = getDownload(downloadUpdater.id);
if (download != null) {
downloadUpdater.onExisting(download);
} else {
loadDownload(downloadUpdater);
while (!loadingDownload && !dowloadUpdateQueue.isEmpty()) {
DownloadUpdater downloadUpdater = dowloadUpdateQueue.remove();
Download download = getDownload(downloadUpdater.id);
if (download != null) {
downloadUpdater.onExisting(download);
} else {
loadDownload(downloadUpdater);
}
}
}
......
......@@ -270,11 +270,14 @@ public abstract class DownloadService extends Service {
* @param context A {@link Context}.
* @param clazz The concrete download service being targeted by the intent.
* @param id The content id.
* @param foreground Whether this intent will be used to start the service in the foreground.
* @return Created Intent.
*/
public static Intent buildRemoveDownloadIntent(
Context context, Class<? extends DownloadService> clazz, String id) {
return getIntent(context, clazz, ACTION_REMOVE).putExtra(KEY_CONTENT_ID, id);
Context context, Class<? extends DownloadService> clazz, String id, boolean foreground) {
return getIntent(context, clazz, ACTION_REMOVE)
.putExtra(KEY_CONTENT_ID, id)
.putExtra(KEY_FOREGROUND, foreground);
}
/**
......@@ -308,7 +311,7 @@ public abstract class DownloadService extends Service {
*/
public static void startWithRemoveDownload(
Context context, Class<? extends DownloadService> clazz, String id, boolean foreground) {
Intent intent = buildRemoveDownloadIntent(context, clazz, id);
Intent intent = buildRemoveDownloadIntent(context, clazz, id, foreground);
if (foreground) {
Util.startForegroundService(context, intent);
} else {
......@@ -393,7 +396,7 @@ public abstract class DownloadService extends Service {
Log.e(TAG, "Ignored ADD action: Failed to deserialize download_action extra", e);
}
if (downloadAction != null) {
downloadManager.handleAction(downloadAction);
downloadManager.addDownload(downloadAction);
}
}
break;
......
......@@ -166,7 +166,7 @@ public final class DownloadState {
action.type,
action.uri,
action.customCacheKey,
/* state= */ action.isRemoveAction ? STATE_REMOVING : STATE_QUEUED,
/* state= */ STATE_QUEUED,
/* downloadPercentage= */ C.PERCENTAGE_UNSET,
/* downloadedBytes= */ 0,
/* totalBytes= */ C.LENGTH_UNSET,
......@@ -231,8 +231,7 @@ public final class DownloadState {
type,
action.uri,
action.customCacheKey,
getNextState(
state, manualStopReason != 0 || notMetRequirements != 0, action.isRemoveAction),
getNextState(state, manualStopReason != 0 || notMetRequirements != 0),
/* downloadPercentage= */ C.PERCENTAGE_UNSET,
downloadedBytes,
/* totalBytes= */ C.LENGTH_UNSET,
......@@ -252,7 +251,7 @@ public final class DownloadState {
type,
uri,
cacheKey,
getNextState(state, manualStopReason != 0 || notMetRequirements != 0, true),
STATE_REMOVING,
/* downloadPercentage= */ C.PERCENTAGE_UNSET,
downloadedBytes,
/* totalBytes= */ C.LENGTH_UNSET,
......@@ -265,25 +264,19 @@ public final class DownloadState {
customMetadata);
}
private static int getNextState(int currentState, boolean isStopped, boolean remove) {
int nextState;
if (remove) {
nextState = STATE_REMOVING;
private static int getNextState(int currentState, boolean isStopped) {
if (currentState == STATE_REMOVING || currentState == STATE_RESTARTING) {
return STATE_RESTARTING;
} else if (isStopped) {
return STATE_STOPPED;
} else {
if (currentState == STATE_REMOVING || currentState == STATE_RESTARTING) {
nextState = STATE_RESTARTING;
} else if (isStopped) {
nextState = STATE_STOPPED;
} else {
nextState = STATE_QUEUED;
}
return STATE_QUEUED;
}
return nextState;
}
private static StreamKey[] mergeStreamKeys(DownloadState downloadState, DownloadAction action) {
StreamKey[] streamKeys = downloadState.streamKeys;
if (!action.isRemoveAction && streamKeys.length > 0) {
if (streamKeys.length > 0) {
if (action.keys.isEmpty()) {
streamKeys = new StreamKey[0];
} else {
......
......@@ -397,7 +397,6 @@ public class DownloadHelperTest {
assertThat(downloadAction.type).isEqualTo(TEST_DOWNLOAD_TYPE);
assertThat(downloadAction.uri).isEqualTo(testUri);
assertThat(downloadAction.customCacheKey).isEqualTo(TEST_CACHE_KEY);
assertThat(downloadAction.isRemoveAction).isFalse();
assertThat(downloadAction.data).isEqualTo(data);
assertThat(downloadAction.keys)
.containsExactly(
......
......@@ -127,16 +127,11 @@ public class DownloadIndexUtilTest {
/* customCacheKey= */ "key234",
new byte[] {5, 4, 3, 2, 1});
actionFile.store(action1, action2);
DownloadAction action3 =
DownloadAction.createRemoveAction(
TYPE_DASH, Uri.parse("https://www.test.com/download3"), /* customCacheKey= */ "key345");
actionFile.store(action1, action2, action3);
DownloadIndexUtil.upgradeActionFile(actionFile, downloadIndex, /* downloadIdProvider= */ null);
assertDownloadIndexContainsAction(action1, DownloadState.STATE_QUEUED);
assertDownloadIndexContainsAction(action2, DownloadState.STATE_QUEUED);
assertDownloadIndexContainsAction(action3, DownloadState.STATE_REMOVING);
}
private void assertDownloadIndexContainsAction(DownloadAction action, int state)
......
......@@ -119,20 +119,6 @@ public class DownloadStateTest {
}
@Test
public void mergeAction_queuedDownloadRemoveAction_stateBecomesRemoving() {
DownloadAction downloadAction = createRemoveAction();
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(downloadAction).setState(DownloadState.STATE_QUEUED);
DownloadState downloadState = downloadStateBuilder.build();
DownloadState mergedDownloadState = downloadState.mergeAction(downloadAction);
DownloadState expectedDownloadState =
downloadStateBuilder.setState(DownloadState.STATE_REMOVING).build();
assertEqual(mergedDownloadState, expectedDownloadState);
}
@Test
public void mergeAction_removingDownloadDownloadAction_stateBecomesRestarting() {
DownloadAction downloadAction = createDownloadAction();
DownloadStateBuilder downloadStateBuilder =
......@@ -180,22 +166,6 @@ public class DownloadStateTest {
}
@Test
public void mergeAction_stoppedDownloadRemoveAction_stateBecomesRemoving() {
DownloadAction downloadAction = createRemoveAction();
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(downloadAction)
.setState(DownloadState.STATE_STOPPED)
.setManualStopReason(DownloadState.MANUAL_STOP_REASON_UNDEFINED);
DownloadState downloadState = downloadStateBuilder.build();
DownloadState mergedDownloadState = downloadState.mergeAction(downloadAction);
DownloadState expectedDownloadState =
downloadStateBuilder.setState(DownloadState.STATE_REMOVING).build();
assertEqual(mergedDownloadState, expectedDownloadState);
}
@Test
public void mergeAction_manualStopReasonSetButNotInStoppedState_stateBecomesStopped() {
DownloadAction downloadAction = createDownloadAction();
DownloadStateBuilder downloadStateBuilder =
......@@ -228,20 +198,6 @@ public class DownloadStateTest {
}
@Test
public void mergeAction_restartingDownloadRemoveAction_stateBecomesRemoving() {
DownloadAction downloadAction = createRemoveAction();
DownloadStateBuilder downloadStateBuilder =
new DownloadStateBuilder(downloadAction).setState(DownloadState.STATE_RESTARTING);
DownloadState downloadState = downloadStateBuilder.build();
DownloadState mergedDownloadState = downloadState.mergeAction(downloadAction);
DownloadState expectedDownloadState =
downloadStateBuilder.setState(DownloadState.STATE_REMOVING).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);
......@@ -340,9 +296,4 @@ public class DownloadStateTest {
/* customCacheKey= */ null,
/* data= */ null);
}
private DownloadAction createRemoveAction() {
return DownloadAction.createRemoveAction(
DownloadAction.TYPE_DASH, testUri, /* customCacheKey= */ null);
}
}
......@@ -22,7 +22,8 @@ import java.nio.charset.Charset;
/** Data for DASH downloading tests. */
/* package */ interface DashDownloadTestData {
Uri TEST_MPD_URI = Uri.parse("test.mpd");
String TEST_ID = "test.mpd";
Uri TEST_MPD_URI = Uri.parse(TEST_ID);
byte[] TEST_MPD =
("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
......
......@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.dash.offline;
import static com.google.android.exoplayer2.source.dash.offline.DashDownloadTestData.TEST_ID;
import static com.google.android.exoplayer2.source.dash.offline.DashDownloadTestData.TEST_MPD;
import static com.google.android.exoplayer2.source.dash.offline.DashDownloadTestData.TEST_MPD_URI;
import static com.google.android.exoplayer2.testutil.CacheAsserts.assertCacheEmpty;
......@@ -22,9 +23,7 @@ import static com.google.android.exoplayer2.testutil.CacheAsserts.assertCachedDa
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.net.Uri;
import android.os.ConditionVariable;
import androidx.annotation.Nullable;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.offline.DefaultDownloadIndex;
......@@ -230,11 +229,16 @@ public class DownloadManagerDashTest {
}
private void handleDownloadAction(StreamKey... keys) {
downloadManager.handleAction(newAction(TEST_MPD_URI, false, null, keys));
ArrayList<StreamKey> keysList = new ArrayList<>();
Collections.addAll(keysList, keys);
DownloadAction action =
DownloadAction.createDownloadAction(
DownloadAction.TYPE_DASH, TEST_MPD_URI, keysList, /* customCacheKey= */ null, null);
downloadManager.addDownload(action);
}
private void handleRemoveAction() {
downloadManager.handleAction(newAction(TEST_MPD_URI, true, null));
downloadManager.removeDownload(TEST_ID);
}
private void createDownloadManager() {
......@@ -257,20 +261,4 @@ public class DownloadManagerDashTest {
});
}
private static DownloadAction newAction(
Uri uri, boolean isRemoveAction, @Nullable byte[] data, StreamKey... keys) {
ArrayList<StreamKey> keysList = new ArrayList<>();
Collections.addAll(keysList, keys);
DownloadAction result;
if (isRemoveAction) {
result =
DownloadAction.createRemoveAction(
DownloadAction.TYPE_DASH, uri, /* customCacheKey= */ null);
} else {
result =
DownloadAction.createDownloadAction(
DownloadAction.TYPE_DASH, uri, keysList, /* customCacheKey= */ null, data);
}
return result;
}
}
......@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.dash.offline;
import static com.google.android.exoplayer2.source.dash.offline.DashDownloadTestData.TEST_ID;
import static com.google.android.exoplayer2.source.dash.offline.DashDownloadTestData.TEST_MPD;
import static com.google.android.exoplayer2.source.dash.offline.DashDownloadTestData.TEST_MPD_URI;
import static com.google.android.exoplayer2.testutil.CacheAsserts.assertCacheEmpty;
......@@ -22,7 +23,6 @@ import static com.google.android.exoplayer2.testutil.CacheAsserts.assertCachedDa
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import androidx.annotation.Nullable;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
......@@ -187,37 +187,29 @@ public class DownloadServiceDashTest {
assertCacheEmpty(cache);
}
private void removeAll() throws Throwable {
callDownloadServiceOnStart(newAction(TEST_MPD_URI, true, null));
}
private void downloadKeys(StreamKey... keys) {
callDownloadServiceOnStart(newAction(TEST_MPD_URI, false, null, keys));
}
private void callDownloadServiceOnStart(final DownloadAction action) {
private void removeAll() {
dummyMainThread.runOnMainThread(
() -> {
Intent startIntent =
DownloadService.buildAddActionIntent(context, DownloadService.class, action, false);
DownloadService.buildRemoveDownloadIntent(
context, DownloadService.class, TEST_ID, /* foreground= */ false);
dashDownloadService.onStartCommand(startIntent, 0, 0);
});
}
private static DownloadAction newAction(
Uri uri, boolean isRemoveAction, @Nullable byte[] data, StreamKey... keys) {
private void downloadKeys(StreamKey... keys) {
ArrayList<StreamKey> keysList = new ArrayList<>();
Collections.addAll(keysList, keys);
DownloadAction result;
if (isRemoveAction) {
result =
DownloadAction.createRemoveAction(
DownloadAction.TYPE_DASH, uri, /* customCacheKey= */ null);
} else {
result =
DownloadAction.createDownloadAction(
DownloadAction.TYPE_DASH, uri, keysList, /* customCacheKey= */ null, data);
}
return result;
DownloadAction action =
DownloadAction.createDownloadAction(
DownloadAction.TYPE_DASH, TEST_MPD_URI, keysList, /* customCacheKey= */ null, null);
dummyMainThread.runOnMainThread(
() -> {
Intent startIntent =
DownloadService.buildAddActionIntent(
context, DownloadService.class, action, /* foreground= */ false);
dashDownloadService.onStartCommand(startIntent, 0, 0);
});
}
}
......@@ -16,11 +16,15 @@
package com.google.android.exoplayer2.testutil;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import android.os.ConditionVariable;
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;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
......@@ -115,4 +119,37 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
return actionStates.get(taskId);
}
}
public void assertState(String taskId, @State int expectedState, int timeoutMs) {
ArrayList<Integer> receivedStates = new ArrayList<>();
while (true) {
Integer state = null;
try {
state = pollStateChange(taskId, timeoutMs);
} catch (InterruptedException e) {
fail(e.getMessage());
}
if (state != null) {
if (expectedState == state) {
return;
}
receivedStates.add(state);
} else {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < receivedStates.size(); i++) {
if (i > 0) {
sb.append(',');
}
sb.append(DownloadState.getStateString(receivedStates.get(i)));
}
fail(
String.format(
Locale.US,
"for download (%s) expected:<%s> but was:<%s>",
taskId,
DownloadState.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