mirror of
https://github.com/samsonjs/media.git
synced 2026-03-27 09:45:47 +00:00
Simplify offline Requirements
- Remove NETWORK_TYPE_NOT_ROAMING and NETWORK_TYPE_METERED because JobScheduler doesn't support them, and they're probably not useful to many people (data when roaming is normally enabled/disabled at the OS level, and restricting to *only* metered networks seems niche) - Convert network requirements proper flags - Stop persisting requirements in DownloadIndex. The direction we're headed to solve the manager start/stop problem is going to involve state in DownloadManager determining whether downloads actually start, and if we're doing that then it's no worse to do it for this as well PiperOrigin-RevId: 242713196
This commit is contained in:
parent
9e6f9ee9dd
commit
3f565c33be
11 changed files with 111 additions and 251 deletions
|
|
@ -104,18 +104,10 @@ public final class JobDispatcherScheduler implements Scheduler {
|
|||
.setService(JobDispatcherSchedulerService.class) // the JobService that will be called
|
||||
.setTag(tag);
|
||||
|
||||
switch (requirements.getRequiredNetworkType()) {
|
||||
case Requirements.NETWORK_TYPE_NONE:
|
||||
// do nothing.
|
||||
break;
|
||||
case Requirements.NETWORK_TYPE_ANY:
|
||||
builder.addConstraint(Constraint.ON_ANY_NETWORK);
|
||||
break;
|
||||
case Requirements.NETWORK_TYPE_UNMETERED:
|
||||
builder.addConstraint(Constraint.ON_UNMETERED_NETWORK);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
if (requirements.isUnmeteredNetworkRequired()) {
|
||||
builder.addConstraint(Constraint.ON_UNMETERED_NETWORK);
|
||||
} else if (requirements.isNetworkRequired()) {
|
||||
builder.addConstraint(Constraint.ON_ANY_NETWORK);
|
||||
}
|
||||
|
||||
if (requirements.isIdleRequired()) {
|
||||
|
|
|
|||
|
|
@ -57,15 +57,20 @@ public final class DefaultDownloadIndex implements DownloadIndex {
|
|||
private static final String COLUMN_DOWNLOADED_BYTES = "downloaded_bytes";
|
||||
private static final String COLUMN_TOTAL_BYTES = "total_bytes";
|
||||
private static final String COLUMN_FAILURE_REASON = "failure_reason";
|
||||
private static final String COLUMN_NOT_MET_REQUIREMENTS = "not_met_requirements";
|
||||
private static final String COLUMN_MANUAL_STOP_REASON = "manual_stop_reason";
|
||||
private static final String COLUMN_START_TIME_MS = "start_time_ms";
|
||||
private static final String COLUMN_UPDATE_TIME_MS = "update_time_ms";
|
||||
|
||||
/** @deprecated No longer used. */
|
||||
@SuppressWarnings("DeprecatedIsStillUsed")
|
||||
@Deprecated
|
||||
private static final String COLUMN_STOP_FLAGS = "stop_flags";
|
||||
|
||||
/** @deprecated No longer used. */
|
||||
@SuppressWarnings("DeprecatedIsStillUsed")
|
||||
@Deprecated
|
||||
private static final String COLUMN_NOT_MET_REQUIREMENTS = "not_met_requirements";
|
||||
|
||||
private static final int COLUMN_INDEX_ID = 0;
|
||||
private static final int COLUMN_INDEX_TYPE = 1;
|
||||
private static final int COLUMN_INDEX_URI = 2;
|
||||
|
|
@ -77,10 +82,9 @@ public final class DefaultDownloadIndex implements DownloadIndex {
|
|||
private static final int COLUMN_INDEX_DOWNLOADED_BYTES = 8;
|
||||
private static final int COLUMN_INDEX_TOTAL_BYTES = 9;
|
||||
private static final int COLUMN_INDEX_FAILURE_REASON = 10;
|
||||
private static final int COLUMN_INDEX_NOT_MET_REQUIREMENTS = 11;
|
||||
private static final int COLUMN_INDEX_MANUAL_STOP_REASON = 12;
|
||||
private static final int COLUMN_INDEX_START_TIME_MS = 13;
|
||||
private static final int COLUMN_INDEX_UPDATE_TIME_MS = 14;
|
||||
private static final int COLUMN_INDEX_MANUAL_STOP_REASON = 11;
|
||||
private static final int COLUMN_INDEX_START_TIME_MS = 12;
|
||||
private static final int COLUMN_INDEX_UPDATE_TIME_MS = 13;
|
||||
|
||||
private static final String WHERE_ID_EQUALS = COLUMN_ID + " = ?";
|
||||
private static final String WHERE_STATE_TERMINAL =
|
||||
|
|
@ -99,7 +103,6 @@ public final class DefaultDownloadIndex implements DownloadIndex {
|
|||
COLUMN_DOWNLOADED_BYTES,
|
||||
COLUMN_TOTAL_BYTES,
|
||||
COLUMN_FAILURE_REASON,
|
||||
COLUMN_NOT_MET_REQUIREMENTS,
|
||||
COLUMN_MANUAL_STOP_REASON,
|
||||
COLUMN_START_TIME_MS,
|
||||
COLUMN_UPDATE_TIME_MS
|
||||
|
|
@ -204,7 +207,7 @@ public final class DefaultDownloadIndex implements DownloadIndex {
|
|||
values.put(COLUMN_TOTAL_BYTES, downloadState.getTotalBytes());
|
||||
values.put(COLUMN_FAILURE_REASON, downloadState.failureReason);
|
||||
values.put(COLUMN_STOP_FLAGS, 0);
|
||||
values.put(COLUMN_NOT_MET_REQUIREMENTS, downloadState.notMetRequirements);
|
||||
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);
|
||||
|
|
@ -356,7 +359,6 @@ public final class DefaultDownloadIndex implements DownloadIndex {
|
|||
action,
|
||||
cursor.getInt(COLUMN_INDEX_STATE),
|
||||
cursor.getInt(COLUMN_INDEX_FAILURE_REASON),
|
||||
cursor.getInt(COLUMN_INDEX_NOT_MET_REQUIREMENTS),
|
||||
cursor.getInt(COLUMN_INDEX_MANUAL_STOP_REASON),
|
||||
cursor.getLong(COLUMN_INDEX_START_TIME_MS),
|
||||
cursor.getLong(COLUMN_INDEX_UPDATE_TIME_MS),
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ public final class DownloadIndexUtil {
|
|||
throws IOException {
|
||||
DownloadState downloadState = downloadIndex.getDownloadState(action.id);
|
||||
if (downloadState != null) {
|
||||
downloadState = downloadState.copyWithMergedAction(action);
|
||||
downloadState = downloadState.copyWithMergedAction(action, /* canStart= */ true);
|
||||
} else {
|
||||
downloadState = new DownloadState(action);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,8 +113,7 @@ public final class DownloadManager {
|
|||
/** The default minimum number of times a download must be retried before failing. */
|
||||
public static final int DEFAULT_MIN_RETRY_COUNT = 5;
|
||||
/** The default requirement is that the device has network connectivity. */
|
||||
public static final Requirements DEFAULT_REQUIREMENTS =
|
||||
new Requirements(Requirements.NETWORK_TYPE_ANY, false, false);
|
||||
public static final Requirements DEFAULT_REQUIREMENTS = new Requirements(Requirements.NETWORK);
|
||||
|
||||
// Messages posted to the main handler.
|
||||
private static final int MSG_INITIALIZED = 0;
|
||||
|
|
@ -623,7 +622,8 @@ public final class DownloadManager {
|
|||
downloadState = new DownloadState(action);
|
||||
logd("Download state is created for " + action.id);
|
||||
} else {
|
||||
downloadState = downloadState.copyWithMergedAction(action);
|
||||
downloadState =
|
||||
downloadState.copyWithMergedAction(action, /* canStart= */ notMetRequirements == 0);
|
||||
logd("Download state is loaded for " + action.id);
|
||||
}
|
||||
addDownloadForState(downloadState);
|
||||
|
|
@ -840,7 +840,8 @@ public final class DownloadManager {
|
|||
}
|
||||
|
||||
public void addAction(DownloadAction newAction) {
|
||||
downloadState = downloadState.copyWithMergedAction(newAction);
|
||||
downloadState =
|
||||
downloadState.copyWithMergedAction(newAction, /* canStart= */ notMetRequirements == 0);
|
||||
initialize();
|
||||
}
|
||||
|
||||
|
|
@ -854,7 +855,6 @@ public final class DownloadManager {
|
|||
downloadState.action,
|
||||
state,
|
||||
state != STATE_FAILED ? FAILURE_REASON_NONE : failureReason,
|
||||
notMetRequirements,
|
||||
manualStopReason,
|
||||
downloadState.startTimeMs,
|
||||
/* updateTimeMs= */ System.currentTimeMillis(),
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@ package com.google.android.exoplayer2.offline;
|
|||
|
||||
import androidx.annotation.IntDef;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.scheduler.Requirements;
|
||||
import com.google.android.exoplayer2.scheduler.Requirements.RequirementFlags;
|
||||
import com.google.android.exoplayer2.upstream.cache.CacheUtil.CachingCounters;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import java.lang.annotation.Documented;
|
||||
|
|
@ -124,8 +122,6 @@ public final class DownloadState {
|
|||
* #FAILURE_REASON_NONE}.
|
||||
*/
|
||||
@FailureReason public final int failureReason;
|
||||
/** Not met requirements to download. */
|
||||
@Requirements.RequirementFlags public final int notMetRequirements;
|
||||
/** The manual stop reason. */
|
||||
public final int manualStopReason;
|
||||
|
||||
|
|
@ -145,7 +141,6 @@ public final class DownloadState {
|
|||
action,
|
||||
/* state= */ STATE_QUEUED,
|
||||
FAILURE_REASON_NONE,
|
||||
/* notMetRequirements= */ 0,
|
||||
/* manualStopReason= */ 0,
|
||||
/* startTimeMs= */ currentTimeMs,
|
||||
/* updateTimeMs= */ currentTimeMs,
|
||||
|
|
@ -156,20 +151,18 @@ public final class DownloadState {
|
|||
DownloadAction action,
|
||||
@State int state,
|
||||
@FailureReason int failureReason,
|
||||
@RequirementFlags int notMetRequirements,
|
||||
int manualStopReason,
|
||||
long startTimeMs,
|
||||
long updateTimeMs,
|
||||
CachingCounters counters) {
|
||||
Assertions.checkNotNull(counters);
|
||||
Assertions.checkState((failureReason == FAILURE_REASON_NONE) == (state != STATE_FAILED));
|
||||
if (manualStopReason != 0 || notMetRequirements != 0) {
|
||||
if (manualStopReason != 0) {
|
||||
Assertions.checkState(state != STATE_DOWNLOADING && state != STATE_QUEUED);
|
||||
}
|
||||
this.action = action;
|
||||
this.state = state;
|
||||
this.failureReason = failureReason;
|
||||
this.notMetRequirements = notMetRequirements;
|
||||
this.manualStopReason = manualStopReason;
|
||||
this.startTimeMs = startTimeMs;
|
||||
this.updateTimeMs = updateTimeMs;
|
||||
|
|
@ -181,14 +174,14 @@ public final class DownloadState {
|
|||
* 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}.
|
||||
*/
|
||||
public DownloadState copyWithMergedAction(DownloadAction newAction) {
|
||||
public DownloadState copyWithMergedAction(DownloadAction newAction, boolean canStart) {
|
||||
return new DownloadState(
|
||||
action.copyWithMergedAction(newAction),
|
||||
getNextState(state, manualStopReason != 0 || notMetRequirements != 0),
|
||||
getNextState(state, canStart && manualStopReason == 0),
|
||||
FAILURE_REASON_NONE,
|
||||
notMetRequirements,
|
||||
manualStopReason,
|
||||
startTimeMs,
|
||||
/* updateTimeMs= */ System.currentTimeMillis(),
|
||||
|
|
@ -205,7 +198,6 @@ public final class DownloadState {
|
|||
action,
|
||||
state,
|
||||
FAILURE_REASON_NONE,
|
||||
notMetRequirements,
|
||||
manualStopReason,
|
||||
startTimeMs,
|
||||
/* updateTimeMs= */ System.currentTimeMillis(),
|
||||
|
|
@ -240,13 +232,13 @@ public final class DownloadState {
|
|||
this.counters = counters;
|
||||
}
|
||||
|
||||
private static int getNextState(int currentState, boolean isStopped) {
|
||||
private static int getNextState(int currentState, boolean canStart) {
|
||||
if (currentState == STATE_REMOVING || currentState == STATE_RESTARTING) {
|
||||
return STATE_RESTARTING;
|
||||
} else if (isStopped) {
|
||||
return STATE_STOPPED;
|
||||
} else {
|
||||
} else if (canStart) {
|
||||
return STATE_QUEUED;
|
||||
} else {
|
||||
return STATE_STOPPED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,36 +93,11 @@ public final class PlatformScheduler implements Scheduler {
|
|||
String servicePackage) {
|
||||
JobInfo.Builder builder = new JobInfo.Builder(jobId, jobServiceComponentName);
|
||||
|
||||
int networkType;
|
||||
switch (requirements.getRequiredNetworkType()) {
|
||||
case Requirements.NETWORK_TYPE_NONE:
|
||||
networkType = JobInfo.NETWORK_TYPE_NONE;
|
||||
break;
|
||||
case Requirements.NETWORK_TYPE_ANY:
|
||||
networkType = JobInfo.NETWORK_TYPE_ANY;
|
||||
break;
|
||||
case Requirements.NETWORK_TYPE_UNMETERED:
|
||||
networkType = JobInfo.NETWORK_TYPE_UNMETERED;
|
||||
break;
|
||||
case Requirements.NETWORK_TYPE_NOT_ROAMING:
|
||||
if (Util.SDK_INT >= 24) {
|
||||
networkType = JobInfo.NETWORK_TYPE_NOT_ROAMING;
|
||||
} else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
break;
|
||||
case Requirements.NETWORK_TYPE_METERED:
|
||||
if (Util.SDK_INT >= 26) {
|
||||
networkType = JobInfo.NETWORK_TYPE_METERED;
|
||||
} else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
if (requirements.isUnmeteredNetworkRequired()) {
|
||||
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
|
||||
} else if (requirements.isNetworkRequired()) {
|
||||
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
|
||||
}
|
||||
|
||||
builder.setRequiredNetworkType(networkType);
|
||||
builder.setRequiresDeviceIdle(requirements.isIdleRequired());
|
||||
builder.setRequiresCharging(requirements.isChargingRequired());
|
||||
builder.setPersisted(true);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import android.net.NetworkInfo;
|
|||
import android.os.BatteryManager;
|
||||
import android.os.PowerManager;
|
||||
import androidx.annotation.IntDef;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Log;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.lang.annotation.Documented;
|
||||
|
|
@ -38,112 +37,60 @@ import java.lang.annotation.RetentionPolicy;
|
|||
public final class Requirements {
|
||||
|
||||
/**
|
||||
* Network types. One of {@link #NETWORK_TYPE_NONE}, {@link #NETWORK_TYPE_ANY}, {@link
|
||||
* #NETWORK_TYPE_UNMETERED}, {@link #NETWORK_TYPE_NOT_ROAMING} or {@link #NETWORK_TYPE_METERED}.
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({
|
||||
NETWORK_TYPE_NONE,
|
||||
NETWORK_TYPE_ANY,
|
||||
NETWORK_TYPE_UNMETERED,
|
||||
NETWORK_TYPE_NOT_ROAMING,
|
||||
NETWORK_TYPE_METERED,
|
||||
})
|
||||
public @interface NetworkType {}
|
||||
|
||||
/**
|
||||
* Requirement flags.
|
||||
*
|
||||
* <p>Combination of the following values is possible:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Only one of {@link #NETWORK_TYPE_ANY}, {@link #NETWORK_TYPE_UNMETERED}, {@link
|
||||
* #NETWORK_TYPE_NOT_ROAMING} or {@link #NETWORK_TYPE_METERED}.
|
||||
* <li>{@link #DEVICE_IDLE}
|
||||
* <li>{@link #DEVICE_CHARGING}
|
||||
* <ul>
|
||||
* Requirement flags. Possible flag values are {@link #NETWORK}, {@link #NETWORK_UNMETERED},
|
||||
* {@link #DEVICE_IDLE} and {@link #DEVICE_CHARGING}.
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(
|
||||
flag = true,
|
||||
value = {
|
||||
NETWORK_TYPE_ANY,
|
||||
NETWORK_TYPE_UNMETERED,
|
||||
NETWORK_TYPE_NOT_ROAMING,
|
||||
NETWORK_TYPE_METERED,
|
||||
DEVICE_IDLE,
|
||||
DEVICE_CHARGING
|
||||
})
|
||||
value = {NETWORK, NETWORK_UNMETERED, DEVICE_IDLE, DEVICE_CHARGING})
|
||||
public @interface RequirementFlags {}
|
||||
|
||||
/** This job doesn't require network connectivity. */
|
||||
public static final int NETWORK_TYPE_NONE = 0;
|
||||
/** This job requires network connectivity. */
|
||||
public static final int NETWORK_TYPE_ANY = 1;
|
||||
/** This job requires network connectivity that is unmetered. */
|
||||
public static final int NETWORK_TYPE_UNMETERED = 1 << 1;
|
||||
/** This job requires network connectivity that is not roaming. */
|
||||
public static final int NETWORK_TYPE_NOT_ROAMING = 1 << 2;
|
||||
/** This job requires metered connectivity such as most cellular data networks. */
|
||||
public static final int NETWORK_TYPE_METERED = 1 << 3;
|
||||
/** This job requires the device to be idle. */
|
||||
public static final int DEVICE_IDLE = 1 << 4;
|
||||
/** This job requires the device to be charging. */
|
||||
public static final int DEVICE_CHARGING = 1 << 5;
|
||||
|
||||
private static final int NETWORK_TYPE_MASK = 0b1111;
|
||||
/** Requirement that the device has network connectivity. */
|
||||
public static final int NETWORK = 1;
|
||||
/** Requirement that the device has a network connection that is unmetered. */
|
||||
public static final int NETWORK_UNMETERED = 1 << 1;
|
||||
/** Requirement that the device is idle. */
|
||||
public static final int DEVICE_IDLE = 1 << 2;
|
||||
/** Requirement that the device is charging. */
|
||||
public static final int DEVICE_CHARGING = 1 << 3;
|
||||
|
||||
private static final String TAG = "Requirements";
|
||||
|
||||
private static final String[] NETWORK_TYPE_STRINGS;
|
||||
|
||||
static {
|
||||
if (Scheduler.DEBUG) {
|
||||
NETWORK_TYPE_STRINGS =
|
||||
new String[] {
|
||||
"NETWORK_TYPE_NONE",
|
||||
"NETWORK_TYPE_ANY",
|
||||
"NETWORK_TYPE_UNMETERED",
|
||||
"NETWORK_TYPE_NOT_ROAMING",
|
||||
"NETWORK_TYPE_METERED"
|
||||
};
|
||||
} else {
|
||||
NETWORK_TYPE_STRINGS = null;
|
||||
}
|
||||
}
|
||||
|
||||
@RequirementFlags private final int requirements;
|
||||
|
||||
/**
|
||||
* @param networkType Required network type.
|
||||
* @param charging Whether the device should be charging.
|
||||
* @param idle Whether the device should be idle.
|
||||
*/
|
||||
public Requirements(@NetworkType int networkType, boolean charging, boolean idle) {
|
||||
this(networkType | (charging ? DEVICE_CHARGING : 0) | (idle ? DEVICE_IDLE : 0));
|
||||
}
|
||||
|
||||
/** @param requirements A combination of requirement flags. */
|
||||
public Requirements(@RequirementFlags int requirements) {
|
||||
if ((requirements & NETWORK_UNMETERED) != 0) {
|
||||
// Make sure network requirement flags are consistent.
|
||||
requirements |= NETWORK;
|
||||
}
|
||||
this.requirements = requirements;
|
||||
int networkType = getRequiredNetworkType();
|
||||
// Check if only one network type is specified.
|
||||
Assertions.checkState((networkType & (networkType - 1)) == 0);
|
||||
}
|
||||
|
||||
/** Returns required network type. */
|
||||
public int getRequiredNetworkType() {
|
||||
return requirements & NETWORK_TYPE_MASK;
|
||||
/** Returns the requirements. */
|
||||
@RequirementFlags
|
||||
public int getRequirements() {
|
||||
return requirements;
|
||||
}
|
||||
|
||||
/** Returns whether the device should be charging. */
|
||||
/** Returns whether network connectivity is required. */
|
||||
public boolean isNetworkRequired() {
|
||||
return (requirements & NETWORK) != 0;
|
||||
}
|
||||
|
||||
/** Returns whether un-metered network connectivity is required. */
|
||||
public boolean isUnmeteredNetworkRequired() {
|
||||
return (requirements & NETWORK_UNMETERED) != 0;
|
||||
}
|
||||
|
||||
/** Returns whether the device is required to be charging. */
|
||||
public boolean isChargingRequired() {
|
||||
return (requirements & DEVICE_CHARGING) != 0;
|
||||
}
|
||||
|
||||
/** Returns whether the device should be idle. */
|
||||
/** Returns whether the device is required to be idle. */
|
||||
public boolean isIdleRequired() {
|
||||
return (requirements & DEVICE_IDLE) != 0;
|
||||
}
|
||||
|
|
@ -159,62 +106,47 @@ public final class Requirements {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns {@link RequirementFlags} that are not met, or 0.
|
||||
* Returns requirements that are not met, or 0.
|
||||
*
|
||||
* @param context Any context.
|
||||
* @return RequirementFlags that are not met, or 0.
|
||||
* @return The requirements that are not met, or 0.
|
||||
*/
|
||||
@RequirementFlags
|
||||
public int getNotMetRequirements(Context context) {
|
||||
return (!checkNetworkRequirements(context) ? getRequiredNetworkType() : 0)
|
||||
| (!checkChargingRequirement(context) ? DEVICE_CHARGING : 0)
|
||||
| (!checkIdleRequirement(context) ? DEVICE_IDLE : 0);
|
||||
}
|
||||
|
||||
/** Returns the requirement flags. */
|
||||
@RequirementFlags
|
||||
public int getRequirements() {
|
||||
return requirements;
|
||||
}
|
||||
|
||||
private boolean checkNetworkRequirements(Context context) {
|
||||
int networkRequirement = getRequiredNetworkType();
|
||||
if (networkRequirement == NETWORK_TYPE_NONE) {
|
||||
return true;
|
||||
@RequirementFlags int notMetRequirements = getNotMetNetworkRequirements(context);
|
||||
if (isChargingRequired() && !isDeviceCharging(context)) {
|
||||
notMetRequirements |= DEVICE_CHARGING;
|
||||
}
|
||||
if (isIdleRequired() && !isDeviceIdle(context)) {
|
||||
notMetRequirements |= DEVICE_IDLE;
|
||||
}
|
||||
return notMetRequirements;
|
||||
}
|
||||
|
||||
@RequirementFlags
|
||||
private int getNotMetNetworkRequirements(Context context) {
|
||||
if (!isNetworkRequired()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ConnectivityManager connectivityManager =
|
||||
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
|
||||
if (networkInfo == null || !networkInfo.isConnected()) {
|
||||
logd("No network info or no connection.");
|
||||
return false;
|
||||
if (networkInfo == null
|
||||
|| !networkInfo.isConnected()
|
||||
|| !isInternetConnectivityValidated(connectivityManager)) {
|
||||
logd("No network info, connection or connectivity.");
|
||||
return requirements & (NETWORK | NETWORK_UNMETERED);
|
||||
}
|
||||
if (!checkInternetConnectivity(connectivityManager)) {
|
||||
return false;
|
||||
|
||||
if (isUnmeteredNetworkRequired() && connectivityManager.isActiveNetworkMetered()) {
|
||||
return NETWORK_UNMETERED;
|
||||
}
|
||||
if (networkRequirement == NETWORK_TYPE_ANY) {
|
||||
return true;
|
||||
}
|
||||
if (networkRequirement == NETWORK_TYPE_NOT_ROAMING) {
|
||||
boolean roaming = networkInfo.isRoaming();
|
||||
logd("Roaming: " + roaming);
|
||||
return !roaming;
|
||||
}
|
||||
boolean activeNetworkMetered = connectivityManager.isActiveNetworkMetered();
|
||||
logd("Metered network: " + activeNetworkMetered);
|
||||
if (networkRequirement == NETWORK_TYPE_UNMETERED) {
|
||||
return !activeNetworkMetered;
|
||||
}
|
||||
if (networkRequirement == NETWORK_TYPE_METERED) {
|
||||
return activeNetworkMetered;
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private boolean checkChargingRequirement(Context context) {
|
||||
if (!isChargingRequired()) {
|
||||
return true;
|
||||
}
|
||||
private boolean isDeviceCharging(Context context) {
|
||||
Intent batteryStatus =
|
||||
context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
if (batteryStatus == null) {
|
||||
|
|
@ -225,17 +157,14 @@ public final class Requirements {
|
|||
|| status == BatteryManager.BATTERY_STATUS_FULL;
|
||||
}
|
||||
|
||||
private boolean checkIdleRequirement(Context context) {
|
||||
if (!isIdleRequired()) {
|
||||
return true;
|
||||
}
|
||||
private boolean isDeviceIdle(Context context) {
|
||||
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
return Util.SDK_INT >= 23
|
||||
? powerManager.isDeviceIdleMode()
|
||||
: Util.SDK_INT >= 20 ? !powerManager.isInteractive() : !powerManager.isScreenOn();
|
||||
}
|
||||
|
||||
private static boolean checkInternetConnectivity(ConnectivityManager connectivityManager) {
|
||||
private static boolean isInternetConnectivityValidated(ConnectivityManager connectivityManager) {
|
||||
if (Util.SDK_INT < 23) {
|
||||
// TODO Check internet connectivity using http://clients3.google.com/generate_204 on API
|
||||
// levels prior to 23.
|
||||
|
|
@ -261,18 +190,6 @@ public final class Requirements {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (!Scheduler.DEBUG) {
|
||||
return super.toString();
|
||||
}
|
||||
return "requirements{"
|
||||
+ NETWORK_TYPE_STRINGS[getRequiredNetworkType()]
|
||||
+ (isChargingRequired() ? ",charging" : "")
|
||||
+ (isIdleRequired() ? ",idle" : "")
|
||||
+ '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ public final class RequirementsWatcher {
|
|||
notMetRequirements = requirements.getNotMetRequirements(context);
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
if (requirements.getRequiredNetworkType() != Requirements.NETWORK_TYPE_NONE) {
|
||||
if (requirements.isNetworkRequired()) {
|
||||
if (Util.SDK_INT >= 23) {
|
||||
registerNetworkCallbackV23();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -81,7 +81,6 @@ public class DefaultDownloadIndexTest {
|
|||
.setDownloadedBytes(200)
|
||||
.setTotalBytes(400)
|
||||
.setFailureReason(DownloadState.FAILURE_REASON_UNKNOWN)
|
||||
.setNotMetRequirements(0x87654321)
|
||||
.setManualStopReason(0x12345678)
|
||||
.setStartTimeMs(10)
|
||||
.setUpdateTimeMs(20)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ class DownloadStateBuilder {
|
|||
@Nullable private String cacheKey;
|
||||
private int state;
|
||||
private int failureReason;
|
||||
private int notMetRequirements;
|
||||
private int manualStopReason;
|
||||
private long startTimeMs;
|
||||
private long updateTimeMs;
|
||||
|
|
@ -122,11 +121,6 @@ class DownloadStateBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public DownloadStateBuilder setNotMetRequirements(int notMetRequirements) {
|
||||
this.notMetRequirements = notMetRequirements;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownloadStateBuilder setManualStopReason(int manualStopReason) {
|
||||
this.manualStopReason = manualStopReason;
|
||||
return this;
|
||||
|
|
@ -158,7 +152,6 @@ class DownloadStateBuilder {
|
|||
action,
|
||||
state,
|
||||
failureReason,
|
||||
notMetRequirements,
|
||||
manualStopReason,
|
||||
startTimeMs,
|
||||
updateTimeMs,
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public class DownloadStateTest {
|
|||
.build();
|
||||
|
||||
try {
|
||||
downloadState.copyWithMergedAction(downloadAction);
|
||||
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
|
||||
fail();
|
||||
} catch (Exception e) {
|
||||
// Expected.
|
||||
|
|
@ -64,7 +64,7 @@ public class DownloadStateTest {
|
|||
.build();
|
||||
|
||||
try {
|
||||
downloadState.copyWithMergedAction(downloadAction);
|
||||
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
|
||||
fail();
|
||||
} catch (Exception e) {
|
||||
// Expected.
|
||||
|
|
@ -78,7 +78,7 @@ public class DownloadStateTest {
|
|||
new DownloadStateBuilder(downloadAction).setState(DownloadState.STATE_QUEUED);
|
||||
DownloadState downloadState = downloadStateBuilder.build();
|
||||
|
||||
downloadState.copyWithMergedAction(downloadAction);
|
||||
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -90,7 +90,8 @@ public class DownloadStateTest {
|
|||
.setState(DownloadState.STATE_QUEUED);
|
||||
DownloadState downloadState = downloadStateBuilder.build();
|
||||
|
||||
DownloadState mergedDownloadState = downloadState.copyWithMergedAction(downloadAction);
|
||||
DownloadState mergedDownloadState =
|
||||
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
|
||||
|
||||
DownloadState expectedDownloadState = downloadStateBuilder.setUri(downloadAction.uri).build();
|
||||
assertEqual(mergedDownloadState, expectedDownloadState);
|
||||
|
|
@ -112,7 +113,8 @@ public class DownloadStateTest {
|
|||
.setCustomMetadata(new byte[0]);
|
||||
DownloadState downloadState = downloadStateBuilder.build();
|
||||
|
||||
DownloadState mergedDownloadState = downloadState.copyWithMergedAction(downloadAction);
|
||||
DownloadState mergedDownloadState =
|
||||
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
|
||||
|
||||
DownloadState expectedDownloadState =
|
||||
downloadStateBuilder.setCustomMetadata(downloadAction.data).build();
|
||||
|
|
@ -126,7 +128,8 @@ public class DownloadStateTest {
|
|||
new DownloadStateBuilder(downloadAction).setState(DownloadState.STATE_REMOVING);
|
||||
DownloadState downloadState = downloadStateBuilder.build();
|
||||
|
||||
DownloadState mergedDownloadState = downloadState.copyWithMergedAction(downloadAction);
|
||||
DownloadState mergedDownloadState =
|
||||
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
|
||||
|
||||
DownloadState expectedDownloadState =
|
||||
downloadStateBuilder.setState(DownloadState.STATE_RESTARTING).build();
|
||||
|
|
@ -142,7 +145,8 @@ public class DownloadStateTest {
|
|||
.setFailureReason(DownloadState.FAILURE_REASON_UNKNOWN);
|
||||
DownloadState downloadState = downloadStateBuilder.build();
|
||||
|
||||
DownloadState mergedDownloadState = downloadState.copyWithMergedAction(downloadAction);
|
||||
DownloadState mergedDownloadState =
|
||||
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
|
||||
|
||||
DownloadState expectedDownloadState =
|
||||
downloadStateBuilder
|
||||
|
|
@ -161,7 +165,8 @@ public class DownloadStateTest {
|
|||
.setManualStopReason(DownloadState.MANUAL_STOP_REASON_UNDEFINED);
|
||||
DownloadState downloadState = downloadStateBuilder.build();
|
||||
|
||||
DownloadState mergedDownloadState = downloadState.copyWithMergedAction(downloadAction);
|
||||
DownloadState mergedDownloadState =
|
||||
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
|
||||
|
||||
assertEqual(mergedDownloadState, downloadState);
|
||||
}
|
||||
|
|
@ -175,23 +180,8 @@ public class DownloadStateTest {
|
|||
.setManualStopReason(DownloadState.MANUAL_STOP_REASON_UNDEFINED);
|
||||
DownloadState downloadState = downloadStateBuilder.build();
|
||||
|
||||
DownloadState mergedDownloadState = downloadState.copyWithMergedAction(downloadAction);
|
||||
|
||||
DownloadState expectedDownloadState =
|
||||
downloadStateBuilder.setState(DownloadState.STATE_STOPPED).build();
|
||||
assertEqual(mergedDownloadState, expectedDownloadState);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeAction_notMetRequirementsSetButNotInStoppedState_stateBecomesStopped() {
|
||||
DownloadAction downloadAction = createDownloadAction();
|
||||
DownloadStateBuilder downloadStateBuilder =
|
||||
new DownloadStateBuilder(downloadAction)
|
||||
.setState(DownloadState.STATE_COMPLETED)
|
||||
.setNotMetRequirements(0x12345678);
|
||||
DownloadState downloadState = downloadStateBuilder.build();
|
||||
|
||||
DownloadState mergedDownloadState = downloadState.copyWithMergedAction(downloadAction);
|
||||
DownloadState mergedDownloadState =
|
||||
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
|
||||
|
||||
DownloadState expectedDownloadState =
|
||||
downloadStateBuilder.setState(DownloadState.STATE_STOPPED).build();
|
||||
|
|
@ -259,7 +249,8 @@ public class DownloadStateTest {
|
|||
.setStreamKeys(keys1);
|
||||
DownloadState downloadState = downloadStateBuilder.build();
|
||||
|
||||
DownloadState mergedDownloadState = downloadState.copyWithMergedAction(downloadAction);
|
||||
DownloadState mergedDownloadState =
|
||||
downloadState.copyWithMergedAction(downloadAction, /* canStart= */ true);
|
||||
|
||||
DownloadState expectedDownloadState = downloadStateBuilder.setStreamKeys(expectedKeys).build();
|
||||
assertEqual(mergedDownloadState, expectedDownloadState);
|
||||
|
|
@ -282,7 +273,6 @@ public class DownloadStateTest {
|
|||
}
|
||||
assertThat(downloadState.failureReason).isEqualTo(that.failureReason);
|
||||
assertThat(downloadState.manualStopReason).isEqualTo(that.manualStopReason);
|
||||
assertThat(downloadState.notMetRequirements).isEqualTo(that.notMetRequirements);
|
||||
}
|
||||
|
||||
private DownloadAction createDownloadAction() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue