Add DownloadState not met requirement stop flags

PiperOrigin-RevId: 231223201
This commit is contained in:
eguven 2019-01-28 16:24:47 +00:00 committed by Oliver Woodman
parent 19144c4c73
commit bac8dfea12
6 changed files with 81 additions and 55 deletions

View File

@ -132,6 +132,7 @@ public final class DefaultDownloadIndex implements DownloadIndex {
private static final String COLUMN_TOTAL_BYTES = "total_bytes"; private static final String COLUMN_TOTAL_BYTES = "total_bytes";
private static final String COLUMN_FAILURE_REASON = "failure_reason"; private static final String COLUMN_FAILURE_REASON = "failure_reason";
private static final String COLUMN_STOP_FLAGS = "stop_flags"; private static final String COLUMN_STOP_FLAGS = "stop_flags";
private static final String COLUMN_NOT_MET_REQUIREMENTS = "not_met_requirements";
private static final String COLUMN_START_TIME_MS = "start_time_ms"; private static final String COLUMN_START_TIME_MS = "start_time_ms";
private static final String COLUMN_UPDATE_TIME_MS = "update_time_ms"; private static final String COLUMN_UPDATE_TIME_MS = "update_time_ms";
private static final String COLUMN_STREAM_KEYS = "stream_keys"; private static final String COLUMN_STREAM_KEYS = "stream_keys";
@ -147,10 +148,11 @@ public final class DefaultDownloadIndex implements DownloadIndex {
private static final int COLUMN_INDEX_TOTAL_BYTES = 7; private static final int COLUMN_INDEX_TOTAL_BYTES = 7;
private static final int COLUMN_INDEX_FAILURE_REASON = 8; private static final int COLUMN_INDEX_FAILURE_REASON = 8;
private static final int COLUMN_INDEX_STOP_FLAGS = 9; private static final int COLUMN_INDEX_STOP_FLAGS = 9;
private static final int COLUMN_INDEX_START_TIME_MS = 10; private static final int COLUMN_INDEX_NOT_MET_REQUIREMENTS = 10;
private static final int COLUMN_INDEX_UPDATE_TIME_MS = 11; private static final int COLUMN_INDEX_START_TIME_MS = 11;
private static final int COLUMN_INDEX_STREAM_KEYS = 12; private static final int COLUMN_INDEX_UPDATE_TIME_MS = 12;
private static final int COLUMN_INDEX_CUSTOM_METADATA = 13; private static final int COLUMN_INDEX_STREAM_KEYS = 13;
private static final int COLUMN_INDEX_CUSTOM_METADATA = 14;
private static final String COLUMN_SELECTION_ID = COLUMN_ID + " = ?"; private static final String COLUMN_SELECTION_ID = COLUMN_ID + " = ?";
@ -166,6 +168,7 @@ public final class DefaultDownloadIndex implements DownloadIndex {
COLUMN_TOTAL_BYTES, COLUMN_TOTAL_BYTES,
COLUMN_FAILURE_REASON, COLUMN_FAILURE_REASON,
COLUMN_STOP_FLAGS, COLUMN_STOP_FLAGS,
COLUMN_NOT_MET_REQUIREMENTS,
COLUMN_START_TIME_MS, COLUMN_START_TIME_MS,
COLUMN_UPDATE_TIME_MS, COLUMN_UPDATE_TIME_MS,
COLUMN_STREAM_KEYS, COLUMN_STREAM_KEYS,
@ -197,6 +200,8 @@ public final class DefaultDownloadIndex implements DownloadIndex {
+ " INTEGER NOT NULL," + " INTEGER NOT NULL,"
+ COLUMN_STOP_FLAGS + COLUMN_STOP_FLAGS
+ " INTEGER NOT NULL," + " INTEGER NOT NULL,"
+ COLUMN_NOT_MET_REQUIREMENTS
+ " INTEGER NOT NULL,"
+ COLUMN_START_TIME_MS + COLUMN_START_TIME_MS
+ " INTEGER NOT NULL," + " INTEGER NOT NULL,"
+ COLUMN_UPDATE_TIME_MS + COLUMN_UPDATE_TIME_MS
@ -241,6 +246,7 @@ public final class DefaultDownloadIndex implements DownloadIndex {
values.put(COLUMN_TOTAL_BYTES, downloadState.totalBytes); values.put(COLUMN_TOTAL_BYTES, downloadState.totalBytes);
values.put(COLUMN_FAILURE_REASON, downloadState.failureReason); values.put(COLUMN_FAILURE_REASON, downloadState.failureReason);
values.put(COLUMN_STOP_FLAGS, downloadState.stopFlags); values.put(COLUMN_STOP_FLAGS, downloadState.stopFlags);
values.put(COLUMN_NOT_MET_REQUIREMENTS, downloadState.notMetRequirements);
values.put(COLUMN_START_TIME_MS, downloadState.startTimeMs); values.put(COLUMN_START_TIME_MS, downloadState.startTimeMs);
values.put(COLUMN_UPDATE_TIME_MS, downloadState.updateTimeMs); values.put(COLUMN_UPDATE_TIME_MS, downloadState.updateTimeMs);
values.put(COLUMN_STREAM_KEYS, encodeStreamKeys(downloadState.streamKeys)); values.put(COLUMN_STREAM_KEYS, encodeStreamKeys(downloadState.streamKeys));
@ -312,6 +318,7 @@ public final class DefaultDownloadIndex implements DownloadIndex {
cursor.getLong(COLUMN_INDEX_TOTAL_BYTES), cursor.getLong(COLUMN_INDEX_TOTAL_BYTES),
cursor.getInt(COLUMN_INDEX_FAILURE_REASON), cursor.getInt(COLUMN_INDEX_FAILURE_REASON),
cursor.getInt(COLUMN_INDEX_STOP_FLAGS), cursor.getInt(COLUMN_INDEX_STOP_FLAGS),
cursor.getInt(COLUMN_INDEX_NOT_MET_REQUIREMENTS),
cursor.getLong(COLUMN_INDEX_START_TIME_MS), cursor.getLong(COLUMN_INDEX_START_TIME_MS),
cursor.getLong(COLUMN_INDEX_UPDATE_TIME_MS), cursor.getLong(COLUMN_INDEX_UPDATE_TIME_MS),
decodeStreamKeys(cursor.getString(COLUMN_INDEX_STREAM_KEYS)), decodeStreamKeys(cursor.getString(COLUMN_INDEX_STREAM_KEYS)),

View File

@ -115,6 +115,7 @@ public final class DownloadIndexUtil {
/* totalBytes= */ C.LENGTH_UNSET, /* totalBytes= */ C.LENGTH_UNSET,
downloadState.failureReason, downloadState.failureReason,
downloadState.stopFlags, downloadState.stopFlags,
downloadState.notMetRequirements,
downloadState.startTimeMs, downloadState.startTimeMs,
downloadState.updateTimeMs, downloadState.updateTimeMs,
newKeys, newKeys,
@ -136,6 +137,7 @@ public final class DownloadIndexUtil {
/* totalBytes= */ C.LENGTH_UNSET, /* totalBytes= */ C.LENGTH_UNSET,
DownloadState.FAILURE_REASON_NONE, DownloadState.FAILURE_REASON_NONE,
/* stopFlags= */ 0, /* stopFlags= */ 0,
/* notMetRequirements= */ 0,
/* startTimeMs= */ currentTimeMs, /* startTimeMs= */ currentTimeMs,
/* updateTimeMs= */ currentTimeMs, /* updateTimeMs= */ currentTimeMs,
action.keys.toArray(new StreamKey[0]), action.keys.toArray(new StreamKey[0]),

View File

@ -26,6 +26,7 @@ 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_RESTARTING;
import static com.google.android.exoplayer2.offline.DownloadState.STATE_STOPPED; import static com.google.android.exoplayer2.offline.DownloadState.STATE_STOPPED;
import static com.google.android.exoplayer2.offline.DownloadState.STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY; import static com.google.android.exoplayer2.offline.DownloadState.STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY;
import static com.google.android.exoplayer2.offline.DownloadState.STOP_FLAG_REQUIREMENTS_NOT_MET;
import static com.google.android.exoplayer2.offline.DownloadState.STOP_FLAG_STOPPED; import static com.google.android.exoplayer2.offline.DownloadState.STOP_FLAG_STOPPED;
import android.content.Context; import android.content.Context;
@ -119,6 +120,7 @@ public final class DownloadManager {
private boolean initialized; private boolean initialized;
private boolean released; private boolean released;
@DownloadState.StopFlags private int stickyStopFlags; @DownloadState.StopFlags private int stickyStopFlags;
@Requirements.RequirementFlags private int notMetRequirements;
private RequirementsWatcher requirementsWatcher; private RequirementsWatcher requirementsWatcher;
/** /**
@ -194,7 +196,7 @@ public final class DownloadManager {
return; return;
} }
requirementsWatcher.stop(); requirementsWatcher.stop();
notifyListenersRequirementsStateChange(watchRequirements(requirements)); onRequirementsStateChanged(watchRequirements(requirements));
} }
/** Returns the requirements needed to be met to start downloads. */ /** Returns the requirements needed to be met to start downloads. */
@ -349,7 +351,8 @@ public final class DownloadManager {
} }
} }
Download download = Download download =
new Download(this, downloaderFactory, action, minRetryCount, stickyStopFlags); new Download(
this, downloaderFactory, action, minRetryCount, stickyStopFlags, notMetRequirements);
downloads.add(download); downloads.add(download);
logd("Download is added", download); logd("Download is added", download);
} }
@ -401,13 +404,16 @@ public final class DownloadManager {
} }
} }
private void notifyListenersRequirementsStateChange( private void onRequirementsStateChanged(@Requirements.RequirementFlags int notMetRequirements) {
@Requirements.RequirementFlags int notMetRequirements) { this.notMetRequirements = notMetRequirements;
logdFlags("Not met requirements are changed", notMetRequirements); logdFlags("Not met requirements are changed", notMetRequirements);
for (Listener listener : listeners) { for (Listener listener : listeners) {
listener.onRequirementsStateChanged( listener.onRequirementsStateChanged(
DownloadManager.this, requirementsWatcher.getRequirements(), notMetRequirements); DownloadManager.this, requirementsWatcher.getRequirements(), notMetRequirements);
} }
for (int i = 0; i < downloads.size(); i++) {
downloads.get(i).setNotMetRequirements(notMetRequirements);
}
} }
private void loadActions() { private void loadActions() {
@ -486,7 +492,9 @@ public final class DownloadManager {
@Requirements.RequirementFlags @Requirements.RequirementFlags
private int watchRequirements(Requirements requirements) { private int watchRequirements(Requirements requirements) {
requirementsWatcher = new RequirementsWatcher(context, new RequirementListener(), requirements); RequirementsWatcher.Listener listener =
(requirementsWatcher, notMetRequirements) -> onRequirementsStateChanged(notMetRequirements);
requirementsWatcher = new RequirementsWatcher(context, listener, requirements);
@Requirements.RequirementFlags int notMetRequirements = requirementsWatcher.start(); @Requirements.RequirementFlags int notMetRequirements = requirementsWatcher.start();
if (notMetRequirements == 0) { if (notMetRequirements == 0) {
startDownloads(); startDownloads();
@ -511,17 +519,23 @@ public final class DownloadManager {
@MonotonicNonNull private DownloadThread downloadThread; @MonotonicNonNull private DownloadThread downloadThread;
@MonotonicNonNull @DownloadState.FailureReason private int failureReason; @MonotonicNonNull @DownloadState.FailureReason private int failureReason;
@DownloadState.StopFlags private int stopFlags; @DownloadState.StopFlags private int stopFlags;
@Requirements.RequirementFlags private int notMetRequirements;
private Download( private Download(
DownloadManager downloadManager, DownloadManager downloadManager,
DownloaderFactory downloaderFactory, DownloaderFactory downloaderFactory,
DownloadAction action, DownloadAction action,
int minRetryCount, int minRetryCount,
int stopFlags) { @DownloadState.StopFlags int stopFlags,
@Requirements.RequirementFlags int notMetRequirements) {
this.id = action.id; this.id = action.id;
this.downloadManager = downloadManager; this.downloadManager = downloadManager;
this.downloaderFactory = downloaderFactory; this.downloaderFactory = downloaderFactory;
this.minRetryCount = minRetryCount; this.minRetryCount = minRetryCount;
this.notMetRequirements = notMetRequirements;
if (notMetRequirements != 0) {
stopFlags |= STOP_FLAG_REQUIREMENTS_NOT_MET;
}
this.stopFlags = stopFlags; this.stopFlags = stopFlags;
this.startTimeMs = System.currentTimeMillis(); this.startTimeMs = System.currentTimeMillis();
actionQueue = new ArrayDeque<>(); actionQueue = new ArrayDeque<>();
@ -579,6 +593,7 @@ public final class DownloadManager {
totalBytes, totalBytes,
failureReason, failureReason,
stopFlags, stopFlags,
notMetRequirements,
startTimeMs, startTimeMs,
/* updateTimeMs= */ System.currentTimeMillis(), /* updateTimeMs= */ System.currentTimeMillis(),
action.keys.toArray(new StreamKey[0]), action.keys.toArray(new StreamKey[0]),
@ -628,6 +643,13 @@ public final class DownloadManager {
} }
} }
public void setNotMetRequirements(@Requirements.RequirementFlags int notMetRequirements) {
this.notMetRequirements = notMetRequirements;
updateStopFlags(
STOP_FLAG_REQUIREMENTS_NOT_MET,
notMetRequirements != 0 ? STOP_FLAG_REQUIREMENTS_NOT_MET : 0);
}
private void initialize(boolean restart) { private void initialize(boolean restart) {
DownloadAction action = actionQueue.peek(); DownloadAction action = actionQueue.peek();
if (action.isRemoveAction) { if (action.isRemoveAction) {
@ -770,19 +792,4 @@ public final class DownloadManager {
} }
} }
private class RequirementListener implements RequirementsWatcher.Listener {
@Override
public void requirementsMet(RequirementsWatcher requirementsWatcher) {
startDownloads();
notifyListenersRequirementsStateChange(0);
}
@Override
public void requirementsNotMet(
RequirementsWatcher requirementsWatcher,
@Requirements.RequirementFlags int notMetRequirements) {
stopDownloads();
notifyListenersRequirementsStateChange(notMetRequirements);
}
}
} }

View File

@ -19,6 +19,7 @@ import android.net.Uri;
import android.support.annotation.IntDef; import android.support.annotation.IntDef;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.scheduler.Requirements;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -80,12 +81,18 @@ public final class DownloadState {
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef( @IntDef(
flag = true, flag = true,
value = {STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY, STOP_FLAG_STOPPED}) value = {
STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY,
STOP_FLAG_STOPPED,
STOP_FLAG_REQUIREMENTS_NOT_MET
})
public @interface StopFlags {} public @interface StopFlags {}
/** Download can't be started as the manager isn't ready. */ /** Download can't be started as the manager isn't ready. */
public static final int STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY = 1; public static final int STOP_FLAG_DOWNLOAD_MANAGER_NOT_READY = 1;
/** All downloads are stopped by the application. */ /** Download is stopped by the application. */
public static final int STOP_FLAG_STOPPED = 1 << 1; public static final int STOP_FLAG_STOPPED = 1 << 1;
/** Download is stopped as the requirements are not met. */
public static final int STOP_FLAG_REQUIREMENTS_NOT_MET = 1 << 2;
/** Returns the state string for the given state value. */ /** Returns the state string for the given state value. */
public static String getStateString(@State int state) { public static String getStateString(@State int state) {
@ -153,7 +160,9 @@ public final class DownloadState {
*/ */
@FailureReason public final int failureReason; @FailureReason public final int failureReason;
/** Download stop flags. These flags stop downloading any content. */ /** Download stop flags. These flags stop downloading any content. */
public final int stopFlags; @StopFlags public final int stopFlags;
/** Not met requirements to download. */
@Requirements.RequirementFlags public final int notMetRequirements;
/* package */ DownloadState( /* package */ DownloadState(
String id, String id,
@ -166,13 +175,17 @@ public final class DownloadState {
long totalBytes, long totalBytes,
@FailureReason int failureReason, @FailureReason int failureReason,
@StopFlags int stopFlags, @StopFlags int stopFlags,
@Requirements.RequirementFlags int notMetRequirements,
long startTimeMs, long startTimeMs,
long updateTimeMs, long updateTimeMs,
StreamKey[] streamKeys, StreamKey[] streamKeys,
byte[] customMetadata) { byte[] customMetadata) {
this.stopFlags = stopFlags;
Assertions.checkState( Assertions.checkState(
failureReason == FAILURE_REASON_NONE ? state != STATE_FAILED : state == STATE_FAILED); failureReason == FAILURE_REASON_NONE ? state != STATE_FAILED : state == STATE_FAILED);
Assertions.checkState(
(stopFlags & STOP_FLAG_REQUIREMENTS_NOT_MET) == 0
? notMetRequirements == 0
: notMetRequirements != 0);
// TODO enable this when we start changing state immediately // TODO enable this when we start changing state immediately
// Assertions.checkState(stopFlags == 0 || (state != STATE_DOWNLOADING && state != // Assertions.checkState(stopFlags == 0 || (state != STATE_DOWNLOADING && state !=
// STATE_QUEUED)); // STATE_QUEUED));
@ -180,14 +193,16 @@ public final class DownloadState {
this.type = type; this.type = type;
this.uri = uri; this.uri = uri;
this.cacheKey = cacheKey; this.cacheKey = cacheKey;
this.streamKeys = streamKeys;
this.customMetadata = customMetadata;
this.state = state; this.state = state;
this.downloadPercentage = downloadPercentage; this.downloadPercentage = downloadPercentage;
this.downloadedBytes = downloadedBytes; this.downloadedBytes = downloadedBytes;
this.totalBytes = totalBytes; this.totalBytes = totalBytes;
this.failureReason = failureReason; this.failureReason = failureReason;
this.stopFlags = stopFlags;
this.notMetRequirements = notMetRequirements;
this.startTimeMs = startTimeMs; this.startTimeMs = startTimeMs;
this.updateTimeMs = updateTimeMs; this.updateTimeMs = updateTimeMs;
this.streamKeys = streamKeys;
this.customMetadata = customMetadata;
} }
} }

View File

@ -42,23 +42,14 @@ public final class RequirementsWatcher {
* Requirements} are met. * Requirements} are met.
*/ */
public interface Listener { public interface Listener {
/** /**
* Called when all of the requirements are met. * Called when there is a change on the met requirements.
*
* @param requirementsWatcher Calling instance.
*/
void requirementsMet(RequirementsWatcher requirementsWatcher);
/**
* Called when there is at least one not met requirement and there is a change on which of the
* requirements are not met.
* *
* @param requirementsWatcher Calling instance. * @param requirementsWatcher Calling instance.
* @param notMetRequirements {@link Requirements.RequirementFlags RequirementFlags} that are not * @param notMetRequirements {@link Requirements.RequirementFlags RequirementFlags} that are not
* met, or 0. * met, or 0.
*/ */
void requirementsNotMet( void onRequirementsStateChanged(
RequirementsWatcher requirementsWatcher, RequirementsWatcher requirementsWatcher,
@Requirements.RequirementFlags int notMetRequirements); @Requirements.RequirementFlags int notMetRequirements);
} }
@ -172,17 +163,10 @@ public final class RequirementsWatcher {
private void checkRequirements() { private void checkRequirements() {
@Requirements.RequirementFlags @Requirements.RequirementFlags
int notMetRequirements = requirements.getNotMetRequirements(context); int notMetRequirements = requirements.getNotMetRequirements(context);
if (this.notMetRequirements == notMetRequirements) { if (this.notMetRequirements != notMetRequirements) {
logd("notMetRequirements hasn't changed: " + notMetRequirements);
return;
}
this.notMetRequirements = notMetRequirements; this.notMetRequirements = notMetRequirements;
if (notMetRequirements == 0) { logd("notMetRequirements has changed: " + notMetRequirements);
logd("start job"); listener.onRequirementsStateChanged(this, notMetRequirements);
listener.requirementsMet(this);
} else {
logd("stop job");
listener.requirementsNotMet(this, notMetRequirements);
} }
} }

View File

@ -80,13 +80,14 @@ public class DefaultDownloadIndexTest {
.setDownloadedBytes(200) .setDownloadedBytes(200)
.setTotalBytes(400) .setTotalBytes(400)
.setFailureReason(DownloadState.FAILURE_REASON_UNKNOWN) .setFailureReason(DownloadState.FAILURE_REASON_UNKNOWN)
.setStopFlags(DownloadState.STOP_FLAG_STOPPED) .setStopFlags(DownloadState.STOP_FLAG_REQUIREMENTS_NOT_MET)
.setNotMetRequirements(0x87654321)
.setStartTimeMs(10) .setStartTimeMs(10)
.setUpdateTimeMs(20) .setUpdateTimeMs(20)
.setStreamKeys( .setStreamKeys(
new StreamKey(/* periodIndex= */ 0, /* groupIndex= */ 1, /* trackIndex= */ 2), new StreamKey(/* periodIndex= */ 0, /* groupIndex= */ 1, /* trackIndex= */ 2),
new StreamKey(/* periodIndex= */ 3, /* groupIndex= */ 4, /* trackIndex= */ 5)) new StreamKey(/* periodIndex= */ 3, /* groupIndex= */ 4, /* trackIndex= */ 5))
.setCustomMetadata(new byte[] {0, 1, 2, 3}) .setCustomMetadata(new byte[] {0, 1, 2, 3, 7, 8, 9, 10})
.build(); .build();
downloadIndex.putDownloadState(downloadState); downloadIndex.putDownloadState(downloadState);
DownloadState readDownloadState = downloadIndex.getDownloadState(id); DownloadState readDownloadState = downloadIndex.getDownloadState(id);
@ -238,6 +239,9 @@ public class DefaultDownloadIndexTest {
if (downloadState.stopFlags != that.stopFlags) { if (downloadState.stopFlags != that.stopFlags) {
return false; return false;
} }
if (downloadState.notMetRequirements != that.notMetRequirements) {
return false;
}
if (!downloadState.id.equals(that.id)) { if (!downloadState.id.equals(that.id)) {
return false; return false;
} }
@ -269,6 +273,7 @@ public class DefaultDownloadIndexTest {
private long totalBytes; private long totalBytes;
private int failureReason; private int failureReason;
private int stopFlags; private int stopFlags;
private int notMetRequirements;
private long startTimeMs; private long startTimeMs;
private long updateTimeMs; private long updateTimeMs;
private StreamKey[] streamKeys; private StreamKey[] streamKeys;
@ -341,6 +346,11 @@ public class DefaultDownloadIndexTest {
return this; return this;
} }
public DownloadStateBuilder setNotMetRequirements(int notMetRequirements) {
this.notMetRequirements = notMetRequirements;
return this;
}
public DownloadStateBuilder setStartTimeMs(long startTimeMs) { public DownloadStateBuilder setStartTimeMs(long startTimeMs) {
this.startTimeMs = startTimeMs; this.startTimeMs = startTimeMs;
return this; return this;
@ -373,6 +383,7 @@ public class DefaultDownloadIndexTest {
totalBytes, totalBytes,
failureReason, failureReason,
stopFlags, stopFlags,
notMetRequirements,
startTimeMs, startTimeMs,
updateTimeMs, updateTimeMs,
streamKeys, streamKeys,