Merge "Dump most recent constraint changes per job." into sc-dev
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package com.android.server.job.controllers;
|
||||
|
||||
import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
|
||||
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
@@ -59,6 +60,8 @@ public final class BackgroundJobsController extends StateController {
|
||||
|
||||
private final AppStateTrackerImpl mAppStateTracker;
|
||||
|
||||
private final UpdateJobFunctor mUpdateJobFunctor = new UpdateJobFunctor();
|
||||
|
||||
public BackgroundJobsController(JobSchedulerService service) {
|
||||
super(service);
|
||||
|
||||
@@ -69,7 +72,7 @@ public final class BackgroundJobsController extends StateController {
|
||||
|
||||
@Override
|
||||
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
|
||||
updateSingleJobRestrictionLocked(jobStatus, UNKNOWN);
|
||||
updateSingleJobRestrictionLocked(jobStatus, sElapsedRealtimeClock.millis(), UNKNOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -79,7 +82,7 @@ public final class BackgroundJobsController extends StateController {
|
||||
|
||||
@Override
|
||||
public void evaluateStateLocked(JobStatus jobStatus) {
|
||||
updateSingleJobRestrictionLocked(jobStatus, UNKNOWN);
|
||||
updateSingleJobRestrictionLocked(jobStatus, sElapsedRealtimeClock.millis(), UNKNOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -163,33 +166,34 @@ public final class BackgroundJobsController extends StateController {
|
||||
}
|
||||
|
||||
private void updateJobRestrictionsLocked(int filterUid, int newActiveState) {
|
||||
final UpdateJobFunctor updateTrackedJobs = new UpdateJobFunctor(newActiveState);
|
||||
mUpdateJobFunctor.prepare(newActiveState);
|
||||
|
||||
final long start = DEBUG ? SystemClock.elapsedRealtimeNanos() : 0;
|
||||
|
||||
final JobStore store = mService.getJobStore();
|
||||
if (filterUid > 0) {
|
||||
store.forEachJobForSourceUid(filterUid, updateTrackedJobs);
|
||||
store.forEachJobForSourceUid(filterUid, mUpdateJobFunctor);
|
||||
} else {
|
||||
store.forEachJob(updateTrackedJobs);
|
||||
store.forEachJob(mUpdateJobFunctor);
|
||||
}
|
||||
|
||||
final long time = DEBUG ? (SystemClock.elapsedRealtimeNanos() - start) : 0;
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, String.format(
|
||||
"Job status updated: %d/%d checked/total jobs, %d us",
|
||||
updateTrackedJobs.mCheckedCount,
|
||||
updateTrackedJobs.mTotalCount,
|
||||
mUpdateJobFunctor.mCheckedCount,
|
||||
mUpdateJobFunctor.mTotalCount,
|
||||
(time / 1000)
|
||||
));
|
||||
));
|
||||
}
|
||||
|
||||
if (updateTrackedJobs.mChanged) {
|
||||
if (mUpdateJobFunctor.mChanged) {
|
||||
mStateChangedListener.onControllerStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
boolean updateSingleJobRestrictionLocked(JobStatus jobStatus, int activeState) {
|
||||
boolean updateSingleJobRestrictionLocked(JobStatus jobStatus, final long nowElapsed,
|
||||
int activeState) {
|
||||
final int uid = jobStatus.getSourceUid();
|
||||
final String packageName = jobStatus.getSourcePackageName();
|
||||
|
||||
@@ -205,26 +209,32 @@ public final class BackgroundJobsController extends StateController {
|
||||
if (isActive && jobStatus.getStandbyBucket() == NEVER_INDEX) {
|
||||
jobStatus.maybeLogBucketMismatch();
|
||||
}
|
||||
boolean didChange = jobStatus.setBackgroundNotRestrictedConstraintSatisfied(canRun);
|
||||
boolean didChange =
|
||||
jobStatus.setBackgroundNotRestrictedConstraintSatisfied(nowElapsed, canRun);
|
||||
didChange |= jobStatus.setUidActive(isActive);
|
||||
return didChange;
|
||||
}
|
||||
|
||||
private final class UpdateJobFunctor implements Consumer<JobStatus> {
|
||||
final int activeState;
|
||||
int mActiveState;
|
||||
boolean mChanged = false;
|
||||
int mTotalCount = 0;
|
||||
int mCheckedCount = 0;
|
||||
long mUpdateTimeElapsed = 0;
|
||||
|
||||
public UpdateJobFunctor(int newActiveState) {
|
||||
activeState = newActiveState;
|
||||
void prepare(int newActiveState) {
|
||||
mActiveState = newActiveState;
|
||||
mUpdateTimeElapsed = sElapsedRealtimeClock.millis();
|
||||
mChanged = false;
|
||||
mTotalCount = 0;
|
||||
mCheckedCount = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JobStatus jobStatus) {
|
||||
mTotalCount++;
|
||||
mCheckedCount++;
|
||||
if (updateSingleJobRestrictionLocked(jobStatus, activeState)) {
|
||||
if (updateSingleJobRestrictionLocked(jobStatus, mUpdateTimeElapsed, mActiveState)) {
|
||||
mChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,10 +65,12 @@ public final class BatteryController extends RestrictingController {
|
||||
@Override
|
||||
public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
|
||||
if (taskStatus.hasPowerConstraint()) {
|
||||
final long nowElapsed = sElapsedRealtimeClock.millis();
|
||||
mTrackedTasks.add(taskStatus);
|
||||
taskStatus.setTrackingController(JobStatus.TRACKING_BATTERY);
|
||||
taskStatus.setChargingConstraintSatisfied(mChargeTracker.isOnStablePower());
|
||||
taskStatus.setBatteryNotLowConstraintSatisfied(mChargeTracker.isBatteryNotLow());
|
||||
taskStatus.setChargingConstraintSatisfied(nowElapsed, mChargeTracker.isOnStablePower());
|
||||
taskStatus.setBatteryNotLowConstraintSatisfied(
|
||||
nowElapsed, mChargeTracker.isBatteryNotLow());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,14 +99,15 @@ public final class BatteryController extends RestrictingController {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "maybeReportNewChargingStateLocked: " + stablePower);
|
||||
}
|
||||
final long nowElapsed = sElapsedRealtimeClock.millis();
|
||||
boolean reportChange = false;
|
||||
for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
|
||||
final JobStatus ts = mTrackedTasks.valueAt(i);
|
||||
boolean previous = ts.setChargingConstraintSatisfied(stablePower);
|
||||
boolean previous = ts.setChargingConstraintSatisfied(nowElapsed, stablePower);
|
||||
if (previous != stablePower) {
|
||||
reportChange = true;
|
||||
}
|
||||
previous = ts.setBatteryNotLowConstraintSatisfied(batteryNotLow);
|
||||
previous = ts.setBatteryNotLowConstraintSatisfied(nowElapsed, batteryNotLow);
|
||||
if (previous != batteryNotLow) {
|
||||
reportChange = true;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
|
||||
|
||||
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
|
||||
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.job.JobInfo;
|
||||
@@ -461,11 +462,12 @@ public final class ConnectivityController extends RestrictingController implemen
|
||||
final Network network = mConnManager.getActiveNetworkForUid(
|
||||
jobStatus.getSourceUid(), jobStatus.shouldIgnoreNetworkBlocking());
|
||||
final NetworkCapabilities capabilities = getNetworkCapabilities(network);
|
||||
return updateConstraintsSatisfied(jobStatus, network, capabilities);
|
||||
return updateConstraintsSatisfied(jobStatus, sElapsedRealtimeClock.millis(),
|
||||
network, capabilities);
|
||||
}
|
||||
|
||||
private boolean updateConstraintsSatisfied(JobStatus jobStatus, Network network,
|
||||
NetworkCapabilities capabilities) {
|
||||
private boolean updateConstraintsSatisfied(JobStatus jobStatus, final long nowElapsed,
|
||||
Network network, NetworkCapabilities capabilities) {
|
||||
// TODO: consider matching against non-active networks
|
||||
|
||||
final boolean ignoreBlocked = jobStatus.shouldIgnoreNetworkBlocking();
|
||||
@@ -476,7 +478,7 @@ public final class ConnectivityController extends RestrictingController implemen
|
||||
final boolean satisfied = isSatisfied(jobStatus, network, capabilities, mConstants);
|
||||
|
||||
final boolean changed = jobStatus
|
||||
.setConnectivityConstraintSatisfied(connected && satisfied);
|
||||
.setConnectivityConstraintSatisfied(nowElapsed, connected && satisfied);
|
||||
|
||||
// Pass along the evaluated network for job to use; prevents race
|
||||
// conditions as default routes change over time, and opens the door to
|
||||
@@ -530,6 +532,7 @@ public final class ConnectivityController extends RestrictingController implemen
|
||||
NetworkCapabilities exemptedNetworkCapabilities = null;
|
||||
boolean exemptedNetworkMatch = false;
|
||||
|
||||
final long nowElapsed = sElapsedRealtimeClock.millis();
|
||||
boolean changed = false;
|
||||
for (int i = jobs.size() - 1; i >= 0; i--) {
|
||||
final JobStatus js = jobs.valueAt(i);
|
||||
@@ -555,7 +558,7 @@ public final class ConnectivityController extends RestrictingController implemen
|
||||
// job hasn't yet been evaluated against the currently
|
||||
// active network; typically when we just lost a network.
|
||||
if (match || !Objects.equals(js.network, net)) {
|
||||
changed |= updateConstraintsSatisfied(js, net, netCap);
|
||||
changed |= updateConstraintsSatisfied(js, nowElapsed, net, netCap);
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.job.controllers;
|
||||
|
||||
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
|
||||
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.job.JobInfo;
|
||||
import android.database.ContentObserver;
|
||||
@@ -74,6 +76,7 @@ public final class ContentObserverController extends StateController {
|
||||
@Override
|
||||
public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
|
||||
if (taskStatus.hasContentTriggerConstraint()) {
|
||||
final long nowElapsed = sElapsedRealtimeClock.millis();
|
||||
if (taskStatus.contentObserverJobInstance == null) {
|
||||
taskStatus.contentObserverJobInstance = new JobInstance(taskStatus);
|
||||
}
|
||||
@@ -110,7 +113,7 @@ public final class ContentObserverController extends StateController {
|
||||
}
|
||||
taskStatus.changedAuthorities = null;
|
||||
taskStatus.changedUris = null;
|
||||
taskStatus.setContentTriggerConstraintSatisfied(havePendingUris);
|
||||
taskStatus.setContentTriggerConstraintSatisfied(nowElapsed, havePendingUris);
|
||||
}
|
||||
if (lastJob != null && lastJob.contentObserverJobInstance != null) {
|
||||
// And now we can detach the instance state from the last job.
|
||||
@@ -295,7 +298,8 @@ public final class ContentObserverController extends StateController {
|
||||
boolean reportChange = false;
|
||||
synchronized (mLock) {
|
||||
if (mTriggerPending) {
|
||||
if (mJobStatus.setContentTriggerConstraintSatisfied(true)) {
|
||||
final long nowElapsed = sElapsedRealtimeClock.millis();
|
||||
if (mJobStatus.setContentTriggerConstraintSatisfied(nowElapsed, true)) {
|
||||
reportChange = true;
|
||||
}
|
||||
unscheduleLocked();
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.job.controllers;
|
||||
|
||||
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
|
||||
|
||||
import android.app.job.JobInfo;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@@ -104,8 +106,10 @@ public final class DeviceIdleJobsController extends StateController {
|
||||
+ Arrays.toString(mPowerSaveTempWhitelistAppIds));
|
||||
}
|
||||
boolean changed = false;
|
||||
final long nowElapsed = sElapsedRealtimeClock.millis();
|
||||
for (int i = 0; i < mAllowInIdleJobs.size(); i++) {
|
||||
changed |= updateTaskStateLocked(mAllowInIdleJobs.valueAt(i));
|
||||
changed |=
|
||||
updateTaskStateLocked(mAllowInIdleJobs.valueAt(i), nowElapsed);
|
||||
}
|
||||
if (changed) {
|
||||
mStateChangedListener.onControllerStateChanged();
|
||||
@@ -147,6 +151,7 @@ public final class DeviceIdleJobsController extends StateController {
|
||||
}
|
||||
mDeviceIdleMode = enabled;
|
||||
if (DEBUG) Slog.d(TAG, "mDeviceIdleMode=" + mDeviceIdleMode);
|
||||
mDeviceIdleUpdateFunctor.prepare();
|
||||
if (enabled) {
|
||||
mHandler.removeMessages(PROCESS_BACKGROUND_JOBS);
|
||||
mService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor);
|
||||
@@ -180,7 +185,7 @@ public final class DeviceIdleJobsController extends StateController {
|
||||
Slog.d(TAG, "uid " + uid + " going " + (active ? "active" : "inactive"));
|
||||
}
|
||||
mForegroundUids.put(uid, active);
|
||||
mDeviceIdleUpdateFunctor.mChanged = false;
|
||||
mDeviceIdleUpdateFunctor.prepare();
|
||||
mService.getJobStore().forEachJobForSourceUid(uid, mDeviceIdleUpdateFunctor);
|
||||
if (mDeviceIdleUpdateFunctor.mChanged) {
|
||||
mStateChangedListener.onControllerStateChanged();
|
||||
@@ -203,12 +208,12 @@ public final class DeviceIdleJobsController extends StateController {
|
||||
UserHandle.getAppId(job.getSourceUid()));
|
||||
}
|
||||
|
||||
private boolean updateTaskStateLocked(JobStatus task) {
|
||||
private boolean updateTaskStateLocked(JobStatus task, final long nowElapsed) {
|
||||
final boolean allowInIdle = ((task.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0)
|
||||
&& (mForegroundUids.get(task.getSourceUid()) || isTempWhitelistedLocked(task));
|
||||
final boolean whitelisted = isWhitelistedLocked(task);
|
||||
final boolean enableTask = !mDeviceIdleMode || whitelisted || allowInIdle;
|
||||
return task.setDeviceNotDozingConstraintSatisfied(enableTask, whitelisted);
|
||||
return task.setDeviceNotDozingConstraintSatisfied(nowElapsed, enableTask, whitelisted);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -216,7 +221,7 @@ public final class DeviceIdleJobsController extends StateController {
|
||||
if ((jobStatus.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0) {
|
||||
mAllowInIdleJobs.add(jobStatus);
|
||||
}
|
||||
updateTaskStateLocked(jobStatus);
|
||||
updateTaskStateLocked(jobStatus, sElapsedRealtimeClock.millis());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -282,10 +287,16 @@ public final class DeviceIdleJobsController extends StateController {
|
||||
|
||||
final class DeviceIdleUpdateFunctor implements Consumer<JobStatus> {
|
||||
boolean mChanged;
|
||||
long mUpdateTimeElapsed = 0;
|
||||
|
||||
void prepare() {
|
||||
mChanged = false;
|
||||
mUpdateTimeElapsed = sElapsedRealtimeClock.millis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JobStatus jobStatus) {
|
||||
mChanged |= updateTaskStateLocked(jobStatus);
|
||||
mChanged |= updateTaskStateLocked(jobStatus, mUpdateTimeElapsed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,7 +311,7 @@ public final class DeviceIdleJobsController extends StateController {
|
||||
case PROCESS_BACKGROUND_JOBS:
|
||||
// Just process all the jobs, the ones in foreground should already be running.
|
||||
synchronized (mLock) {
|
||||
mDeviceIdleUpdateFunctor.mChanged = false;
|
||||
mDeviceIdleUpdateFunctor.prepare();
|
||||
mService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor);
|
||||
if (mDeviceIdleUpdateFunctor.mChanged) {
|
||||
mStateChangedListener.onControllerStateChanged();
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.job.controllers;
|
||||
|
||||
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.UserHandle;
|
||||
@@ -58,9 +60,10 @@ public final class IdleController extends RestrictingController implements Idlen
|
||||
@Override
|
||||
public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
|
||||
if (taskStatus.hasIdleConstraint()) {
|
||||
final long nowElapsed = sElapsedRealtimeClock.millis();
|
||||
mTrackedTasks.add(taskStatus);
|
||||
taskStatus.setTrackingController(JobStatus.TRACKING_IDLE);
|
||||
taskStatus.setIdleConstraintSatisfied(mIdleTracker.isIdle());
|
||||
taskStatus.setIdleConstraintSatisfied(nowElapsed, mIdleTracker.isIdle());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,8 +93,9 @@ public final class IdleController extends RestrictingController implements Idlen
|
||||
@Override
|
||||
public void reportNewIdleState(boolean isIdle) {
|
||||
synchronized (mLock) {
|
||||
final long nowElapsed = sElapsedRealtimeClock.millis();
|
||||
for (int i = mTrackedTasks.size()-1; i >= 0; i--) {
|
||||
mTrackedTasks.valueAt(i).setIdleConstraintSatisfied(isIdle);
|
||||
mTrackedTasks.valueAt(i).setIdleConstraintSatisfied(nowElapsed, isIdle);
|
||||
}
|
||||
}
|
||||
mStateChangedListener.onControllerStateChanged();
|
||||
|
||||
@@ -73,6 +73,8 @@ public final class JobStatus {
|
||||
private static final String TAG = "JobScheduler.JobStatus";
|
||||
static final boolean DEBUG = JobSchedulerService.DEBUG;
|
||||
|
||||
private static final int NUM_CONSTRAINT_CHANGE_HISTORY = 10;
|
||||
|
||||
public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
|
||||
public static final long NO_EARLIEST_RUNTIME = 0L;
|
||||
|
||||
@@ -350,6 +352,10 @@ public final class JobStatus {
|
||||
*/
|
||||
private Pair<Long, Long> mPersistedUtcTimes;
|
||||
|
||||
private int mConstraintChangeHistoryIndex = 0;
|
||||
private final long[] mConstraintUpdatedTimesElapsed = new long[NUM_CONSTRAINT_CHANGE_HISTORY];
|
||||
private final int[] mConstraintStatusHistory = new int[NUM_CONSTRAINT_CHANGE_HISTORY];
|
||||
|
||||
/**
|
||||
* For use only by ContentObserverController: state it is maintaining about content URIs
|
||||
* being observed.
|
||||
@@ -1090,28 +1096,28 @@ public final class JobStatus {
|
||||
}
|
||||
|
||||
/** @return true if the constraint was changed, false otherwise. */
|
||||
boolean setChargingConstraintSatisfied(boolean state) {
|
||||
return setConstraintSatisfied(CONSTRAINT_CHARGING, state);
|
||||
boolean setChargingConstraintSatisfied(final long nowElapsed, boolean state) {
|
||||
return setConstraintSatisfied(CONSTRAINT_CHARGING, nowElapsed, state);
|
||||
}
|
||||
|
||||
/** @return true if the constraint was changed, false otherwise. */
|
||||
boolean setBatteryNotLowConstraintSatisfied(boolean state) {
|
||||
return setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, state);
|
||||
boolean setBatteryNotLowConstraintSatisfied(final long nowElapsed, boolean state) {
|
||||
return setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, nowElapsed, state);
|
||||
}
|
||||
|
||||
/** @return true if the constraint was changed, false otherwise. */
|
||||
boolean setStorageNotLowConstraintSatisfied(boolean state) {
|
||||
return setConstraintSatisfied(CONSTRAINT_STORAGE_NOT_LOW, state);
|
||||
boolean setStorageNotLowConstraintSatisfied(final long nowElapsed, boolean state) {
|
||||
return setConstraintSatisfied(CONSTRAINT_STORAGE_NOT_LOW, nowElapsed, state);
|
||||
}
|
||||
|
||||
/** @return true if the constraint was changed, false otherwise. */
|
||||
boolean setTimingDelayConstraintSatisfied(boolean state) {
|
||||
return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, state);
|
||||
boolean setTimingDelayConstraintSatisfied(final long nowElapsed, boolean state) {
|
||||
return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, nowElapsed, state);
|
||||
}
|
||||
|
||||
/** @return true if the constraint was changed, false otherwise. */
|
||||
boolean setDeadlineConstraintSatisfied(boolean state) {
|
||||
if (setConstraintSatisfied(CONSTRAINT_DEADLINE, state)) {
|
||||
boolean setDeadlineConstraintSatisfied(final long nowElapsed, boolean state) {
|
||||
if (setConstraintSatisfied(CONSTRAINT_DEADLINE, nowElapsed, state)) {
|
||||
// The constraint was changed. Update the ready flag.
|
||||
mReadyDeadlineSatisfied = !job.isPeriodic() && hasDeadlineConstraint() && state;
|
||||
return true;
|
||||
@@ -1120,24 +1126,25 @@ public final class JobStatus {
|
||||
}
|
||||
|
||||
/** @return true if the constraint was changed, false otherwise. */
|
||||
boolean setIdleConstraintSatisfied(boolean state) {
|
||||
return setConstraintSatisfied(CONSTRAINT_IDLE, state);
|
||||
boolean setIdleConstraintSatisfied(final long nowElapsed, boolean state) {
|
||||
return setConstraintSatisfied(CONSTRAINT_IDLE, nowElapsed, state);
|
||||
}
|
||||
|
||||
/** @return true if the constraint was changed, false otherwise. */
|
||||
boolean setConnectivityConstraintSatisfied(boolean state) {
|
||||
return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, state);
|
||||
boolean setConnectivityConstraintSatisfied(final long nowElapsed, boolean state) {
|
||||
return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, nowElapsed, state);
|
||||
}
|
||||
|
||||
/** @return true if the constraint was changed, false otherwise. */
|
||||
boolean setContentTriggerConstraintSatisfied(boolean state) {
|
||||
return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, state);
|
||||
boolean setContentTriggerConstraintSatisfied(final long nowElapsed, boolean state) {
|
||||
return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, nowElapsed, state);
|
||||
}
|
||||
|
||||
/** @return true if the constraint was changed, false otherwise. */
|
||||
boolean setDeviceNotDozingConstraintSatisfied(boolean state, boolean whitelisted) {
|
||||
boolean setDeviceNotDozingConstraintSatisfied(final long nowElapsed,
|
||||
boolean state, boolean whitelisted) {
|
||||
dozeWhitelisted = whitelisted;
|
||||
if (setConstraintSatisfied(CONSTRAINT_DEVICE_NOT_DOZING, state)) {
|
||||
if (setConstraintSatisfied(CONSTRAINT_DEVICE_NOT_DOZING, nowElapsed, state)) {
|
||||
// The constraint was changed. Update the ready flag.
|
||||
mReadyNotDozing = state || canRunInDoze();
|
||||
return true;
|
||||
@@ -1146,8 +1153,8 @@ public final class JobStatus {
|
||||
}
|
||||
|
||||
/** @return true if the constraint was changed, false otherwise. */
|
||||
boolean setBackgroundNotRestrictedConstraintSatisfied(boolean state) {
|
||||
if (setConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED, state)) {
|
||||
boolean setBackgroundNotRestrictedConstraintSatisfied(final long nowElapsed, boolean state) {
|
||||
if (setConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED, nowElapsed, state)) {
|
||||
// The constraint was changed. Update the ready flag.
|
||||
mReadyNotRestrictedInBg = state;
|
||||
return true;
|
||||
@@ -1156,8 +1163,8 @@ public final class JobStatus {
|
||||
}
|
||||
|
||||
/** @return true if the constraint was changed, false otherwise. */
|
||||
boolean setQuotaConstraintSatisfied(boolean state) {
|
||||
if (setConstraintSatisfied(CONSTRAINT_WITHIN_QUOTA, state)) {
|
||||
boolean setQuotaConstraintSatisfied(final long nowElapsed, boolean state) {
|
||||
if (setConstraintSatisfied(CONSTRAINT_WITHIN_QUOTA, nowElapsed, state)) {
|
||||
// The constraint was changed. Update the ready flag.
|
||||
mReadyWithinQuota = state;
|
||||
return true;
|
||||
@@ -1166,8 +1173,8 @@ public final class JobStatus {
|
||||
}
|
||||
|
||||
/** @return true if the constraint was changed, false otherwise. */
|
||||
boolean setExpeditedJobQuotaConstraintSatisfied(boolean state) {
|
||||
if (setConstraintSatisfied(CONSTRAINT_WITHIN_EXPEDITED_QUOTA, state)) {
|
||||
boolean setExpeditedJobQuotaConstraintSatisfied(final long nowElapsed, boolean state) {
|
||||
if (setConstraintSatisfied(CONSTRAINT_WITHIN_EXPEDITED_QUOTA, nowElapsed, state)) {
|
||||
// The constraint was changed. Update the ready flag.
|
||||
mReadyWithinExpeditedQuota = state;
|
||||
// DeviceIdleJobsController currently only tracks jobs with the WILL_BE_FOREGROUND flag.
|
||||
@@ -1190,7 +1197,7 @@ public final class JobStatus {
|
||||
}
|
||||
|
||||
/** @return true if the constraint was changed, false otherwise. */
|
||||
boolean setConstraintSatisfied(int constraint, boolean state) {
|
||||
boolean setConstraintSatisfied(int constraint, final long nowElapsed, boolean state) {
|
||||
boolean old = (satisfiedConstraints&constraint) != 0;
|
||||
if (old == state) {
|
||||
return false;
|
||||
@@ -1212,6 +1219,12 @@ public final class JobStatus {
|
||||
: FrameworkStatsLog
|
||||
.SCHEDULED_JOB_CONSTRAINT_CHANGED__STATE__UNSATISFIED);
|
||||
}
|
||||
|
||||
mConstraintUpdatedTimesElapsed[mConstraintChangeHistoryIndex] = nowElapsed;
|
||||
mConstraintStatusHistory[mConstraintChangeHistoryIndex] = satisfiedConstraints;
|
||||
mConstraintChangeHistoryIndex =
|
||||
(mConstraintChangeHistoryIndex + 1) % NUM_CONSTRAINT_CHANGE_HISTORY;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1700,7 +1713,7 @@ public final class JobStatus {
|
||||
}
|
||||
|
||||
// Dumpsys infrastructure
|
||||
public void dump(IndentingPrintWriter pw, boolean full, long elapsedRealtimeMillis) {
|
||||
public void dump(IndentingPrintWriter pw, boolean full, long nowElapsed) {
|
||||
UserHandle.formatUid(pw, callingUid);
|
||||
pw.print(" tag="); pw.println(tag);
|
||||
|
||||
@@ -1830,6 +1843,22 @@ public final class JobStatus {
|
||||
dumpConstraints(pw,
|
||||
((requiredConstraints | CONSTRAINT_WITHIN_QUOTA) & ~satisfiedConstraints));
|
||||
pw.println();
|
||||
|
||||
pw.println("Constraint history:");
|
||||
pw.increaseIndent();
|
||||
for (int h = 0; h < NUM_CONSTRAINT_CHANGE_HISTORY; ++h) {
|
||||
final int idx = (h + mConstraintChangeHistoryIndex) % NUM_CONSTRAINT_CHANGE_HISTORY;
|
||||
if (mConstraintUpdatedTimesElapsed[idx] == 0) {
|
||||
continue;
|
||||
}
|
||||
TimeUtils.formatDuration(mConstraintUpdatedTimesElapsed[idx], nowElapsed, pw);
|
||||
// dumpConstraints prepends with a space, so no need to add a space after the =
|
||||
pw.print(" =");
|
||||
dumpConstraints(pw, mConstraintStatusHistory[idx]);
|
||||
pw.println();
|
||||
}
|
||||
pw.decreaseIndent();
|
||||
|
||||
if (dozeWhitelisted) {
|
||||
pw.println("Doze whitelisted: true");
|
||||
}
|
||||
@@ -1910,26 +1939,25 @@ public final class JobStatus {
|
||||
pw.increaseIndent();
|
||||
if (whenStandbyDeferred != 0) {
|
||||
pw.print("Deferred since: ");
|
||||
TimeUtils.formatDuration(whenStandbyDeferred, elapsedRealtimeMillis, pw);
|
||||
TimeUtils.formatDuration(whenStandbyDeferred, nowElapsed, pw);
|
||||
pw.println();
|
||||
}
|
||||
if (mFirstForceBatchedTimeElapsed != 0) {
|
||||
pw.print("Time since first force batch attempt: ");
|
||||
TimeUtils.formatDuration(mFirstForceBatchedTimeElapsed, elapsedRealtimeMillis, pw);
|
||||
TimeUtils.formatDuration(mFirstForceBatchedTimeElapsed, nowElapsed, pw);
|
||||
pw.println();
|
||||
}
|
||||
pw.decreaseIndent();
|
||||
|
||||
pw.print("Enqueue time: ");
|
||||
TimeUtils.formatDuration(enqueueTime, elapsedRealtimeMillis, pw);
|
||||
TimeUtils.formatDuration(enqueueTime, nowElapsed, pw);
|
||||
pw.println();
|
||||
pw.print("Run time: earliest=");
|
||||
formatRunTime(pw, earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME, elapsedRealtimeMillis);
|
||||
formatRunTime(pw, earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME, nowElapsed);
|
||||
pw.print(", latest=");
|
||||
formatRunTime(pw, latestRunTimeElapsedMillis, NO_LATEST_RUNTIME, elapsedRealtimeMillis);
|
||||
formatRunTime(pw, latestRunTimeElapsedMillis, NO_LATEST_RUNTIME, nowElapsed);
|
||||
pw.print(", original latest=");
|
||||
formatRunTime(pw, mOriginalLatestRunTimeElapsedMillis,
|
||||
NO_LATEST_RUNTIME, elapsedRealtimeMillis);
|
||||
formatRunTime(pw, mOriginalLatestRunTimeElapsedMillis, NO_LATEST_RUNTIME, nowElapsed);
|
||||
pw.println();
|
||||
if (numFailures != 0) {
|
||||
pw.print("Num failures: "); pw.println(numFailures);
|
||||
|
||||
@@ -626,6 +626,7 @@ public final class QuotaController extends StateController {
|
||||
|
||||
@Override
|
||||
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
|
||||
final long nowElapsed = sElapsedRealtimeClock.millis();
|
||||
final int userId = jobStatus.getSourceUserId();
|
||||
final String pkgName = jobStatus.getSourcePackageName();
|
||||
ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, pkgName);
|
||||
@@ -636,11 +637,11 @@ public final class QuotaController extends StateController {
|
||||
jobs.add(jobStatus);
|
||||
jobStatus.setTrackingController(JobStatus.TRACKING_QUOTA);
|
||||
final boolean isWithinQuota = isWithinQuotaLocked(jobStatus);
|
||||
setConstraintSatisfied(jobStatus, isWithinQuota);
|
||||
setConstraintSatisfied(jobStatus, nowElapsed, isWithinQuota);
|
||||
final boolean outOfEJQuota;
|
||||
if (jobStatus.isRequestedExpeditedJob()) {
|
||||
final boolean isWithinEJQuota = isWithinEJQuotaLocked(jobStatus);
|
||||
setExpeditedConstraintSatisfied(jobStatus, isWithinEJQuota);
|
||||
setExpeditedConstraintSatisfied(jobStatus, nowElapsed, isWithinEJQuota);
|
||||
outOfEJQuota = !isWithinEJQuota;
|
||||
} else {
|
||||
outOfEJQuota = false;
|
||||
@@ -1397,7 +1398,8 @@ public final class QuotaController extends StateController {
|
||||
synchronized (mLock) {
|
||||
final ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
|
||||
quota.transactOnDebitsLocked(-credit);
|
||||
if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
|
||||
if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
|
||||
userId, packageName)) {
|
||||
mStateChangedListener.onControllerStateChanged();
|
||||
}
|
||||
}
|
||||
@@ -1499,11 +1501,12 @@ public final class QuotaController extends StateController {
|
||||
|
||||
private void maybeUpdateAllConstraintsLocked() {
|
||||
boolean changed = false;
|
||||
final long nowElapsed = sElapsedRealtimeClock.millis();
|
||||
for (int u = 0; u < mTrackedJobs.numMaps(); ++u) {
|
||||
final int userId = mTrackedJobs.keyAt(u);
|
||||
for (int p = 0; p < mTrackedJobs.numElementsForKey(userId); ++p) {
|
||||
final String packageName = mTrackedJobs.keyAt(u, p);
|
||||
changed |= maybeUpdateConstraintForPkgLocked(userId, packageName);
|
||||
changed |= maybeUpdateConstraintForPkgLocked(nowElapsed, userId, packageName);
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
@@ -1516,7 +1519,7 @@ public final class QuotaController extends StateController {
|
||||
*
|
||||
* @return true if at least one job had its bit changed
|
||||
*/
|
||||
private boolean maybeUpdateConstraintForPkgLocked(final int userId,
|
||||
private boolean maybeUpdateConstraintForPkgLocked(final long nowElapsed, final int userId,
|
||||
@NonNull final String packageName) {
|
||||
ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, packageName);
|
||||
if (jobs == null || jobs.size() == 0) {
|
||||
@@ -1533,21 +1536,21 @@ public final class QuotaController extends StateController {
|
||||
if (isTopStartedJobLocked(js)) {
|
||||
// Job was started while the app was in the TOP state so we should allow it to
|
||||
// finish.
|
||||
changed |= js.setQuotaConstraintSatisfied(true);
|
||||
changed |= js.setQuotaConstraintSatisfied(nowElapsed, true);
|
||||
} else if (realStandbyBucket != ACTIVE_INDEX
|
||||
&& realStandbyBucket == js.getEffectiveStandbyBucket()) {
|
||||
// An app in the ACTIVE bucket may be out of quota while the job could be in quota
|
||||
// for some reason. Therefore, avoid setting the real value here and check each job
|
||||
// individually.
|
||||
changed |= setConstraintSatisfied(js, realInQuota);
|
||||
changed |= setConstraintSatisfied(js, nowElapsed, realInQuota);
|
||||
} else {
|
||||
// This job is somehow exempted. Need to determine its own quota status.
|
||||
changed |= setConstraintSatisfied(js, isWithinQuotaLocked(js));
|
||||
changed |= setConstraintSatisfied(js, nowElapsed, isWithinQuotaLocked(js));
|
||||
}
|
||||
|
||||
if (js.isRequestedExpeditedJob()) {
|
||||
boolean isWithinEJQuota = isWithinEJQuotaLocked(js);
|
||||
changed |= setExpeditedConstraintSatisfied(js, isWithinEJQuota);
|
||||
changed |= setExpeditedConstraintSatisfied(js, nowElapsed, isWithinEJQuota);
|
||||
outOfEJQuota |= !isWithinEJQuota;
|
||||
}
|
||||
}
|
||||
@@ -1566,14 +1569,21 @@ public final class QuotaController extends StateController {
|
||||
private final SparseArrayMap<String, Integer> mToScheduleStartAlarms =
|
||||
new SparseArrayMap<>();
|
||||
public boolean wasJobChanged;
|
||||
long mUpdateTimeElapsed = 0;
|
||||
|
||||
void prepare() {
|
||||
mUpdateTimeElapsed = sElapsedRealtimeClock.millis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JobStatus jobStatus) {
|
||||
wasJobChanged |= setConstraintSatisfied(jobStatus, isWithinQuotaLocked(jobStatus));
|
||||
wasJobChanged |= setConstraintSatisfied(
|
||||
jobStatus, mUpdateTimeElapsed, isWithinQuotaLocked(jobStatus));
|
||||
final boolean outOfEJQuota;
|
||||
if (jobStatus.isRequestedExpeditedJob()) {
|
||||
final boolean isWithinEJQuota = isWithinEJQuotaLocked(jobStatus);
|
||||
wasJobChanged |= setExpeditedConstraintSatisfied(jobStatus, isWithinEJQuota);
|
||||
wasJobChanged |= setExpeditedConstraintSatisfied(
|
||||
jobStatus, mUpdateTimeElapsed, isWithinEJQuota);
|
||||
outOfEJQuota = !isWithinEJQuota;
|
||||
} else {
|
||||
outOfEJQuota = false;
|
||||
@@ -1611,6 +1621,7 @@ public final class QuotaController extends StateController {
|
||||
private final UidConstraintUpdater mUpdateUidConstraints = new UidConstraintUpdater();
|
||||
|
||||
private boolean maybeUpdateConstraintForUidLocked(final int uid) {
|
||||
mUpdateUidConstraints.prepare();
|
||||
mService.getJobStore().forEachJobForSourceUid(uid, mUpdateUidConstraints);
|
||||
|
||||
mUpdateUidConstraints.postProcess();
|
||||
@@ -1716,21 +1727,22 @@ public final class QuotaController extends StateController {
|
||||
mInQuotaAlarmListener.addAlarmLocked(userId, packageName, inQuotaTimeElapsed);
|
||||
}
|
||||
|
||||
private boolean setConstraintSatisfied(@NonNull JobStatus jobStatus, boolean isWithinQuota) {
|
||||
private boolean setConstraintSatisfied(@NonNull JobStatus jobStatus, long nowElapsed,
|
||||
boolean isWithinQuota) {
|
||||
if (!isWithinQuota && jobStatus.getWhenStandbyDeferred() == 0) {
|
||||
// Mark that the job is being deferred due to buckets.
|
||||
jobStatus.setWhenStandbyDeferred(sElapsedRealtimeClock.millis());
|
||||
jobStatus.setWhenStandbyDeferred(nowElapsed);
|
||||
}
|
||||
return jobStatus.setQuotaConstraintSatisfied(isWithinQuota);
|
||||
return jobStatus.setQuotaConstraintSatisfied(nowElapsed, isWithinQuota);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the satisfaction changes, this will tell connectivity & background jobs controller to
|
||||
* also re-evaluate their state.
|
||||
*/
|
||||
private boolean setExpeditedConstraintSatisfied(@NonNull JobStatus jobStatus,
|
||||
private boolean setExpeditedConstraintSatisfied(@NonNull JobStatus jobStatus, long nowElapsed,
|
||||
boolean isWithinQuota) {
|
||||
if (jobStatus.setExpeditedJobQuotaConstraintSatisfied(isWithinQuota)) {
|
||||
if (jobStatus.setExpeditedJobQuotaConstraintSatisfied(nowElapsed, isWithinQuota)) {
|
||||
mBackgroundJobsController.evaluateStateLocked(jobStatus);
|
||||
mConnectivityController.evaluateStateLocked(jobStatus);
|
||||
if (isWithinQuota && jobStatus.isReady()) {
|
||||
@@ -2188,7 +2200,8 @@ public final class QuotaController extends StateController {
|
||||
final ShrinkableDebits quota =
|
||||
getEJQuotaLocked(mPkg.userId, mPkg.packageName);
|
||||
quota.transactOnDebitsLocked(-mEJRewardTopAppMs * numTimeChunks);
|
||||
if (maybeUpdateConstraintForPkgLocked(mPkg.userId, mPkg.packageName)) {
|
||||
if (maybeUpdateConstraintForPkgLocked(nowElapsed,
|
||||
mPkg.userId, mPkg.packageName)) {
|
||||
mStateChangedListener.onControllerStateChanged();
|
||||
}
|
||||
}
|
||||
@@ -2292,7 +2305,8 @@ public final class QuotaController extends StateController {
|
||||
if (timer != null && timer.isActive()) {
|
||||
timer.rescheduleCutoff();
|
||||
}
|
||||
if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
|
||||
if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
|
||||
userId, packageName)) {
|
||||
mStateChangedListener.onControllerStateChanged();
|
||||
}
|
||||
}
|
||||
@@ -2417,7 +2431,8 @@ public final class QuotaController extends StateController {
|
||||
if (timeRemainingMs <= 50) {
|
||||
// Less than 50 milliseconds left. Start process of shutting down jobs.
|
||||
if (DEBUG) Slog.d(TAG, pkg + " has reached its quota.");
|
||||
if (maybeUpdateConstraintForPkgLocked(pkg.userId, pkg.packageName)) {
|
||||
if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
|
||||
pkg.userId, pkg.packageName)) {
|
||||
mStateChangedListener.onControllerStateChanged();
|
||||
}
|
||||
} else {
|
||||
@@ -2444,7 +2459,8 @@ public final class QuotaController extends StateController {
|
||||
pkg.userId, pkg.packageName);
|
||||
if (timeRemainingMs <= 0) {
|
||||
if (DEBUG) Slog.d(TAG, pkg + " has reached its EJ quota.");
|
||||
if (maybeUpdateConstraintForPkgLocked(pkg.userId, pkg.packageName)) {
|
||||
if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
|
||||
pkg.userId, pkg.packageName)) {
|
||||
mStateChangedListener.onControllerStateChanged();
|
||||
}
|
||||
} else {
|
||||
@@ -2475,7 +2491,8 @@ public final class QuotaController extends StateController {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Checking pkg " + string(userId, packageName));
|
||||
}
|
||||
if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
|
||||
if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
|
||||
userId, packageName)) {
|
||||
mStateChangedListener.onControllerStateChanged();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -61,9 +61,11 @@ public final class StorageController extends StateController {
|
||||
@Override
|
||||
public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
|
||||
if (taskStatus.hasStorageNotLowConstraint()) {
|
||||
final long nowElapsed = sElapsedRealtimeClock.millis();
|
||||
mTrackedTasks.add(taskStatus);
|
||||
taskStatus.setTrackingController(JobStatus.TRACKING_STORAGE);
|
||||
taskStatus.setStorageNotLowConstraintSatisfied(mStorageTracker.isStorageNotLow());
|
||||
taskStatus.setStorageNotLowConstraintSatisfied(
|
||||
nowElapsed, mStorageTracker.isStorageNotLow());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,12 +78,13 @@ public final class StorageController extends StateController {
|
||||
}
|
||||
|
||||
private void maybeReportNewStorageState() {
|
||||
final long nowElapsed = sElapsedRealtimeClock.millis();
|
||||
final boolean storageNotLow = mStorageTracker.isStorageNotLow();
|
||||
boolean reportChange = false;
|
||||
synchronized (mLock) {
|
||||
for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
|
||||
final JobStatus ts = mTrackedTasks.valueAt(i);
|
||||
reportChange |= ts.setStorageNotLowConstraintSatisfied(storageNotLow);
|
||||
reportChange |= ts.setStorageNotLowConstraintSatisfied(nowElapsed, storageNotLow);
|
||||
}
|
||||
}
|
||||
if (storageNotLow) {
|
||||
|
||||
@@ -258,9 +258,9 @@ public final class TimeController extends StateController {
|
||||
|
||||
if (jobDeadline <= nowElapsedMillis) {
|
||||
if (job.hasTimingDelayConstraint()) {
|
||||
job.setTimingDelayConstraintSatisfied(true);
|
||||
job.setTimingDelayConstraintSatisfied(nowElapsedMillis, true);
|
||||
}
|
||||
job.setDeadlineConstraintSatisfied(true);
|
||||
job.setDeadlineConstraintSatisfied(nowElapsedMillis, true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -332,7 +332,7 @@ public final class TimeController extends StateController {
|
||||
private boolean evaluateTimingDelayConstraint(JobStatus job, long nowElapsedMillis) {
|
||||
final long jobDelayTime = job.getEarliestRunTime();
|
||||
if (jobDelayTime <= nowElapsedMillis) {
|
||||
job.setTimingDelayConstraintSatisfied(true);
|
||||
job.setTimingDelayConstraintSatisfied(nowElapsedMillis, true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -25,6 +25,7 @@ import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
|
||||
import static com.android.server.job.JobSchedulerService.RARE_INDEX;
|
||||
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
|
||||
import static com.android.server.job.JobSchedulerService.WORKING_INDEX;
|
||||
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
|
||||
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BACKGROUND_NOT_RESTRICTED;
|
||||
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BATTERY_NOT_LOW;
|
||||
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CHARGING;
|
||||
@@ -101,7 +102,7 @@ public class JobStatusTest {
|
||||
Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
|
||||
JobSchedulerService.sUptimeMillisClock =
|
||||
Clock.fixed(SystemClock.uptimeClock().instant(), ZoneOffset.UTC);
|
||||
JobSchedulerService.sElapsedRealtimeClock =
|
||||
sElapsedRealtimeClock =
|
||||
Clock.fixed(SystemClock.elapsedRealtimeClock().instant(), ZoneOffset.UTC);
|
||||
}
|
||||
|
||||
@@ -204,7 +205,7 @@ public class JobStatusTest {
|
||||
|
||||
@Test
|
||||
public void testFraction() throws Exception {
|
||||
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
|
||||
final long now = sElapsedRealtimeClock.millis();
|
||||
|
||||
assertEquals(1, createJobStatus(0, Long.MAX_VALUE).getFractionRunTime(), DELTA);
|
||||
|
||||
@@ -261,15 +262,15 @@ public class JobStatusTest {
|
||||
final JobStatus job = createJobStatus(jobInfo);
|
||||
|
||||
markImplicitConstraintsSatisfied(job, true);
|
||||
job.setChargingConstraintSatisfied(false);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
job.setChargingConstraintSatisfied(true);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
|
||||
markImplicitConstraintsSatisfied(job, false);
|
||||
job.setChargingConstraintSatisfied(false);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
job.setChargingConstraintSatisfied(true);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
}
|
||||
|
||||
@@ -282,15 +283,15 @@ public class JobStatusTest {
|
||||
final JobStatus job = createJobStatus(jobInfo);
|
||||
|
||||
markImplicitConstraintsSatisfied(job, true);
|
||||
job.setIdleConstraintSatisfied(false);
|
||||
job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
|
||||
job.setIdleConstraintSatisfied(true);
|
||||
job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
|
||||
|
||||
markImplicitConstraintsSatisfied(job, false);
|
||||
job.setIdleConstraintSatisfied(false);
|
||||
job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
|
||||
job.setIdleConstraintSatisfied(true);
|
||||
job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
|
||||
}
|
||||
|
||||
@@ -303,15 +304,15 @@ public class JobStatusTest {
|
||||
final JobStatus job = createJobStatus(jobInfo);
|
||||
|
||||
markImplicitConstraintsSatisfied(job, true);
|
||||
job.setBatteryNotLowConstraintSatisfied(false);
|
||||
job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
|
||||
job.setBatteryNotLowConstraintSatisfied(true);
|
||||
job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
|
||||
|
||||
markImplicitConstraintsSatisfied(job, false);
|
||||
job.setBatteryNotLowConstraintSatisfied(false);
|
||||
job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
|
||||
job.setBatteryNotLowConstraintSatisfied(true);
|
||||
job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
|
||||
}
|
||||
|
||||
@@ -324,15 +325,15 @@ public class JobStatusTest {
|
||||
final JobStatus job = createJobStatus(jobInfo);
|
||||
|
||||
markImplicitConstraintsSatisfied(job, true);
|
||||
job.setStorageNotLowConstraintSatisfied(false);
|
||||
job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
|
||||
job.setStorageNotLowConstraintSatisfied(true);
|
||||
job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
|
||||
|
||||
markImplicitConstraintsSatisfied(job, false);
|
||||
job.setStorageNotLowConstraintSatisfied(false);
|
||||
job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
|
||||
job.setStorageNotLowConstraintSatisfied(true);
|
||||
job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
|
||||
}
|
||||
|
||||
@@ -345,15 +346,15 @@ public class JobStatusTest {
|
||||
final JobStatus job = createJobStatus(jobInfo);
|
||||
|
||||
markImplicitConstraintsSatisfied(job, true);
|
||||
job.setTimingDelayConstraintSatisfied(false);
|
||||
job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
|
||||
job.setTimingDelayConstraintSatisfied(true);
|
||||
job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
|
||||
|
||||
markImplicitConstraintsSatisfied(job, false);
|
||||
job.setTimingDelayConstraintSatisfied(false);
|
||||
job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
|
||||
job.setTimingDelayConstraintSatisfied(true);
|
||||
job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
|
||||
}
|
||||
|
||||
@@ -366,15 +367,15 @@ public class JobStatusTest {
|
||||
final JobStatus job = createJobStatus(jobInfo);
|
||||
|
||||
markImplicitConstraintsSatisfied(job, true);
|
||||
job.setDeadlineConstraintSatisfied(false);
|
||||
job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
|
||||
job.setDeadlineConstraintSatisfied(true);
|
||||
job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
|
||||
|
||||
markImplicitConstraintsSatisfied(job, false);
|
||||
job.setDeadlineConstraintSatisfied(false);
|
||||
job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
|
||||
job.setDeadlineConstraintSatisfied(true);
|
||||
job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
|
||||
}
|
||||
|
||||
@@ -387,15 +388,15 @@ public class JobStatusTest {
|
||||
final JobStatus job = createJobStatus(jobInfo);
|
||||
|
||||
markImplicitConstraintsSatisfied(job, true);
|
||||
job.setConnectivityConstraintSatisfied(false);
|
||||
job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
|
||||
job.setConnectivityConstraintSatisfied(true);
|
||||
job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
|
||||
|
||||
markImplicitConstraintsSatisfied(job, false);
|
||||
job.setConnectivityConstraintSatisfied(false);
|
||||
job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
|
||||
job.setConnectivityConstraintSatisfied(true);
|
||||
job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
|
||||
}
|
||||
|
||||
@@ -410,15 +411,15 @@ public class JobStatusTest {
|
||||
final JobStatus job = createJobStatus(jobInfo);
|
||||
|
||||
markImplicitConstraintsSatisfied(job, true);
|
||||
job.setContentTriggerConstraintSatisfied(false);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
job.setContentTriggerConstraintSatisfied(true);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
|
||||
markImplicitConstraintsSatisfied(job, false);
|
||||
job.setContentTriggerConstraintSatisfied(false);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
job.setContentTriggerConstraintSatisfied(true);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
}
|
||||
|
||||
@@ -436,15 +437,15 @@ public class JobStatusTest {
|
||||
|
||||
markImplicitConstraintsSatisfied(job, false);
|
||||
|
||||
job.setChargingConstraintSatisfied(false);
|
||||
job.setConnectivityConstraintSatisfied(false);
|
||||
job.setContentTriggerConstraintSatisfied(false);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
job.setChargingConstraintSatisfied(true);
|
||||
job.setConnectivityConstraintSatisfied(true);
|
||||
job.setContentTriggerConstraintSatisfied(true);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
// Still false because implicit constraints aren't satisfied.
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
|
||||
@@ -452,61 +453,61 @@ public class JobStatusTest {
|
||||
|
||||
markImplicitConstraintsSatisfied(job, true);
|
||||
|
||||
job.setChargingConstraintSatisfied(false);
|
||||
job.setConnectivityConstraintSatisfied(false);
|
||||
job.setContentTriggerConstraintSatisfied(false);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
|
||||
// Turn on constraints one at a time.
|
||||
job.setChargingConstraintSatisfied(true);
|
||||
job.setConnectivityConstraintSatisfied(false);
|
||||
job.setContentTriggerConstraintSatisfied(false);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
|
||||
job.setChargingConstraintSatisfied(false);
|
||||
job.setConnectivityConstraintSatisfied(false);
|
||||
job.setContentTriggerConstraintSatisfied(true);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
|
||||
job.setChargingConstraintSatisfied(false);
|
||||
job.setConnectivityConstraintSatisfied(true);
|
||||
job.setContentTriggerConstraintSatisfied(false);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
|
||||
// With two of the 3 constraints satisfied (and implicit constraints also satisfied), only
|
||||
// the unsatisfied constraint should return true.
|
||||
job.setChargingConstraintSatisfied(true);
|
||||
job.setConnectivityConstraintSatisfied(false);
|
||||
job.setContentTriggerConstraintSatisfied(true);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
|
||||
job.setChargingConstraintSatisfied(true);
|
||||
job.setConnectivityConstraintSatisfied(true);
|
||||
job.setContentTriggerConstraintSatisfied(false);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
|
||||
job.setChargingConstraintSatisfied(false);
|
||||
job.setConnectivityConstraintSatisfied(true);
|
||||
job.setContentTriggerConstraintSatisfied(true);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
|
||||
job.setChargingConstraintSatisfied(true);
|
||||
job.setConnectivityConstraintSatisfied(true);
|
||||
job.setContentTriggerConstraintSatisfied(true);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
@@ -526,15 +527,15 @@ public class JobStatusTest {
|
||||
|
||||
markImplicitConstraintsSatisfied(job, false);
|
||||
|
||||
job.setChargingConstraintSatisfied(false);
|
||||
job.setContentTriggerConstraintSatisfied(false);
|
||||
job.setDeadlineConstraintSatisfied(false);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
|
||||
job.setChargingConstraintSatisfied(true);
|
||||
job.setContentTriggerConstraintSatisfied(true);
|
||||
job.setDeadlineConstraintSatisfied(true);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
// Still false because implicit constraints aren't satisfied.
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
@@ -542,18 +543,18 @@ public class JobStatusTest {
|
||||
|
||||
markImplicitConstraintsSatisfied(job, true);
|
||||
|
||||
job.setChargingConstraintSatisfied(false);
|
||||
job.setContentTriggerConstraintSatisfied(false);
|
||||
job.setDeadlineConstraintSatisfied(false);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
// Once implicit constraint are satisfied, deadline constraint should always return true.
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
|
||||
|
||||
// Turn on constraints one at a time.
|
||||
job.setChargingConstraintSatisfied(true);
|
||||
job.setContentTriggerConstraintSatisfied(false);
|
||||
job.setDeadlineConstraintSatisfied(false);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
// Deadline should force isReady to be true, but isn't needed for the job to be
|
||||
// considered ready.
|
||||
@@ -561,17 +562,17 @@ public class JobStatusTest {
|
||||
// Once implicit constraint are satisfied, deadline constraint should always return true.
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
|
||||
|
||||
job.setChargingConstraintSatisfied(false);
|
||||
job.setContentTriggerConstraintSatisfied(true);
|
||||
job.setDeadlineConstraintSatisfied(false);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
// Once implicit constraint are satisfied, deadline constraint should always return true.
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
|
||||
|
||||
job.setChargingConstraintSatisfied(false);
|
||||
job.setContentTriggerConstraintSatisfied(false);
|
||||
job.setDeadlineConstraintSatisfied(true);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
// Since the deadline constraint is satisfied, none of the other explicit constraints are
|
||||
// needed.
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
@@ -581,33 +582,33 @@ public class JobStatusTest {
|
||||
|
||||
// With two of the 3 constraints satisfied (and implicit constraints also satisfied), only
|
||||
// the unsatisfied constraint should return true.
|
||||
job.setChargingConstraintSatisfied(true);
|
||||
job.setContentTriggerConstraintSatisfied(true);
|
||||
job.setDeadlineConstraintSatisfied(false);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
// Once implicit constraint are satisfied, deadline constraint should always return true.
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
|
||||
|
||||
job.setChargingConstraintSatisfied(true);
|
||||
job.setContentTriggerConstraintSatisfied(false);
|
||||
job.setDeadlineConstraintSatisfied(true);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
// Once implicit constraint are satisfied, deadline constraint should always return true.
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
|
||||
|
||||
job.setChargingConstraintSatisfied(false);
|
||||
job.setContentTriggerConstraintSatisfied(true);
|
||||
job.setDeadlineConstraintSatisfied(true);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
// Once implicit constraint are satisfied, deadline constraint should always return true.
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
|
||||
|
||||
job.setChargingConstraintSatisfied(true);
|
||||
job.setContentTriggerConstraintSatisfied(true);
|
||||
job.setDeadlineConstraintSatisfied(true);
|
||||
job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
|
||||
// Once implicit constraint are satisfied, deadline constraint should always return true.
|
||||
@@ -621,15 +622,15 @@ public class JobStatusTest {
|
||||
new JobInfo.Builder(101, new ComponentName("foo", "bar")).build());
|
||||
|
||||
markImplicitConstraintsSatisfied(job, false);
|
||||
job.setDeviceNotDozingConstraintSatisfied(false, false);
|
||||
job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), false, false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
|
||||
job.setDeviceNotDozingConstraintSatisfied(true, false);
|
||||
job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), true, false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
|
||||
|
||||
markImplicitConstraintsSatisfied(job, true);
|
||||
job.setDeviceNotDozingConstraintSatisfied(false, false);
|
||||
job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), false, false);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
|
||||
job.setDeviceNotDozingConstraintSatisfied(true, false);
|
||||
job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), true, false);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
|
||||
}
|
||||
|
||||
@@ -640,15 +641,15 @@ public class JobStatusTest {
|
||||
new JobInfo.Builder(101, new ComponentName("foo", "bar")).build());
|
||||
|
||||
markImplicitConstraintsSatisfied(job, false);
|
||||
job.setQuotaConstraintSatisfied(false);
|
||||
job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
|
||||
job.setQuotaConstraintSatisfied(true);
|
||||
job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
|
||||
|
||||
markImplicitConstraintsSatisfied(job, true);
|
||||
job.setQuotaConstraintSatisfied(false);
|
||||
job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
|
||||
job.setQuotaConstraintSatisfied(true);
|
||||
job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
|
||||
}
|
||||
|
||||
@@ -659,22 +660,24 @@ public class JobStatusTest {
|
||||
new JobInfo.Builder(101, new ComponentName("foo", "bar")).build());
|
||||
|
||||
markImplicitConstraintsSatisfied(job, false);
|
||||
job.setBackgroundNotRestrictedConstraintSatisfied(false);
|
||||
job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
|
||||
job.setBackgroundNotRestrictedConstraintSatisfied(true);
|
||||
job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
|
||||
|
||||
markImplicitConstraintsSatisfied(job, true);
|
||||
job.setBackgroundNotRestrictedConstraintSatisfied(false);
|
||||
job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
|
||||
job.setBackgroundNotRestrictedConstraintSatisfied(true);
|
||||
job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
|
||||
}
|
||||
|
||||
private void markImplicitConstraintsSatisfied(JobStatus job, boolean isSatisfied) {
|
||||
job.setQuotaConstraintSatisfied(isSatisfied);
|
||||
job.setDeviceNotDozingConstraintSatisfied(isSatisfied, false);
|
||||
job.setBackgroundNotRestrictedConstraintSatisfied(isSatisfied);
|
||||
job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), isSatisfied);
|
||||
job.setDeviceNotDozingConstraintSatisfied(
|
||||
sElapsedRealtimeClock.millis(), isSatisfied, false);
|
||||
job.setBackgroundNotRestrictedConstraintSatisfied(
|
||||
sElapsedRealtimeClock.millis(), isSatisfied);
|
||||
}
|
||||
|
||||
private static JobStatus createJobStatus(long earliestRunTimeElapsedMillis,
|
||||
|
||||
@@ -359,8 +359,9 @@ public class QuotaControllerTest {
|
||||
// Make sure tests aren't passing just because the default bucket is likely ACTIVE.
|
||||
js.setStandbyBucket(FREQUENT_INDEX);
|
||||
// Make sure Doze and background-not-restricted don't affect tests.
|
||||
js.setDeviceNotDozingConstraintSatisfied(/* state */ true, /* allowlisted */false);
|
||||
js.setBackgroundNotRestrictedConstraintSatisfied(true);
|
||||
js.setDeviceNotDozingConstraintSatisfied(/* nowElapsed */ sElapsedRealtimeClock.millis(),
|
||||
/* state */ true, /* allowlisted */false);
|
||||
js.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
|
||||
return js;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user