Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2562d562 authored by Dan Sinkiewicz's avatar Dan Sinkiewicz Committed by Android (Google) Code Review
Browse files

Merge "Revert "Add exemptions to flex policy."" into main

parents a7ca4840 57ed8cfb
Loading
Loading
Loading
Loading
+13 −80
Original line number Diff line number Diff line
@@ -159,7 +159,6 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Predicate;

@@ -302,8 +301,6 @@ public class JobSchedulerService extends com.android.server.SystemService
    private final ConnectivityController mConnectivityController;
    /** Need directly for sending uid state changes */
    private final DeviceIdleJobsController mDeviceIdleJobsController;
    /** Need directly for sending exempted bucket changes */
    private final FlexibilityController mFlexibilityController;
    /** Needed to get next estimated launch time. */
    private final PrefetchController mPrefetchController;
    /** Needed to get remaining quota time. */
@@ -516,10 +513,6 @@ public class JobSchedulerService extends com.android.server.SystemService
                    if (name == null) {
                        continue;
                    }
                    if (DEBUG) {
                        Slog.d(TAG, "DeviceConfig " + name
                                + " changed to " + properties.getString(name, null));
                    }
                    switch (name) {
                        case Constants.KEY_ENABLE_API_QUOTAS:
                        case Constants.KEY_ENABLE_EXECUTION_SAFEGUARDS_UDC:
@@ -2539,17 +2532,17 @@ public class JobSchedulerService extends com.android.server.SystemService
        mControllers = new ArrayList<StateController>();
        mPrefetchController = new PrefetchController(this);
        mControllers.add(mPrefetchController);
        mFlexibilityController =
        final FlexibilityController flexibilityController =
                new FlexibilityController(this, mPrefetchController);
        mControllers.add(mFlexibilityController);
        mControllers.add(flexibilityController);
        mConnectivityController =
                new ConnectivityController(this, mFlexibilityController);
                new ConnectivityController(this, flexibilityController);
        mControllers.add(mConnectivityController);
        mControllers.add(new TimeController(this));
        final IdleController idleController = new IdleController(this, mFlexibilityController);
        final IdleController idleController = new IdleController(this, flexibilityController);
        mControllers.add(idleController);
        final BatteryController batteryController =
                new BatteryController(this, mFlexibilityController);
                new BatteryController(this, flexibilityController);
        mControllers.add(batteryController);
        mStorageController = new StorageController(this);
        mControllers.add(mStorageController);
@@ -3197,13 +3190,6 @@ public class JobSchedulerService extends com.android.server.SystemService
        }
    }

    @Override
    public void onExemptedBucketChanged(@NonNull ArraySet<JobStatus> changedJobs) {
        if (changedJobs.size() > 0) {
            mFlexibilityController.onExemptedBucketChanged(changedJobs);
        }
    }

    @Override
    public void onRestrictionStateChanged(@NonNull JobRestriction restriction,
            boolean stopOvertimeJobs) {
@@ -3511,10 +3497,7 @@ public class JobSchedulerService extends com.android.server.SystemService
                }

                final boolean shouldForceBatchJob;
                if (job.overrideState > JobStatus.OVERRIDE_NONE) {
                    // The job should run for some test. Don't force batch it.
                    shouldForceBatchJob = false;
                } else if (job.shouldTreatAsExpeditedJob() || job.shouldTreatAsUserInitiatedJob()) {
                if (job.shouldTreatAsExpeditedJob() || job.shouldTreatAsUserInitiatedJob()) {
                    // Never batch expedited or user-initiated jobs, even for RESTRICTED apps.
                    shouldForceBatchJob = false;
                } else if (job.getEffectiveStandbyBucket() == RESTRICTED_INDEX) {
@@ -4967,8 +4950,6 @@ public class JobSchedulerService extends com.android.server.SystemService
        Slog.d(TAG, "executeRunCommand(): " + pkgName + "/" + namespace + "/" + userId
                + " " + jobId + " s=" + satisfied + " f=" + force);

        final CountDownLatch delayLatch = new CountDownLatch(1);
        final JobStatus js;
        try {
            final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0,
                    userId != UserHandle.USER_ALL ? userId : UserHandle.USER_SYSTEM);
@@ -4977,7 +4958,7 @@ public class JobSchedulerService extends com.android.server.SystemService
            }

            synchronized (mLock) {
                js = mJobs.getJobByUidAndJobId(uid, namespace, jobId);
                final JobStatus js = mJobs.getJobByUidAndJobId(uid, namespace, jobId);
                if (js == null) {
                    return JobSchedulerShellCommand.CMD_ERR_NO_JOB;
                }
@@ -4988,45 +4969,9 @@ public class JobSchedulerService extends com.android.server.SystemService
                // Re-evaluate constraints after the override is set in case one of the overridden
                // constraints was preventing another constraint from thinking it needed to update.
                for (int c = mControllers.size() - 1; c >= 0; --c) {
                    mControllers.get(c).evaluateStateLocked(js);
                }

                if (!js.isConstraintsSatisfied()) {
                    if (js.hasConnectivityConstraint()
                            && !js.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY)
                            && js.wouldBeReadyWithConstraint(JobStatus.CONSTRAINT_CONNECTIVITY)) {
                        // Because of how asynchronous the connectivity signals are, JobScheduler
                        // may not get the connectivity satisfaction signal immediately. In this
                        // case, wait a few seconds to see if it comes in before saying the
                        // connectivity constraint isn't satisfied.
                        mHandler.postDelayed(
                                checkConstraintRunnableForTesting(
                                        mHandler, js, delayLatch, 5, 1000),
                                1000);
                    } else {
                        // There's no asynchronous signal to wait for. We can immediately say the
                        // job's constraints aren't satisfied and return.
                        js.overrideState = JobStatus.OVERRIDE_NONE;
                        return JobSchedulerShellCommand.CMD_ERR_CONSTRAINTS;
                    }
                } else {
                    delayLatch.countDown();
                }
            }
        } catch (RemoteException e) {
            // can't happen
            return 0;
                    mControllers.get(c).reevaluateStateLocked(uid);
                }

        // Choose to block the return until we're sure about the state of the connectivity job
        // so that tests can expect a reliable state after calling the run command.
        try {
            delayLatch.await(7L, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Slog.e(TAG, "Couldn't wait for asynchronous constraint change", e);
        }

        synchronized (mLock) {
                if (!js.isConstraintsSatisfied()) {
                    js.overrideState = JobStatus.OVERRIDE_NONE;
                    return JobSchedulerShellCommand.CMD_ERR_CONSTRAINTS;
@@ -5035,22 +4980,10 @@ public class JobSchedulerService extends com.android.server.SystemService
                queueReadyJobsForExecutionLocked();
                maybeRunPendingJobsLocked();
            }
        return 0;
    }

    private static Runnable checkConstraintRunnableForTesting(@NonNull final Handler handler,
            @NonNull final JobStatus js, @NonNull final CountDownLatch latch,
            final int remainingAttempts, final long delayMs) {
        return () -> {
            if (remainingAttempts <= 0 || js.isConstraintsSatisfied()) {
                latch.countDown();
                return;
        } catch (RemoteException e) {
            // can't happen
        }
            handler.postDelayed(
                    checkConstraintRunnableForTesting(
                            handler, js, latch, remainingAttempts - 1, delayMs),
                    delayMs);
        };
        return 0;
    }

    // Shell command infrastructure: immediately timeout currently executing jobs
+0 −6
Original line number Diff line number Diff line
@@ -60,12 +60,6 @@ public interface StateChangedListener {

    void onNetworkChanged(JobStatus jobStatus, Network newNetwork);

    /**
     * Called when these jobs are added or removed from the
     * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_EXEMPTED} bucket.
     */
    void onExemptedBucketChanged(@NonNull ArraySet<JobStatus> jobs);

    /**
     * Called when these jobs are added or removed from the
     * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED} bucket.
+19 −52
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;

import static com.android.server.job.JobSchedulerService.EXEMPTED_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BATTERY_NOT_LOW;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CHARGING;
@@ -181,12 +180,8 @@ public final class FlexibilityController extends StateController {
                }
            };

    private static final int MSG_CHECK_ALL_JOBS = 0;
    /** Check the jobs in {@link #mJobsToCheck} */
    private static final int MSG_CHECK_JOBS = 1;

    @GuardedBy("mLock")
    private final ArraySet<JobStatus> mJobsToCheck = new ArraySet<>();
    private static final int MSG_UPDATE_JOBS = 0;
    private static final int MSG_UPDATE_JOB = 1;

    public FlexibilityController(
            JobSchedulerService service, PrefetchController prefetchController) {
@@ -271,14 +266,7 @@ public final class FlexibilityController extends StateController {
    @GuardedBy("mLock")
    boolean isFlexibilitySatisfiedLocked(JobStatus js) {
        return !mFlexibilityEnabled
                // Exclude all jobs of the TOP app
                || mService.getUidBias(js.getSourceUid()) == JobInfo.BIAS_TOP_APP
                // Only exclude DEFAULT+ priority jobs for BFGS+ apps
                || (mService.getUidBias(js.getSourceUid()) >= JobInfo.BIAS_BOUND_FOREGROUND_SERVICE
                        && js.getEffectivePriority() >= JobInfo.PRIORITY_DEFAULT)
                // Only exclude DEFAULT+ priority jobs for EXEMPTED apps
                || (js.getStandbyBucket() == EXEMPTED_INDEX
                        && js.getEffectivePriority() >= JobInfo.PRIORITY_DEFAULT)
                || hasEnoughSatisfiedConstraintsLocked(js)
                || mService.isCurrentlyRunningLocked(js);
    }
@@ -383,16 +371,8 @@ public final class FlexibilityController extends StateController {

                // Push the job update to the handler to avoid blocking other controllers and
                // potentially batch back-to-back controller state updates together.
                mHandler.obtainMessage(MSG_CHECK_ALL_JOBS).sendToTarget();
            }
        }
                mHandler.obtainMessage(MSG_UPDATE_JOBS).sendToTarget();
            }

    /** Called with a set of apps who have been added to or removed from the exempted bucket. */
    public void onExemptedBucketChanged(@NonNull ArraySet<JobStatus> changedJobs) {
        synchronized (mLock) {
            mJobsToCheck.addAll(changedJobs);
            mHandler.sendEmptyMessage(MSG_CHECK_JOBS);
        }
    }

@@ -505,9 +485,7 @@ public final class FlexibilityController extends StateController {
    @Override
    @GuardedBy("mLock")
    public void onUidBiasChangedLocked(int uid, int prevBias, int newBias) {
        if (prevBias < JobInfo.BIAS_BOUND_FOREGROUND_SERVICE
                && newBias < JobInfo.BIAS_BOUND_FOREGROUND_SERVICE) {
            // All changes are below BFGS. There's no significant change to care about.
        if (prevBias != JobInfo.BIAS_TOP_APP && newBias != JobInfo.BIAS_TOP_APP) {
            return;
        }
        final long nowElapsed = sElapsedRealtimeClock.millis();
@@ -732,8 +710,7 @@ public final class FlexibilityController extends StateController {
                    }
                    mFlexibilityTracker.setNumDroppedFlexibleConstraints(js,
                            js.getNumAppliedFlexibleConstraints());
                    mJobsToCheck.add(js);
                    mHandler.sendEmptyMessage(MSG_CHECK_JOBS);
                    mHandler.obtainMessage(MSG_UPDATE_JOB, js).sendToTarget();
                    return;
                }
                if (nextTimeElapsed == NO_LIFECYCLE_END) {
@@ -784,11 +761,10 @@ public final class FlexibilityController extends StateController {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_CHECK_ALL_JOBS:
                    removeMessages(MSG_CHECK_ALL_JOBS);
                case MSG_UPDATE_JOBS:
                    removeMessages(MSG_UPDATE_JOBS);

                    synchronized (mLock) {
                        mJobsToCheck.clear();
                        final long nowElapsed = sElapsedRealtimeClock.millis();
                        final ArraySet<JobStatus> changedJobs = new ArraySet<>();

@@ -814,25 +790,19 @@ public final class FlexibilityController extends StateController {
                    }
                    break;

                case MSG_CHECK_JOBS:
                case MSG_UPDATE_JOB:
                    synchronized (mLock) {
                        final long nowElapsed = sElapsedRealtimeClock.millis();
                        ArraySet<JobStatus> changedJobs = new ArraySet<>();

                        for (int i = mJobsToCheck.size() - 1; i >= 0; --i) {
                            final JobStatus js = mJobsToCheck.valueAt(i);
                        final JobStatus js = (JobStatus) msg.obj;
                        if (DEBUG) {
                                Slog.d(TAG, "Checking on " + js.toShortString());
                            Slog.d("blah", "Checking on " + js.toShortString());
                        }
                        final long nowElapsed = sElapsedRealtimeClock.millis();
                        if (js.setFlexibilityConstraintSatisfied(
                                nowElapsed, isFlexibilitySatisfiedLocked(js))) {
                                changedJobs.add(js);
                            }
                        }

                        mJobsToCheck.clear();
                        if (changedJobs.size() > 0) {
                            mStateChangedListener.onControllerStateChanged(changedJobs);
                            // TODO(141645789): add method that will take a single job
                            ArraySet<JobStatus> changedJob = new ArraySet<>();
                            changedJob.add(js);
                            mStateChangedListener.onControllerStateChanged(changedJob);
                        }
                    }
                    break;
@@ -1015,10 +985,7 @@ public final class FlexibilityController extends StateController {
            pw.println(":");
            pw.increaseIndent();

            pw.print(KEY_APPLIED_CONSTRAINTS, APPLIED_CONSTRAINTS);
            pw.print("(");
            JobStatus.dumpConstraints(pw, APPLIED_CONSTRAINTS);
            pw.println(")");
            pw.print(KEY_APPLIED_CONSTRAINTS, APPLIED_CONSTRAINTS).println();
            pw.print(KEY_DEADLINE_PROXIMITY_LIMIT, DEADLINE_PROXIMITY_LIMIT_MS).println();
            pw.print(KEY_FALLBACK_FLEXIBILITY_DEADLINE, FALLBACK_FLEXIBILITY_DEADLINE_MS).println();
            pw.print(KEY_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS,
+4 −1
Original line number Diff line number Diff line
@@ -106,8 +106,11 @@ public final class JobStatus {
    public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
    public static final long NO_EARLIEST_RUNTIME = 0L;

    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public static final int CONSTRAINT_CHARGING = JobInfo.CONSTRAINT_FLAG_CHARGING; // 1 < 0
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public static final int CONSTRAINT_IDLE = JobInfo.CONSTRAINT_FLAG_DEVICE_IDLE;  // 1 << 2
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public static final int CONSTRAINT_BATTERY_NOT_LOW =
            JobInfo.CONSTRAINT_FLAG_BATTERY_NOT_LOW; // 1 << 1
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@@ -2191,7 +2194,7 @@ public final class JobStatus {
     * @return Whether or not this job would be ready to run if it had the specified constraint
     * granted, based on its requirements.
     */
    public boolean wouldBeReadyWithConstraint(int constraint) {
    boolean wouldBeReadyWithConstraint(int constraint) {
        return readinessStatusWithConstraint(constraint, true);
    }

+0 −8
Original line number Diff line number Diff line
@@ -2511,7 +2511,6 @@ public final class QuotaController extends StateController {
                    + " to bucketIndex " + bucketIndex);
        }
        List<JobStatus> restrictedChanges = new ArrayList<>();
        ArraySet<JobStatus> exemptedChanges = new ArraySet<>();
        synchronized (mLock) {
            ShrinkableDebits debits = mEJStats.get(userId, packageName);
            if (debits != null) {
@@ -2531,10 +2530,6 @@ public final class QuotaController extends StateController {
                        && bucketIndex != js.getStandbyBucket()) {
                    restrictedChanges.add(js);
                }
                if ((bucketIndex == EXEMPTED_INDEX || js.getStandbyBucket() == EXEMPTED_INDEX)
                        && bucketIndex != js.getStandbyBucket()) {
                    exemptedChanges.add(js);
                }
                js.setStandbyBucket(bucketIndex);
            }
            Timer timer = mPkgTimers.get(userId, packageName);
@@ -2549,9 +2544,6 @@ public final class QuotaController extends StateController {
                    maybeUpdateConstraintForPkgLocked(
                            sElapsedRealtimeClock.millis(), userId, packageName));
        }
        if (exemptedChanges.size() > 0) {
            mStateChangedListener.onExemptedBucketChanged(exemptedChanges);
        }
        if (restrictedChanges.size() > 0) {
            mStateChangedListener.onRestrictedBucketChanged(restrictedChanges);
        }
Loading