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

Commit b0001f6f authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Remove internal locking from JobStatus.

Now all state of JobStatus is implicitly protected by the lock
of whoever is using it -- in this case the global lock for the
JobSchedulerService.  This allows us to remove all of the atomic
variables and just replace those with a simple bit field.

The required constraints for a job are now statically defined
once a JobStatus is created, and don't change.  (They wouldn't
change before, but now this is absolutely specified to be the
case.)  This required tweaking the constructors a bit so that
the earliest and latest run times are computed as part of the
core class initialization.

Also clarified methods on StateController that are called with
the lock held, and took advantage of that in the various
controllers to not now redundantly re-acquire the lock.

Change-Id: I595c5e7d1bff1bd2ff906d612581af82878a25ee
parent 9d3a4e1c
Loading
Loading
Loading
Loading
+24 −30
Original line number Diff line number Diff line
@@ -237,7 +237,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
    }

    public int scheduleAsPackage(JobInfo job, int uId, String packageName, int userId) {
        JobStatus jobStatus = new JobStatus(getLock(), job, uId, packageName, userId);
        JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId);
        try {
            if (ActivityManagerNative.getDefault().getAppStartMode(uId,
                    job.getService().getPackageName()) == ActivityManager.APP_START_MODE_DISABLED) {
@@ -476,7 +476,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
                    JobStatus job = jobs.valueAt(i);
                    for (int controller=0; controller<mControllers.size(); controller++) {
                        mControllers.get(controller).deviceIdleModeChanged(mDeviceIdleMode);
                        mControllers.get(controller).maybeStartTrackingJob(job, null);
                        mControllers.get(controller).maybeStartTrackingJobLocked(job, null);
                    }
                }
                // GO GO GO!
@@ -491,19 +491,16 @@ public final class JobSchedulerService extends com.android.server.SystemService
     * about.
     */
    private void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) {
        boolean update;
        boolean rocking;
        synchronized (mLock) {
            update = mJobs.add(jobStatus);
            rocking = mReadyToRock;
        }
        if (rocking) {
            final boolean update = mJobs.add(jobStatus);
            if (mReadyToRock) {
                for (int i = 0; i < mControllers.size(); i++) {
                    StateController controller = mControllers.get(i);
                    if (update) {
                    controller.maybeStopTrackingJob(jobStatus, true);
                        controller.maybeStopTrackingJobLocked(jobStatus, true);
                    }
                    controller.maybeStartTrackingJobLocked(jobStatus, lastJob);
                }
                controller.maybeStartTrackingJob(jobStatus, lastJob);
            }
        }
    }
@@ -513,21 +510,18 @@ public final class JobSchedulerService extends com.android.server.SystemService
     * object removed.
     */
    private boolean stopTrackingJob(JobStatus jobStatus, boolean writeBack) {
        boolean removed;
        boolean rocking;
        synchronized (mLock) {
            // Remove from store as well as controllers.
            removed = mJobs.remove(jobStatus, writeBack);
            rocking = mReadyToRock;
        }
        if (removed && rocking) {
            final boolean removed = mJobs.remove(jobStatus, writeBack);
            if (removed && mReadyToRock) {
                for (int i=0; i<mControllers.size(); i++) {
                    StateController controller = mControllers.get(i);
                controller.maybeStopTrackingJob(jobStatus, false);
                    controller.maybeStopTrackingJobLocked(jobStatus, false);
                }
            }
            return removed;
        }
    }

    private boolean stopJobOnServiceContextLocked(JobStatus job, int reason) {
        for (int i=0; i<mActiveServices.size(); i++) {
@@ -759,7 +753,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
                        Slog.d(TAG, "    queued " + job.toShortString());
                    }
                    mPendingJobs.add(job);
                } else if (areJobConstraintsNotSatisfied(job)) {
                } else if (areJobConstraintsNotSatisfiedLocked(job)) {
                    stopJobOnServiceContextLocked(job,
                            JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED);
                }
@@ -826,7 +820,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
                        runnableJobs = new ArrayList<>();
                    }
                    runnableJobs.add(job);
                } else if (areJobConstraintsNotSatisfied(job)) {
                } else if (areJobConstraintsNotSatisfiedLocked(job)) {
                    stopJobOnServiceContextLocked(job,
                            JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED);
                }
