Merge "Dump most recent constraint changes per job." into sc-dev

This commit is contained in:
Kweku Adams
2021-02-22 15:54:24 +00:00
committed by Android (Google) Code Review
12 changed files with 292 additions and 205 deletions

View File

@@ -17,6 +17,7 @@
package com.android.server.job.controllers; package com.android.server.job.controllers;
import static com.android.server.job.JobSchedulerService.NEVER_INDEX; import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.UserHandle; import android.os.UserHandle;
@@ -59,6 +60,8 @@ public final class BackgroundJobsController extends StateController {
private final AppStateTrackerImpl mAppStateTracker; private final AppStateTrackerImpl mAppStateTracker;
private final UpdateJobFunctor mUpdateJobFunctor = new UpdateJobFunctor();
public BackgroundJobsController(JobSchedulerService service) { public BackgroundJobsController(JobSchedulerService service) {
super(service); super(service);
@@ -69,7 +72,7 @@ public final class BackgroundJobsController extends StateController {
@Override @Override
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) { public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
updateSingleJobRestrictionLocked(jobStatus, UNKNOWN); updateSingleJobRestrictionLocked(jobStatus, sElapsedRealtimeClock.millis(), UNKNOWN);
} }
@Override @Override
@@ -79,7 +82,7 @@ public final class BackgroundJobsController extends StateController {
@Override @Override
public void evaluateStateLocked(JobStatus jobStatus) { public void evaluateStateLocked(JobStatus jobStatus) {
updateSingleJobRestrictionLocked(jobStatus, UNKNOWN); updateSingleJobRestrictionLocked(jobStatus, sElapsedRealtimeClock.millis(), UNKNOWN);
} }
@Override @Override
@@ -163,33 +166,34 @@ public final class BackgroundJobsController extends StateController {
} }
private void updateJobRestrictionsLocked(int filterUid, int newActiveState) { private void updateJobRestrictionsLocked(int filterUid, int newActiveState) {
final UpdateJobFunctor updateTrackedJobs = new UpdateJobFunctor(newActiveState); mUpdateJobFunctor.prepare(newActiveState);
final long start = DEBUG ? SystemClock.elapsedRealtimeNanos() : 0; final long start = DEBUG ? SystemClock.elapsedRealtimeNanos() : 0;
final JobStore store = mService.getJobStore(); final JobStore store = mService.getJobStore();
if (filterUid > 0) { if (filterUid > 0) {
store.forEachJobForSourceUid(filterUid, updateTrackedJobs); store.forEachJobForSourceUid(filterUid, mUpdateJobFunctor);
} else { } else {
store.forEachJob(updateTrackedJobs); store.forEachJob(mUpdateJobFunctor);
} }
final long time = DEBUG ? (SystemClock.elapsedRealtimeNanos() - start) : 0; final long time = DEBUG ? (SystemClock.elapsedRealtimeNanos() - start) : 0;
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, String.format( Slog.d(TAG, String.format(
"Job status updated: %d/%d checked/total jobs, %d us", "Job status updated: %d/%d checked/total jobs, %d us",
updateTrackedJobs.mCheckedCount, mUpdateJobFunctor.mCheckedCount,
updateTrackedJobs.mTotalCount, mUpdateJobFunctor.mTotalCount,
(time / 1000) (time / 1000)
)); ));
} }
if (updateTrackedJobs.mChanged) { if (mUpdateJobFunctor.mChanged) {
mStateChangedListener.onControllerStateChanged(); mStateChangedListener.onControllerStateChanged();
} }
} }
boolean updateSingleJobRestrictionLocked(JobStatus jobStatus, int activeState) { boolean updateSingleJobRestrictionLocked(JobStatus jobStatus, final long nowElapsed,
int activeState) {
final int uid = jobStatus.getSourceUid(); final int uid = jobStatus.getSourceUid();
final String packageName = jobStatus.getSourcePackageName(); final String packageName = jobStatus.getSourcePackageName();
@@ -205,26 +209,32 @@ public final class BackgroundJobsController extends StateController {
if (isActive && jobStatus.getStandbyBucket() == NEVER_INDEX) { if (isActive && jobStatus.getStandbyBucket() == NEVER_INDEX) {
jobStatus.maybeLogBucketMismatch(); jobStatus.maybeLogBucketMismatch();
} }
boolean didChange = jobStatus.setBackgroundNotRestrictedConstraintSatisfied(canRun); boolean didChange =
jobStatus.setBackgroundNotRestrictedConstraintSatisfied(nowElapsed, canRun);
didChange |= jobStatus.setUidActive(isActive); didChange |= jobStatus.setUidActive(isActive);
return didChange; return didChange;
} }
private final class UpdateJobFunctor implements Consumer<JobStatus> { private final class UpdateJobFunctor implements Consumer<JobStatus> {
final int activeState; int mActiveState;
boolean mChanged = false; boolean mChanged = false;
int mTotalCount = 0; int mTotalCount = 0;
int mCheckedCount = 0; int mCheckedCount = 0;
long mUpdateTimeElapsed = 0;
public UpdateJobFunctor(int newActiveState) { void prepare(int newActiveState) {
activeState = newActiveState; mActiveState = newActiveState;
mUpdateTimeElapsed = sElapsedRealtimeClock.millis();
mChanged = false;
mTotalCount = 0;
mCheckedCount = 0;
} }
@Override @Override
public void accept(JobStatus jobStatus) { public void accept(JobStatus jobStatus) {
mTotalCount++; mTotalCount++;
mCheckedCount++; mCheckedCount++;
if (updateSingleJobRestrictionLocked(jobStatus, activeState)) { if (updateSingleJobRestrictionLocked(jobStatus, mUpdateTimeElapsed, mActiveState)) {
mChanged = true; mChanged = true;
} }
} }

View File

@@ -65,10 +65,12 @@ public final class BatteryController extends RestrictingController {
@Override @Override
public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) { public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
if (taskStatus.hasPowerConstraint()) { if (taskStatus.hasPowerConstraint()) {
final long nowElapsed = sElapsedRealtimeClock.millis();
mTrackedTasks.add(taskStatus); mTrackedTasks.add(taskStatus);
taskStatus.setTrackingController(JobStatus.TRACKING_BATTERY); taskStatus.setTrackingController(JobStatus.TRACKING_BATTERY);
taskStatus.setChargingConstraintSatisfied(mChargeTracker.isOnStablePower()); taskStatus.setChargingConstraintSatisfied(nowElapsed, mChargeTracker.isOnStablePower());
taskStatus.setBatteryNotLowConstraintSatisfied(mChargeTracker.isBatteryNotLow()); taskStatus.setBatteryNotLowConstraintSatisfied(
nowElapsed, mChargeTracker.isBatteryNotLow());
} }
} }
@@ -97,14 +99,15 @@ public final class BatteryController extends RestrictingController {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "maybeReportNewChargingStateLocked: " + stablePower); Slog.d(TAG, "maybeReportNewChargingStateLocked: " + stablePower);
} }
final long nowElapsed = sElapsedRealtimeClock.millis();
boolean reportChange = false; boolean reportChange = false;
for (int i = mTrackedTasks.size() - 1; i >= 0; i--) { for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
final JobStatus ts = mTrackedTasks.valueAt(i); final JobStatus ts = mTrackedTasks.valueAt(i);
boolean previous = ts.setChargingConstraintSatisfied(stablePower); boolean previous = ts.setChargingConstraintSatisfied(nowElapsed, stablePower);
if (previous != stablePower) { if (previous != stablePower) {
reportChange = true; reportChange = true;
} }
previous = ts.setBatteryNotLowConstraintSatisfied(batteryNotLow); previous = ts.setBatteryNotLowConstraintSatisfied(nowElapsed, batteryNotLow);
if (previous != batteryNotLow) { if (previous != batteryNotLow) {
reportChange = true; reportChange = true;
} }

View File

@@ -20,6 +20,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; 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.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.job.JobInfo; import android.app.job.JobInfo;
@@ -461,11 +462,12 @@ public final class ConnectivityController extends RestrictingController implemen
final Network network = mConnManager.getActiveNetworkForUid( final Network network = mConnManager.getActiveNetworkForUid(
jobStatus.getSourceUid(), jobStatus.shouldIgnoreNetworkBlocking()); jobStatus.getSourceUid(), jobStatus.shouldIgnoreNetworkBlocking());
final NetworkCapabilities capabilities = getNetworkCapabilities(network); final NetworkCapabilities capabilities = getNetworkCapabilities(network);
return updateConstraintsSatisfied(jobStatus, network, capabilities); return updateConstraintsSatisfied(jobStatus, sElapsedRealtimeClock.millis(),
network, capabilities);
} }
private boolean updateConstraintsSatisfied(JobStatus jobStatus, Network network, private boolean updateConstraintsSatisfied(JobStatus jobStatus, final long nowElapsed,
NetworkCapabilities capabilities) { Network network, NetworkCapabilities capabilities) {
// TODO: consider matching against non-active networks // TODO: consider matching against non-active networks
final boolean ignoreBlocked = jobStatus.shouldIgnoreNetworkBlocking(); 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 satisfied = isSatisfied(jobStatus, network, capabilities, mConstants);
final boolean changed = jobStatus final boolean changed = jobStatus
.setConnectivityConstraintSatisfied(connected && satisfied); .setConnectivityConstraintSatisfied(nowElapsed, connected && satisfied);
// Pass along the evaluated network for job to use; prevents race // Pass along the evaluated network for job to use; prevents race
// conditions as default routes change over time, and opens the door to // 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; NetworkCapabilities exemptedNetworkCapabilities = null;
boolean exemptedNetworkMatch = false; boolean exemptedNetworkMatch = false;
final long nowElapsed = sElapsedRealtimeClock.millis();
boolean changed = false; boolean changed = false;
for (int i = jobs.size() - 1; i >= 0; i--) { for (int i = jobs.size() - 1; i >= 0; i--) {
final JobStatus js = jobs.valueAt(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 // job hasn't yet been evaluated against the currently
// active network; typically when we just lost a network. // active network; typically when we just lost a network.
if (match || !Objects.equals(js.network, net)) { if (match || !Objects.equals(js.network, net)) {
changed |= updateConstraintsSatisfied(js, net, netCap); changed |= updateConstraintsSatisfied(js, nowElapsed, net, netCap);
} }
} }
return changed; return changed;

View File

@@ -16,6 +16,8 @@
package com.android.server.job.controllers; package com.android.server.job.controllers;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import android.annotation.UserIdInt; import android.annotation.UserIdInt;
import android.app.job.JobInfo; import android.app.job.JobInfo;
import android.database.ContentObserver; import android.database.ContentObserver;
@@ -74,6 +76,7 @@ public final class ContentObserverController extends StateController {
@Override @Override
public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) { public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
if (taskStatus.hasContentTriggerConstraint()) { if (taskStatus.hasContentTriggerConstraint()) {
final long nowElapsed = sElapsedRealtimeClock.millis();
if (taskStatus.contentObserverJobInstance == null) { if (taskStatus.contentObserverJobInstance == null) {
taskStatus.contentObserverJobInstance = new JobInstance(taskStatus); taskStatus.contentObserverJobInstance = new JobInstance(taskStatus);
} }
@@ -110,7 +113,7 @@ public final class ContentObserverController extends StateController {
} }
taskStatus.changedAuthorities = null; taskStatus.changedAuthorities = null;
taskStatus.changedUris = null; taskStatus.changedUris = null;
taskStatus.setContentTriggerConstraintSatisfied(havePendingUris); taskStatus.setContentTriggerConstraintSatisfied(nowElapsed, havePendingUris);
} }
if (lastJob != null && lastJob.contentObserverJobInstance != null) { if (lastJob != null && lastJob.contentObserverJobInstance != null) {
// And now we can detach the instance state from the last job. // 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; boolean reportChange = false;
synchronized (mLock) { synchronized (mLock) {
if (mTriggerPending) { if (mTriggerPending) {
if (mJobStatus.setContentTriggerConstraintSatisfied(true)) { final long nowElapsed = sElapsedRealtimeClock.millis();
if (mJobStatus.setContentTriggerConstraintSatisfied(nowElapsed, true)) {
reportChange = true; reportChange = true;
} }
unscheduleLocked(); unscheduleLocked();

View File

@@ -16,6 +16,8 @@
package com.android.server.job.controllers; package com.android.server.job.controllers;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import android.app.job.JobInfo; import android.app.job.JobInfo;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
@@ -104,8 +106,10 @@ public final class DeviceIdleJobsController extends StateController {
+ Arrays.toString(mPowerSaveTempWhitelistAppIds)); + Arrays.toString(mPowerSaveTempWhitelistAppIds));
} }
boolean changed = false; boolean changed = false;
final long nowElapsed = sElapsedRealtimeClock.millis();
for (int i = 0; i < mAllowInIdleJobs.size(); i++) { for (int i = 0; i < mAllowInIdleJobs.size(); i++) {
changed |= updateTaskStateLocked(mAllowInIdleJobs.valueAt(i)); changed |=
updateTaskStateLocked(mAllowInIdleJobs.valueAt(i), nowElapsed);
} }
if (changed) { if (changed) {
mStateChangedListener.onControllerStateChanged(); mStateChangedListener.onControllerStateChanged();
@@ -147,6 +151,7 @@ public final class DeviceIdleJobsController extends StateController {
} }
mDeviceIdleMode = enabled; mDeviceIdleMode = enabled;
if (DEBUG) Slog.d(TAG, "mDeviceIdleMode=" + mDeviceIdleMode); if (DEBUG) Slog.d(TAG, "mDeviceIdleMode=" + mDeviceIdleMode);
mDeviceIdleUpdateFunctor.prepare();
if (enabled) { if (enabled) {
mHandler.removeMessages(PROCESS_BACKGROUND_JOBS); mHandler.removeMessages(PROCESS_BACKGROUND_JOBS);
mService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor); mService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor);
@@ -180,7 +185,7 @@ public final class DeviceIdleJobsController extends StateController {
Slog.d(TAG, "uid " + uid + " going " + (active ? "active" : "inactive")); Slog.d(TAG, "uid " + uid + " going " + (active ? "active" : "inactive"));
} }
mForegroundUids.put(uid, active); mForegroundUids.put(uid, active);
mDeviceIdleUpdateFunctor.mChanged = false; mDeviceIdleUpdateFunctor.prepare();
mService.getJobStore().forEachJobForSourceUid(uid, mDeviceIdleUpdateFunctor); mService.getJobStore().forEachJobForSourceUid(uid, mDeviceIdleUpdateFunctor);
if (mDeviceIdleUpdateFunctor.mChanged) { if (mDeviceIdleUpdateFunctor.mChanged) {
mStateChangedListener.onControllerStateChanged(); mStateChangedListener.onControllerStateChanged();
@@ -203,12 +208,12 @@ public final class DeviceIdleJobsController extends StateController {
UserHandle.getAppId(job.getSourceUid())); 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) final boolean allowInIdle = ((task.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0)
&& (mForegroundUids.get(task.getSourceUid()) || isTempWhitelistedLocked(task)); && (mForegroundUids.get(task.getSourceUid()) || isTempWhitelistedLocked(task));
final boolean whitelisted = isWhitelistedLocked(task); final boolean whitelisted = isWhitelistedLocked(task);
final boolean enableTask = !mDeviceIdleMode || whitelisted || allowInIdle; final boolean enableTask = !mDeviceIdleMode || whitelisted || allowInIdle;
return task.setDeviceNotDozingConstraintSatisfied(enableTask, whitelisted); return task.setDeviceNotDozingConstraintSatisfied(nowElapsed, enableTask, whitelisted);
} }
@Override @Override
@@ -216,7 +221,7 @@ public final class DeviceIdleJobsController extends StateController {
if ((jobStatus.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0) { if ((jobStatus.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0) {
mAllowInIdleJobs.add(jobStatus); mAllowInIdleJobs.add(jobStatus);
} }
updateTaskStateLocked(jobStatus); updateTaskStateLocked(jobStatus, sElapsedRealtimeClock.millis());
} }
@Override @Override
@@ -282,10 +287,16 @@ public final class DeviceIdleJobsController extends StateController {
final class DeviceIdleUpdateFunctor implements Consumer<JobStatus> { final class DeviceIdleUpdateFunctor implements Consumer<JobStatus> {
boolean mChanged; boolean mChanged;
long mUpdateTimeElapsed = 0;
void prepare() {
mChanged = false;
mUpdateTimeElapsed = sElapsedRealtimeClock.millis();
}
@Override @Override
public void accept(JobStatus jobStatus) { 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: case PROCESS_BACKGROUND_JOBS:
// Just process all the jobs, the ones in foreground should already be running. // Just process all the jobs, the ones in foreground should already be running.
synchronized (mLock) { synchronized (mLock) {
mDeviceIdleUpdateFunctor.mChanged = false; mDeviceIdleUpdateFunctor.prepare();
mService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor); mService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor);
if (mDeviceIdleUpdateFunctor.mChanged) { if (mDeviceIdleUpdateFunctor.mChanged) {
mStateChangedListener.onControllerStateChanged(); mStateChangedListener.onControllerStateChanged();

View File

@@ -16,6 +16,8 @@
package com.android.server.job.controllers; package com.android.server.job.controllers;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.UserHandle; import android.os.UserHandle;
@@ -58,9 +60,10 @@ public final class IdleController extends RestrictingController implements Idlen
@Override @Override
public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) { public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
if (taskStatus.hasIdleConstraint()) { if (taskStatus.hasIdleConstraint()) {
final long nowElapsed = sElapsedRealtimeClock.millis();
mTrackedTasks.add(taskStatus); mTrackedTasks.add(taskStatus);
taskStatus.setTrackingController(JobStatus.TRACKING_IDLE); 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 @Override
public void reportNewIdleState(boolean isIdle) { public void reportNewIdleState(boolean isIdle) {
synchronized (mLock) { synchronized (mLock) {
final long nowElapsed = sElapsedRealtimeClock.millis();
for (int i = mTrackedTasks.size()-1; i >= 0; i--) { for (int i = mTrackedTasks.size()-1; i >= 0; i--) {
mTrackedTasks.valueAt(i).setIdleConstraintSatisfied(isIdle); mTrackedTasks.valueAt(i).setIdleConstraintSatisfied(nowElapsed, isIdle);
} }
} }
mStateChangedListener.onControllerStateChanged(); mStateChangedListener.onControllerStateChanged();

View File

@@ -73,6 +73,8 @@ public final class JobStatus {
private static final String TAG = "JobScheduler.JobStatus"; private static final String TAG = "JobScheduler.JobStatus";
static final boolean DEBUG = JobSchedulerService.DEBUG; 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_LATEST_RUNTIME = Long.MAX_VALUE;
public static final long NO_EARLIEST_RUNTIME = 0L; public static final long NO_EARLIEST_RUNTIME = 0L;
@@ -350,6 +352,10 @@ public final class JobStatus {
*/ */
private Pair<Long, Long> mPersistedUtcTimes; 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 * For use only by ContentObserverController: state it is maintaining about content URIs
* being observed. * being observed.
@@ -1090,28 +1096,28 @@ public final class JobStatus {
} }
/** @return true if the constraint was changed, false otherwise. */ /** @return true if the constraint was changed, false otherwise. */
boolean setChargingConstraintSatisfied(boolean state) { boolean setChargingConstraintSatisfied(final long nowElapsed, boolean state) {
return setConstraintSatisfied(CONSTRAINT_CHARGING, state); return setConstraintSatisfied(CONSTRAINT_CHARGING, nowElapsed, state);
} }
/** @return true if the constraint was changed, false otherwise. */ /** @return true if the constraint was changed, false otherwise. */
boolean setBatteryNotLowConstraintSatisfied(boolean state) { boolean setBatteryNotLowConstraintSatisfied(final long nowElapsed, boolean state) {
return setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, state); return setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, nowElapsed, state);
} }
/** @return true if the constraint was changed, false otherwise. */ /** @return true if the constraint was changed, false otherwise. */
boolean setStorageNotLowConstraintSatisfied(boolean state) { boolean setStorageNotLowConstraintSatisfied(final long nowElapsed, boolean state) {
return setConstraintSatisfied(CONSTRAINT_STORAGE_NOT_LOW, state); return setConstraintSatisfied(CONSTRAINT_STORAGE_NOT_LOW, nowElapsed, state);
} }
/** @return true if the constraint was changed, false otherwise. */ /** @return true if the constraint was changed, false otherwise. */
boolean setTimingDelayConstraintSatisfied(boolean state) { boolean setTimingDelayConstraintSatisfied(final long nowElapsed, boolean state) {
return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, state); return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, nowElapsed, state);
} }
/** @return true if the constraint was changed, false otherwise. */ /** @return true if the constraint was changed, false otherwise. */
boolean setDeadlineConstraintSatisfied(boolean state) { boolean setDeadlineConstraintSatisfied(final long nowElapsed, boolean state) {
if (setConstraintSatisfied(CONSTRAINT_DEADLINE, state)) { if (setConstraintSatisfied(CONSTRAINT_DEADLINE, nowElapsed, state)) {
// The constraint was changed. Update the ready flag. // The constraint was changed. Update the ready flag.
mReadyDeadlineSatisfied = !job.isPeriodic() && hasDeadlineConstraint() && state; mReadyDeadlineSatisfied = !job.isPeriodic() && hasDeadlineConstraint() && state;
return true; return true;
@@ -1120,24 +1126,25 @@ public final class JobStatus {
} }
/** @return true if the constraint was changed, false otherwise. */ /** @return true if the constraint was changed, false otherwise. */
boolean setIdleConstraintSatisfied(boolean state) { boolean setIdleConstraintSatisfied(final long nowElapsed, boolean state) {
return setConstraintSatisfied(CONSTRAINT_IDLE, state); return setConstraintSatisfied(CONSTRAINT_IDLE, nowElapsed, state);
} }
/** @return true if the constraint was changed, false otherwise. */ /** @return true if the constraint was changed, false otherwise. */
boolean setConnectivityConstraintSatisfied(boolean state) { boolean setConnectivityConstraintSatisfied(final long nowElapsed, boolean state) {
return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, state); return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, nowElapsed, state);
} }
/** @return true if the constraint was changed, false otherwise. */ /** @return true if the constraint was changed, false otherwise. */
boolean setContentTriggerConstraintSatisfied(boolean state) { boolean setContentTriggerConstraintSatisfied(final long nowElapsed, boolean state) {
return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, state); return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, nowElapsed, state);
} }
/** @return true if the constraint was changed, false otherwise. */ /** @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; 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. // The constraint was changed. Update the ready flag.
mReadyNotDozing = state || canRunInDoze(); mReadyNotDozing = state || canRunInDoze();
return true; return true;
@@ -1146,8 +1153,8 @@ public final class JobStatus {
} }
/** @return true if the constraint was changed, false otherwise. */ /** @return true if the constraint was changed, false otherwise. */
boolean setBackgroundNotRestrictedConstraintSatisfied(boolean state) { boolean setBackgroundNotRestrictedConstraintSatisfied(final long nowElapsed, boolean state) {
if (setConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED, state)) { if (setConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED, nowElapsed, state)) {
// The constraint was changed. Update the ready flag. // The constraint was changed. Update the ready flag.
mReadyNotRestrictedInBg = state; mReadyNotRestrictedInBg = state;
return true; return true;
@@ -1156,8 +1163,8 @@ public final class JobStatus {
} }
/** @return true if the constraint was changed, false otherwise. */ /** @return true if the constraint was changed, false otherwise. */
boolean setQuotaConstraintSatisfied(boolean state) { boolean setQuotaConstraintSatisfied(final long nowElapsed, boolean state) {
if (setConstraintSatisfied(CONSTRAINT_WITHIN_QUOTA, state)) { if (setConstraintSatisfied(CONSTRAINT_WITHIN_QUOTA, nowElapsed, state)) {
// The constraint was changed. Update the ready flag. // The constraint was changed. Update the ready flag.
mReadyWithinQuota = state; mReadyWithinQuota = state;
return true; return true;
@@ -1166,8 +1173,8 @@ public final class JobStatus {
} }
/** @return true if the constraint was changed, false otherwise. */ /** @return true if the constraint was changed, false otherwise. */
boolean setExpeditedJobQuotaConstraintSatisfied(boolean state) { boolean setExpeditedJobQuotaConstraintSatisfied(final long nowElapsed, boolean state) {
if (setConstraintSatisfied(CONSTRAINT_WITHIN_EXPEDITED_QUOTA, state)) { if (setConstraintSatisfied(CONSTRAINT_WITHIN_EXPEDITED_QUOTA, nowElapsed, state)) {
// The constraint was changed. Update the ready flag. // The constraint was changed. Update the ready flag.
mReadyWithinExpeditedQuota = state; mReadyWithinExpeditedQuota = state;
// DeviceIdleJobsController currently only tracks jobs with the WILL_BE_FOREGROUND flag. // 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. */ /** @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; boolean old = (satisfiedConstraints&constraint) != 0;
if (old == state) { if (old == state) {
return false; return false;
@@ -1212,6 +1219,12 @@ public final class JobStatus {
: FrameworkStatsLog : FrameworkStatsLog
.SCHEDULED_JOB_CONSTRAINT_CHANGED__STATE__UNSATISFIED); .SCHEDULED_JOB_CONSTRAINT_CHANGED__STATE__UNSATISFIED);
} }
mConstraintUpdatedTimesElapsed[mConstraintChangeHistoryIndex] = nowElapsed;
mConstraintStatusHistory[mConstraintChangeHistoryIndex] = satisfiedConstraints;
mConstraintChangeHistoryIndex =
(mConstraintChangeHistoryIndex + 1) % NUM_CONSTRAINT_CHANGE_HISTORY;
return true; return true;
} }
@@ -1700,7 +1713,7 @@ public final class JobStatus {
} }
// Dumpsys infrastructure // Dumpsys infrastructure
public void dump(IndentingPrintWriter pw, boolean full, long elapsedRealtimeMillis) { public void dump(IndentingPrintWriter pw, boolean full, long nowElapsed) {
UserHandle.formatUid(pw, callingUid); UserHandle.formatUid(pw, callingUid);
pw.print(" tag="); pw.println(tag); pw.print(" tag="); pw.println(tag);
@@ -1830,6 +1843,22 @@ public final class JobStatus {
dumpConstraints(pw, dumpConstraints(pw,
((requiredConstraints | CONSTRAINT_WITHIN_QUOTA) & ~satisfiedConstraints)); ((requiredConstraints | CONSTRAINT_WITHIN_QUOTA) & ~satisfiedConstraints));
pw.println(); 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) { if (dozeWhitelisted) {
pw.println("Doze whitelisted: true"); pw.println("Doze whitelisted: true");
} }
@@ -1910,26 +1939,25 @@ public final class JobStatus {
pw.increaseIndent(); pw.increaseIndent();
if (whenStandbyDeferred != 0) { if (whenStandbyDeferred != 0) {
pw.print("Deferred since: "); pw.print("Deferred since: ");
TimeUtils.formatDuration(whenStandbyDeferred, elapsedRealtimeMillis, pw); TimeUtils.formatDuration(whenStandbyDeferred, nowElapsed, pw);
pw.println(); pw.println();
} }
if (mFirstForceBatchedTimeElapsed != 0) { if (mFirstForceBatchedTimeElapsed != 0) {
pw.print("Time since first force batch attempt: "); pw.print("Time since first force batch attempt: ");
TimeUtils.formatDuration(mFirstForceBatchedTimeElapsed, elapsedRealtimeMillis, pw); TimeUtils.formatDuration(mFirstForceBatchedTimeElapsed, nowElapsed, pw);
pw.println(); pw.println();
} }
pw.decreaseIndent(); pw.decreaseIndent();
pw.print("Enqueue time: "); pw.print("Enqueue time: ");
TimeUtils.formatDuration(enqueueTime, elapsedRealtimeMillis, pw); TimeUtils.formatDuration(enqueueTime, nowElapsed, pw);
pw.println(); pw.println();
pw.print("Run time: earliest="); pw.print("Run time: earliest=");
formatRunTime(pw, earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME, elapsedRealtimeMillis); formatRunTime(pw, earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME, nowElapsed);
pw.print(", latest="); pw.print(", latest=");
formatRunTime(pw, latestRunTimeElapsedMillis, NO_LATEST_RUNTIME, elapsedRealtimeMillis); formatRunTime(pw, latestRunTimeElapsedMillis, NO_LATEST_RUNTIME, nowElapsed);
pw.print(", original latest="); pw.print(", original latest=");
formatRunTime(pw, mOriginalLatestRunTimeElapsedMillis, formatRunTime(pw, mOriginalLatestRunTimeElapsedMillis, NO_LATEST_RUNTIME, nowElapsed);
NO_LATEST_RUNTIME, elapsedRealtimeMillis);
pw.println(); pw.println();
if (numFailures != 0) { if (numFailures != 0) {
pw.print("Num failures: "); pw.println(numFailures); pw.print("Num failures: "); pw.println(numFailures);

View File

@@ -626,6 +626,7 @@ public final class QuotaController extends StateController {
@Override @Override
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) { public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
final long nowElapsed = sElapsedRealtimeClock.millis();
final int userId = jobStatus.getSourceUserId(); final int userId = jobStatus.getSourceUserId();
final String pkgName = jobStatus.getSourcePackageName(); final String pkgName = jobStatus.getSourcePackageName();
ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, pkgName); ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, pkgName);
@@ -636,11 +637,11 @@ public final class QuotaController extends StateController {
jobs.add(jobStatus); jobs.add(jobStatus);
jobStatus.setTrackingController(JobStatus.TRACKING_QUOTA); jobStatus.setTrackingController(JobStatus.TRACKING_QUOTA);
final boolean isWithinQuota = isWithinQuotaLocked(jobStatus); final boolean isWithinQuota = isWithinQuotaLocked(jobStatus);
setConstraintSatisfied(jobStatus, isWithinQuota); setConstraintSatisfied(jobStatus, nowElapsed, isWithinQuota);
final boolean outOfEJQuota; final boolean outOfEJQuota;
if (jobStatus.isRequestedExpeditedJob()) { if (jobStatus.isRequestedExpeditedJob()) {
final boolean isWithinEJQuota = isWithinEJQuotaLocked(jobStatus); final boolean isWithinEJQuota = isWithinEJQuotaLocked(jobStatus);
setExpeditedConstraintSatisfied(jobStatus, isWithinEJQuota); setExpeditedConstraintSatisfied(jobStatus, nowElapsed, isWithinEJQuota);
outOfEJQuota = !isWithinEJQuota; outOfEJQuota = !isWithinEJQuota;
} else { } else {
outOfEJQuota = false; outOfEJQuota = false;
@@ -1397,7 +1398,8 @@ public final class QuotaController extends StateController {
synchronized (mLock) { synchronized (mLock) {
final ShrinkableDebits quota = getEJQuotaLocked(userId, packageName); final ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
quota.transactOnDebitsLocked(-credit); quota.transactOnDebitsLocked(-credit);
if (maybeUpdateConstraintForPkgLocked(userId, packageName)) { if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
userId, packageName)) {
mStateChangedListener.onControllerStateChanged(); mStateChangedListener.onControllerStateChanged();
} }
} }
@@ -1499,11 +1501,12 @@ public final class QuotaController extends StateController {
private void maybeUpdateAllConstraintsLocked() { private void maybeUpdateAllConstraintsLocked() {
boolean changed = false; boolean changed = false;
final long nowElapsed = sElapsedRealtimeClock.millis();
for (int u = 0; u < mTrackedJobs.numMaps(); ++u) { for (int u = 0; u < mTrackedJobs.numMaps(); ++u) {
final int userId = mTrackedJobs.keyAt(u); final int userId = mTrackedJobs.keyAt(u);
for (int p = 0; p < mTrackedJobs.numElementsForKey(userId); ++p) { for (int p = 0; p < mTrackedJobs.numElementsForKey(userId); ++p) {
final String packageName = mTrackedJobs.keyAt(u, p); final String packageName = mTrackedJobs.keyAt(u, p);
changed |= maybeUpdateConstraintForPkgLocked(userId, packageName); changed |= maybeUpdateConstraintForPkgLocked(nowElapsed, userId, packageName);
} }
} }
if (changed) { if (changed) {
@@ -1516,7 +1519,7 @@ public final class QuotaController extends StateController {
* *
* @return true if at least one job had its bit changed * @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) { @NonNull final String packageName) {
ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, packageName); ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, packageName);
if (jobs == null || jobs.size() == 0) { if (jobs == null || jobs.size() == 0) {
@@ -1533,21 +1536,21 @@ public final class QuotaController extends StateController {
if (isTopStartedJobLocked(js)) { if (isTopStartedJobLocked(js)) {
// Job was started while the app was in the TOP state so we should allow it to // Job was started while the app was in the TOP state so we should allow it to
// finish. // finish.
changed |= js.setQuotaConstraintSatisfied(true); changed |= js.setQuotaConstraintSatisfied(nowElapsed, true);
} else if (realStandbyBucket != ACTIVE_INDEX } else if (realStandbyBucket != ACTIVE_INDEX
&& realStandbyBucket == js.getEffectiveStandbyBucket()) { && realStandbyBucket == js.getEffectiveStandbyBucket()) {
// An app in the ACTIVE bucket may be out of quota while the job could be in quota // 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 // for some reason. Therefore, avoid setting the real value here and check each job
// individually. // individually.
changed |= setConstraintSatisfied(js, realInQuota); changed |= setConstraintSatisfied(js, nowElapsed, realInQuota);
} else { } else {
// This job is somehow exempted. Need to determine its own quota status. // 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()) { if (js.isRequestedExpeditedJob()) {
boolean isWithinEJQuota = isWithinEJQuotaLocked(js); boolean isWithinEJQuota = isWithinEJQuotaLocked(js);
changed |= setExpeditedConstraintSatisfied(js, isWithinEJQuota); changed |= setExpeditedConstraintSatisfied(js, nowElapsed, isWithinEJQuota);
outOfEJQuota |= !isWithinEJQuota; outOfEJQuota |= !isWithinEJQuota;
} }
} }
@@ -1566,14 +1569,21 @@ public final class QuotaController extends StateController {
private final SparseArrayMap<String, Integer> mToScheduleStartAlarms = private final SparseArrayMap<String, Integer> mToScheduleStartAlarms =
new SparseArrayMap<>(); new SparseArrayMap<>();
public boolean wasJobChanged; public boolean wasJobChanged;
long mUpdateTimeElapsed = 0;
void prepare() {
mUpdateTimeElapsed = sElapsedRealtimeClock.millis();
}
@Override @Override
public void accept(JobStatus jobStatus) { public void accept(JobStatus jobStatus) {
wasJobChanged |= setConstraintSatisfied(jobStatus, isWithinQuotaLocked(jobStatus)); wasJobChanged |= setConstraintSatisfied(
jobStatus, mUpdateTimeElapsed, isWithinQuotaLocked(jobStatus));
final boolean outOfEJQuota; final boolean outOfEJQuota;
if (jobStatus.isRequestedExpeditedJob()) { if (jobStatus.isRequestedExpeditedJob()) {
final boolean isWithinEJQuota = isWithinEJQuotaLocked(jobStatus); final boolean isWithinEJQuota = isWithinEJQuotaLocked(jobStatus);
wasJobChanged |= setExpeditedConstraintSatisfied(jobStatus, isWithinEJQuota); wasJobChanged |= setExpeditedConstraintSatisfied(
jobStatus, mUpdateTimeElapsed, isWithinEJQuota);
outOfEJQuota = !isWithinEJQuota; outOfEJQuota = !isWithinEJQuota;
} else { } else {
outOfEJQuota = false; outOfEJQuota = false;
@@ -1611,6 +1621,7 @@ public final class QuotaController extends StateController {
private final UidConstraintUpdater mUpdateUidConstraints = new UidConstraintUpdater(); private final UidConstraintUpdater mUpdateUidConstraints = new UidConstraintUpdater();
private boolean maybeUpdateConstraintForUidLocked(final int uid) { private boolean maybeUpdateConstraintForUidLocked(final int uid) {
mUpdateUidConstraints.prepare();
mService.getJobStore().forEachJobForSourceUid(uid, mUpdateUidConstraints); mService.getJobStore().forEachJobForSourceUid(uid, mUpdateUidConstraints);
mUpdateUidConstraints.postProcess(); mUpdateUidConstraints.postProcess();
@@ -1716,21 +1727,22 @@ public final class QuotaController extends StateController {
mInQuotaAlarmListener.addAlarmLocked(userId, packageName, inQuotaTimeElapsed); 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) { if (!isWithinQuota && jobStatus.getWhenStandbyDeferred() == 0) {
// Mark that the job is being deferred due to buckets. // 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 * If the satisfaction changes, this will tell connectivity & background jobs controller to
* also re-evaluate their state. * also re-evaluate their state.
*/ */
private boolean setExpeditedConstraintSatisfied(@NonNull JobStatus jobStatus, private boolean setExpeditedConstraintSatisfied(@NonNull JobStatus jobStatus, long nowElapsed,
boolean isWithinQuota) { boolean isWithinQuota) {
if (jobStatus.setExpeditedJobQuotaConstraintSatisfied(isWithinQuota)) { if (jobStatus.setExpeditedJobQuotaConstraintSatisfied(nowElapsed, isWithinQuota)) {
mBackgroundJobsController.evaluateStateLocked(jobStatus); mBackgroundJobsController.evaluateStateLocked(jobStatus);
mConnectivityController.evaluateStateLocked(jobStatus); mConnectivityController.evaluateStateLocked(jobStatus);
if (isWithinQuota && jobStatus.isReady()) { if (isWithinQuota && jobStatus.isReady()) {
@@ -2188,7 +2200,8 @@ public final class QuotaController extends StateController {
final ShrinkableDebits quota = final ShrinkableDebits quota =
getEJQuotaLocked(mPkg.userId, mPkg.packageName); getEJQuotaLocked(mPkg.userId, mPkg.packageName);
quota.transactOnDebitsLocked(-mEJRewardTopAppMs * numTimeChunks); quota.transactOnDebitsLocked(-mEJRewardTopAppMs * numTimeChunks);
if (maybeUpdateConstraintForPkgLocked(mPkg.userId, mPkg.packageName)) { if (maybeUpdateConstraintForPkgLocked(nowElapsed,
mPkg.userId, mPkg.packageName)) {
mStateChangedListener.onControllerStateChanged(); mStateChangedListener.onControllerStateChanged();
} }
} }
@@ -2292,7 +2305,8 @@ public final class QuotaController extends StateController {
if (timer != null && timer.isActive()) { if (timer != null && timer.isActive()) {
timer.rescheduleCutoff(); timer.rescheduleCutoff();
} }
if (maybeUpdateConstraintForPkgLocked(userId, packageName)) { if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
userId, packageName)) {
mStateChangedListener.onControllerStateChanged(); mStateChangedListener.onControllerStateChanged();
} }
} }
@@ -2417,7 +2431,8 @@ public final class QuotaController extends StateController {
if (timeRemainingMs <= 50) { if (timeRemainingMs <= 50) {
// Less than 50 milliseconds left. Start process of shutting down jobs. // Less than 50 milliseconds left. Start process of shutting down jobs.
if (DEBUG) Slog.d(TAG, pkg + " has reached its quota."); 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(); mStateChangedListener.onControllerStateChanged();
} }
} else { } else {
@@ -2444,7 +2459,8 @@ public final class QuotaController extends StateController {
pkg.userId, pkg.packageName); pkg.userId, pkg.packageName);
if (timeRemainingMs <= 0) { if (timeRemainingMs <= 0) {
if (DEBUG) Slog.d(TAG, pkg + " has reached its EJ quota."); 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(); mStateChangedListener.onControllerStateChanged();
} }
} else { } else {
@@ -2475,7 +2491,8 @@ public final class QuotaController extends StateController {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "Checking pkg " + string(userId, packageName)); Slog.d(TAG, "Checking pkg " + string(userId, packageName));
} }
if (maybeUpdateConstraintForPkgLocked(userId, packageName)) { if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
userId, packageName)) {
mStateChangedListener.onControllerStateChanged(); mStateChangedListener.onControllerStateChanged();
} }
break; break;

View File

@@ -61,9 +61,11 @@ public final class StorageController extends StateController {
@Override @Override
public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) { public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
if (taskStatus.hasStorageNotLowConstraint()) { if (taskStatus.hasStorageNotLowConstraint()) {
final long nowElapsed = sElapsedRealtimeClock.millis();
mTrackedTasks.add(taskStatus); mTrackedTasks.add(taskStatus);
taskStatus.setTrackingController(JobStatus.TRACKING_STORAGE); 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() { private void maybeReportNewStorageState() {
final long nowElapsed = sElapsedRealtimeClock.millis();
final boolean storageNotLow = mStorageTracker.isStorageNotLow(); final boolean storageNotLow = mStorageTracker.isStorageNotLow();
boolean reportChange = false; boolean reportChange = false;
synchronized (mLock) { synchronized (mLock) {
for (int i = mTrackedTasks.size() - 1; i >= 0; i--) { for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
final JobStatus ts = mTrackedTasks.valueAt(i); final JobStatus ts = mTrackedTasks.valueAt(i);
reportChange |= ts.setStorageNotLowConstraintSatisfied(storageNotLow); reportChange |= ts.setStorageNotLowConstraintSatisfied(nowElapsed, storageNotLow);
} }
} }
if (storageNotLow) { if (storageNotLow) {

View File

@@ -258,9 +258,9 @@ public final class TimeController extends StateController {
if (jobDeadline <= nowElapsedMillis) { if (jobDeadline <= nowElapsedMillis) {
if (job.hasTimingDelayConstraint()) { if (job.hasTimingDelayConstraint()) {
job.setTimingDelayConstraintSatisfied(true); job.setTimingDelayConstraintSatisfied(nowElapsedMillis, true);
} }
job.setDeadlineConstraintSatisfied(true); job.setDeadlineConstraintSatisfied(nowElapsedMillis, true);
return true; return true;
} }
return false; return false;
@@ -332,7 +332,7 @@ public final class TimeController extends StateController {
private boolean evaluateTimingDelayConstraint(JobStatus job, long nowElapsedMillis) { private boolean evaluateTimingDelayConstraint(JobStatus job, long nowElapsedMillis) {
final long jobDelayTime = job.getEarliestRunTime(); final long jobDelayTime = job.getEarliestRunTime();
if (jobDelayTime <= nowElapsedMillis) { if (jobDelayTime <= nowElapsedMillis) {
job.setTimingDelayConstraintSatisfied(true); job.setTimingDelayConstraintSatisfied(nowElapsedMillis, true);
return true; return true;
} }
return false; return false;

View File

@@ -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.RARE_INDEX;
import static com.android.server.job.JobSchedulerService.RESTRICTED_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.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_BACKGROUND_NOT_RESTRICTED;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BATTERY_NOT_LOW; import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BATTERY_NOT_LOW;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CHARGING; import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CHARGING;
@@ -101,7 +102,7 @@ public class JobStatusTest {
Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC); Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
JobSchedulerService.sUptimeMillisClock = JobSchedulerService.sUptimeMillisClock =
Clock.fixed(SystemClock.uptimeClock().instant(), ZoneOffset.UTC); Clock.fixed(SystemClock.uptimeClock().instant(), ZoneOffset.UTC);
JobSchedulerService.sElapsedRealtimeClock = sElapsedRealtimeClock =
Clock.fixed(SystemClock.elapsedRealtimeClock().instant(), ZoneOffset.UTC); Clock.fixed(SystemClock.elapsedRealtimeClock().instant(), ZoneOffset.UTC);
} }
@@ -204,7 +205,7 @@ public class JobStatusTest {
@Test @Test
public void testFraction() throws Exception { 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); assertEquals(1, createJobStatus(0, Long.MAX_VALUE).getFractionRunTime(), DELTA);
@@ -261,15 +262,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo); final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true); markImplicitConstraintsSatisfied(job, true);
job.setChargingConstraintSatisfied(false); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
job.setChargingConstraintSatisfied(true); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
markImplicitConstraintsSatisfied(job, false); markImplicitConstraintsSatisfied(job, false);
job.setChargingConstraintSatisfied(false); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
job.setChargingConstraintSatisfied(true); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
} }
@@ -282,15 +283,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo); final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true); markImplicitConstraintsSatisfied(job, true);
job.setIdleConstraintSatisfied(false); job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
job.setIdleConstraintSatisfied(true); job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
markImplicitConstraintsSatisfied(job, false); markImplicitConstraintsSatisfied(job, false);
job.setIdleConstraintSatisfied(false); job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
job.setIdleConstraintSatisfied(true); job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
} }
@@ -303,15 +304,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo); final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true); markImplicitConstraintsSatisfied(job, true);
job.setBatteryNotLowConstraintSatisfied(false); job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
job.setBatteryNotLowConstraintSatisfied(true); job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
markImplicitConstraintsSatisfied(job, false); markImplicitConstraintsSatisfied(job, false);
job.setBatteryNotLowConstraintSatisfied(false); job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
job.setBatteryNotLowConstraintSatisfied(true); job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
} }
@@ -324,15 +325,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo); final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true); markImplicitConstraintsSatisfied(job, true);
job.setStorageNotLowConstraintSatisfied(false); job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
job.setStorageNotLowConstraintSatisfied(true); job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
markImplicitConstraintsSatisfied(job, false); markImplicitConstraintsSatisfied(job, false);
job.setStorageNotLowConstraintSatisfied(false); job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
job.setStorageNotLowConstraintSatisfied(true); job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
} }
@@ -345,15 +346,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo); final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true); markImplicitConstraintsSatisfied(job, true);
job.setTimingDelayConstraintSatisfied(false); job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
job.setTimingDelayConstraintSatisfied(true); job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
markImplicitConstraintsSatisfied(job, false); markImplicitConstraintsSatisfied(job, false);
job.setTimingDelayConstraintSatisfied(false); job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
job.setTimingDelayConstraintSatisfied(true); job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
} }
@@ -366,15 +367,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo); final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true); markImplicitConstraintsSatisfied(job, true);
job.setDeadlineConstraintSatisfied(false); job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
job.setDeadlineConstraintSatisfied(true); job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
markImplicitConstraintsSatisfied(job, false); markImplicitConstraintsSatisfied(job, false);
job.setDeadlineConstraintSatisfied(false); job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
job.setDeadlineConstraintSatisfied(true); job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
} }
@@ -387,15 +388,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo); final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true); markImplicitConstraintsSatisfied(job, true);
job.setConnectivityConstraintSatisfied(false); job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
job.setConnectivityConstraintSatisfied(true); job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
markImplicitConstraintsSatisfied(job, false); markImplicitConstraintsSatisfied(job, false);
job.setConnectivityConstraintSatisfied(false); job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
job.setConnectivityConstraintSatisfied(true); job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
} }
@@ -410,15 +411,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo); final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true); markImplicitConstraintsSatisfied(job, true);
job.setContentTriggerConstraintSatisfied(false); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
job.setContentTriggerConstraintSatisfied(true); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
markImplicitConstraintsSatisfied(job, false); markImplicitConstraintsSatisfied(job, false);
job.setContentTriggerConstraintSatisfied(false); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
job.setContentTriggerConstraintSatisfied(true); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
} }
@@ -436,15 +437,15 @@ public class JobStatusTest {
markImplicitConstraintsSatisfied(job, false); markImplicitConstraintsSatisfied(job, false);
job.setChargingConstraintSatisfied(false); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setConnectivityConstraintSatisfied(false); job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setContentTriggerConstraintSatisfied(false); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
job.setChargingConstraintSatisfied(true); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setConnectivityConstraintSatisfied(true); job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setContentTriggerConstraintSatisfied(true); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
// Still false because implicit constraints aren't satisfied. // Still false because implicit constraints aren't satisfied.
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
@@ -452,61 +453,61 @@ public class JobStatusTest {
markImplicitConstraintsSatisfied(job, true); markImplicitConstraintsSatisfied(job, true);
job.setChargingConstraintSatisfied(false); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setConnectivityConstraintSatisfied(false); job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setContentTriggerConstraintSatisfied(false); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// Turn on constraints one at a time. // Turn on constraints one at a time.
job.setChargingConstraintSatisfied(true); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setConnectivityConstraintSatisfied(false); job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setContentTriggerConstraintSatisfied(false); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
job.setChargingConstraintSatisfied(false); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setConnectivityConstraintSatisfied(false); job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setContentTriggerConstraintSatisfied(true); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
job.setChargingConstraintSatisfied(false); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setConnectivityConstraintSatisfied(true); job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setContentTriggerConstraintSatisfied(false); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// With two of the 3 constraints satisfied (and implicit constraints also satisfied), only // With two of the 3 constraints satisfied (and implicit constraints also satisfied), only
// the unsatisfied constraint should return true. // the unsatisfied constraint should return true.
job.setChargingConstraintSatisfied(true); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setConnectivityConstraintSatisfied(false); job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setContentTriggerConstraintSatisfied(true); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
job.setChargingConstraintSatisfied(true); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setConnectivityConstraintSatisfied(true); job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setContentTriggerConstraintSatisfied(false); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
job.setChargingConstraintSatisfied(false); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setConnectivityConstraintSatisfied(true); job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setContentTriggerConstraintSatisfied(true); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
job.setChargingConstraintSatisfied(true); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setConnectivityConstraintSatisfied(true); job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setContentTriggerConstraintSatisfied(true); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
@@ -526,15 +527,15 @@ public class JobStatusTest {
markImplicitConstraintsSatisfied(job, false); markImplicitConstraintsSatisfied(job, false);
job.setChargingConstraintSatisfied(false); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setContentTriggerConstraintSatisfied(false); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setDeadlineConstraintSatisfied(false); job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
job.setChargingConstraintSatisfied(true); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setContentTriggerConstraintSatisfied(true); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setDeadlineConstraintSatisfied(true); job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
// Still false because implicit constraints aren't satisfied. // Still false because implicit constraints aren't satisfied.
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
@@ -542,18 +543,18 @@ public class JobStatusTest {
markImplicitConstraintsSatisfied(job, true); markImplicitConstraintsSatisfied(job, true);
job.setChargingConstraintSatisfied(false); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setContentTriggerConstraintSatisfied(false); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setDeadlineConstraintSatisfied(false); job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// Once implicit constraint are satisfied, deadline constraint should always return true. // Once implicit constraint are satisfied, deadline constraint should always return true.
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
// Turn on constraints one at a time. // Turn on constraints one at a time.
job.setChargingConstraintSatisfied(true); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setContentTriggerConstraintSatisfied(false); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setDeadlineConstraintSatisfied(false); job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
// Deadline should force isReady to be true, but isn't needed for the job to be // Deadline should force isReady to be true, but isn't needed for the job to be
// considered ready. // considered ready.
@@ -561,17 +562,17 @@ public class JobStatusTest {
// Once implicit constraint are satisfied, deadline constraint should always return true. // Once implicit constraint are satisfied, deadline constraint should always return true.
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
job.setChargingConstraintSatisfied(false); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setContentTriggerConstraintSatisfied(true); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setDeadlineConstraintSatisfied(false); job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// Once implicit constraint are satisfied, deadline constraint should always return true. // Once implicit constraint are satisfied, deadline constraint should always return true.
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
job.setChargingConstraintSatisfied(false); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setContentTriggerConstraintSatisfied(false); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setDeadlineConstraintSatisfied(true); job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
// Since the deadline constraint is satisfied, none of the other explicit constraints are // Since the deadline constraint is satisfied, none of the other explicit constraints are
// needed. // needed.
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); 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 // With two of the 3 constraints satisfied (and implicit constraints also satisfied), only
// the unsatisfied constraint should return true. // the unsatisfied constraint should return true.
job.setChargingConstraintSatisfied(true); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setContentTriggerConstraintSatisfied(true); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setDeadlineConstraintSatisfied(false); job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// Once implicit constraint are satisfied, deadline constraint should always return true. // Once implicit constraint are satisfied, deadline constraint should always return true.
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
job.setChargingConstraintSatisfied(true); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setContentTriggerConstraintSatisfied(false); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setDeadlineConstraintSatisfied(true); job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// Once implicit constraint are satisfied, deadline constraint should always return true. // Once implicit constraint are satisfied, deadline constraint should always return true.
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
job.setChargingConstraintSatisfied(false); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
job.setContentTriggerConstraintSatisfied(true); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setDeadlineConstraintSatisfied(true); job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// Once implicit constraint are satisfied, deadline constraint should always return true. // Once implicit constraint are satisfied, deadline constraint should always return true.
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
job.setChargingConstraintSatisfied(true); job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setContentTriggerConstraintSatisfied(true); job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
job.setDeadlineConstraintSatisfied(true); job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// Once implicit constraint are satisfied, deadline constraint should always return true. // 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()); new JobInfo.Builder(101, new ComponentName("foo", "bar")).build());
markImplicitConstraintsSatisfied(job, false); markImplicitConstraintsSatisfied(job, false);
job.setDeviceNotDozingConstraintSatisfied(false, false); job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), false, false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
job.setDeviceNotDozingConstraintSatisfied(true, false); job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), true, false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
markImplicitConstraintsSatisfied(job, true); markImplicitConstraintsSatisfied(job, true);
job.setDeviceNotDozingConstraintSatisfied(false, false); job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), false, false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
job.setDeviceNotDozingConstraintSatisfied(true, false); job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), true, false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
} }
@@ -640,15 +641,15 @@ public class JobStatusTest {
new JobInfo.Builder(101, new ComponentName("foo", "bar")).build()); new JobInfo.Builder(101, new ComponentName("foo", "bar")).build());
markImplicitConstraintsSatisfied(job, false); markImplicitConstraintsSatisfied(job, false);
job.setQuotaConstraintSatisfied(false); job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
job.setQuotaConstraintSatisfied(true); job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
markImplicitConstraintsSatisfied(job, true); markImplicitConstraintsSatisfied(job, true);
job.setQuotaConstraintSatisfied(false); job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
job.setQuotaConstraintSatisfied(true); job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
} }
@@ -659,22 +660,24 @@ public class JobStatusTest {
new JobInfo.Builder(101, new ComponentName("foo", "bar")).build()); new JobInfo.Builder(101, new ComponentName("foo", "bar")).build());
markImplicitConstraintsSatisfied(job, false); markImplicitConstraintsSatisfied(job, false);
job.setBackgroundNotRestrictedConstraintSatisfied(false); job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
job.setBackgroundNotRestrictedConstraintSatisfied(true); job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED)); assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
markImplicitConstraintsSatisfied(job, true); markImplicitConstraintsSatisfied(job, true);
job.setBackgroundNotRestrictedConstraintSatisfied(false); job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
job.setBackgroundNotRestrictedConstraintSatisfied(true); job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED)); assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
} }
private void markImplicitConstraintsSatisfied(JobStatus job, boolean isSatisfied) { private void markImplicitConstraintsSatisfied(JobStatus job, boolean isSatisfied) {
job.setQuotaConstraintSatisfied(isSatisfied); job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), isSatisfied);
job.setDeviceNotDozingConstraintSatisfied(isSatisfied, false); job.setDeviceNotDozingConstraintSatisfied(
job.setBackgroundNotRestrictedConstraintSatisfied(isSatisfied); sElapsedRealtimeClock.millis(), isSatisfied, false);
job.setBackgroundNotRestrictedConstraintSatisfied(
sElapsedRealtimeClock.millis(), isSatisfied);
} }
private static JobStatus createJobStatus(long earliestRunTimeElapsedMillis, private static JobStatus createJobStatus(long earliestRunTimeElapsedMillis,

View File

@@ -359,8 +359,9 @@ public class QuotaControllerTest {
// Make sure tests aren't passing just because the default bucket is likely ACTIVE. // Make sure tests aren't passing just because the default bucket is likely ACTIVE.
js.setStandbyBucket(FREQUENT_INDEX); js.setStandbyBucket(FREQUENT_INDEX);
// Make sure Doze and background-not-restricted don't affect tests. // Make sure Doze and background-not-restricted don't affect tests.
js.setDeviceNotDozingConstraintSatisfied(/* state */ true, /* allowlisted */false); js.setDeviceNotDozingConstraintSatisfied(/* nowElapsed */ sElapsedRealtimeClock.millis(),
js.setBackgroundNotRestrictedConstraintSatisfied(true); /* state */ true, /* allowlisted */false);
js.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
return js; return js;
} }