@@ -875,7 +869,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
         *      - It's not ready
         *      - It's running on a JSC.
         */
        private boolean areJobConstraintsNotSatisfied(JobStatus job) {
        private boolean areJobConstraintsNotSatisfiedLocked(JobStatus job) {
            return !job.isReady() && isCurrentlyActiveLocked(job);
        }

@@ -893,7 +887,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
                if (DEBUG) {
                    Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs.");
                }
                assignJobsToContextsH();
                assignJobsToContextsLocked();
                reportActive();
            }
        }
@@ -905,7 +899,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
     * run higher priority ones.
     * Lock on mJobs before calling this function.
     */
    private void assignJobsToContextsH() {
    private void assignJobsToContextsLocked() {
        if (DEBUG) {
            Slog.d(TAG, printPendingQueue());
        }
@@ -990,7 +984,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
                    }
                    for (int ic=0; ic<mControllers.size(); ic++) {
                        StateController controller = mControllers.get(ic);
                        controller.prepareForExecution(contextIdToJobMap[i]);
                        controller.prepareForExecutionLocked(contextIdToJobMap[i]);
                    }
                    if (!mActiveServices.get(i).executeRunnableJob(contextIdToJobMap[i])) {
                        Slog.d(TAG, "Error executing " + contextIdToJobMap[i]);
@@ -1222,7 +1216,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
            }
            for (int i=0; i<mControllers.size(); i++) {
                pw.println();
                mControllers.get(i).dumpControllerState(pw);
                mControllers.get(i).dumpControllerStateLocked(pw);
            }
            pw.println();
            pw.println(printPendingQueue());
+1 −2
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

@@ -680,7 +679,7 @@ public class JobStore {
            parser.nextTag(); // Consume </extras>

            JobStatus js = new JobStatus(
                    mLock, jobBuilder.build(), uid, sourcePackageName, sourceUserId,
                    jobBuilder.build(), uid, sourcePackageName, sourceUserId,
                    elapsedRuntimes.first, elapsedRuntimes.second);
            return js;
        }
+20 −27
Original line number Diff line number Diff line
@@ -64,8 +64,7 @@ public class AppIdleController extends StateController {
    }

    @Override
    public void maybeStartTrackingJob(JobStatus jobStatus, JobStatus lastJob) {
        synchronized (mLock) {
    public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
        mTrackedTasks.add(jobStatus);
        String packageName = jobStatus.getSourcePackageName();
        final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
@@ -74,30 +73,26 @@ public class AppIdleController extends StateController {
            Slog.d(LOG_TAG, "Start tracking, setting idle state of "
                    + packageName + " to " + appIdle);
        }
            jobStatus.appNotIdleConstraintSatisfied.set(!appIdle);
        }
        jobStatus.setAppNotIdleConstraintSatisfied(!appIdle);
    }

    @Override
    public void maybeStopTrackingJob(JobStatus jobStatus, boolean forUpdate) {
        synchronized (mLock) {
    public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) {
        mTrackedTasks.remove(jobStatus);
    }
    }

    @Override
    public void dumpControllerState(PrintWriter pw) {
    public void dumpControllerStateLocked(PrintWriter pw) {
        pw.println("AppIdle");
        pw.println("Parole On: " + mAppIdleParoleOn);
        synchronized (mLock) {
        for (JobStatus task : mTrackedTasks) {
            pw.print(task.getSourcePackageName());
                pw.print(":idle=" + !task.appNotIdleConstraintSatisfied.get());
            pw.print(":idle="
                    + ((task.satisfiedConstraints&JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0));
            pw.print(", ");
        }
        pw.println();
    }
    }

    void setAppIdleParoleOn(boolean isAppIdleParoleOn) {
        // Flag if any app's idle state has changed
@@ -114,8 +109,7 @@ public class AppIdleController extends StateController {
                if (DEBUG) {
                    Slog.d(LOG_TAG, "Setting idle state of " + packageName + " to " + appIdle);
                }
                if (task.appNotIdleConstraintSatisfied.get() == appIdle) {
                    task.appNotIdleConstraintSatisfied.set(!appIdle);
                if (task.setAppNotIdleConstraintSatisfied(!appIdle)) {
                    changed = true;
                }
            }
@@ -137,12 +131,11 @@ public class AppIdleController extends StateController {
                for (JobStatus task : mTrackedTasks) {
                    if (task.getSourcePackageName().equals(packageName)
                            && task.getSourceUserId() == userId) {
                        if (task.appNotIdleConstraintSatisfied.get() != !idle) {
                        if (task.setAppNotIdleConstraintSatisfied(!idle)) {
                            if (DEBUG) {
                                Slog.d(LOG_TAG, "App Idle state changed, setting idle state of "
                                        + packageName + " to " + idle);
                            }
                            task.appNotIdleConstraintSatisfied.set(!idle);
                            changed = true;
                        }
                    }
+14 −20
Original line number Diff line number Diff line
@@ -78,24 +78,20 @@ public class BatteryController extends StateController {
    }

    @Override
    public void maybeStartTrackingJob(JobStatus taskStatus, JobStatus lastJob) {
    public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
        final boolean isOnStablePower = mChargeTracker.isOnStablePower();
        if (taskStatus.hasChargingConstraint()) {
            synchronized (mLock) {
            mTrackedTasks.add(taskStatus);
                taskStatus.chargingConstraintSatisfied.set(isOnStablePower);
            }
            taskStatus.setChargingConstraintSatisfied(isOnStablePower);
        }
    }

    @Override
    public void maybeStopTrackingJob(JobStatus taskStatus, boolean forUpdate) {
    public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) {
        if (taskStatus.hasChargingConstraint()) {
            synchronized (mLock) {
            mTrackedTasks.remove(taskStatus);
        }
    }
    }

    private void maybeReportNewChargingState() {
        final boolean stablePower = mChargeTracker.isOnStablePower();
@@ -105,7 +101,7 @@ public class BatteryController extends StateController {
        boolean reportChange = false;
        synchronized (mLock) {
            for (JobStatus ts : mTrackedTasks) {
                boolean previous = ts.chargingConstraintSatisfied.getAndSet(stablePower);
                boolean previous = ts.setChargingConstraintSatisfied(stablePower);
                if (previous != stablePower) {
                    reportChange = true;
                }
@@ -198,10 +194,9 @@ public class BatteryController extends StateController {
    }

    @Override
    public void dumpControllerState(PrintWriter pw) {
    public void dumpControllerStateLocked(PrintWriter pw) {
        pw.println("Batt.");
        pw.println("Stable power: " + mChargeTracker.isOnStablePower());
        synchronized (mLock) {
        Iterator<JobStatus> it = mTrackedTasks.iterator();
        if (it.hasNext()) {
            pw.print(String.valueOf(it.next().hashCode()));
@@ -212,4 +207,3 @@ public class BatteryController extends StateController {
        pw.println();
    }
}
}
+9 −17
Original line number Diff line number Diff line
@@ -83,24 +83,20 @@ public class ConnectivityController extends StateController implements
    }

    @Override
    public void maybeStartTrackingJob(JobStatus jobStatus, JobStatus lastJob) {
    public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
        if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) {
            synchronized (mLock) {
                jobStatus.connectivityConstraintSatisfied.set(mNetworkConnected);
                jobStatus.unmeteredConstraintSatisfied.set(mNetworkUnmetered);
            jobStatus.setConnectivityConstraintSatisfied(mNetworkConnected);
            jobStatus.setUnmeteredConstraintSatisfied(mNetworkUnmetered);
            mTrackedJobs.add(jobStatus);
        }
    }
    }

    @Override
    public void maybeStopTrackingJob(JobStatus jobStatus, boolean forUpdate) {
    public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) {
        if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) {
            synchronized (mLock) {
            mTrackedJobs.remove(jobStatus);
        }
    }
    }

    /**
     * @param userId Id of the user for whom we are updating the connectivity state.
@@ -112,12 +108,8 @@ public class ConnectivityController extends StateController implements
                if (js.getUserId() != userId) {
                    continue;
                }
                boolean prevIsConnected =
                        js.connectivityConstraintSatisfied.getAndSet(mNetworkConnected);
                boolean prevIsMetered = js.unmeteredConstraintSatisfied.getAndSet(mNetworkUnmetered);
                if (prevIsConnected != mNetworkConnected || prevIsMetered != mNetworkUnmetered) {
                    changed = true;
                }
                changed |= js.setConnectivityConstraintSatisfied(mNetworkConnected);
                changed |= js.setUnmeteredConstraintSatisfied(mNetworkUnmetered);
            }
            if (changed) {
                mStateChangedListener.onControllerStateChanged();
@@ -189,7 +181,7 @@ public class ConnectivityController extends StateController implements
    };

    @Override
    public void dumpControllerState(PrintWriter pw) {
    public void dumpControllerStateLocked(PrintWriter pw) {
        pw.println("Conn.");
        pw.println("connected: " + mNetworkConnected + " unmetered: " + mNetworkUnmetered);
        for (JobStatus js: mTrackedJobs) {
Loading