diff --git a/apex/jobscheduler/README_js-mainline.md b/apex/jobscheduler/README_js-mainline.md
new file mode 100644
index 0000000..b5fea5e
--- /dev/null
+++ b/apex/jobscheduler/README_js-mainline.md
@@ -0,0 +1,51 @@
+# Making Job Scheduler into a Mainline Module
+
+## TODOs
+
+See also:
+- http://go/moving-js-code-for-mainline
+- http://go/jobscheduler-code-dependencies-2019-07
+
+- [ ] Move client code
+  - [ ] Move code
+  - [ ] Make build file
+  - [ ] "m jobscheduler-framework" pass
+  - [ ] "m framework" pass
+  - [ ] "m service" pass
+- [ ] Move proto
+  - No, couldn't do it, because it's referred to by incidentd_proto
+- [ ] Move service
+  - [X] Move code (done, but it won't compile yet)
+  - [X] Make build file
+  - [X] "m service" pass
+  - [X] "m jobscheduler-service" pass
+    - To make it pass, jobscheduler-service has to link services.jar too. Many dependencies.
+- [ ] Move this into `frameworks/apex/jobscheduler/...`. Currently it's in `frameworks/base/apex/...`
+because `frameworks/apex/` is not a part of any git projects. (and also working on multiple
+projects is a pain.)
+
+
+## Problems
+- Couldn't move dumpsys proto files. They are used by incidentd_proto, which is in the platform
+  (not updatable).
+  - One idea is *not* to move the proto files into apex but keep them in the platform.
+    Then we make sure to extend the proto files in a backward-compat way (which we do anyway)
+    and always use the latest file from the JS apex.
+
+- There are a lot of build tasks that use "framework.jar". (Examples: hiddenapi-greylist.txt check,
+  update-api / public API check and SDK stub (android.jar) creation)
+  To make the downstream build modules buildable, we need to include js-framework.jar in
+  framework.jar. However it turned out to be tricky because soong has special logic for "framework"
+  and "framework.jar".
+  i.e. Conceptually, we can do it by renaming `framework` to `framework-minus-jobscheduler`, build
+  `jobscheduler-framework` with `framework-minus-jobscheduler`, and create `framework` by merging
+  `framework-minus-jobscheduler` and `jobscheduler-framework`.
+  However it didn't quite work because of the special casing.
+
+- JS-service uses a lot of other code in `services`, so it needs to link services.core.jar e.g.
+ - Common system service code, e.g. `com.android.server.SystemService`
+ - Common utility code, e.g. `FgThread` and `IoThread`
+ - Other system services such as `DeviceIdleController` and `ActivityManagerService`
+ - Server side singleton. `AppStateTracker`
+ - `DeviceIdleController.LocalService`, which is a local service but there's no interface class.
+ - `XxxInternal` interfaces that are not in the framework side. -> We should be able to move them.
diff --git a/apex/jobscheduler/service/Android.bp b/apex/jobscheduler/service/Android.bp
new file mode 100644
index 0000000..ca6dc45
--- /dev/null
+++ b/apex/jobscheduler/service/Android.bp
@@ -0,0 +1,15 @@
+// Job Scheduler Service jar, which will eventually be put in the jobscheduler mainline apex.
+// jobscheduler-service needs to be added to PRODUCT_SYSTEM_SERVER_JARS.
+java_library {
+    name: "jobscheduler-service",
+    installable: true,
+
+    srcs: [
+        "java/**/*.java",
+    ],
+
+    libs: [
+        "framework",
+        "services.core",
+    ],
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/GrantedUriPermissions.java b/apex/jobscheduler/service/java/com/android/server/job/GrantedUriPermissions.java
new file mode 100644
index 0000000..005b189
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/GrantedUriPermissions.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job;
+
+import android.app.IActivityManager;
+import android.app.UriGrantsManager;
+import android.content.ClipData;
+import android.content.ContentProvider;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+import com.android.server.LocalServices;
+import com.android.server.uri.UriGrantsManagerInternal;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+public final class GrantedUriPermissions {
+    private final int mGrantFlags;
+    private final int mSourceUserId;
+    private final String mTag;
+    private final IBinder mPermissionOwner;
+    private final ArrayList<Uri> mUris = new ArrayList<>();
+
+    private GrantedUriPermissions(IActivityManager am, int grantFlags, int uid, String tag)
+            throws RemoteException {
+        mGrantFlags = grantFlags;
+        mSourceUserId = UserHandle.getUserId(uid);
+        mTag = tag;
+        mPermissionOwner = LocalServices
+                .getService(UriGrantsManagerInternal.class).newUriPermissionOwner("job: " + tag);
+    }
+
+    public void revoke(IActivityManager am) {
+        for (int i = mUris.size()-1; i >= 0; i--) {
+            LocalServices.getService(UriGrantsManagerInternal.class).revokeUriPermissionFromOwner(
+                    mPermissionOwner, mUris.get(i), mGrantFlags, mSourceUserId);
+        }
+        mUris.clear();
+    }
+
+    public static boolean checkGrantFlags(int grantFlags) {
+        return (grantFlags & (Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                |Intent.FLAG_GRANT_READ_URI_PERMISSION)) != 0;
+    }
+
+    public static GrantedUriPermissions createFromIntent(IActivityManager am, Intent intent,
+            int sourceUid, String targetPackage, int targetUserId, String tag) {
+        int grantFlags = intent.getFlags();
+        if (!checkGrantFlags(grantFlags)) {
+            return null;
+        }
+
+        GrantedUriPermissions perms = null;
+
+        Uri data = intent.getData();
+        if (data != null) {
+            perms = grantUri(am, data, sourceUid, targetPackage, targetUserId, grantFlags, tag,
+                    perms);
+        }
+
+        ClipData clip = intent.getClipData();
+        if (clip != null) {
+            perms = grantClip(am, clip, sourceUid, targetPackage, targetUserId, grantFlags, tag,
+                    perms);
+        }
+
+        return perms;
+    }
+
+    public static GrantedUriPermissions createFromClip(IActivityManager am, ClipData clip,
+            int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag) {
+        if (!checkGrantFlags(grantFlags)) {
+            return null;
+        }
+        GrantedUriPermissions perms = null;
+        if (clip != null) {
+            perms = grantClip(am, clip, sourceUid, targetPackage, targetUserId, grantFlags,
+                    tag, perms);
+        }
+        return perms;
+    }
+
+    private static GrantedUriPermissions grantClip(IActivityManager am, ClipData clip,
+            int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag,
+            GrantedUriPermissions curPerms) {
+        final int N = clip.getItemCount();
+        for (int i = 0; i < N; i++) {
+            curPerms = grantItem(am, clip.getItemAt(i), sourceUid, targetPackage, targetUserId,
+                    grantFlags, tag, curPerms);
+        }
+        return curPerms;
+    }
+
+    private static GrantedUriPermissions grantUri(IActivityManager am, Uri uri,
+            int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag,
+            GrantedUriPermissions curPerms) {
+        try {
+            int sourceUserId = ContentProvider.getUserIdFromUri(uri,
+                    UserHandle.getUserId(sourceUid));
+            uri = ContentProvider.getUriWithoutUserId(uri);
+            if (curPerms == null) {
+                curPerms = new GrantedUriPermissions(am, grantFlags, sourceUid, tag);
+            }
+            UriGrantsManager.getService().grantUriPermissionFromOwner(curPerms.mPermissionOwner,
+                    sourceUid, targetPackage, uri, grantFlags, sourceUserId, targetUserId);
+            curPerms.mUris.add(uri);
+        } catch (RemoteException e) {
+            Slog.e("JobScheduler", "AM dead");
+        }
+        return curPerms;
+    }
+
+    private static GrantedUriPermissions grantItem(IActivityManager am, ClipData.Item item,
+            int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag,
+            GrantedUriPermissions curPerms) {
+        if (item.getUri() != null) {
+            curPerms = grantUri(am, item.getUri(), sourceUid, targetPackage, targetUserId,
+                    grantFlags, tag, curPerms);
+        }
+        Intent intent = item.getIntent();
+        if (intent != null && intent.getData() != null) {
+            curPerms = grantUri(am, intent.getData(), sourceUid, targetPackage, targetUserId,
+                    grantFlags, tag, curPerms);
+        }
+        return curPerms;
+    }
+
+    // Dumpsys infrastructure
+    public void dump(PrintWriter pw, String prefix) {
+        pw.print(prefix); pw.print("mGrantFlags=0x"); pw.print(Integer.toHexString(mGrantFlags));
+        pw.print(" mSourceUserId="); pw.println(mSourceUserId);
+        pw.print(prefix); pw.print("mTag="); pw.println(mTag);
+        pw.print(prefix); pw.print("mPermissionOwner="); pw.println(mPermissionOwner);
+        for (int i = 0; i < mUris.size(); i++) {
+            pw.print(prefix); pw.print("#"); pw.print(i); pw.print(": ");
+            pw.println(mUris.get(i));
+        }
+    }
+
+    public void dump(ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+
+        proto.write(GrantedUriPermissionsDumpProto.FLAGS, mGrantFlags);
+        proto.write(GrantedUriPermissionsDumpProto.SOURCE_USER_ID, mSourceUserId);
+        proto.write(GrantedUriPermissionsDumpProto.TAG, mTag);
+        proto.write(GrantedUriPermissionsDumpProto.PERMISSION_OWNER, mPermissionOwner.toString());
+        for (int i = 0; i < mUris.size(); i++) {
+            Uri u = mUris.get(i);
+            if (u != null) {
+                proto.write(GrantedUriPermissionsDumpProto.URIS, u.toString());
+            }
+        }
+
+        proto.end(token);
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobCompletedListener.java b/apex/jobscheduler/service/java/com/android/server/job/JobCompletedListener.java
new file mode 100644
index 0000000..34ba753b3
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobCompletedListener.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job;
+
+import com.android.server.job.controllers.JobStatus;
+
+/**
+ * Used for communication between {@link com.android.server.job.JobServiceContext} and the
+ * {@link com.android.server.job.JobSchedulerService}.
+ */
+public interface JobCompletedListener {
+    /**
+     * Callback for when a job is completed.
+     * @param needsReschedule Whether the implementing class should reschedule this job.
+     */
+    void onJobCompletedLocked(JobStatus jobStatus, boolean needsReschedule);
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
new file mode 100644
index 0000000..bec1947
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
@@ -0,0 +1,722 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.job;
+
+import android.app.ActivityManager;
+import android.app.job.JobInfo;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.procstats.ProcessStats;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.StatLogger;
+import com.android.server.job.JobSchedulerService.Constants;
+import com.android.server.job.JobSchedulerService.MaxJobCountsPerMemoryTrimLevel;
+import com.android.server.job.controllers.JobStatus;
+import com.android.server.job.controllers.StateController;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * This class decides, given the various configuration and the system status, how many more jobs
+ * can start.
+ */
+class JobConcurrencyManager {
+    private static final String TAG = JobSchedulerService.TAG;
+    private static final boolean DEBUG = JobSchedulerService.DEBUG;
+
+    private final Object mLock;
+    private final JobSchedulerService mService;
+    private final JobSchedulerService.Constants mConstants;
+    private final Context mContext;
+    private final Handler mHandler;
+
+    private PowerManager mPowerManager;
+
+    private boolean mCurrentInteractiveState;
+    private boolean mEffectiveInteractiveState;
+
+    private long mLastScreenOnRealtime;
+    private long mLastScreenOffRealtime;
+
+    private static final int MAX_JOB_CONTEXTS_COUNT = JobSchedulerService.MAX_JOB_CONTEXTS_COUNT;
+
+    /**
+     * This array essentially stores the state of mActiveServices array.
+     * The ith index stores the job present on the ith JobServiceContext.
+     * We manipulate this array until we arrive at what jobs should be running on
+     * what JobServiceContext.
+     */
+    JobStatus[] mRecycledAssignContextIdToJobMap = new JobStatus[MAX_JOB_CONTEXTS_COUNT];
+
+    boolean[] mRecycledSlotChanged = new boolean[MAX_JOB_CONTEXTS_COUNT];
+
+    int[] mRecycledPreferredUidForContext = new int[MAX_JOB_CONTEXTS_COUNT];
+
+    /** Max job counts according to the current system state. */
+    private JobSchedulerService.MaxJobCounts mMaxJobCounts;
+
+    private final JobCountTracker mJobCountTracker = new JobCountTracker();
+
+    /** Current memory trim level. */
+    private int mLastMemoryTrimLevel;
+
+    /** Used to throttle heavy API calls. */
+    private long mNextSystemStateRefreshTime;
+    private static final int SYSTEM_STATE_REFRESH_MIN_INTERVAL = 1000;
+
+    private final StatLogger mStatLogger = new StatLogger(new String[]{
+            "assignJobsToContexts",
+            "refreshSystemState",
+    });
+
+    interface Stats {
+        int ASSIGN_JOBS_TO_CONTEXTS = 0;
+        int REFRESH_SYSTEM_STATE = 1;
+
+        int COUNT = REFRESH_SYSTEM_STATE + 1;
+    }
+
+    JobConcurrencyManager(JobSchedulerService service) {
+        mService = service;
+        mLock = mService.mLock;
+        mConstants = service.mConstants;
+        mContext = service.getContext();
+
+        mHandler = BackgroundThread.getHandler();
+    }
+
+    public void onSystemReady() {
+        mPowerManager = mContext.getSystemService(PowerManager.class);
+
+        final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
+        mContext.registerReceiver(mReceiver, filter);
+
+        onInteractiveStateChanged(mPowerManager.isInteractive());
+    }
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case Intent.ACTION_SCREEN_ON:
+                    onInteractiveStateChanged(true);
+                    break;
+                case Intent.ACTION_SCREEN_OFF:
+                    onInteractiveStateChanged(false);
+                    break;
+            }
+        }
+    };
+
+    /**
+     * Called when the screen turns on / off.
+     */
+    private void onInteractiveStateChanged(boolean interactive) {
+        synchronized (mLock) {
+            if (mCurrentInteractiveState == interactive) {
+                return;
+            }
+            mCurrentInteractiveState = interactive;
+            if (DEBUG) {
+                Slog.d(TAG, "Interactive: " + interactive);
+            }
+
+            final long nowRealtime = JobSchedulerService.sElapsedRealtimeClock.millis();
+            if (interactive) {
+                mLastScreenOnRealtime = nowRealtime;
+                mEffectiveInteractiveState = true;
+
+                mHandler.removeCallbacks(mRampUpForScreenOff);
+            } else {
+                mLastScreenOffRealtime = nowRealtime;
+
+                // Set mEffectiveInteractiveState to false after the delay, when we may increase
+                // the concurrency.
+                // We don't need a wakeup alarm here. When there's a pending job, there should
+                // also be jobs running too, meaning the device should be awake.
+
+                // Note: we can't directly do postDelayed(this::rampUpForScreenOn), because
+                // we need the exact same instance for removeCallbacks().
+                mHandler.postDelayed(mRampUpForScreenOff,
+                        mConstants.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.getValue());
+            }
+        }
+    }
+
+    private final Runnable mRampUpForScreenOff = this::rampUpForScreenOff;
+
+    /**
+     * Called in {@link Constants#SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS} after
+     * the screen turns off, in order to increase concurrency.
+     */
+    private void rampUpForScreenOff() {
+        synchronized (mLock) {
+            // Make sure the screen has really been off for the configured duration.
+            // (There could be a race.)
+            if (!mEffectiveInteractiveState) {
+                return;
+            }
+            if (mLastScreenOnRealtime > mLastScreenOffRealtime) {
+                return;
+            }
+            final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
+            if ((mLastScreenOffRealtime
+                    + mConstants.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.getValue())
+                    > now) {
+                return;
+            }
+
+            mEffectiveInteractiveState = false;
+
+            if (DEBUG) {
+                Slog.d(TAG, "Ramping up concurrency");
+            }
+
+            mService.maybeRunPendingJobsLocked();
+        }
+    }
+
+    private boolean isFgJob(JobStatus job) {
+        return job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP;
+    }
+
+    @GuardedBy("mLock")
+    private void refreshSystemStateLocked() {
+        final long nowUptime = JobSchedulerService.sUptimeMillisClock.millis();
+
+        // Only refresh the information every so often.
+        if (nowUptime < mNextSystemStateRefreshTime) {
+            return;
+        }
+
+        final long start = mStatLogger.getTime();
+        mNextSystemStateRefreshTime = nowUptime + SYSTEM_STATE_REFRESH_MIN_INTERVAL;
+
+        mLastMemoryTrimLevel = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+        try {
+            mLastMemoryTrimLevel = ActivityManager.getService().getMemoryTrimLevel();
+        } catch (RemoteException e) {
+        }
+
+        mStatLogger.logDurationStat(Stats.REFRESH_SYSTEM_STATE, start);
+    }
+
+    @GuardedBy("mLock")
+    private void updateMaxCountsLocked() {
+        refreshSystemStateLocked();
+
+        final MaxJobCountsPerMemoryTrimLevel jobCounts = mEffectiveInteractiveState
+                ? mConstants.MAX_JOB_COUNTS_SCREEN_ON
+                : mConstants.MAX_JOB_COUNTS_SCREEN_OFF;
+
+
+        switch (mLastMemoryTrimLevel) {
+            case ProcessStats.ADJ_MEM_FACTOR_MODERATE:
+                mMaxJobCounts = jobCounts.moderate;
+                break;
+            case ProcessStats.ADJ_MEM_FACTOR_LOW:
+                mMaxJobCounts = jobCounts.low;
+                break;
+            case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
+                mMaxJobCounts = jobCounts.critical;
+                break;
+            default:
+                mMaxJobCounts = jobCounts.normal;
+                break;
+        }
+    }
+
+    /**
+     * Takes jobs from pending queue and runs them on available contexts.
+     * If no contexts are available, preempts lower priority jobs to
+     * run higher priority ones.
+     * Lock on mJobs before calling this function.
+     */
+    @GuardedBy("mLock")
+    void assignJobsToContextsLocked() {
+        final long start = mStatLogger.getTime();
+
+        assignJobsToContextsInternalLocked();
+
+        mStatLogger.logDurationStat(Stats.ASSIGN_JOBS_TO_CONTEXTS, start);
+    }
+
+    @GuardedBy("mLock")
+    private void assignJobsToContextsInternalLocked() {
+        if (DEBUG) {
+            Slog.d(TAG, printPendingQueueLocked());
+        }
+
+        final JobPackageTracker tracker = mService.mJobPackageTracker;
+        final List<JobStatus> pendingJobs = mService.mPendingJobs;
+        final List<JobServiceContext> activeServices = mService.mActiveServices;
+        final List<StateController> controllers = mService.mControllers;
+
+        updateMaxCountsLocked();
+
+        // To avoid GC churn, we recycle the arrays.
+        JobStatus[] contextIdToJobMap = mRecycledAssignContextIdToJobMap;
+        boolean[] slotChanged = mRecycledSlotChanged;
+        int[] preferredUidForContext = mRecycledPreferredUidForContext;
+
+
+        // Initialize the work variables and also count running jobs.
+        mJobCountTracker.reset(
+                mMaxJobCounts.getMaxTotal(),
+                mMaxJobCounts.getMaxBg(),
+                mMaxJobCounts.getMinBg());
+
+        for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) {
+            final JobServiceContext js = mService.mActiveServices.get(i);
+            final JobStatus status = js.getRunningJobLocked();
+
+            if ((contextIdToJobMap[i] = status) != null) {
+                mJobCountTracker.incrementRunningJobCount(isFgJob(status));
+            }
+
+            slotChanged[i] = false;
+            preferredUidForContext[i] = js.getPreferredUid();
+        }
+        if (DEBUG) {
+            Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs initial"));
+        }
+
+        // Next, update the job priorities, and also count the pending FG / BG jobs.
+        for (int i = 0; i < pendingJobs.size(); i++) {
+            final JobStatus pending = pendingJobs.get(i);
+
+            // If job is already running, go to next job.
+            int jobRunningContext = findJobContextIdFromMap(pending, contextIdToJobMap);
+            if (jobRunningContext != -1) {
+                continue;
+            }
+
+            final int priority = mService.evaluateJobPriorityLocked(pending);
+            pending.lastEvaluatedPriority = priority;
+
+            mJobCountTracker.incrementPendingJobCount(isFgJob(pending));
+        }
+
+        mJobCountTracker.onCountDone();
+
+        for (int i = 0; i < pendingJobs.size(); i++) {
+            final JobStatus nextPending = pendingJobs.get(i);
+
+            // Unfortunately we need to repeat this relatively expensive check.
+            int jobRunningContext = findJobContextIdFromMap(nextPending, contextIdToJobMap);
+            if (jobRunningContext != -1) {
+                continue;
+            }
+
+            final boolean isPendingFg = isFgJob(nextPending);
+
+            // Find an available slot for nextPending. The context should be available OR
+            // it should have lowest priority among all running jobs
+            // (sharing the same Uid as nextPending)
+            int minPriorityForPreemption = Integer.MAX_VALUE;
+            int selectedContextId = -1;
+            boolean startingJob = false;
+            for (int j=0; j<MAX_JOB_CONTEXTS_COUNT; j++) {
+                JobStatus job = contextIdToJobMap[j];
+                int preferredUid = preferredUidForContext[j];
+                if (job == null) {
+                    final boolean preferredUidOkay = (preferredUid == nextPending.getUid())
+                            || (preferredUid == JobServiceContext.NO_PREFERRED_UID);
+
+                    if (preferredUidOkay && mJobCountTracker.canJobStart(isPendingFg)) {
+                        // This slot is free, and we haven't yet hit the limit on
+                        // concurrent jobs...  we can just throw the job in to here.
+                        selectedContextId = j;
+                        startingJob = true;
+                        break;
+                    }
+                    // No job on this context, but nextPending can't run here because
+                    // the context has a preferred Uid or we have reached the limit on
+                    // concurrent jobs.
+                    continue;
+                }
+                if (job.getUid() != nextPending.getUid()) {
+                    continue;
+                }
+
+                final int jobPriority = mService.evaluateJobPriorityLocked(job);
+                if (jobPriority >= nextPending.lastEvaluatedPriority) {
+                    continue;
+                }
+
+                // TODO lastEvaluatedPriority should be evaluateJobPriorityLocked. (double check it)
+                if (minPriorityForPreemption > nextPending.lastEvaluatedPriority) {
+                    minPriorityForPreemption = nextPending.lastEvaluatedPriority;
+                    selectedContextId = j;
+                    // In this case, we're just going to preempt a low priority job, we're not
+                    // actually starting a job, so don't set startingJob.
+                }
+            }
+            if (selectedContextId != -1) {
+                contextIdToJobMap[selectedContextId] = nextPending;
+                slotChanged[selectedContextId] = true;
+            }
+            if (startingJob) {
+                // Increase the counters when we're going to start a job.
+                mJobCountTracker.onStartingNewJob(isPendingFg);
+            }
+        }
+        if (DEBUG) {
+            Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs final"));
+        }
+
+        mJobCountTracker.logStatus();
+
+        tracker.noteConcurrency(mJobCountTracker.getTotalRunningJobCountToNote(),
+                mJobCountTracker.getFgRunningJobCountToNote());
+
+        for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) {
+            boolean preservePreferredUid = false;
+            if (slotChanged[i]) {
+                JobStatus js = activeServices.get(i).getRunningJobLocked();
+                if (js != null) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "preempting job: "
+                                + activeServices.get(i).getRunningJobLocked());
+                    }
+                    // preferredUid will be set to uid of currently running job.
+                    activeServices.get(i).preemptExecutingJobLocked();
+                    preservePreferredUid = true;
+                } else {
+                    final JobStatus pendingJob = contextIdToJobMap[i];
+                    if (DEBUG) {
+                        Slog.d(TAG, "About to run job on context "
+                                + i + ", job: " + pendingJob);
+                    }
+                    for (int ic=0; ic<controllers.size(); ic++) {
+                        controllers.get(ic).prepareForExecutionLocked(pendingJob);
+                    }
+                    if (!activeServices.get(i).executeRunnableJob(pendingJob)) {
+                        Slog.d(TAG, "Error executing " + pendingJob);
+                    }
+                    if (pendingJobs.remove(pendingJob)) {
+                        tracker.noteNonpending(pendingJob);
+                    }
+                }
+            }
+            if (!preservePreferredUid) {
+                activeServices.get(i).clearPreferredUid();
+            }
+        }
+    }
+
+    private static int findJobContextIdFromMap(JobStatus jobStatus, JobStatus[] map) {
+        for (int i=0; i<map.length; i++) {
+            if (map[i] != null && map[i].matches(jobStatus.getUid(), jobStatus.getJobId())) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    @GuardedBy("mLock")
+    private String printPendingQueueLocked() {
+        StringBuilder s = new StringBuilder("Pending queue: ");
+        Iterator<JobStatus> it = mService.mPendingJobs.iterator();
+        while (it.hasNext()) {
+            JobStatus js = it.next();
+            s.append("(")
+                    .append(js.getJob().getId())
+                    .append(", ")
+                    .append(js.getUid())
+                    .append(") ");
+        }
+        return s.toString();
+    }
+
+    private static String printContextIdToJobMap(JobStatus[] map, String initial) {
+        StringBuilder s = new StringBuilder(initial + ": ");
+        for (int i=0; i<map.length; i++) {
+            s.append("(")
+                    .append(map[i] == null? -1: map[i].getJobId())
+                    .append(map[i] == null? -1: map[i].getUid())
+                    .append(")" );
+        }
+        return s.toString();
+    }
+
+
+    public void dumpLocked(IndentingPrintWriter pw, long now, long nowRealtime) {
+        pw.println("Concurrency:");
+
+        pw.increaseIndent();
+        try {
+            pw.print("Screen state: current ");
+            pw.print(mCurrentInteractiveState ? "ON" : "OFF");
+            pw.print("  effective ");
+            pw.print(mEffectiveInteractiveState ? "ON" : "OFF");
+            pw.println();
+
+            pw.print("Last screen ON : ");
+            TimeUtils.dumpTimeWithDelta(pw, now - nowRealtime + mLastScreenOnRealtime, now);
+            pw.println();
+
+            pw.print("Last screen OFF: ");
+            TimeUtils.dumpTimeWithDelta(pw, now - nowRealtime + mLastScreenOffRealtime, now);
+            pw.println();
+
+            pw.println();
+
+            pw.println("Current max jobs:");
+            pw.println("  ");
+            pw.println(mJobCountTracker);
+
+            pw.println();
+
+            pw.print("mLastMemoryTrimLevel: ");
+            pw.print(mLastMemoryTrimLevel);
+            pw.println();
+
+            mStatLogger.dump(pw);
+        } finally {
+            pw.decreaseIndent();
+        }
+    }
+
+    public void dumpProtoLocked(ProtoOutputStream proto, long tag, long now, long nowRealtime) {
+        final long token = proto.start(tag);
+
+        proto.write(JobConcurrencyManagerProto.CURRENT_INTERACTIVE,
+                mCurrentInteractiveState);
+        proto.write(JobConcurrencyManagerProto.EFFECTIVE_INTERACTIVE,
+                mEffectiveInteractiveState);
+
+        proto.write(JobConcurrencyManagerProto.TIME_SINCE_LAST_SCREEN_ON_MS,
+                nowRealtime - mLastScreenOnRealtime);
+        proto.write(JobConcurrencyManagerProto.TIME_SINCE_LAST_SCREEN_OFF_MS,
+                nowRealtime - mLastScreenOffRealtime);
+
+        mJobCountTracker.dumpProto(proto, JobConcurrencyManagerProto.JOB_COUNT_TRACKER);
+
+        proto.write(JobConcurrencyManagerProto.MEMORY_TRIM_LEVEL,
+                mLastMemoryTrimLevel);
+
+        proto.end(token);
+    }
+
+    /**
+     * This class decides, taking into account {@link #mMaxJobCounts} and how mny jos are running /
+     * pending, how many more job can start.
+     *
+     * Extracted for testing and logging.
+     */
+    @VisibleForTesting
+    static class JobCountTracker {
+        private int mConfigNumMaxTotalJobs;
+        private int mConfigNumMaxBgJobs;
+        private int mConfigNumMinBgJobs;
+
+        private int mNumRunningFgJobs;
+        private int mNumRunningBgJobs;
+
+        private int mNumPendingFgJobs;
+        private int mNumPendingBgJobs;
+
+        private int mNumStartingFgJobs;
+        private int mNumStartingBgJobs;
+
+        private int mNumReservedForBg;
+        private int mNumActualMaxFgJobs;
+        private int mNumActualMaxBgJobs;
+
+        void reset(int numTotalMaxJobs, int numMaxBgJobs, int numMinBgJobs) {
+            mConfigNumMaxTotalJobs = numTotalMaxJobs;
+            mConfigNumMaxBgJobs = numMaxBgJobs;
+            mConfigNumMinBgJobs = numMinBgJobs;
+
+            mNumRunningFgJobs = 0;
+            mNumRunningBgJobs = 0;
+
+            mNumPendingFgJobs = 0;
+            mNumPendingBgJobs = 0;
+
+            mNumStartingFgJobs = 0;
+            mNumStartingBgJobs = 0;
+
+            mNumReservedForBg = 0;
+            mNumActualMaxFgJobs = 0;
+            mNumActualMaxBgJobs = 0;
+        }
+
+        void incrementRunningJobCount(boolean isFg) {
+            if (isFg) {
+                mNumRunningFgJobs++;
+            } else {
+                mNumRunningBgJobs++;
+            }
+        }
+
+        void incrementPendingJobCount(boolean isFg) {
+            if (isFg) {
+                mNumPendingFgJobs++;
+            } else {
+                mNumPendingBgJobs++;
+            }
+        }
+
+        void onStartingNewJob(boolean isFg) {
+            if (isFg) {
+                mNumStartingFgJobs++;
+            } else {
+                mNumStartingBgJobs++;
+            }
+        }
+
+        void onCountDone() {
+            // Note some variables are used only here but are made class members in order to have
+            // them on logcat / dumpsys.
+
+            // How many slots should we allocate to BG jobs at least?
+            // That's basically "getMinBg()", but if there are less jobs, decrease it.
+            // (e.g. even if min-bg is 2, if there's only 1 running+pending job, this has to be 1.)
+            final int reservedForBg = Math.min(
+                    mConfigNumMinBgJobs,
+                    mNumRunningBgJobs + mNumPendingBgJobs);
+
+            // However, if there are FG jobs already running, we have to adjust it.
+            mNumReservedForBg = Math.min(reservedForBg,
+                    mConfigNumMaxTotalJobs - mNumRunningFgJobs);
+
+            // Max FG is [total - [number needed for BG jobs]]
+            // [number needed for BG jobs] is the bigger one of [running BG] or [reserved BG]
+            final int maxFg =
+                    mConfigNumMaxTotalJobs - Math.max(mNumRunningBgJobs, mNumReservedForBg);
+
+            // The above maxFg is the theoretical max. If there are less FG jobs, the actual
+            // max FG will be lower accordingly.
+            mNumActualMaxFgJobs = Math.min(
+                    maxFg,
+                    mNumRunningFgJobs + mNumPendingFgJobs);
+
+            // Max BG is [total - actual max FG], but cap at [config max BG].
+            final int maxBg = Math.min(
+                    mConfigNumMaxBgJobs,
+                    mConfigNumMaxTotalJobs - mNumActualMaxFgJobs);
+
+            // If there are less BG jobs than maxBg, then reduce the actual max BG accordingly.
+            // This isn't needed for the logic to work, but this will give consistent output
+            // on logcat and dumpsys.
+            mNumActualMaxBgJobs = Math.min(
+                    maxBg,
+                    mNumRunningBgJobs + mNumPendingBgJobs);
+        }
+
+        boolean canJobStart(boolean isFg) {
+            if (isFg) {
+                return mNumRunningFgJobs + mNumStartingFgJobs < mNumActualMaxFgJobs;
+            } else {
+                return mNumRunningBgJobs + mNumStartingBgJobs < mNumActualMaxBgJobs;
+            }
+        }
+
+        public int getNumStartingFgJobs() {
+            return mNumStartingFgJobs;
+        }
+
+        public int getNumStartingBgJobs() {
+            return mNumStartingBgJobs;
+        }
+
+        int getTotalRunningJobCountToNote() {
+            return mNumRunningFgJobs + mNumRunningBgJobs
+                    + mNumStartingFgJobs + mNumStartingBgJobs;
+        }
+
+        int getFgRunningJobCountToNote() {
+            return mNumRunningFgJobs + mNumStartingFgJobs;
+        }
+
+        void logStatus() {
+            if (DEBUG) {
+                Slog.d(TAG, "assignJobsToContexts: " + this);
+            }
+        }
+
+        public String toString() {
+            final int totalFg = mNumRunningFgJobs + mNumStartingFgJobs;
+            final int totalBg = mNumRunningBgJobs + mNumStartingBgJobs;
+            return String.format(
+                    "Config={tot=%d bg min/max=%d/%d}"
+                            + " Running[FG/BG (total)]: %d / %d (%d)"
+                            + " Pending: %d / %d (%d)"
+                            + " Actual max: %d%s / %d%s (%d%s)"
+                            + " Res BG: %d"
+                            + " Starting: %d / %d (%d)"
+                            + " Total: %d%s / %d%s (%d%s)",
+                    mConfigNumMaxTotalJobs,
+                    mConfigNumMinBgJobs,
+                    mConfigNumMaxBgJobs,
+
+                    mNumRunningFgJobs, mNumRunningBgJobs,
+                    mNumRunningFgJobs + mNumRunningBgJobs,
+
+                    mNumPendingFgJobs, mNumPendingBgJobs,
+                    mNumPendingFgJobs + mNumPendingBgJobs,
+
+                    mNumActualMaxFgJobs, (totalFg <= mConfigNumMaxTotalJobs) ? "" : "*",
+                    mNumActualMaxBgJobs, (totalBg <= mConfigNumMaxBgJobs) ? "" : "*",
+
+                    mNumActualMaxFgJobs + mNumActualMaxBgJobs,
+                    (mNumActualMaxFgJobs + mNumActualMaxBgJobs <= mConfigNumMaxTotalJobs)
+                            ? "" : "*",
+
+                    mNumReservedForBg,
+
+                    mNumStartingFgJobs, mNumStartingBgJobs, mNumStartingFgJobs + mNumStartingBgJobs,
+
+                    totalFg, (totalFg <= mNumActualMaxFgJobs) ? "" : "*",
+                    totalBg, (totalBg <= mNumActualMaxBgJobs) ? "" : "*",
+                    totalFg + totalBg, (totalFg + totalBg <= mConfigNumMaxTotalJobs) ? "" : "*"
+            );
+        }
+
+        public void dumpProto(ProtoOutputStream proto, long fieldId) {
+            final long token = proto.start(fieldId);
+
+            proto.write(JobCountTrackerProto.CONFIG_NUM_MAX_TOTAL_JOBS, mConfigNumMaxTotalJobs);
+            proto.write(JobCountTrackerProto.CONFIG_NUM_MAX_BG_JOBS, mConfigNumMaxBgJobs);
+            proto.write(JobCountTrackerProto.CONFIG_NUM_MIN_BG_JOBS, mConfigNumMinBgJobs);
+
+            proto.write(JobCountTrackerProto.NUM_RUNNING_FG_JOBS, mNumRunningFgJobs);
+            proto.write(JobCountTrackerProto.NUM_RUNNING_BG_JOBS, mNumRunningBgJobs);
+
+            proto.write(JobCountTrackerProto.NUM_PENDING_FG_JOBS, mNumPendingFgJobs);
+            proto.write(JobCountTrackerProto.NUM_PENDING_BG_JOBS, mNumPendingBgJobs);
+
+            proto.end(token);
+        }
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java b/apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java
new file mode 100644
index 0000000..e28e5bd
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java
@@ -0,0 +1,653 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job;
+
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+import static com.android.server.job.JobSchedulerService.sSystemClock;
+import static com.android.server.job.JobSchedulerService.sUptimeMillisClock;
+
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.os.UserHandle;
+import android.text.format.DateFormat;
+import android.util.ArrayMap;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.util.RingBufferIndices;
+import com.android.server.job.controllers.JobStatus;
+
+import java.io.PrintWriter;
+
+public final class JobPackageTracker {
+    // We batch every 30 minutes.
+    static final long BATCHING_TIME = 30*60*1000;
+    // Number of historical data sets we keep.
+    static final int NUM_HISTORY = 5;
+
+    private static final int EVENT_BUFFER_SIZE = 100;
+
+    public static final int EVENT_CMD_MASK = 0xff;
+    public static final int EVENT_STOP_REASON_SHIFT = 8;
+    public static final int EVENT_STOP_REASON_MASK = 0xff << EVENT_STOP_REASON_SHIFT;
+    public static final int EVENT_NULL = 0;
+    public static final int EVENT_START_JOB = 1;
+    public static final int EVENT_STOP_JOB = 2;
+    public static final int EVENT_START_PERIODIC_JOB = 3;
+    public static final int EVENT_STOP_PERIODIC_JOB = 4;
+
+    private final RingBufferIndices mEventIndices = new RingBufferIndices(EVENT_BUFFER_SIZE);
+    private final int[] mEventCmds = new int[EVENT_BUFFER_SIZE];
+    private final long[] mEventTimes = new long[EVENT_BUFFER_SIZE];
+    private final int[] mEventUids = new int[EVENT_BUFFER_SIZE];
+    private final String[] mEventTags = new String[EVENT_BUFFER_SIZE];
+    private final int[] mEventJobIds = new int[EVENT_BUFFER_SIZE];
+    private final String[] mEventReasons = new String[EVENT_BUFFER_SIZE];
+
+    public void addEvent(int cmd, int uid, String tag, int jobId, int stopReason,
+            String debugReason) {
+        int index = mEventIndices.add();
+        mEventCmds[index] = cmd | ((stopReason<<EVENT_STOP_REASON_SHIFT) & EVENT_STOP_REASON_MASK);
+        mEventTimes[index] = sElapsedRealtimeClock.millis();
+        mEventUids[index] = uid;
+        mEventTags[index] = tag;
+        mEventJobIds[index] = jobId;
+        mEventReasons[index] = debugReason;
+    }
+
+    DataSet mCurDataSet = new DataSet();
+    DataSet[] mLastDataSets = new DataSet[NUM_HISTORY];
+
+    final static class PackageEntry {
+        long pastActiveTime;
+        long activeStartTime;
+        int activeNesting;
+        int activeCount;
+        boolean hadActive;
+        long pastActiveTopTime;
+        long activeTopStartTime;
+        int activeTopNesting;
+        int activeTopCount;
+        boolean hadActiveTop;
+        long pastPendingTime;
+        long pendingStartTime;
+        int pendingNesting;
+        int pendingCount;
+        boolean hadPending;
+        final SparseIntArray stopReasons = new SparseIntArray();
+
+        public long getActiveTime(long now) {
+            long time = pastActiveTime;
+            if (activeNesting > 0) {
+                time += now - activeStartTime;
+            }
+            return time;
+        }
+
+        public long getActiveTopTime(long now) {
+            long time = pastActiveTopTime;
+            if (activeTopNesting > 0) {
+                time += now - activeTopStartTime;
+            }
+            return time;
+        }
+
+        public long getPendingTime(long now) {
+            long time = pastPendingTime;
+            if (pendingNesting > 0) {
+                time += now - pendingStartTime;
+            }
+            return time;
+        }
+    }
+
+    final static class DataSet {
+        final SparseArray<ArrayMap<String, PackageEntry>> mEntries = new SparseArray<>();
+        final long mStartUptimeTime;
+        final long mStartElapsedTime;
+        final long mStartClockTime;
+        long mSummedTime;
+        int mMaxTotalActive;
+        int mMaxFgActive;
+
+        public DataSet(DataSet otherTimes) {
+            mStartUptimeTime = otherTimes.mStartUptimeTime;
+            mStartElapsedTime = otherTimes.mStartElapsedTime;
+            mStartClockTime = otherTimes.mStartClockTime;
+        }
+
+        public DataSet() {
+            mStartUptimeTime = sUptimeMillisClock.millis();
+            mStartElapsedTime = sElapsedRealtimeClock.millis();
+            mStartClockTime = sSystemClock.millis();
+        }
+
+        private PackageEntry getOrCreateEntry(int uid, String pkg) {
+            ArrayMap<String, PackageEntry> uidMap = mEntries.get(uid);
+            if (uidMap == null) {
+                uidMap = new ArrayMap<>();
+                mEntries.put(uid, uidMap);
+            }
+            PackageEntry entry = uidMap.get(pkg);
+            if (entry == null) {
+                entry = new PackageEntry();
+                uidMap.put(pkg, entry);
+            }
+            return entry;
+        }
+
+        public PackageEntry getEntry(int uid, String pkg) {
+            ArrayMap<String, PackageEntry> uidMap = mEntries.get(uid);
+            if (uidMap == null) {
+                return null;
+            }
+            return uidMap.get(pkg);
+        }
+
+        long getTotalTime(long now) {
+            if (mSummedTime > 0) {
+                return mSummedTime;
+            }
+            return now - mStartUptimeTime;
+        }
+
+        void incPending(int uid, String pkg, long now) {
+            PackageEntry pe = getOrCreateEntry(uid, pkg);
+            if (pe.pendingNesting == 0) {
+                pe.pendingStartTime = now;
+                pe.pendingCount++;
+            }
+            pe.pendingNesting++;
+        }
+
+        void decPending(int uid, String pkg, long now) {
+            PackageEntry pe = getOrCreateEntry(uid, pkg);
+            if (pe.pendingNesting == 1) {
+                pe.pastPendingTime += now - pe.pendingStartTime;
+            }
+            pe.pendingNesting--;
+        }
+
+        void incActive(int uid, String pkg, long now) {
+            PackageEntry pe = getOrCreateEntry(uid, pkg);
+            if (pe.activeNesting == 0) {
+                pe.activeStartTime = now;
+                pe.activeCount++;
+            }
+            pe.activeNesting++;
+        }
+
+        void decActive(int uid, String pkg, long now, int stopReason) {
+            PackageEntry pe = getOrCreateEntry(uid, pkg);
+            if (pe.activeNesting == 1) {
+                pe.pastActiveTime += now - pe.activeStartTime;
+            }
+            pe.activeNesting--;
+            int count = pe.stopReasons.get(stopReason, 0);
+            pe.stopReasons.put(stopReason, count+1);
+        }
+
+        void incActiveTop(int uid, String pkg, long now) {
+            PackageEntry pe = getOrCreateEntry(uid, pkg);
+            if (pe.activeTopNesting == 0) {
+                pe.activeTopStartTime = now;
+                pe.activeTopCount++;
+            }
+            pe.activeTopNesting++;
+        }
+
+        void decActiveTop(int uid, String pkg, long now, int stopReason) {
+            PackageEntry pe = getOrCreateEntry(uid, pkg);
+            if (pe.activeTopNesting == 1) {
+                pe.pastActiveTopTime += now - pe.activeTopStartTime;
+            }
+            pe.activeTopNesting--;
+            int count = pe.stopReasons.get(stopReason, 0);
+            pe.stopReasons.put(stopReason, count+1);
+        }
+
+        void finish(DataSet next, long now) {
+            for (int i = mEntries.size() - 1; i >= 0; i--) {
+                ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
+                for (int j = uidMap.size() - 1; j >= 0; j--) {
+                    PackageEntry pe = uidMap.valueAt(j);
+                    if (pe.activeNesting > 0 || pe.activeTopNesting > 0 || pe.pendingNesting > 0) {
+                        // Propagate existing activity in to next data set.
+                        PackageEntry nextPe = next.getOrCreateEntry(mEntries.keyAt(i), uidMap.keyAt(j));
+                        nextPe.activeStartTime = now;
+                        nextPe.activeNesting = pe.activeNesting;
+                        nextPe.activeTopStartTime = now;
+                        nextPe.activeTopNesting = pe.activeTopNesting;
+                        nextPe.pendingStartTime = now;
+                        nextPe.pendingNesting = pe.pendingNesting;
+                        // Finish it off.
+                        if (pe.activeNesting > 0) {
+                            pe.pastActiveTime += now - pe.activeStartTime;
+                            pe.activeNesting = 0;
+                        }
+                        if (pe.activeTopNesting > 0) {
+                            pe.pastActiveTopTime += now - pe.activeTopStartTime;
+                            pe.activeTopNesting = 0;
+                        }
+                        if (pe.pendingNesting > 0) {
+                            pe.pastPendingTime += now - pe.pendingStartTime;
+                            pe.pendingNesting = 0;
+                        }
+                    }
+                }
+            }
+        }
+
+        void addTo(DataSet out, long now) {
+            out.mSummedTime += getTotalTime(now);
+            for (int i = mEntries.size() - 1; i >= 0; i--) {
+                ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
+                for (int j = uidMap.size() - 1; j >= 0; j--) {
+                    PackageEntry pe = uidMap.valueAt(j);
+                    PackageEntry outPe = out.getOrCreateEntry(mEntries.keyAt(i), uidMap.keyAt(j));
+                    outPe.pastActiveTime += pe.pastActiveTime;
+                    outPe.activeCount += pe.activeCount;
+                    outPe.pastActiveTopTime += pe.pastActiveTopTime;
+                    outPe.activeTopCount += pe.activeTopCount;
+                    outPe.pastPendingTime += pe.pastPendingTime;
+                    outPe.pendingCount += pe.pendingCount;
+                    if (pe.activeNesting > 0) {
+                        outPe.pastActiveTime += now - pe.activeStartTime;
+                        outPe.hadActive = true;
+                    }
+                    if (pe.activeTopNesting > 0) {
+                        outPe.pastActiveTopTime += now - pe.activeTopStartTime;
+                        outPe.hadActiveTop = true;
+                    }
+                    if (pe.pendingNesting > 0) {
+                        outPe.pastPendingTime += now - pe.pendingStartTime;
+                        outPe.hadPending = true;
+                    }
+                    for (int k = pe.stopReasons.size()-1; k >= 0; k--) {
+                        int type = pe.stopReasons.keyAt(k);
+                        outPe.stopReasons.put(type, outPe.stopReasons.get(type, 0)
+                                + pe.stopReasons.valueAt(k));
+                    }
+                }
+            }
+            if (mMaxTotalActive > out.mMaxTotalActive) {
+                out.mMaxTotalActive = mMaxTotalActive;
+            }
+            if (mMaxFgActive > out.mMaxFgActive) {
+                out.mMaxFgActive = mMaxFgActive;
+            }
+        }
+
+        void printDuration(PrintWriter pw, long period, long duration, int count, String suffix) {
+            float fraction = duration / (float) period;
+            int percent = (int) ((fraction * 100) + .5f);
+            if (percent > 0) {
+                pw.print(" ");
+                pw.print(percent);
+                pw.print("% ");
+                pw.print(count);
+                pw.print("x ");
+                pw.print(suffix);
+            } else if (count > 0) {
+                pw.print(" ");
+                pw.print(count);
+                pw.print("x ");
+                pw.print(suffix);
+            }
+        }
+
+        void dump(PrintWriter pw, String header, String prefix, long now, long nowElapsed,
+                int filterUid) {
+            final long period = getTotalTime(now);
+            pw.print(prefix); pw.print(header); pw.print(" at ");
+            pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", mStartClockTime).toString());
+            pw.print(" (");
+            TimeUtils.formatDuration(mStartElapsedTime, nowElapsed, pw);
+            pw.print(") over ");
+            TimeUtils.formatDuration(period, pw);
+            pw.println(":");
+            final int NE = mEntries.size();
+            for (int i = 0; i < NE; i++) {
+                int uid = mEntries.keyAt(i);
+                if (filterUid != -1 && filterUid != UserHandle.getAppId(uid)) {
+                    continue;
+                }
+                ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
+                final int NP = uidMap.size();
+                for (int j = 0; j < NP; j++) {
+                    PackageEntry pe = uidMap.valueAt(j);
+                    pw.print(prefix); pw.print("  ");
+                    UserHandle.formatUid(pw, uid);
+                    pw.print(" / "); pw.print(uidMap.keyAt(j));
+                    pw.println(":");
+                    pw.print(prefix); pw.print("   ");
+                    printDuration(pw, period, pe.getPendingTime(now), pe.pendingCount, "pending");
+                    printDuration(pw, period, pe.getActiveTime(now), pe.activeCount, "active");
+                    printDuration(pw, period, pe.getActiveTopTime(now), pe.activeTopCount,
+                            "active-top");
+                    if (pe.pendingNesting > 0 || pe.hadPending) {
+                        pw.print(" (pending)");
+                    }
+                    if (pe.activeNesting > 0 || pe.hadActive) {
+                        pw.print(" (active)");
+                    }
+                    if (pe.activeTopNesting > 0 || pe.hadActiveTop) {
+                        pw.print(" (active-top)");
+                    }
+                    pw.println();
+                    if (pe.stopReasons.size() > 0) {
+                        pw.print(prefix); pw.print("    ");
+                        for (int k = 0; k < pe.stopReasons.size(); k++) {
+                            if (k > 0) {
+                                pw.print(", ");
+                            }
+                            pw.print(pe.stopReasons.valueAt(k));
+                            pw.print("x ");
+                            pw.print(JobParameters.getReasonName(pe.stopReasons.keyAt(k)));
+                        }
+                        pw.println();
+                    }
+                }
+            }
+            pw.print(prefix); pw.print("  Max concurrency: ");
+            pw.print(mMaxTotalActive); pw.print(" total, ");
+            pw.print(mMaxFgActive); pw.println(" foreground");
+        }
+
+        private void printPackageEntryState(ProtoOutputStream proto, long fieldId,
+                long duration, int count) {
+            final long token = proto.start(fieldId);
+            proto.write(DataSetProto.PackageEntryProto.State.DURATION_MS, duration);
+            proto.write(DataSetProto.PackageEntryProto.State.COUNT, count);
+            proto.end(token);
+        }
+
+        void dump(ProtoOutputStream proto, long fieldId, long now, long nowElapsed, int filterUid) {
+            final long token = proto.start(fieldId);
+            final long period = getTotalTime(now);
+
+            proto.write(DataSetProto.START_CLOCK_TIME_MS, mStartClockTime);
+            proto.write(DataSetProto.ELAPSED_TIME_MS, nowElapsed - mStartElapsedTime);
+            proto.write(DataSetProto.PERIOD_MS, period);
+
+            final int NE = mEntries.size();
+            for (int i = 0; i < NE; i++) {
+                int uid = mEntries.keyAt(i);
+                if (filterUid != -1 && filterUid != UserHandle.getAppId(uid)) {
+                    continue;
+                }
+                ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
+                final int NP = uidMap.size();
+                for (int j = 0; j < NP; j++) {
+                    final long peToken = proto.start(DataSetProto.PACKAGE_ENTRIES);
+                    PackageEntry pe = uidMap.valueAt(j);
+
+                    proto.write(DataSetProto.PackageEntryProto.UID, uid);
+                    proto.write(DataSetProto.PackageEntryProto.PACKAGE_NAME, uidMap.keyAt(j));
+
+                    printPackageEntryState(proto, DataSetProto.PackageEntryProto.PENDING_STATE,
+                            pe.getPendingTime(now), pe.pendingCount);
+                    printPackageEntryState(proto, DataSetProto.PackageEntryProto.ACTIVE_STATE,
+                            pe.getActiveTime(now), pe.activeCount);
+                    printPackageEntryState(proto, DataSetProto.PackageEntryProto.ACTIVE_TOP_STATE,
+                            pe.getActiveTopTime(now), pe.activeTopCount);
+
+                    proto.write(DataSetProto.PackageEntryProto.PENDING,
+                          pe.pendingNesting > 0 || pe.hadPending);
+                    proto.write(DataSetProto.PackageEntryProto.ACTIVE,
+                          pe.activeNesting > 0 || pe.hadActive);
+                    proto.write(DataSetProto.PackageEntryProto.ACTIVE_TOP,
+                          pe.activeTopNesting > 0 || pe.hadActiveTop);
+
+                    for (int k = 0; k < pe.stopReasons.size(); k++) {
+                        final long srcToken =
+                                proto.start(DataSetProto.PackageEntryProto.STOP_REASONS);
+
+                        proto.write(DataSetProto.PackageEntryProto.StopReasonCount.REASON,
+                                pe.stopReasons.keyAt(k));
+                        proto.write(DataSetProto.PackageEntryProto.StopReasonCount.COUNT,
+                                pe.stopReasons.valueAt(k));
+
+                        proto.end(srcToken);
+                    }
+
+                    proto.end(peToken);
+                }
+            }
+
+            proto.write(DataSetProto.MAX_CONCURRENCY, mMaxTotalActive);
+            proto.write(DataSetProto.MAX_FOREGROUND_CONCURRENCY, mMaxFgActive);
+
+            proto.end(token);
+        }
+    }
+
+    void rebatchIfNeeded(long now) {
+        long totalTime = mCurDataSet.getTotalTime(now);
+        if (totalTime > BATCHING_TIME) {
+            DataSet last = mCurDataSet;
+            last.mSummedTime = totalTime;
+            mCurDataSet = new DataSet();
+            last.finish(mCurDataSet, now);
+            System.arraycopy(mLastDataSets, 0, mLastDataSets, 1, mLastDataSets.length-1);
+            mLastDataSets[0] = last;
+        }
+    }
+
+    public void notePending(JobStatus job) {
+        final long now = sUptimeMillisClock.millis();
+        job.madePending = now;
+        rebatchIfNeeded(now);
+        mCurDataSet.incPending(job.getSourceUid(), job.getSourcePackageName(), now);
+    }
+
+    public void noteNonpending(JobStatus job) {
+        final long now = sUptimeMillisClock.millis();
+        mCurDataSet.decPending(job.getSourceUid(), job.getSourcePackageName(), now);
+        rebatchIfNeeded(now);
+    }
+
+    public void noteActive(JobStatus job) {
+        final long now = sUptimeMillisClock.millis();
+        job.madeActive = now;
+        rebatchIfNeeded(now);
+        if (job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
+            mCurDataSet.incActiveTop(job.getSourceUid(), job.getSourcePackageName(), now);
+        } else {
+            mCurDataSet.incActive(job.getSourceUid(), job.getSourcePackageName(), now);
+        }
+        addEvent(job.getJob().isPeriodic() ? EVENT_START_PERIODIC_JOB :  EVENT_START_JOB,
+                job.getSourceUid(), job.getBatteryName(), job.getJobId(), 0, null);
+    }
+
+    public void noteInactive(JobStatus job, int stopReason, String debugReason) {
+        final long now = sUptimeMillisClock.millis();
+        if (job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
+            mCurDataSet.decActiveTop(job.getSourceUid(), job.getSourcePackageName(), now,
+                    stopReason);
+        } else {
+            mCurDataSet.decActive(job.getSourceUid(), job.getSourcePackageName(), now, stopReason);
+        }
+        rebatchIfNeeded(now);
+        addEvent(job.getJob().isPeriodic() ? EVENT_STOP_JOB :  EVENT_STOP_PERIODIC_JOB,
+                job.getSourceUid(), job.getBatteryName(), job.getJobId(), stopReason, debugReason);
+    }
+
+    public void noteConcurrency(int totalActive, int fgActive) {
+        if (totalActive > mCurDataSet.mMaxTotalActive) {
+            mCurDataSet.mMaxTotalActive = totalActive;
+        }
+        if (fgActive > mCurDataSet.mMaxFgActive) {
+            mCurDataSet.mMaxFgActive = fgActive;
+        }
+    }
+
+    public float getLoadFactor(JobStatus job) {
+        final int uid = job.getSourceUid();
+        final String pkg = job.getSourcePackageName();
+        PackageEntry cur = mCurDataSet.getEntry(uid, pkg);
+        PackageEntry last = mLastDataSets[0] != null ? mLastDataSets[0].getEntry(uid, pkg) : null;
+        if (cur == null && last == null) {
+            return 0;
+        }
+        final long now = sUptimeMillisClock.millis();
+        long time = 0;
+        if (cur != null) {
+            time += cur.getActiveTime(now) + cur.getPendingTime(now);
+        }
+        long period = mCurDataSet.getTotalTime(now);
+        if (last != null) {
+            time += last.getActiveTime(now) + last.getPendingTime(now);
+            period += mLastDataSets[0].getTotalTime(now);
+        }
+        return time / (float)period;
+    }
+
+    public void dump(PrintWriter pw, String prefix, int filterUid) {
+        final long now = sUptimeMillisClock.millis();
+        final long nowElapsed = sElapsedRealtimeClock.millis();
+        final DataSet total;
+        if (mLastDataSets[0] != null) {
+            total = new DataSet(mLastDataSets[0]);
+            mLastDataSets[0].addTo(total, now);
+        } else {
+            total = new DataSet(mCurDataSet);
+        }
+        mCurDataSet.addTo(total, now);
+        for (int i = 1; i < mLastDataSets.length; i++) {
+            if (mLastDataSets[i] != null) {
+                mLastDataSets[i].dump(pw, "Historical stats", prefix, now, nowElapsed, filterUid);
+                pw.println();
+            }
+        }
+        total.dump(pw, "Current stats", prefix, now, nowElapsed, filterUid);
+    }
+
+    public void dump(ProtoOutputStream proto, long fieldId, int filterUid) {
+        final long token = proto.start(fieldId);
+        final long now = sUptimeMillisClock.millis();
+        final long nowElapsed = sElapsedRealtimeClock.millis();
+
+        final DataSet total;
+        if (mLastDataSets[0] != null) {
+            total = new DataSet(mLastDataSets[0]);
+            mLastDataSets[0].addTo(total, now);
+        } else {
+            total = new DataSet(mCurDataSet);
+        }
+        mCurDataSet.addTo(total, now);
+
+        for (int i = 1; i < mLastDataSets.length; i++) {
+            if (mLastDataSets[i] != null) {
+                mLastDataSets[i].dump(proto, JobPackageTrackerDumpProto.HISTORICAL_STATS,
+                        now, nowElapsed, filterUid);
+            }
+        }
+        total.dump(proto, JobPackageTrackerDumpProto.CURRENT_STATS,
+                now, nowElapsed, filterUid);
+
+        proto.end(token);
+    }
+
+    public boolean dumpHistory(PrintWriter pw, String prefix, int filterUid) {
+        final int size = mEventIndices.size();
+        if (size <= 0) {
+            return false;
+        }
+        pw.println("  Job history:");
+        final long now = sElapsedRealtimeClock.millis();
+        for (int i=0; i<size; i++) {
+            final int index = mEventIndices.indexOf(i);
+            final int uid = mEventUids[index];
+            if (filterUid != -1 && filterUid != UserHandle.getAppId(uid)) {
+                continue;
+            }
+            final int cmd = mEventCmds[index] & EVENT_CMD_MASK;
+            if (cmd == EVENT_NULL) {
+                continue;
+            }
+            final String label;
+            switch (cmd) {
+                case EVENT_START_JOB:           label = "  START"; break;
+                case EVENT_STOP_JOB:            label = "   STOP"; break;
+                case EVENT_START_PERIODIC_JOB:  label = "START-P"; break;
+                case EVENT_STOP_PERIODIC_JOB:   label = " STOP-P"; break;
+                default:                        label = "     ??"; break;
+            }
+            pw.print(prefix);
+            TimeUtils.formatDuration(mEventTimes[index]-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
+            pw.print(" ");
+            pw.print(label);
+            pw.print(": #");
+            UserHandle.formatUid(pw, uid);
+            pw.print("/");
+            pw.print(mEventJobIds[index]);
+            pw.print(" ");
+            pw.print(mEventTags[index]);
+            if (cmd == EVENT_STOP_JOB || cmd == EVENT_STOP_PERIODIC_JOB) {
+                pw.print(" ");
+                final String reason = mEventReasons[index];
+                if (reason != null) {
+                    pw.print(mEventReasons[index]);
+                } else {
+                    pw.print(JobParameters.getReasonName((mEventCmds[index] & EVENT_STOP_REASON_MASK)
+                            >> EVENT_STOP_REASON_SHIFT));
+                }
+            }
+            pw.println();
+        }
+        return true;
+    }
+
+    public void dumpHistory(ProtoOutputStream proto, long fieldId, int filterUid) {
+        final int size = mEventIndices.size();
+        if (size == 0) {
+            return;
+        }
+        final long token = proto.start(fieldId);
+
+        final long now = sElapsedRealtimeClock.millis();
+        for (int i = 0; i < size; i++) {
+            final int index = mEventIndices.indexOf(i);
+            final int uid = mEventUids[index];
+            if (filterUid != -1 && filterUid != UserHandle.getAppId(uid)) {
+                continue;
+            }
+            final int cmd = mEventCmds[index] & EVENT_CMD_MASK;
+            if (cmd == EVENT_NULL) {
+                continue;
+            }
+            final long heToken = proto.start(JobPackageHistoryProto.HISTORY_EVENT);
+
+            proto.write(JobPackageHistoryProto.HistoryEvent.EVENT, cmd);
+            proto.write(JobPackageHistoryProto.HistoryEvent.TIME_SINCE_EVENT_MS, now - mEventTimes[index]);
+            proto.write(JobPackageHistoryProto.HistoryEvent.UID, uid);
+            proto.write(JobPackageHistoryProto.HistoryEvent.JOB_ID, mEventJobIds[index]);
+            proto.write(JobPackageHistoryProto.HistoryEvent.TAG, mEventTags[index]);
+            if (cmd == EVENT_STOP_JOB || cmd == EVENT_STOP_PERIODIC_JOB) {
+                proto.write(JobPackageHistoryProto.HistoryEvent.STOP_REASON,
+                    (mEventCmds[index] & EVENT_STOP_REASON_MASK) >> EVENT_STOP_REASON_SHIFT);
+            }
+
+            proto.end(heToken);
+        }
+
+        proto.end(token);
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
new file mode 100644
index 0000000..e44e902
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -0,0 +1,3657 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job;
+
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
+import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
+import android.app.AlarmManager;
+import android.app.AppGlobals;
+import android.app.IUidObserver;
+import android.app.job.IJobScheduler;
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobProtoEnums;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.app.job.JobSnapshot;
+import android.app.job.JobWorkItem;
+import android.app.usage.UsageStatsManager;
+import android.app.usage.UsageStatsManagerInternal;
+import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManagerInternal;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.ServiceInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.BatteryStats;
+import android.os.BatteryStatsInternal;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IThermalService;
+import android.os.IThermalStatusListener;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ServiceManager;
+import android.os.ShellCallback;
+import android.os.SystemClock;
+import android.os.Temperature;
+import android.os.UserHandle;
+import android.os.UserManagerInternal;
+import android.os.WorkSource;
+import android.provider.Settings;
+import android.text.format.DateUtils;
+import android.util.KeyValueListParser;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.util.StatsLog;
+import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
+import com.android.server.AppStateTracker;
+import com.android.server.DeviceIdleController;
+import com.android.server.FgThread;
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
+import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
+import com.android.server.job.JobSchedulerServiceDumpProto.RegisteredJob;
+import com.android.server.job.controllers.BackgroundJobsController;
+import com.android.server.job.controllers.BatteryController;
+import com.android.server.job.controllers.ConnectivityController;
+import com.android.server.job.controllers.ContentObserverController;
+import com.android.server.job.controllers.DeviceIdleJobsController;
+import com.android.server.job.controllers.IdleController;
+import com.android.server.job.controllers.JobStatus;
+import com.android.server.job.controllers.QuotaController;
+import com.android.server.job.controllers.StateController;
+import com.android.server.job.controllers.StorageController;
+import com.android.server.job.controllers.TimeController;
+
+import libcore.util.EmptyArray;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.time.Clock;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+/**
+ * Responsible for taking jobs representing work to be performed by a client app, and determining
+ * based on the criteria specified when that job should be run against the client application's
+ * endpoint.
+ * Implements logic for scheduling, and rescheduling jobs. The JobSchedulerService knows nothing
+ * about constraints, or the state of active jobs. It receives callbacks from the various
+ * controllers and completed jobs and operates accordingly.
+ *
+ * Note on locking: Any operations that manipulate {@link #mJobs} need to lock on that object.
+ * Any function with the suffix 'Locked' also needs to lock on {@link #mJobs}.
+ * @hide
+ */
+public class JobSchedulerService extends com.android.server.SystemService
+        implements StateChangedListener, JobCompletedListener {
+    public static final String TAG = "JobScheduler";
+    public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    public static final boolean DEBUG_STANDBY = DEBUG || false;
+
+    /** The maximum number of concurrent jobs we run at one time. */
+    static final int MAX_JOB_CONTEXTS_COUNT = 16;
+    /** Enforce a per-app limit on scheduled jobs? */
+    private static final boolean ENFORCE_MAX_JOBS = true;
+    /** The maximum number of jobs that we allow an unprivileged app to schedule */
+    private static final int MAX_JOBS_PER_APP = 100;
+
+    @VisibleForTesting
+    public static Clock sSystemClock = Clock.systemUTC();
+    @VisibleForTesting
+    public static Clock sUptimeMillisClock = SystemClock.uptimeClock();
+    @VisibleForTesting
+    public static Clock sElapsedRealtimeClock = SystemClock.elapsedRealtimeClock();
+
+    /** Global local for all job scheduler state. */
+    final Object mLock = new Object();
+    /** Master list of jobs. */
+    final JobStore mJobs;
+    /** Tracking the standby bucket state of each app */
+    final StandbyTracker mStandbyTracker;
+    /** Tracking amount of time each package runs for. */
+    final JobPackageTracker mJobPackageTracker = new JobPackageTracker();
+    final JobConcurrencyManager mConcurrencyManager;
+
+    static final int MSG_JOB_EXPIRED = 0;
+    static final int MSG_CHECK_JOB = 1;
+    static final int MSG_STOP_JOB = 2;
+    static final int MSG_CHECK_JOB_GREEDY = 3;
+    static final int MSG_UID_STATE_CHANGED = 4;
+    static final int MSG_UID_GONE = 5;
+    static final int MSG_UID_ACTIVE = 6;
+    static final int MSG_UID_IDLE = 7;
+
+    /**
+     * Track Services that have currently active or pending jobs. The index is provided by
+     * {@link JobStatus#getServiceToken()}
+     */
+    final List<JobServiceContext> mActiveServices = new ArrayList<>();
+
+    /** List of controllers that will notify this service of updates to jobs. */
+    final List<StateController> mControllers;
+    /** Need direct access to this for testing. */
+    private final BatteryController mBatteryController;
+    /** Need direct access to this for testing. */
+    private final StorageController mStorageController;
+    /** Need directly for sending uid state changes */
+    private final DeviceIdleJobsController mDeviceIdleJobsController;
+    /** Needed to get remaining quota time. */
+    private final QuotaController mQuotaController;
+
+    /** Need directly for receiving thermal events */
+    private IThermalService mThermalService;
+    /** Thermal constraint. */
+    @GuardedBy("mLock")
+    private boolean mThermalConstraint = false;
+
+    /**
+     * Queue of pending jobs. The JobServiceContext class will receive jobs from this list
+     * when ready to execute them.
+     */
+    final ArrayList<JobStatus> mPendingJobs = new ArrayList<>();
+
+    int[] mStartedUsers = EmptyArray.INT;
+
+    final JobHandler mHandler;
+    final JobSchedulerStub mJobSchedulerStub;
+
+    PackageManagerInternal mLocalPM;
+    ActivityManagerInternal mActivityManagerInternal;
+    IBatteryStats mBatteryStats;
+    DeviceIdleController.LocalService mLocalDeviceIdleController;
+    AppStateTracker mAppStateTracker;
+    final UsageStatsManagerInternal mUsageStats;
+
+    /**
+     * Set to true once we are allowed to run third party apps.
+     */
+    boolean mReadyToRock;
+
+    /**
+     * What we last reported to DeviceIdleController about whether we are active.
+     */
+    boolean mReportedActive;
+
+    /**
+     * Are we currently in device-wide standby parole?
+     */
+    volatile boolean mInParole;
+
+    /**
+     * A mapping of which uids are currently in the foreground to their effective priority.
+     */
+    final SparseIntArray mUidPriorityOverride = new SparseIntArray();
+
+    /**
+     * Which uids are currently performing backups, so we shouldn't allow their jobs to run.
+     */
+    final SparseIntArray mBackingUpUids = new SparseIntArray();
+
+    /**
+     * Count standby heartbeats, and keep track of which beat each bucket's jobs will
+     * next become runnable.  Index into this array is by normalized bucket:
+     * { ACTIVE, WORKING, FREQUENT, RARE, NEVER }.  The ACTIVE and NEVER bucket
+     * milestones are not updated: ACTIVE apps get jobs whenever they ask for them,
+     * and NEVER apps don't get them at all.
+     */
+    final long[] mNextBucketHeartbeat = { 0, 0, 0, 0, Long.MAX_VALUE };
+    long mHeartbeat = 0;
+    long mLastHeartbeatTime = sElapsedRealtimeClock.millis();
+
+    /**
+     * Named indices into the STANDBY_BEATS array, for clarity in referring to
+     * specific buckets' bookkeeping.
+     */
+    public static final int ACTIVE_INDEX = 0;
+    public static final int WORKING_INDEX = 1;
+    public static final int FREQUENT_INDEX = 2;
+    public static final int RARE_INDEX = 3;
+    public static final int NEVER_INDEX = 4;
+
+    /**
+     * Bookkeeping about when jobs last run.  We keep our own record in heartbeat time,
+     * rather than rely on Usage Stats' timestamps, because heartbeat time can be
+     * manipulated for testing purposes and we need job runnability to track that rather
+     * than real time.
+     *
+     * Outer SparseArray slices by user handle; inner map of package name to heartbeat
+     * is a HashMap<> rather than ArrayMap<> because we expect O(hundreds) of keys
+     * and it will be accessed in a known-hot code path.
+     */
+    final SparseArray<HashMap<String, Long>> mLastJobHeartbeats = new SparseArray<>();
+
+    static final String HEARTBEAT_TAG = "*job.heartbeat*";
+    final HeartbeatAlarmListener mHeartbeatAlarm = new HeartbeatAlarmListener();
+
+    // -- Pre-allocated temporaries only for use in assignJobsToContextsLocked --
+
+    private class ConstantsObserver extends ContentObserver {
+        private ContentResolver mResolver;
+
+        public ConstantsObserver(Handler handler) {
+            super(handler);
+        }
+
+        public void start(ContentResolver resolver) {
+            mResolver = resolver;
+            mResolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.JOB_SCHEDULER_CONSTANTS), false, this);
+            updateConstants();
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            updateConstants();
+        }
+
+        private void updateConstants() {
+            synchronized (mLock) {
+                try {
+                    mConstants.updateConstantsLocked(Settings.Global.getString(mResolver,
+                            Settings.Global.JOB_SCHEDULER_CONSTANTS));
+                    for (int controller = 0; controller < mControllers.size(); controller++) {
+                        final StateController sc = mControllers.get(controller);
+                        sc.onConstantsUpdatedLocked();
+                    }
+                } catch (IllegalArgumentException e) {
+                    // Failed to parse the settings string, log this and move on
+                    // with defaults.
+                    Slog.e(TAG, "Bad jobscheduler settings", e);
+                }
+            }
+
+            if (mConstants.USE_HEARTBEATS) {
+                // Reset the heartbeat alarm based on the new heartbeat duration
+                setNextHeartbeatAlarm();
+            }
+        }
+    }
+
+    /**
+     *  Thermal event received from Thermal Service
+     */
+    private final class ThermalStatusListener extends IThermalStatusListener.Stub {
+        @Override public void onStatusChange(int status) {
+            // Throttle for Temperature.THROTTLING_SEVERE and above
+            synchronized (mLock) {
+                mThermalConstraint = status >= Temperature.THROTTLING_SEVERE;
+            }
+            onControllerStateChanged();
+        }
+    }
+
+    static class MaxJobCounts {
+        private final KeyValueListParser.IntValue mTotal;
+        private final KeyValueListParser.IntValue mMaxBg;
+        private final KeyValueListParser.IntValue mMinBg;
+
+        MaxJobCounts(int totalDefault, String totalKey,
+                int maxBgDefault, String maxBgKey, int minBgDefault, String minBgKey) {
+            mTotal = new KeyValueListParser.IntValue(totalKey, totalDefault);
+            mMaxBg = new KeyValueListParser.IntValue(maxBgKey, maxBgDefault);
+            mMinBg = new KeyValueListParser.IntValue(minBgKey, minBgDefault);
+        }
+
+        public void parse(KeyValueListParser parser) {
+            mTotal.parse(parser);
+            mMaxBg.parse(parser);
+            mMinBg.parse(parser);
+
+            if (mTotal.getValue() < 1) {
+                mTotal.setValue(1);
+            } else if (mTotal.getValue() > MAX_JOB_CONTEXTS_COUNT) {
+                mTotal.setValue(MAX_JOB_CONTEXTS_COUNT);
+            }
+
+            if (mMaxBg.getValue() < 1) {
+                mMaxBg.setValue(1);
+            } else if (mMaxBg.getValue() > mTotal.getValue()) {
+                mMaxBg.setValue(mTotal.getValue());
+            }
+            if (mMinBg.getValue() < 0) {
+                mMinBg.setValue(0);
+            } else {
+                if (mMinBg.getValue() > mMaxBg.getValue()) {
+                    mMinBg.setValue(mMaxBg.getValue());
+                }
+                if (mMinBg.getValue() >= mTotal.getValue()) {
+                    mMinBg.setValue(mTotal.getValue() - 1);
+                }
+            }
+        }
+
+        /** Total number of jobs to run simultaneously. */
+        public int getMaxTotal() {
+            return mTotal.getValue();
+        }
+
+        /** Max number of BG (== owned by non-TOP apps) jobs to run simultaneously. */
+        public int getMaxBg() {
+            return mMaxBg.getValue();
+        }
+
+        /**
+         * We try to run at least this many BG (== owned by non-TOP apps) jobs, when there are any
+         * pending, rather than always running the TOTAL number of FG jobs.
+         */
+        public int getMinBg() {
+            return mMinBg.getValue();
+        }
+
+        public void dump(PrintWriter pw, String prefix) {
+            mTotal.dump(pw, prefix);
+            mMaxBg.dump(pw, prefix);
+            mMinBg.dump(pw, prefix);
+        }
+
+        public void dumpProto(ProtoOutputStream proto, long fieldId) {
+            final long token = proto.start(fieldId);
+            mTotal.dumpProto(proto, MaxJobCountsProto.TOTAL_JOBS);
+            mMaxBg.dumpProto(proto, MaxJobCountsProto.MAX_BG);
+            mMinBg.dumpProto(proto, MaxJobCountsProto.MIN_BG);
+            proto.end(token);
+        }
+    }
+
+    /** {@link MaxJobCounts} for each memory trim level. */
+    static class MaxJobCountsPerMemoryTrimLevel {
+        public final MaxJobCounts normal;
+        public final MaxJobCounts moderate;
+        public final MaxJobCounts low;
+        public final MaxJobCounts critical;
+
+        MaxJobCountsPerMemoryTrimLevel(
+                MaxJobCounts normal,
+                MaxJobCounts moderate, MaxJobCounts low,
+                MaxJobCounts critical) {
+            this.normal = normal;
+            this.moderate = moderate;
+            this.low = low;
+            this.critical = critical;
+        }
+
+        public void dumpProto(ProtoOutputStream proto, long fieldId) {
+            final long token = proto.start(fieldId);
+            normal.dumpProto(proto, MaxJobCountsPerMemoryTrimLevelProto.NORMAL);
+            moderate.dumpProto(proto, MaxJobCountsPerMemoryTrimLevelProto.MODERATE);
+            low.dumpProto(proto, MaxJobCountsPerMemoryTrimLevelProto.LOW);
+            critical.dumpProto(proto, MaxJobCountsPerMemoryTrimLevelProto.CRITICAL);
+            proto.end(token);
+        }
+    }
+
+    /**
+     * All times are in milliseconds. These constants are kept synchronized with the system
+     * global Settings. Any access to this class or its fields should be done while
+     * holding the JobSchedulerService.mLock lock.
+     */
+    public static class Constants {
+        // Key names stored in the settings value.
+        private static final String KEY_MIN_IDLE_COUNT = "min_idle_count";
+        private static final String KEY_MIN_CHARGING_COUNT = "min_charging_count";
+        private static final String KEY_MIN_BATTERY_NOT_LOW_COUNT = "min_battery_not_low_count";
+        private static final String KEY_MIN_STORAGE_NOT_LOW_COUNT = "min_storage_not_low_count";
+        private static final String KEY_MIN_CONNECTIVITY_COUNT = "min_connectivity_count";
+        private static final String KEY_MIN_CONTENT_COUNT = "min_content_count";
+        private static final String KEY_MIN_READY_JOBS_COUNT = "min_ready_jobs_count";
+        private static final String KEY_MIN_READY_NON_ACTIVE_JOBS_COUNT =
+                "min_ready_non_active_jobs_count";
+        private static final String KEY_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS =
+                "max_non_active_job_batch_delay_ms";
+        private static final String KEY_HEAVY_USE_FACTOR = "heavy_use_factor";
+        private static final String KEY_MODERATE_USE_FACTOR = "moderate_use_factor";
+
+        // The following values used to be used on P and below. Do not reuse them.
+        private static final String DEPRECATED_KEY_FG_JOB_COUNT = "fg_job_count";
+        private static final String DEPRECATED_KEY_BG_NORMAL_JOB_COUNT = "bg_normal_job_count";
+        private static final String DEPRECATED_KEY_BG_MODERATE_JOB_COUNT = "bg_moderate_job_count";
+        private static final String DEPRECATED_KEY_BG_LOW_JOB_COUNT = "bg_low_job_count";
+        private static final String DEPRECATED_KEY_BG_CRITICAL_JOB_COUNT = "bg_critical_job_count";
+
+        private static final String KEY_MAX_STANDARD_RESCHEDULE_COUNT
+                = "max_standard_reschedule_count";
+        private static final String KEY_MAX_WORK_RESCHEDULE_COUNT = "max_work_reschedule_count";
+        private static final String KEY_MIN_LINEAR_BACKOFF_TIME = "min_linear_backoff_time";
+        private static final String KEY_MIN_EXP_BACKOFF_TIME = "min_exp_backoff_time";
+        private static final String KEY_STANDBY_HEARTBEAT_TIME = "standby_heartbeat_time";
+        private static final String KEY_STANDBY_WORKING_BEATS = "standby_working_beats";
+        private static final String KEY_STANDBY_FREQUENT_BEATS = "standby_frequent_beats";
+        private static final String KEY_STANDBY_RARE_BEATS = "standby_rare_beats";
+        private static final String KEY_CONN_CONGESTION_DELAY_FRAC = "conn_congestion_delay_frac";
+        private static final String KEY_CONN_PREFETCH_RELAX_FRAC = "conn_prefetch_relax_frac";
+        private static final String KEY_USE_HEARTBEATS = "use_heartbeats";
+
+        private static final int DEFAULT_MIN_IDLE_COUNT = 1;
+        private static final int DEFAULT_MIN_CHARGING_COUNT = 1;
+        private static final int DEFAULT_MIN_BATTERY_NOT_LOW_COUNT = 1;
+        private static final int DEFAULT_MIN_STORAGE_NOT_LOW_COUNT = 1;
+        private static final int DEFAULT_MIN_CONNECTIVITY_COUNT = 1;
+        private static final int DEFAULT_MIN_CONTENT_COUNT = 1;
+        private static final int DEFAULT_MIN_READY_JOBS_COUNT = 1;
+        private static final int DEFAULT_MIN_READY_NON_ACTIVE_JOBS_COUNT = 5;
+        private static final long DEFAULT_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS = 31 * MINUTE_IN_MILLIS;
+        private static final float DEFAULT_HEAVY_USE_FACTOR = .9f;
+        private static final float DEFAULT_MODERATE_USE_FACTOR = .5f;
+        private static final int DEFAULT_MAX_STANDARD_RESCHEDULE_COUNT = Integer.MAX_VALUE;
+        private static final int DEFAULT_MAX_WORK_RESCHEDULE_COUNT = Integer.MAX_VALUE;
+        private static final long DEFAULT_MIN_LINEAR_BACKOFF_TIME = JobInfo.MIN_BACKOFF_MILLIS;
+        private static final long DEFAULT_MIN_EXP_BACKOFF_TIME = JobInfo.MIN_BACKOFF_MILLIS;
+        private static final long DEFAULT_STANDBY_HEARTBEAT_TIME = 11 * 60 * 1000L;
+        private static final int DEFAULT_STANDBY_WORKING_BEATS = 11;  // ~ 2 hours, with 11min beats
+        private static final int DEFAULT_STANDBY_FREQUENT_BEATS = 43; // ~ 8 hours
+        private static final int DEFAULT_STANDBY_RARE_BEATS = 130; // ~ 24 hours
+        private static final float DEFAULT_CONN_CONGESTION_DELAY_FRAC = 0.5f;
+        private static final float DEFAULT_CONN_PREFETCH_RELAX_FRAC = 0.5f;
+        private static final boolean DEFAULT_USE_HEARTBEATS = false;
+
+        /**
+         * Minimum # of idle jobs that must be ready in order to force the JMS to schedule things
+         * early.
+         */
+        int MIN_IDLE_COUNT = DEFAULT_MIN_IDLE_COUNT;
+        /**
+         * Minimum # of charging jobs that must be ready in order to force the JMS to schedule
+         * things early.
+         */
+        int MIN_CHARGING_COUNT = DEFAULT_MIN_CHARGING_COUNT;
+        /**
+         * Minimum # of "battery not low" jobs that must be ready in order to force the JMS to
+         * schedule things early.
+         */
+        int MIN_BATTERY_NOT_LOW_COUNT = DEFAULT_MIN_BATTERY_NOT_LOW_COUNT;
+        /**
+         * Minimum # of "storage not low" jobs that must be ready in order to force the JMS to
+         * schedule things early.
+         */
+        int MIN_STORAGE_NOT_LOW_COUNT = DEFAULT_MIN_STORAGE_NOT_LOW_COUNT;
+        /**
+         * Minimum # of connectivity jobs that must be ready in order to force the JMS to schedule
+         * things early.  1 == Run connectivity jobs as soon as ready.
+         */
+        int MIN_CONNECTIVITY_COUNT = DEFAULT_MIN_CONNECTIVITY_COUNT;
+        /**
+         * Minimum # of content trigger jobs that must be ready in order to force the JMS to
+         * schedule things early.
+         */
+        int MIN_CONTENT_COUNT = DEFAULT_MIN_CONTENT_COUNT;
+        /**
+         * Minimum # of jobs (with no particular constraints) for which the JMS will be happy
+         * running some work early.  This (and thus the other min counts) is now set to 1, to
+         * prevent any batching at this level.  Since we now do batching through doze, that is
+         * a much better mechanism.
+         */
+        int MIN_READY_JOBS_COUNT = DEFAULT_MIN_READY_JOBS_COUNT;
+
+        /**
+         * Minimum # of non-ACTIVE jobs for which the JMS will be happy running some work early.
+         */
+        int MIN_READY_NON_ACTIVE_JOBS_COUNT = DEFAULT_MIN_READY_NON_ACTIVE_JOBS_COUNT;
+
+        /**
+         * Don't batch a non-ACTIVE job if it's been delayed due to force batching attempts for
+         * at least this amount of time.
+         */
+        long MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS = DEFAULT_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS;
+
+        /**
+         * This is the job execution factor that is considered to be heavy use of the system.
+         */
+        float HEAVY_USE_FACTOR = DEFAULT_HEAVY_USE_FACTOR;
+        /**
+         * This is the job execution factor that is considered to be moderate use of the system.
+         */
+        float MODERATE_USE_FACTOR = DEFAULT_MODERATE_USE_FACTOR;
+
+        // Max job counts for screen on / off, for each memory trim level.
+        final MaxJobCountsPerMemoryTrimLevel MAX_JOB_COUNTS_SCREEN_ON =
+                new MaxJobCountsPerMemoryTrimLevel(
+                        new MaxJobCounts(
+                                8, "max_job_total_on_normal",
+                                6, "max_job_max_bg_on_normal",
+                                2, "max_job_min_bg_on_normal"),
+                        new MaxJobCounts(
+                                8, "max_job_total_on_moderate",
+                                4, "max_job_max_bg_on_moderate",
+                                2, "max_job_min_bg_on_moderate"),
+                        new MaxJobCounts(
+                                5, "max_job_total_on_low",
+                                1, "max_job_max_bg_on_low",
+                                1, "max_job_min_bg_on_low"),
+                        new MaxJobCounts(
+                                5, "max_job_total_on_critical",
+                                1, "max_job_max_bg_on_critical",
+                                1, "max_job_min_bg_on_critical"));
+
+        final MaxJobCountsPerMemoryTrimLevel MAX_JOB_COUNTS_SCREEN_OFF =
+                new MaxJobCountsPerMemoryTrimLevel(
+                        new MaxJobCounts(
+                                10, "max_job_total_off_normal",
+                                6, "max_job_max_bg_off_normal",
+                                2, "max_job_min_bg_off_normal"),
+                        new MaxJobCounts(
+                                10, "max_job_total_off_moderate",
+                                4, "max_job_max_bg_off_moderate",
+                                2, "max_job_min_bg_off_moderate"),
+                        new MaxJobCounts(
+                                5, "max_job_total_off_low",
+                                1, "max_job_max_bg_off_low",
+                                1, "max_job_min_bg_off_low"),
+                        new MaxJobCounts(
+                                5, "max_job_total_off_critical",
+                                1, "max_job_max_bg_off_critical",
+                                1, "max_job_min_bg_off_critical"));
+
+
+        /** Wait for this long after screen off before increasing the job concurrency. */
+        final KeyValueListParser.IntValue SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS =
+                new KeyValueListParser.IntValue(
+                        "screen_off_job_concurrency_increase_delay_ms", 30_000);
+
+        /**
+         * The maximum number of times we allow a job to have itself rescheduled before
+         * giving up on it, for standard jobs.
+         */
+        int MAX_STANDARD_RESCHEDULE_COUNT = DEFAULT_MAX_STANDARD_RESCHEDULE_COUNT;
+        /**
+         * The maximum number of times we allow a job to have itself rescheduled before
+         * giving up on it, for jobs that are executing work.
+         */
+        int MAX_WORK_RESCHEDULE_COUNT = DEFAULT_MAX_WORK_RESCHEDULE_COUNT;
+        /**
+         * The minimum backoff time to allow for linear backoff.
+         */
+        long MIN_LINEAR_BACKOFF_TIME = DEFAULT_MIN_LINEAR_BACKOFF_TIME;
+        /**
+         * The minimum backoff time to allow for exponential backoff.
+         */
+        long MIN_EXP_BACKOFF_TIME = DEFAULT_MIN_EXP_BACKOFF_TIME;
+        /**
+         * How often we recalculate runnability based on apps' standby bucket assignment.
+         * This should be prime relative to common time interval lengths such as a quarter-
+         * hour or day, so that the heartbeat drifts relative to wall-clock milestones.
+         */
+        long STANDBY_HEARTBEAT_TIME = DEFAULT_STANDBY_HEARTBEAT_TIME;
+        /**
+         * Mapping: standby bucket -> number of heartbeats between each sweep of that
+         * bucket's jobs.
+         *
+         * Bucket assignments as recorded in the JobStatus objects are normalized to be
+         * indices into this array, rather than the raw constants used
+         * by AppIdleHistory.
+         */
+        final int[] STANDBY_BEATS = {
+                0,
+                DEFAULT_STANDBY_WORKING_BEATS,
+                DEFAULT_STANDBY_FREQUENT_BEATS,
+                DEFAULT_STANDBY_RARE_BEATS
+        };
+        /**
+         * The fraction of a job's running window that must pass before we
+         * consider running it when the network is congested.
+         */
+        public float CONN_CONGESTION_DELAY_FRAC = DEFAULT_CONN_CONGESTION_DELAY_FRAC;
+        /**
+         * The fraction of a prefetch job's running window that must pass before
+         * we consider matching it against a metered network.
+         */
+        public float CONN_PREFETCH_RELAX_FRAC = DEFAULT_CONN_PREFETCH_RELAX_FRAC;
+        /**
+         * Whether to use heartbeats or rolling window for quota management. True will use
+         * heartbeats, false will use a rolling window.
+         */
+        public boolean USE_HEARTBEATS = DEFAULT_USE_HEARTBEATS;
+
+        private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+        void updateConstantsLocked(String value) {
+            try {
+                mParser.setString(value);
+            } catch (Exception e) {
+                // Failed to parse the settings string, log this and move on
+                // with defaults.
+                Slog.e(TAG, "Bad jobscheduler settings", e);
+            }
+
+            MIN_IDLE_COUNT = mParser.getInt(KEY_MIN_IDLE_COUNT,
+                    DEFAULT_MIN_IDLE_COUNT);
+            MIN_CHARGING_COUNT = mParser.getInt(KEY_MIN_CHARGING_COUNT,
+                    DEFAULT_MIN_CHARGING_COUNT);
+            MIN_BATTERY_NOT_LOW_COUNT = mParser.getInt(KEY_MIN_BATTERY_NOT_LOW_COUNT,
+                    DEFAULT_MIN_BATTERY_NOT_LOW_COUNT);
+            MIN_STORAGE_NOT_LOW_COUNT = mParser.getInt(KEY_MIN_STORAGE_NOT_LOW_COUNT,
+                    DEFAULT_MIN_STORAGE_NOT_LOW_COUNT);
+            MIN_CONNECTIVITY_COUNT = mParser.getInt(KEY_MIN_CONNECTIVITY_COUNT,
+                    DEFAULT_MIN_CONNECTIVITY_COUNT);
+            MIN_CONTENT_COUNT = mParser.getInt(KEY_MIN_CONTENT_COUNT,
+                    DEFAULT_MIN_CONTENT_COUNT);
+            MIN_READY_JOBS_COUNT = mParser.getInt(KEY_MIN_READY_JOBS_COUNT,
+                    DEFAULT_MIN_READY_JOBS_COUNT);
+            MIN_READY_NON_ACTIVE_JOBS_COUNT = mParser.getInt(
+                    KEY_MIN_READY_NON_ACTIVE_JOBS_COUNT,
+                    DEFAULT_MIN_READY_NON_ACTIVE_JOBS_COUNT);
+            MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS = mParser.getLong(
+                    KEY_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS,
+                    DEFAULT_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS);
+            HEAVY_USE_FACTOR = mParser.getFloat(KEY_HEAVY_USE_FACTOR,
+                    DEFAULT_HEAVY_USE_FACTOR);
+            MODERATE_USE_FACTOR = mParser.getFloat(KEY_MODERATE_USE_FACTOR,
+                    DEFAULT_MODERATE_USE_FACTOR);
+
+            MAX_JOB_COUNTS_SCREEN_ON.normal.parse(mParser);
+            MAX_JOB_COUNTS_SCREEN_ON.moderate.parse(mParser);
+            MAX_JOB_COUNTS_SCREEN_ON.low.parse(mParser);
+            MAX_JOB_COUNTS_SCREEN_ON.critical.parse(mParser);
+
+            MAX_JOB_COUNTS_SCREEN_OFF.normal.parse(mParser);
+            MAX_JOB_COUNTS_SCREEN_OFF.moderate.parse(mParser);
+            MAX_JOB_COUNTS_SCREEN_OFF.low.parse(mParser);
+            MAX_JOB_COUNTS_SCREEN_OFF.critical.parse(mParser);
+
+            SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.parse(mParser);
+
+            MAX_STANDARD_RESCHEDULE_COUNT = mParser.getInt(KEY_MAX_STANDARD_RESCHEDULE_COUNT,
+                    DEFAULT_MAX_STANDARD_RESCHEDULE_COUNT);
+            MAX_WORK_RESCHEDULE_COUNT = mParser.getInt(KEY_MAX_WORK_RESCHEDULE_COUNT,
+                    DEFAULT_MAX_WORK_RESCHEDULE_COUNT);
+            MIN_LINEAR_BACKOFF_TIME = mParser.getDurationMillis(KEY_MIN_LINEAR_BACKOFF_TIME,
+                    DEFAULT_MIN_LINEAR_BACKOFF_TIME);
+            MIN_EXP_BACKOFF_TIME = mParser.getDurationMillis(KEY_MIN_EXP_BACKOFF_TIME,
+                    DEFAULT_MIN_EXP_BACKOFF_TIME);
+            STANDBY_HEARTBEAT_TIME = mParser.getDurationMillis(KEY_STANDBY_HEARTBEAT_TIME,
+                    DEFAULT_STANDBY_HEARTBEAT_TIME);
+            STANDBY_BEATS[WORKING_INDEX] = mParser.getInt(KEY_STANDBY_WORKING_BEATS,
+                    DEFAULT_STANDBY_WORKING_BEATS);
+            STANDBY_BEATS[FREQUENT_INDEX] = mParser.getInt(KEY_STANDBY_FREQUENT_BEATS,
+                    DEFAULT_STANDBY_FREQUENT_BEATS);
+            STANDBY_BEATS[RARE_INDEX] = mParser.getInt(KEY_STANDBY_RARE_BEATS,
+                    DEFAULT_STANDBY_RARE_BEATS);
+            CONN_CONGESTION_DELAY_FRAC = mParser.getFloat(KEY_CONN_CONGESTION_DELAY_FRAC,
+                    DEFAULT_CONN_CONGESTION_DELAY_FRAC);
+            CONN_PREFETCH_RELAX_FRAC = mParser.getFloat(KEY_CONN_PREFETCH_RELAX_FRAC,
+                    DEFAULT_CONN_PREFETCH_RELAX_FRAC);
+            USE_HEARTBEATS = mParser.getBoolean(KEY_USE_HEARTBEATS, DEFAULT_USE_HEARTBEATS);
+        }
+
+        void dump(IndentingPrintWriter pw) {
+            pw.println("Settings:");
+            pw.increaseIndent();
+            pw.printPair(KEY_MIN_IDLE_COUNT, MIN_IDLE_COUNT).println();
+            pw.printPair(KEY_MIN_CHARGING_COUNT, MIN_CHARGING_COUNT).println();
+            pw.printPair(KEY_MIN_BATTERY_NOT_LOW_COUNT, MIN_BATTERY_NOT_LOW_COUNT).println();
+            pw.printPair(KEY_MIN_STORAGE_NOT_LOW_COUNT, MIN_STORAGE_NOT_LOW_COUNT).println();
+            pw.printPair(KEY_MIN_CONNECTIVITY_COUNT, MIN_CONNECTIVITY_COUNT).println();
+            pw.printPair(KEY_MIN_CONTENT_COUNT, MIN_CONTENT_COUNT).println();
+            pw.printPair(KEY_MIN_READY_JOBS_COUNT, MIN_READY_JOBS_COUNT).println();
+            pw.printPair(KEY_MIN_READY_NON_ACTIVE_JOBS_COUNT,
+                    MIN_READY_NON_ACTIVE_JOBS_COUNT).println();
+            pw.printPair(KEY_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS,
+                    MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS).println();
+            pw.printPair(KEY_HEAVY_USE_FACTOR, HEAVY_USE_FACTOR).println();
+            pw.printPair(KEY_MODERATE_USE_FACTOR, MODERATE_USE_FACTOR).println();
+
+            MAX_JOB_COUNTS_SCREEN_ON.normal.dump(pw, "");
+            MAX_JOB_COUNTS_SCREEN_ON.moderate.dump(pw, "");
+            MAX_JOB_COUNTS_SCREEN_ON.low.dump(pw, "");
+            MAX_JOB_COUNTS_SCREEN_ON.critical.dump(pw, "");
+
+            MAX_JOB_COUNTS_SCREEN_OFF.normal.dump(pw, "");
+            MAX_JOB_COUNTS_SCREEN_OFF.moderate.dump(pw, "");
+            MAX_JOB_COUNTS_SCREEN_OFF.low.dump(pw, "");
+            MAX_JOB_COUNTS_SCREEN_OFF.critical.dump(pw, "");
+
+            SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.dump(pw, "");
+
+            pw.printPair(KEY_MAX_STANDARD_RESCHEDULE_COUNT, MAX_STANDARD_RESCHEDULE_COUNT).println();
+            pw.printPair(KEY_MAX_WORK_RESCHEDULE_COUNT, MAX_WORK_RESCHEDULE_COUNT).println();
+            pw.printPair(KEY_MIN_LINEAR_BACKOFF_TIME, MIN_LINEAR_BACKOFF_TIME).println();
+            pw.printPair(KEY_MIN_EXP_BACKOFF_TIME, MIN_EXP_BACKOFF_TIME).println();
+            pw.printPair(KEY_STANDBY_HEARTBEAT_TIME, STANDBY_HEARTBEAT_TIME).println();
+            pw.print("standby_beats={");
+            pw.print(STANDBY_BEATS[0]);
+            for (int i = 1; i < STANDBY_BEATS.length; i++) {
+                pw.print(", ");
+                pw.print(STANDBY_BEATS[i]);
+            }
+            pw.println('}');
+            pw.printPair(KEY_CONN_CONGESTION_DELAY_FRAC, CONN_CONGESTION_DELAY_FRAC).println();
+            pw.printPair(KEY_CONN_PREFETCH_RELAX_FRAC, CONN_PREFETCH_RELAX_FRAC).println();
+            pw.printPair(KEY_USE_HEARTBEATS, USE_HEARTBEATS).println();
+
+            pw.decreaseIndent();
+        }
+
+        void dump(ProtoOutputStream proto) {
+            proto.write(ConstantsProto.MIN_IDLE_COUNT, MIN_IDLE_COUNT);
+            proto.write(ConstantsProto.MIN_CHARGING_COUNT, MIN_CHARGING_COUNT);
+            proto.write(ConstantsProto.MIN_BATTERY_NOT_LOW_COUNT, MIN_BATTERY_NOT_LOW_COUNT);
+            proto.write(ConstantsProto.MIN_STORAGE_NOT_LOW_COUNT, MIN_STORAGE_NOT_LOW_COUNT);
+            proto.write(ConstantsProto.MIN_CONNECTIVITY_COUNT, MIN_CONNECTIVITY_COUNT);
+            proto.write(ConstantsProto.MIN_CONTENT_COUNT, MIN_CONTENT_COUNT);
+            proto.write(ConstantsProto.MIN_READY_JOBS_COUNT, MIN_READY_JOBS_COUNT);
+            proto.write(ConstantsProto.MIN_READY_NON_ACTIVE_JOBS_COUNT,
+                    MIN_READY_NON_ACTIVE_JOBS_COUNT);
+            proto.write(ConstantsProto.MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS,
+                    MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS);
+            proto.write(ConstantsProto.HEAVY_USE_FACTOR, HEAVY_USE_FACTOR);
+            proto.write(ConstantsProto.MODERATE_USE_FACTOR, MODERATE_USE_FACTOR);
+
+            MAX_JOB_COUNTS_SCREEN_ON.dumpProto(proto, ConstantsProto.MAX_JOB_COUNTS_SCREEN_ON);
+            MAX_JOB_COUNTS_SCREEN_OFF.dumpProto(proto, ConstantsProto.MAX_JOB_COUNTS_SCREEN_OFF);
+
+            SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.dumpProto(proto,
+                    ConstantsProto.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS);
+
+            proto.write(ConstantsProto.MAX_STANDARD_RESCHEDULE_COUNT, MAX_STANDARD_RESCHEDULE_COUNT);
+            proto.write(ConstantsProto.MAX_WORK_RESCHEDULE_COUNT, MAX_WORK_RESCHEDULE_COUNT);
+            proto.write(ConstantsProto.MIN_LINEAR_BACKOFF_TIME_MS, MIN_LINEAR_BACKOFF_TIME);
+            proto.write(ConstantsProto.MIN_EXP_BACKOFF_TIME_MS, MIN_EXP_BACKOFF_TIME);
+            proto.write(ConstantsProto.STANDBY_HEARTBEAT_TIME_MS, STANDBY_HEARTBEAT_TIME);
+            for (int period : STANDBY_BEATS) {
+                proto.write(ConstantsProto.STANDBY_BEATS, period);
+            }
+            proto.write(ConstantsProto.CONN_CONGESTION_DELAY_FRAC, CONN_CONGESTION_DELAY_FRAC);
+            proto.write(ConstantsProto.CONN_PREFETCH_RELAX_FRAC, CONN_PREFETCH_RELAX_FRAC);
+            proto.write(ConstantsProto.USE_HEARTBEATS, USE_HEARTBEATS);
+        }
+    }
+
+    final Constants mConstants;
+    final ConstantsObserver mConstantsObserver;
+
+    static final Comparator<JobStatus> mEnqueueTimeComparator = (o1, o2) -> {
+        if (o1.enqueueTime < o2.enqueueTime) {
+            return -1;
+        }
+        return o1.enqueueTime > o2.enqueueTime ? 1 : 0;
+    };
+
+    static <T> void addOrderedItem(ArrayList<T> array, T newItem, Comparator<T> comparator) {
+        int where = Collections.binarySearch(array, newItem, comparator);
+        if (where < 0) {
+            where = ~where;
+        }
+        array.add(where, newItem);
+    }
+
+    /**
+     * Cleans up outstanding jobs when a package is removed. Even if it's being replaced later we
+     * still clean up. On reinstall the package will have a new uid.
+     */
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            if (DEBUG) {
+                Slog.d(TAG, "Receieved: " + action);
+            }
+            final String pkgName = getPackageName(intent);
+            final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+
+            if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
+                // Purge the app's jobs if the whole package was just disabled.  When this is
+                // the case the component name will be a bare package name.
+                if (pkgName != null && pkgUid != -1) {
+                    final String[] changedComponents = intent.getStringArrayExtra(
+                            Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
+                    if (changedComponents != null) {
+                        for (String component : changedComponents) {
+                            if (component.equals(pkgName)) {
+                                if (DEBUG) {
+                                    Slog.d(TAG, "Package state change: " + pkgName);
+                                }
+                                try {
+                                    final int userId = UserHandle.getUserId(pkgUid);
+                                    IPackageManager pm = AppGlobals.getPackageManager();
+                                    final int state = pm.getApplicationEnabledSetting(pkgName, userId);
+                                    if (state == COMPONENT_ENABLED_STATE_DISABLED
+                                            || state ==  COMPONENT_ENABLED_STATE_DISABLED_USER) {
+                                        if (DEBUG) {
+                                            Slog.d(TAG, "Removing jobs for package " + pkgName
+                                                    + " in user " + userId);
+                                        }
+                                        cancelJobsForPackageAndUid(pkgName, pkgUid,
+                                                "app disabled");
+                                    }
+                                } catch (RemoteException|IllegalArgumentException e) {
+                                    /*
+                                     * IllegalArgumentException means that the package doesn't exist.
+                                     * This arises when PACKAGE_CHANGED broadcast delivery has lagged
+                                     * behind outright uninstall, so by the time we try to act it's gone.
+                                     * We don't need to act on this PACKAGE_CHANGED when this happens;
+                                     * we'll get a PACKAGE_REMOVED later and clean up then.
+                                     *
+                                     * RemoteException can't actually happen; the package manager is
+                                     * running in this same process.
+                                     */
+                                }
+                                break;
+                            }
+                        }
+                        if (DEBUG) {
+                            Slog.d(TAG, "Something in " + pkgName
+                                    + " changed. Reevaluating controller states.");
+                        }
+                        synchronized (mLock) {
+                            for (int c = mControllers.size() - 1; c >= 0; --c) {
+                                mControllers.get(c).reevaluateStateLocked(pkgUid);
+                            }
+                        }
+                    }
+                } else {
+                    Slog.w(TAG, "PACKAGE_CHANGED for " + pkgName + " / uid " + pkgUid);
+                }
+            } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+                // If this is an outright uninstall rather than the first half of an
+                // app update sequence, cancel the jobs associated with the app.
+                if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+                    int uidRemoved = intent.getIntExtra(Intent.EXTRA_UID, -1);
+                    if (DEBUG) {
+                        Slog.d(TAG, "Removing jobs for uid: " + uidRemoved);
+                    }
+                    cancelJobsForPackageAndUid(pkgName, uidRemoved, "app uninstalled");
+                    synchronized (mLock) {
+                        for (int c = 0; c < mControllers.size(); ++c) {
+                            mControllers.get(c).onAppRemovedLocked(pkgName, pkgUid);
+                        }
+                    }
+                }
+            } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+                if (DEBUG) {
+                    Slog.d(TAG, "Removing jobs for user: " + userId);
+                }
+                cancelJobsForUser(userId);
+                synchronized (mLock) {
+                    for (int c = 0; c < mControllers.size(); ++c) {
+                        mControllers.get(c).onUserRemovedLocked(userId);
+                    }
+                }
+            } else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
+                // Has this package scheduled any jobs, such that we will take action
+                // if it were to be force-stopped?
+                if (pkgUid != -1) {
+                    List<JobStatus> jobsForUid;
+                    synchronized (mLock) {
+                        jobsForUid = mJobs.getJobsByUid(pkgUid);
+                    }
+                    for (int i = jobsForUid.size() - 1; i >= 0; i--) {
+                        if (jobsForUid.get(i).getSourcePackageName().equals(pkgName)) {
+                            if (DEBUG) {
+                                Slog.d(TAG, "Restart query: package " + pkgName + " at uid "
+                                        + pkgUid + " has jobs");
+                            }
+                            setResultCode(Activity.RESULT_OK);
+                            break;
+                        }
+                    }
+                }
+            } else if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) {
+                // possible force-stop
+                if (pkgUid != -1) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Removing jobs for pkg " + pkgName + " at uid " + pkgUid);
+                    }
+                    cancelJobsForPackageAndUid(pkgName, pkgUid, "app force stopped");
+                }
+            }
+        }
+    };
+
+    private String getPackageName(Intent intent) {
+        Uri uri = intent.getData();
+        String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
+        return pkg;
+    }
+
+    final private IUidObserver mUidObserver = new IUidObserver.Stub() {
+        @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+            mHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, procState).sendToTarget();
+        }
+
+        @Override public void onUidGone(int uid, boolean disabled) {
+            mHandler.obtainMessage(MSG_UID_GONE, uid, disabled ? 1 : 0).sendToTarget();
+        }
+
+        @Override public void onUidActive(int uid) throws RemoteException {
+            mHandler.obtainMessage(MSG_UID_ACTIVE, uid, 0).sendToTarget();
+        }
+
+        @Override public void onUidIdle(int uid, boolean disabled) {
+            mHandler.obtainMessage(MSG_UID_IDLE, uid, disabled ? 1 : 0).sendToTarget();
+        }
+
+        @Override public void onUidCachedChanged(int uid, boolean cached) {
+        }
+    };
+
+    public Context getTestableContext() {
+        return getContext();
+    }
+
+    public Object getLock() {
+        return mLock;
+    }
+
+    public JobStore getJobStore() {
+        return mJobs;
+    }
+
+    public Constants getConstants() {
+        return mConstants;
+    }
+
+    public boolean isChainedAttributionEnabled() {
+        return WorkSource.isChainedBatteryAttributionEnabled(getContext());
+    }
+
+    @Override
+    public void onStartUser(int userHandle) {
+        synchronized (mLock) {
+            mStartedUsers = ArrayUtils.appendInt(mStartedUsers, userHandle);
+        }
+        // Let's kick any outstanding jobs for this user.
+        mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+    }
+
+    @Override
+    public void onUnlockUser(int userHandle) {
+        // Let's kick any outstanding jobs for this user.
+        mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+    }
+
+    @Override
+    public void onStopUser(int userHandle) {
+        synchronized (mLock) {
+            mStartedUsers = ArrayUtils.removeInt(mStartedUsers, userHandle);
+        }
+    }
+
+    /**
+     * Return whether an UID is active or idle.
+     */
+    private boolean isUidActive(int uid) {
+        return mAppStateTracker.isUidActiveSynced(uid);
+    }
+
+    private final Predicate<Integer> mIsUidActivePredicate = this::isUidActive;
+
+    public int scheduleAsPackage(JobInfo job, JobWorkItem work, int uId, String packageName,
+            int userId, String tag) {
+        try {
+            if (ActivityManager.getService().isAppStartModeDisabled(uId,
+                    job.getService().getPackageName())) {
+                Slog.w(TAG, "Not scheduling job " + uId + ":" + job.toString()
+                        + " -- package not allowed to start");
+                return JobScheduler.RESULT_FAILURE;
+            }
+        } catch (RemoteException e) {
+        }
+
+        synchronized (mLock) {
+            final JobStatus toCancel = mJobs.getJobByUidAndJobId(uId, job.getId());
+
+            if (work != null && toCancel != null) {
+                // Fast path: we are adding work to an existing job, and the JobInfo is not
+                // changing.  We can just directly enqueue this work in to the job.
+                if (toCancel.getJob().equals(job)) {
+
+                    toCancel.enqueueWorkLocked(ActivityManager.getService(), work);
+
+                    // If any of work item is enqueued when the source is in the foreground,
+                    // exempt the entire job.
+                    toCancel.maybeAddForegroundExemption(mIsUidActivePredicate);
+
+                    return JobScheduler.RESULT_SUCCESS;
+                }
+            }
+
+            JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag);
+
+            // Give exemption if the source is in the foreground just now.
+            // Note if it's a sync job, this method is called on the handler so it's not exactly
+            // the state when requestSync() was called, but that should be fine because of the
+            // 1 minute foreground grace period.
+            jobStatus.maybeAddForegroundExemption(mIsUidActivePredicate);
+
+            if (DEBUG) Slog.d(TAG, "SCHEDULE: " + jobStatus.toShortString());
+            // Jobs on behalf of others don't apply to the per-app job cap
+            if (ENFORCE_MAX_JOBS && packageName == null) {
+                if (mJobs.countJobsForUid(uId) > MAX_JOBS_PER_APP) {
+                    Slog.w(TAG, "Too many jobs for uid " + uId);
+                    throw new IllegalStateException("Apps may not schedule more than "
+                                + MAX_JOBS_PER_APP + " distinct jobs");
+                }
+            }
+
+            // This may throw a SecurityException.
+            jobStatus.prepareLocked(ActivityManager.getService());
+
+            if (work != null) {
+                // If work has been supplied, enqueue it into the new job.
+                jobStatus.enqueueWorkLocked(ActivityManager.getService(), work);
+            }
+
+            if (toCancel != null) {
+                // Implicitly replaces the existing job record with the new instance
+                cancelJobImplLocked(toCancel, jobStatus, "job rescheduled by app");
+            } else {
+                startTrackingJobLocked(jobStatus, null);
+            }
+            StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED,
+                    uId, null, jobStatus.getBatteryName(),
+                    StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__SCHEDULED,
+                    JobProtoEnums.STOP_REASON_CANCELLED, jobStatus.getStandbyBucket(),
+                    jobStatus.getJobId());
+
+            // If the job is immediately ready to run, then we can just immediately
+            // put it in the pending list and try to schedule it.  This is especially
+            // important for jobs with a 0 deadline constraint, since they will happen a fair
+            // amount, we want to handle them as quickly as possible, and semantically we want to
+            // make sure we have started holding the wake lock for the job before returning to
+            // the caller.
+            // If the job is not yet ready to run, there is nothing more to do -- we are
+            // now just waiting for one of its controllers to change state and schedule
+            // the job appropriately.
+            if (isReadyToBeExecutedLocked(jobStatus)) {
+                // This is a new job, we can just immediately put it on the pending
+                // list and try to run it.
+                mJobPackageTracker.notePending(jobStatus);
+                addOrderedItem(mPendingJobs, jobStatus, mEnqueueTimeComparator);
+                maybeRunPendingJobsLocked();
+            } else {
+                evaluateControllerStatesLocked(jobStatus);
+            }
+        }
+        return JobScheduler.RESULT_SUCCESS;
+    }
+
+    public List<JobInfo> getPendingJobs(int uid) {
+        synchronized (mLock) {
+            List<JobStatus> jobs = mJobs.getJobsByUid(uid);
+            ArrayList<JobInfo> outList = new ArrayList<JobInfo>(jobs.size());
+            for (int i = jobs.size() - 1; i >= 0; i--) {
+                JobStatus job = jobs.get(i);
+                outList.add(job.getJob());
+            }
+            return outList;
+        }
+    }
+
+    public JobInfo getPendingJob(int uid, int jobId) {
+        synchronized (mLock) {
+            List<JobStatus> jobs = mJobs.getJobsByUid(uid);
+            for (int i = jobs.size() - 1; i >= 0; i--) {
+                JobStatus job = jobs.get(i);
+                if (job.getJobId() == jobId) {
+                    return job.getJob();
+                }
+            }
+            return null;
+        }
+    }
+
+    void cancelJobsForUser(int userHandle) {
+        synchronized (mLock) {
+            final List<JobStatus> jobsForUser = mJobs.getJobsByUser(userHandle);
+            for (int i=0; i<jobsForUser.size(); i++) {
+                JobStatus toRemove = jobsForUser.get(i);
+                cancelJobImplLocked(toRemove, null, "user removed");
+            }
+        }
+    }
+
+    private void cancelJobsForNonExistentUsers() {
+        UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
+        synchronized (mLock) {
+            mJobs.removeJobsOfNonUsers(umi.getUserIds());
+        }
+    }
+
+    void cancelJobsForPackageAndUid(String pkgName, int uid, String reason) {
+        if ("android".equals(pkgName)) {
+            Slog.wtfStack(TAG, "Can't cancel all jobs for system package");
+            return;
+        }
+        synchronized (mLock) {
+            final List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
+            for (int i = jobsForUid.size() - 1; i >= 0; i--) {
+                final JobStatus job = jobsForUid.get(i);
+                if (job.getSourcePackageName().equals(pkgName)) {
+                    cancelJobImplLocked(job, null, reason);
+                }
+            }
+        }
+    }
+
+    /**
+     * Entry point from client to cancel all jobs originating from their uid.
+     * This will remove the job from the master list, and cancel the job if it was staged for
+     * execution or being executed.
+     * @param uid Uid to check against for removal of a job.
+     *
+     */
+    public boolean cancelJobsForUid(int uid, String reason) {
+        if (uid == Process.SYSTEM_UID) {
+            Slog.wtfStack(TAG, "Can't cancel all jobs for system uid");
+            return false;
+        }
+
+        boolean jobsCanceled = false;
+        synchronized (mLock) {
+            final List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
+            for (int i=0; i<jobsForUid.size(); i++) {
+                JobStatus toRemove = jobsForUid.get(i);
+                cancelJobImplLocked(toRemove, null, reason);
+                jobsCanceled = true;
+            }
+        }
+        return jobsCanceled;
+    }
+
+    /**
+     * Entry point from client to cancel the job corresponding to the jobId provided.
+     * This will remove the job from the master list, and cancel the job if it was staged for
+     * execution or being executed.
+     * @param uid Uid of the calling client.
+     * @param jobId Id of the job, provided at schedule-time.
+     */
+    public boolean cancelJob(int uid, int jobId, int callingUid) {
+        JobStatus toCancel;
+        synchronized (mLock) {
+            toCancel = mJobs.getJobByUidAndJobId(uid, jobId);
+            if (toCancel != null) {
+                cancelJobImplLocked(toCancel, null,
+                        "cancel() called by app, callingUid=" + callingUid
+                        + " uid=" + uid + " jobId=" + jobId);
+            }
+            return (toCancel != null);
+        }
+    }
+
+    /**
+     * Cancel the given job, stopping it if it's currently executing.  If {@code incomingJob}
+     * is null, the cancelled job is removed outright from the system.  If
+     * {@code incomingJob} is non-null, it replaces {@code cancelled} in the store of
+     * currently scheduled jobs.
+     */
+    private void cancelJobImplLocked(JobStatus cancelled, JobStatus incomingJob, String reason) {
+        if (DEBUG) Slog.d(TAG, "CANCEL: " + cancelled.toShortString());
+        cancelled.unprepareLocked(ActivityManager.getService());
+        stopTrackingJobLocked(cancelled, incomingJob, true /* writeBack */);
+        // Remove from pending queue.
+        if (mPendingJobs.remove(cancelled)) {
+            mJobPackageTracker.noteNonpending(cancelled);
+        }
+        // Cancel if running.
+        stopJobOnServiceContextLocked(cancelled, JobParameters.REASON_CANCELED, reason);
+        // If this is a replacement, bring in the new version of the job
+        if (incomingJob != null) {
+            if (DEBUG) Slog.i(TAG, "Tracking replacement job " + incomingJob.toShortString());
+            startTrackingJobLocked(incomingJob, cancelled);
+        }
+        reportActiveLocked();
+    }
+
+    void updateUidState(int uid, int procState) {
+        synchronized (mLock) {
+            if (procState == ActivityManager.PROCESS_STATE_TOP) {
+                // Only use this if we are exactly the top app.  All others can live
+                // with just the foreground priority.  This means that persistent processes
+                // can never be the top app priority...  that is fine.
+                mUidPriorityOverride.put(uid, JobInfo.PRIORITY_TOP_APP);
+            } else if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
+                mUidPriorityOverride.put(uid, JobInfo.PRIORITY_FOREGROUND_SERVICE);
+            } else if (procState <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
+                mUidPriorityOverride.put(uid, JobInfo.PRIORITY_BOUND_FOREGROUND_SERVICE);
+            } else {
+                mUidPriorityOverride.delete(uid);
+            }
+        }
+    }
+
+    @Override
+    public void onDeviceIdleStateChanged(boolean deviceIdle) {
+        synchronized (mLock) {
+            if (DEBUG) {
+                Slog.d(TAG, "Doze state changed: " + deviceIdle);
+            }
+            if (deviceIdle) {
+                // When becoming idle, make sure no jobs are actively running,
+                // except those using the idle exemption flag.
+                for (int i=0; i<mActiveServices.size(); i++) {
+                    JobServiceContext jsc = mActiveServices.get(i);
+                    final JobStatus executing = jsc.getRunningJobLocked();
+                    if (executing != null
+                            && (executing.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) == 0) {
+                        jsc.cancelExecutingJobLocked(JobParameters.REASON_DEVICE_IDLE,
+                                "cancelled due to doze");
+                    }
+                }
+            } else {
+                // When coming out of idle, allow thing to start back up.
+                if (mReadyToRock) {
+                    if (mLocalDeviceIdleController != null) {
+                        if (!mReportedActive) {
+                            mReportedActive = true;
+                            mLocalDeviceIdleController.setJobsActive(true);
+                        }
+                    }
+                    mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+                }
+            }
+        }
+    }
+
+    void reportActiveLocked() {
+        // active is true if pending queue contains jobs OR some job is running.
+        boolean active = mPendingJobs.size() > 0;
+        if (mPendingJobs.size() <= 0) {
+            for (int i=0; i<mActiveServices.size(); i++) {
+                final JobServiceContext jsc = mActiveServices.get(i);
+                final JobStatus job = jsc.getRunningJobLocked();
+                if (job != null
+                        && (job.getJob().getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) == 0
+                        && !job.dozeWhitelisted
+                        && !job.uidActive) {
+                    // We will report active if we have a job running and it is not an exception
+                    // due to being in the foreground or whitelisted.
+                    active = true;
+                    break;
+                }
+            }
+        }
+
+        if (mReportedActive != active) {
+            mReportedActive = active;
+            if (mLocalDeviceIdleController != null) {
+                mLocalDeviceIdleController.setJobsActive(active);
+            }
+        }
+    }
+
+    void reportAppUsage(String packageName, int userId) {
+        // This app just transitioned into interactive use or near equivalent, so we should
+        // take a look at its job state for feedback purposes.
+    }
+
+    /**
+     * Initializes the system service.
+     * <p>
+     * Subclasses must define a single argument constructor that accepts the context
+     * and passes it to super.
+     * </p>
+     *
+     * @param context The system server context.
+     */
+    public JobSchedulerService(Context context) {
+        super(context);
+
+        mLocalPM = LocalServices.getService(PackageManagerInternal.class);
+        mActivityManagerInternal = Preconditions.checkNotNull(
+                LocalServices.getService(ActivityManagerInternal.class));
+
+        mHandler = new JobHandler(context.getMainLooper());
+        mConstants = new Constants();
+        mConstantsObserver = new ConstantsObserver(mHandler);
+        mJobSchedulerStub = new JobSchedulerStub();
+
+        mConcurrencyManager = new JobConcurrencyManager(this);
+
+        // Set up the app standby bucketing tracker
+        mStandbyTracker = new StandbyTracker();
+        mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
+        mUsageStats.addAppIdleStateChangeListener(mStandbyTracker);
+
+        // The job store needs to call back
+        publishLocalService(JobSchedulerInternal.class, new LocalService());
+
+        // Initialize the job store and set up any persisted jobs
+        mJobs = JobStore.initAndGet(this);
+
+        // Create the controllers.
+        mControllers = new ArrayList<StateController>();
+        mControllers.add(new ConnectivityController(this));
+        mControllers.add(new TimeController(this));
+        mControllers.add(new IdleController(this));
+        mBatteryController = new BatteryController(this);
+        mControllers.add(mBatteryController);
+        mStorageController = new StorageController(this);
+        mControllers.add(mStorageController);
+        mControllers.add(new BackgroundJobsController(this));
+        mControllers.add(new ContentObserverController(this));
+        mDeviceIdleJobsController = new DeviceIdleJobsController(this);
+        mControllers.add(mDeviceIdleJobsController);
+        mQuotaController = new QuotaController(this);
+        mControllers.add(mQuotaController);
+
+        // If the job store determined that it can't yet reschedule persisted jobs,
+        // we need to start watching the clock.
+        if (!mJobs.jobTimesInflatedValid()) {
+            Slog.w(TAG, "!!! RTC not yet good; tracking time updates for job scheduling");
+            context.registerReceiver(mTimeSetReceiver, new IntentFilter(Intent.ACTION_TIME_CHANGED));
+        }
+    }
+
+    private final BroadcastReceiver mTimeSetReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
+                // When we reach clock sanity, recalculate the temporal windows
+                // of all affected jobs.
+                if (mJobs.clockNowValidToInflate(sSystemClock.millis())) {
+                    Slog.i(TAG, "RTC now valid; recalculating persisted job windows");
+
+                    // We've done our job now, so stop watching the time.
+                    context.unregisterReceiver(this);
+
+                    // And kick off the work to update the affected jobs, using a secondary
+                    // thread instead of chugging away here on the main looper thread.
+                    FgThread.getHandler().post(mJobTimeUpdater);
+                }
+            }
+        }
+    };
+
+    private final Runnable mJobTimeUpdater = () -> {
+        final ArrayList<JobStatus> toRemove = new ArrayList<>();
+        final ArrayList<JobStatus> toAdd = new ArrayList<>();
+        synchronized (mLock) {
+            // Note: we intentionally both look up the existing affected jobs and replace them
+            // with recalculated ones inside the same lock lifetime.
+            getJobStore().getRtcCorrectedJobsLocked(toAdd, toRemove);
+
+            // Now, at each position [i], we have both the existing JobStatus
+            // and the one that replaces it.
+            final int N = toAdd.size();
+            for (int i = 0; i < N; i++) {
+                final JobStatus oldJob = toRemove.get(i);
+                final JobStatus newJob = toAdd.get(i);
+                if (DEBUG) {
+                    Slog.v(TAG, "  replacing " + oldJob + " with " + newJob);
+                }
+                cancelJobImplLocked(oldJob, newJob, "deferred rtc calculation");
+            }
+        }
+    };
+
+    @Override
+    public void onStart() {
+        publishBinderService(Context.JOB_SCHEDULER_SERVICE, mJobSchedulerStub);
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (PHASE_SYSTEM_SERVICES_READY == phase) {
+            mConstantsObserver.start(getContext().getContentResolver());
+            for (StateController controller : mControllers) {
+                controller.onSystemServicesReady();
+            }
+
+            mAppStateTracker = Preconditions.checkNotNull(
+                    LocalServices.getService(AppStateTracker.class));
+            if (mConstants.USE_HEARTBEATS) {
+                setNextHeartbeatAlarm();
+            }
+
+            // Register br for package removals and user removals.
+            final IntentFilter filter = new IntentFilter();
+            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+            filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+            filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+            filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
+            filter.addDataScheme("package");
+            getContext().registerReceiverAsUser(
+                    mBroadcastReceiver, UserHandle.ALL, filter, null, null);
+            final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
+            getContext().registerReceiverAsUser(
+                    mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
+            try {
+                ActivityManager.getService().registerUidObserver(mUidObserver,
+                        ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE
+                        | ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_ACTIVE,
+                        ActivityManager.PROCESS_STATE_UNKNOWN, null);
+            } catch (RemoteException e) {
+                // ignored; both services live in system_server
+            }
+
+            mConcurrencyManager.onSystemReady();
+
+            // Remove any jobs that are not associated with any of the current users.
+            cancelJobsForNonExistentUsers();
+            // Register thermal callback
+            mThermalService = IThermalService.Stub.asInterface(
+                    ServiceManager.getService(Context.THERMAL_SERVICE));
+            if (mThermalService != null) {
+                try {
+                    mThermalService.registerThermalStatusListener(new ThermalStatusListener());
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to register thermal callback.", e);
+                }
+            }
+        } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+            synchronized (mLock) {
+                // Let's go!
+                mReadyToRock = true;
+                mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
+                        BatteryStats.SERVICE_NAME));
+                mLocalDeviceIdleController
+                        = LocalServices.getService(DeviceIdleController.LocalService.class);
+                // Create the "runners".
+                for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
+                    mActiveServices.add(
+                            new JobServiceContext(this, mBatteryStats, mJobPackageTracker,
+                                    getContext().getMainLooper()));
+                }
+                // Attach jobs to their controllers.
+                mJobs.forEachJob((job) -> {
+                    for (int controller = 0; controller < mControllers.size(); controller++) {
+                        final StateController sc = mControllers.get(controller);
+                        sc.maybeStartTrackingJobLocked(job, null);
+                    }
+                });
+                // GO GO GO!
+                mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Called when we have a job status object that we need to insert in our
+     * {@link com.android.server.job.JobStore}, and make sure all the relevant controllers know
+     * about.
+     */
+    private void startTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
+        if (!jobStatus.isPreparedLocked()) {
+            Slog.wtf(TAG, "Not yet prepared when started tracking: " + jobStatus);
+        }
+        jobStatus.enqueueTime = sElapsedRealtimeClock.millis();
+        final boolean update = mJobs.add(jobStatus);
+        if (mReadyToRock) {
+            for (int i = 0; i < mControllers.size(); i++) {
+                StateController controller = mControllers.get(i);
+                if (update) {
+                    controller.maybeStopTrackingJobLocked(jobStatus, null, true);
+                }
+                controller.maybeStartTrackingJobLocked(jobStatus, lastJob);
+            }
+        }
+    }
+
+    /**
+     * Called when we want to remove a JobStatus object that we've finished executing.
+     * @return true if the job was removed.
+     */
+    private boolean stopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
+            boolean removeFromPersisted) {
+        // Deal with any remaining work items in the old job.
+        jobStatus.stopTrackingJobLocked(ActivityManager.getService(), incomingJob);
+
+        // Remove from store as well as controllers.
+        final boolean removed = mJobs.remove(jobStatus, removeFromPersisted);
+        if (removed && mReadyToRock) {
+            for (int i=0; i<mControllers.size(); i++) {
+                StateController controller = mControllers.get(i);
+                controller.maybeStopTrackingJobLocked(jobStatus, incomingJob, false);
+            }
+        }
+        return removed;
+    }
+
+    private boolean stopJobOnServiceContextLocked(JobStatus job, int reason, String debugReason) {
+        for (int i=0; i<mActiveServices.size(); i++) {
+            JobServiceContext jsc = mActiveServices.get(i);
+            final JobStatus executing = jsc.getRunningJobLocked();
+            if (executing != null && executing.matches(job.getUid(), job.getJobId())) {
+                jsc.cancelExecutingJobLocked(reason, debugReason);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @param job JobStatus we are querying against.
+     * @return Whether or not the job represented by the status object is currently being run or
+     * is pending.
+     */
+    private boolean isCurrentlyActiveLocked(JobStatus job) {
+        for (int i=0; i<mActiveServices.size(); i++) {
+            JobServiceContext serviceContext = mActiveServices.get(i);
+            final JobStatus running = serviceContext.getRunningJobLocked();
+            if (running != null && running.matches(job.getUid(), job.getJobId())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void noteJobsPending(List<JobStatus> jobs) {
+        for (int i = jobs.size() - 1; i >= 0; i--) {
+            JobStatus job = jobs.get(i);
+            mJobPackageTracker.notePending(job);
+        }
+    }
+
+    void noteJobsNonpending(List<JobStatus> jobs) {
+        for (int i = jobs.size() - 1; i >= 0; i--) {
+            JobStatus job = jobs.get(i);
+            mJobPackageTracker.noteNonpending(job);
+        }
+    }
+
+    /**
+     * Reschedules the given job based on the job's backoff policy. It doesn't make sense to
+     * specify an override deadline on a failed job (the failed job will run even though it's not
+     * ready), so we reschedule it with {@link JobStatus#NO_LATEST_RUNTIME}, but specify that any
+     * ready job with {@link JobStatus#getNumFailures()} > 0 will be executed.
+     *
+     * @param failureToReschedule Provided job status that we will reschedule.
+     * @return A newly instantiated JobStatus with the same constraints as the last job except
+     * with adjusted timing constraints.
+     *
+     * @see #maybeQueueReadyJobsForExecutionLocked
+     */
+    @VisibleForTesting
+    JobStatus getRescheduleJobForFailureLocked(JobStatus failureToReschedule) {
+        final long elapsedNowMillis = sElapsedRealtimeClock.millis();
+        final JobInfo job = failureToReschedule.getJob();
+
+        final long initialBackoffMillis = job.getInitialBackoffMillis();
+        final int backoffAttempts = failureToReschedule.getNumFailures() + 1;
+        long delayMillis;
+
+        if (failureToReschedule.hasWorkLocked()) {
+            if (backoffAttempts > mConstants.MAX_WORK_RESCHEDULE_COUNT) {
+                Slog.w(TAG, "Not rescheduling " + failureToReschedule + ": attempt #"
+                        + backoffAttempts + " > work limit "
+                        + mConstants.MAX_STANDARD_RESCHEDULE_COUNT);
+                return null;
+            }
+        } else if (backoffAttempts > mConstants.MAX_STANDARD_RESCHEDULE_COUNT) {
+            Slog.w(TAG, "Not rescheduling " + failureToReschedule + ": attempt #"
+                    + backoffAttempts + " > std limit " + mConstants.MAX_STANDARD_RESCHEDULE_COUNT);
+            return null;
+        }
+
+        switch (job.getBackoffPolicy()) {
+            case JobInfo.BACKOFF_POLICY_LINEAR: {
+                long backoff = initialBackoffMillis;
+                if (backoff < mConstants.MIN_LINEAR_BACKOFF_TIME) {
+                    backoff = mConstants.MIN_LINEAR_BACKOFF_TIME;
+                }
+                delayMillis = backoff * backoffAttempts;
+            } break;
+            default:
+                if (DEBUG) {
+                    Slog.v(TAG, "Unrecognised back-off policy, defaulting to exponential.");
+                }
+            case JobInfo.BACKOFF_POLICY_EXPONENTIAL: {
+                long backoff = initialBackoffMillis;
+                if (backoff < mConstants.MIN_EXP_BACKOFF_TIME) {
+                    backoff = mConstants.MIN_EXP_BACKOFF_TIME;
+                }
+                delayMillis = (long) Math.scalb(backoff, backoffAttempts - 1);
+            } break;
+        }
+        delayMillis =
+                Math.min(delayMillis, JobInfo.MAX_BACKOFF_DELAY_MILLIS);
+        JobStatus newJob = new JobStatus(failureToReschedule, getCurrentHeartbeat(),
+                elapsedNowMillis + delayMillis,
+                JobStatus.NO_LATEST_RUNTIME, backoffAttempts,
+                failureToReschedule.getLastSuccessfulRunTime(), sSystemClock.millis());
+        if (job.isPeriodic()) {
+            newJob.setOriginalLatestRunTimeElapsed(
+                    failureToReschedule.getOriginalLatestRunTimeElapsed());
+        }
+        for (int ic=0; ic<mControllers.size(); ic++) {
+            StateController controller = mControllers.get(ic);
+            controller.rescheduleForFailureLocked(newJob, failureToReschedule);
+        }
+        return newJob;
+    }
+
+    /**
+     * Maximum time buffer in which JobScheduler will try to optimize periodic job scheduling. This
+     * does not cause a job's period to be larger than requested (eg: if the requested period is
+     * shorter than this buffer). This is used to put a limit on when JobScheduler will intervene
+     * and try to optimize scheduling if the current job finished less than this amount of time to
+     * the start of the next period
+     */
+    private static final long PERIODIC_JOB_WINDOW_BUFFER = 30 * MINUTE_IN_MILLIS;
+
+    /** The maximum period a periodic job can have. Anything higher will be clamped down to this. */
+    public static final long MAX_ALLOWED_PERIOD_MS = 365 * 24 * 60 * 60 * 1000L;
+
+    /**
+     * Called after a periodic has executed so we can reschedule it. We take the last execution
+     * time of the job to be the time of completion (i.e. the time at which this function is
+     * called).
+     * <p>This could be inaccurate b/c the job can run for as long as
+     * {@link com.android.server.job.JobServiceContext#EXECUTING_TIMESLICE_MILLIS}, but will lead
+     * to underscheduling at least, rather than if we had taken the last execution time to be the
+     * start of the execution.
+     * <p>Unlike a reschedule prior to execution, in this case we advance the next-heartbeat
+     * tracking as though the job were newly-scheduled.
+     * @return A new job representing the execution criteria for this instantiation of the
+     * recurring job.
+     */
+    @VisibleForTesting
+    JobStatus getRescheduleJobForPeriodic(JobStatus periodicToReschedule) {
+        final long elapsedNow = sElapsedRealtimeClock.millis();
+        final long newLatestRuntimeElapsed;
+        // Make sure period is in the interval [min_possible_period, max_possible_period].
+        final long period = Math.max(JobInfo.getMinPeriodMillis(),
+                Math.min(MAX_ALLOWED_PERIOD_MS, periodicToReschedule.getJob().getIntervalMillis()));
+        // Make sure flex is in the interval [min_possible_flex, period].
+        final long flex = Math.max(JobInfo.getMinFlexMillis(),
+                Math.min(period, periodicToReschedule.getJob().getFlexMillis()));
+        long rescheduleBuffer = 0;
+
+        long olrte = periodicToReschedule.getOriginalLatestRunTimeElapsed();
+        if (olrte < 0 || olrte == JobStatus.NO_LATEST_RUNTIME) {
+            Slog.wtf(TAG, "Invalid periodic job original latest run time: " + olrte);
+            olrte = elapsedNow;
+        }
+        final long latestRunTimeElapsed = olrte;
+
+        final long diffMs = Math.abs(elapsedNow - latestRunTimeElapsed);
+        if (elapsedNow > latestRunTimeElapsed) {
+            // The job ran past its expected run window. Have it count towards the current window
+            // and schedule a new job for the next window.
+            if (DEBUG) {
+                Slog.i(TAG, "Periodic job ran after its intended window.");
+            }
+            long numSkippedWindows = (diffMs / period) + 1; // +1 to include original window
+            if (period != flex && diffMs > Math.min(PERIODIC_JOB_WINDOW_BUFFER,
+                    (period - flex) / 2)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Custom flex job ran too close to next window.");
+                }
+                // For custom flex periods, if the job was run too close to the next window,
+                // skip the next window and schedule for the following one.
+                numSkippedWindows += 1;
+            }
+            newLatestRuntimeElapsed = latestRunTimeElapsed + (period * numSkippedWindows);
+        } else {
+            newLatestRuntimeElapsed = latestRunTimeElapsed + period;
+            if (diffMs < PERIODIC_JOB_WINDOW_BUFFER && diffMs < period / 6) {
+                // Add a little buffer to the start of the next window so the job doesn't run
+                // too soon after this completed one.
+                rescheduleBuffer = Math.min(PERIODIC_JOB_WINDOW_BUFFER, period / 6 - diffMs);
+            }
+        }
+
+        if (newLatestRuntimeElapsed < elapsedNow) {
+            Slog.wtf(TAG, "Rescheduling calculated latest runtime in the past: "
+                    + newLatestRuntimeElapsed);
+            return new JobStatus(periodicToReschedule, getCurrentHeartbeat(),
+                    elapsedNow + period - flex, elapsedNow + period,
+                    0 /* backoffAttempt */,
+                    sSystemClock.millis() /* lastSuccessfulRunTime */,
+                    periodicToReschedule.getLastFailedRunTime());
+        }
+
+        final long newEarliestRunTimeElapsed = newLatestRuntimeElapsed
+                - Math.min(flex, period - rescheduleBuffer);
+
+        if (DEBUG) {
+            Slog.v(TAG, "Rescheduling executed periodic. New execution window [" +
+                    newEarliestRunTimeElapsed / 1000 + ", " + newLatestRuntimeElapsed / 1000
+                    + "]s");
+        }
+        return new JobStatus(periodicToReschedule, getCurrentHeartbeat(),
+                newEarliestRunTimeElapsed, newLatestRuntimeElapsed,
+                0 /* backoffAttempt */,
+                sSystemClock.millis() /* lastSuccessfulRunTime */,
+                periodicToReschedule.getLastFailedRunTime());
+    }
+
+    /*
+     * We default to "long enough ago that every bucket's jobs are immediately runnable" to
+     * avoid starvation of apps in uncommon-use buckets that might arise from repeated
+     * reboot behavior.
+     */
+    long heartbeatWhenJobsLastRun(String packageName, final @UserIdInt int userId) {
+        // The furthest back in pre-boot time that we need to bother with
+        long heartbeat = -mConstants.STANDBY_BEATS[RARE_INDEX];
+        boolean cacheHit = false;
+        synchronized (mLock) {
+            HashMap<String, Long> jobPackages = mLastJobHeartbeats.get(userId);
+            if (jobPackages != null) {
+                long cachedValue = jobPackages.getOrDefault(packageName, Long.MAX_VALUE);
+                if (cachedValue < Long.MAX_VALUE) {
+                    cacheHit = true;
+                    heartbeat = cachedValue;
+                }
+            }
+            if (!cacheHit) {
+                // We haven't seen it yet; ask usage stats about it
+                final long timeSinceJob = mUsageStats.getTimeSinceLastJobRun(packageName, userId);
+                if (timeSinceJob < Long.MAX_VALUE) {
+                    // Usage stats knows about it from before, so calculate back from that
+                    // and go from there.
+                    heartbeat = mHeartbeat - (timeSinceJob / mConstants.STANDBY_HEARTBEAT_TIME);
+                }
+                // If usage stats returned its "not found" MAX_VALUE, we still have the
+                // negative default 'heartbeat' value we established above
+                setLastJobHeartbeatLocked(packageName, userId, heartbeat);
+            }
+        }
+        if (DEBUG_STANDBY) {
+            Slog.v(TAG, "Last job heartbeat " + heartbeat + " for "
+                    + packageName + "/" + userId);
+        }
+        return heartbeat;
+    }
+
+    long heartbeatWhenJobsLastRun(JobStatus job) {
+        return heartbeatWhenJobsLastRun(job.getSourcePackageName(), job.getSourceUserId());
+    }
+
+    void setLastJobHeartbeatLocked(String packageName, int userId, long heartbeat) {
+        HashMap<String, Long> jobPackages = mLastJobHeartbeats.get(userId);
+        if (jobPackages == null) {
+            jobPackages = new HashMap<>();
+            mLastJobHeartbeats.put(userId, jobPackages);
+        }
+        jobPackages.put(packageName, heartbeat);
+    }
+
+    // JobCompletedListener implementations.
+
+    /**
+     * A job just finished executing. We fetch the
+     * {@link com.android.server.job.controllers.JobStatus} from the store and depending on
+     * whether we want to reschedule we re-add it to the controllers.
+     * @param jobStatus Completed job.
+     * @param needsReschedule Whether the implementing class should reschedule this job.
+     */
+    @Override
+    public void onJobCompletedLocked(JobStatus jobStatus, boolean needsReschedule) {
+        if (DEBUG) {
+            Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule);
+        }
+
+        // If the job wants to be rescheduled, we first need to make the next upcoming
+        // job so we can transfer any appropriate state over from the previous job when
+        // we stop it.
+        final JobStatus rescheduledJob = needsReschedule
+                ? getRescheduleJobForFailureLocked(jobStatus) : null;
+
+        // Do not write back immediately if this is a periodic job. The job may get lost if system
+        // shuts down before it is added back.
+        if (!stopTrackingJobLocked(jobStatus, rescheduledJob, !jobStatus.getJob().isPeriodic())) {
+            if (DEBUG) {
+                Slog.d(TAG, "Could not find job to remove. Was job removed while executing?");
+            }
+            // We still want to check for jobs to execute, because this job may have
+            // scheduled a new job under the same job id, and now we can run it.
+            mHandler.obtainMessage(MSG_CHECK_JOB_GREEDY).sendToTarget();
+            return;
+        }
+
+        if (rescheduledJob != null) {
+            try {
+                rescheduledJob.prepareLocked(ActivityManager.getService());
+            } catch (SecurityException e) {
+                Slog.w(TAG, "Unable to regrant job permissions for " + rescheduledJob);
+            }
+            startTrackingJobLocked(rescheduledJob, jobStatus);
+        } else if (jobStatus.getJob().isPeriodic()) {
+            JobStatus rescheduledPeriodic = getRescheduleJobForPeriodic(jobStatus);
+            try {
+                rescheduledPeriodic.prepareLocked(ActivityManager.getService());
+            } catch (SecurityException e) {
+                Slog.w(TAG, "Unable to regrant job permissions for " + rescheduledPeriodic);
+            }
+            startTrackingJobLocked(rescheduledPeriodic, jobStatus);
+        }
+        jobStatus.unprepareLocked(ActivityManager.getService());
+        reportActiveLocked();
+        mHandler.obtainMessage(MSG_CHECK_JOB_GREEDY).sendToTarget();
+    }
+
+    // StateChangedListener implementations.
+
+    /**
+     * Posts a message to the {@link com.android.server.job.JobSchedulerService.JobHandler} that
+     * some controller's state has changed, so as to run through the list of jobs and start/stop
+     * any that are eligible.
+     */
+    @Override
+    public void onControllerStateChanged() {
+        mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+    }
+
+    @Override
+    public void onRunJobNow(JobStatus jobStatus) {
+        mHandler.obtainMessage(MSG_JOB_EXPIRED, jobStatus).sendToTarget();
+    }
+
+    final private class JobHandler extends Handler {
+
+        public JobHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message message) {
+            synchronized (mLock) {
+                if (!mReadyToRock) {
+                    return;
+                }
+                switch (message.what) {
+                    case MSG_JOB_EXPIRED: {
+                        JobStatus runNow = (JobStatus) message.obj;
+                        // runNow can be null, which is a controller's way of indicating that its
+                        // state is such that all ready jobs should be run immediately.
+                        if (runNow != null && isReadyToBeExecutedLocked(runNow)) {
+                            mJobPackageTracker.notePending(runNow);
+                            addOrderedItem(mPendingJobs, runNow, mEnqueueTimeComparator);
+                        } else {
+                            queueReadyJobsForExecutionLocked();
+                        }
+                    } break;
+                    case MSG_CHECK_JOB:
+                        if (DEBUG) {
+                            Slog.d(TAG, "MSG_CHECK_JOB");
+                        }
+                        removeMessages(MSG_CHECK_JOB);
+                        if (mReportedActive) {
+                            // if jobs are currently being run, queue all ready jobs for execution.
+                            queueReadyJobsForExecutionLocked();
+                        } else {
+                            // Check the list of jobs and run some of them if we feel inclined.
+                            maybeQueueReadyJobsForExecutionLocked();
+                        }
+                        break;
+                    case MSG_CHECK_JOB_GREEDY:
+                        if (DEBUG) {
+                            Slog.d(TAG, "MSG_CHECK_JOB_GREEDY");
+                        }
+                        queueReadyJobsForExecutionLocked();
+                        break;
+                    case MSG_STOP_JOB:
+                        cancelJobImplLocked((JobStatus) message.obj, null,
+                                "app no longer allowed to run");
+                        break;
+
+                    case MSG_UID_STATE_CHANGED: {
+                        final int uid = message.arg1;
+                        final int procState = message.arg2;
+                        updateUidState(uid, procState);
+                        break;
+                    }
+                    case MSG_UID_GONE: {
+                        final int uid = message.arg1;
+                        final boolean disabled = message.arg2 != 0;
+                        updateUidState(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+                        if (disabled) {
+                            cancelJobsForUid(uid, "uid gone");
+                        }
+                        synchronized (mLock) {
+                            mDeviceIdleJobsController.setUidActiveLocked(uid, false);
+                        }
+                        break;
+                    }
+                    case MSG_UID_ACTIVE: {
+                        final int uid = message.arg1;
+                        synchronized (mLock) {
+                            mDeviceIdleJobsController.setUidActiveLocked(uid, true);
+                        }
+                        break;
+                    }
+                    case MSG_UID_IDLE: {
+                        final int uid = message.arg1;
+                        final boolean disabled = message.arg2 != 0;
+                        if (disabled) {
+                            cancelJobsForUid(uid, "app uid idle");
+                        }
+                        synchronized (mLock) {
+                            mDeviceIdleJobsController.setUidActiveLocked(uid, false);
+                        }
+                        break;
+                    }
+
+                }
+                maybeRunPendingJobsLocked();
+                // Don't remove JOB_EXPIRED in case one came along while processing the queue.
+            }
+        }
+    }
+
+    private boolean isJobThermalConstrainedLocked(JobStatus job) {
+        return mThermalConstraint && job.hasConnectivityConstraint()
+                && (evaluateJobPriorityLocked(job) < JobInfo.PRIORITY_FOREGROUND_APP);
+    }
+
+    private void stopNonReadyActiveJobsLocked() {
+        for (int i=0; i<mActiveServices.size(); i++) {
+            JobServiceContext serviceContext = mActiveServices.get(i);
+            final JobStatus running = serviceContext.getRunningJobLocked();
+            if (running == null) {
+                continue;
+            }
+            if (!running.isReady()) {
+                serviceContext.cancelExecutingJobLocked(
+                        JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED,
+                        "cancelled due to unsatisfied constraints");
+            } else if (isJobThermalConstrainedLocked(running)) {
+                serviceContext.cancelExecutingJobLocked(
+                        JobParameters.REASON_DEVICE_THERMAL,
+                        "cancelled due to thermal condition");
+            }
+        }
+    }
+
+    /**
+     * Run through list of jobs and execute all possible - at least one is expired so we do
+     * as many as we can.
+     */
+    private void queueReadyJobsForExecutionLocked() {
+        if (DEBUG) {
+            Slog.d(TAG, "queuing all ready jobs for execution:");
+        }
+        noteJobsNonpending(mPendingJobs);
+        mPendingJobs.clear();
+        stopNonReadyActiveJobsLocked();
+        mJobs.forEachJob(mReadyQueueFunctor);
+        mReadyQueueFunctor.postProcess();
+
+        if (DEBUG) {
+            final int queuedJobs = mPendingJobs.size();
+            if (queuedJobs == 0) {
+                Slog.d(TAG, "No jobs pending.");
+            } else {
+                Slog.d(TAG, queuedJobs + " jobs queued.");
+            }
+        }
+    }
+
+    final class ReadyJobQueueFunctor implements Consumer<JobStatus> {
+        final ArrayList<JobStatus> newReadyJobs = new ArrayList<>();
+
+        @Override
+        public void accept(JobStatus job) {
+            if (isReadyToBeExecutedLocked(job)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "    queued " + job.toShortString());
+                }
+                newReadyJobs.add(job);
+            } else {
+                evaluateControllerStatesLocked(job);
+            }
+        }
+
+        public void postProcess() {
+            noteJobsPending(newReadyJobs);
+            mPendingJobs.addAll(newReadyJobs);
+            if (mPendingJobs.size() > 1) {
+                mPendingJobs.sort(mEnqueueTimeComparator);
+            }
+
+            newReadyJobs.clear();
+        }
+    }
+    private final ReadyJobQueueFunctor mReadyQueueFunctor = new ReadyJobQueueFunctor();
+
+    /**
+     * The state of at least one job has changed. Here is where we could enforce various
+     * policies on when we want to execute jobs.
+     */
+    final class MaybeReadyJobQueueFunctor implements Consumer<JobStatus> {
+        int chargingCount;
+        int batteryNotLowCount;
+        int storageNotLowCount;
+        int idleCount;
+        int backoffCount;
+        int connectivityCount;
+        int contentCount;
+        int forceBatchedCount;
+        int unbatchedCount;
+        final List<JobStatus> runnableJobs = new ArrayList<>();
+
+        public MaybeReadyJobQueueFunctor() {
+            reset();
+        }
+
+        // Functor method invoked for each job via JobStore.forEachJob()
+        @Override
+        public void accept(JobStatus job) {
+            if (isReadyToBeExecutedLocked(job)) {
+                try {
+                    if (ActivityManager.getService().isAppStartModeDisabled(job.getUid(),
+                            job.getJob().getService().getPackageName())) {
+                        Slog.w(TAG, "Aborting job " + job.getUid() + ":"
+                                + job.getJob().toString() + " -- package not allowed to start");
+                        mHandler.obtainMessage(MSG_STOP_JOB, job).sendToTarget();
+                        return;
+                    }
+                } catch (RemoteException e) {
+                }
+                if (mConstants.MIN_READY_NON_ACTIVE_JOBS_COUNT > 1
+                        && job.getStandbyBucket() != ACTIVE_INDEX
+                        && (job.getFirstForceBatchedTimeElapsed() == 0
+                        || sElapsedRealtimeClock.millis() - job.getFirstForceBatchedTimeElapsed()
+                                < mConstants.MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS)) {
+                    // Force batching non-ACTIVE jobs. Don't include them in the other counts.
+                    forceBatchedCount++;
+                    if (job.getFirstForceBatchedTimeElapsed() == 0) {
+                        job.setFirstForceBatchedTimeElapsed(sElapsedRealtimeClock.millis());
+                    }
+                } else {
+                    unbatchedCount++;
+                    if (job.getNumFailures() > 0) {
+                        backoffCount++;
+                    }
+                    if (job.hasIdleConstraint()) {
+                        idleCount++;
+                    }
+                    if (job.hasConnectivityConstraint()) {
+                        connectivityCount++;
+                    }
+                    if (job.hasChargingConstraint()) {
+                        chargingCount++;
+                    }
+                    if (job.hasBatteryNotLowConstraint()) {
+                        batteryNotLowCount++;
+                    }
+                    if (job.hasStorageNotLowConstraint()) {
+                        storageNotLowCount++;
+                    }
+                    if (job.hasContentTriggerConstraint()) {
+                        contentCount++;
+                    }
+                }
+                runnableJobs.add(job);
+            } else {
+                evaluateControllerStatesLocked(job);
+            }
+        }
+
+        public void postProcess() {
+            if (backoffCount > 0 ||
+                    idleCount >= mConstants.MIN_IDLE_COUNT ||
+                    connectivityCount >= mConstants.MIN_CONNECTIVITY_COUNT ||
+                    chargingCount >= mConstants.MIN_CHARGING_COUNT ||
+                    batteryNotLowCount >= mConstants.MIN_BATTERY_NOT_LOW_COUNT ||
+                    storageNotLowCount >= mConstants.MIN_STORAGE_NOT_LOW_COUNT ||
+                    contentCount >= mConstants.MIN_CONTENT_COUNT ||
+                    forceBatchedCount >= mConstants.MIN_READY_NON_ACTIVE_JOBS_COUNT ||
+                    (unbatchedCount > 0 && (unbatchedCount + forceBatchedCount)
+                            >= mConstants.MIN_READY_JOBS_COUNT)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "maybeQueueReadyJobsForExecutionLocked: Running jobs.");
+                }
+                noteJobsPending(runnableJobs);
+                mPendingJobs.addAll(runnableJobs);
+                if (mPendingJobs.size() > 1) {
+                    mPendingJobs.sort(mEnqueueTimeComparator);
+                }
+            } else {
+                if (DEBUG) {
+                    Slog.d(TAG, "maybeQueueReadyJobsForExecutionLocked: Not running anything.");
+                }
+            }
+
+            // Be ready for next time
+            reset();
+        }
+
+        @VisibleForTesting
+        void reset() {
+            chargingCount = 0;
+            idleCount =  0;
+            backoffCount = 0;
+            connectivityCount = 0;
+            batteryNotLowCount = 0;
+            storageNotLowCount = 0;
+            contentCount = 0;
+            forceBatchedCount = 0;
+            unbatchedCount = 0;
+            runnableJobs.clear();
+        }
+    }
+    private final MaybeReadyJobQueueFunctor mMaybeQueueFunctor = new MaybeReadyJobQueueFunctor();
+
+    private void maybeQueueReadyJobsForExecutionLocked() {
+        if (DEBUG) Slog.d(TAG, "Maybe queuing ready jobs...");
+
+        noteJobsNonpending(mPendingJobs);
+        mPendingJobs.clear();
+        stopNonReadyActiveJobsLocked();
+        mJobs.forEachJob(mMaybeQueueFunctor);
+        mMaybeQueueFunctor.postProcess();
+    }
+
+    /**
+     * Heartbeat tracking.  The heartbeat alarm is intentionally non-wakeup.
+     */
+    class HeartbeatAlarmListener implements AlarmManager.OnAlarmListener {
+
+        @Override
+        public void onAlarm() {
+            synchronized (mLock) {
+                final long sinceLast = sElapsedRealtimeClock.millis() - mLastHeartbeatTime;
+                final long beatsElapsed = sinceLast / mConstants.STANDBY_HEARTBEAT_TIME;
+                if (beatsElapsed > 0) {
+                    mLastHeartbeatTime += beatsElapsed * mConstants.STANDBY_HEARTBEAT_TIME;
+                    advanceHeartbeatLocked(beatsElapsed);
+                }
+            }
+            setNextHeartbeatAlarm();
+        }
+    }
+
+    // Intentionally does not touch the alarm timing
+    void advanceHeartbeatLocked(long beatsElapsed) {
+        if (!mConstants.USE_HEARTBEATS) {
+            return;
+        }
+        mHeartbeat += beatsElapsed;
+        if (DEBUG_STANDBY) {
+            Slog.v(TAG, "Advancing standby heartbeat by " + beatsElapsed
+                    + " to " + mHeartbeat);
+        }
+        // Don't update ACTIVE or NEVER bucket milestones.  Note that mHeartbeat
+        // will be equal to mNextBucketHeartbeat[bucket] for one beat, during which
+        // new jobs scheduled by apps in that bucket will be permitted to run
+        // immediately.
+        boolean didAdvanceBucket = false;
+        for (int i = 1; i < mNextBucketHeartbeat.length - 1; i++) {
+            // Did we reach or cross a bucket boundary?
+            if (mHeartbeat >= mNextBucketHeartbeat[i]) {
+                didAdvanceBucket = true;
+            }
+            while (mHeartbeat > mNextBucketHeartbeat[i]) {
+                mNextBucketHeartbeat[i] += mConstants.STANDBY_BEATS[i];
+            }
+            if (DEBUG_STANDBY) {
+                Slog.v(TAG, "   Bucket " + i + " next heartbeat "
+                        + mNextBucketHeartbeat[i]);
+            }
+        }
+
+        if (didAdvanceBucket) {
+            if (DEBUG_STANDBY) {
+                Slog.v(TAG, "Hit bucket boundary; reevaluating job runnability");
+            }
+            mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+        }
+    }
+
+    void setNextHeartbeatAlarm() {
+        final long heartbeatLength;
+        synchronized (mLock) {
+            if (!mConstants.USE_HEARTBEATS) {
+                return;
+            }
+            heartbeatLength = mConstants.STANDBY_HEARTBEAT_TIME;
+        }
+        final long now = sElapsedRealtimeClock.millis();
+        final long nextBeatOrdinal = (now + heartbeatLength) / heartbeatLength;
+        final long nextHeartbeat = nextBeatOrdinal * heartbeatLength;
+        if (DEBUG_STANDBY) {
+            Slog.i(TAG, "Setting heartbeat alarm for " + nextHeartbeat
+                    + " = " + TimeUtils.formatDuration(nextHeartbeat - now));
+        }
+        AlarmManager am = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
+        am.setExact(AlarmManager.ELAPSED_REALTIME, nextHeartbeat,
+                HEARTBEAT_TAG, mHeartbeatAlarm, mHandler);
+    }
+
+    /** Returns true if both the calling and source users for the job are started. */
+    private boolean areUsersStartedLocked(final JobStatus job) {
+        boolean sourceStarted = ArrayUtils.contains(mStartedUsers, job.getSourceUserId());
+        if (job.getUserId() == job.getSourceUserId()) {
+            return sourceStarted;
+        }
+        return sourceStarted && ArrayUtils.contains(mStartedUsers, job.getUserId());
+    }
+
+    /**
+     * Criteria for moving a job into the pending queue:
+     *      - It's ready.
+     *      - It's not pending.
+     *      - It's not already running on a JSC.
+     *      - The user that requested the job is running.
+     *      - The job's standby bucket has come due to be runnable.
+     *      - The component is enabled and runnable.
+     */
+    @VisibleForTesting
+    boolean isReadyToBeExecutedLocked(JobStatus job) {
+        final boolean jobReady = job.isReady();
+
+        if (DEBUG) {
+            Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString()
+                    + " ready=" + jobReady);
+        }
+
+        // This is a condition that is very likely to be false (most jobs that are
+        // scheduled are sitting there, not ready yet) and very cheap to check (just
+        // a few conditions on data in JobStatus).
+        if (!jobReady) {
+            if (job.getSourcePackageName().equals("android.jobscheduler.cts.jobtestapp")) {
+                Slog.v(TAG, "    NOT READY: " + job);
+            }
+            return false;
+        }
+
+        final boolean jobExists = mJobs.containsJob(job);
+
+        final boolean userStarted = areUsersStartedLocked(job);
+
+        if (DEBUG) {
+            Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString()
+                    + " exists=" + jobExists + " userStarted=" + userStarted);
+        }
+
+        // These are also fairly cheap to check, though they typically will not
+        // be conditions we fail.
+        if (!jobExists || !userStarted) {
+            return false;
+        }
+
+        if (isJobThermalConstrainedLocked(job)) {
+            return false;
+        }
+
+        final boolean jobPending = mPendingJobs.contains(job);
+        final boolean jobActive = isCurrentlyActiveLocked(job);
+
+        if (DEBUG) {
+            Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString()
+                    + " pending=" + jobPending + " active=" + jobActive);
+        }
+
+        // These can be a little more expensive (especially jobActive, since we need to
+        // go through the array of all potentially active jobs), so we are doing them
+        // later...  but still before checking with the package manager!
+        if (jobPending || jobActive) {
+            return false;
+        }
+
+        if (mConstants.USE_HEARTBEATS) {
+            // If the app is in a non-active standby bucket, make sure we've waited
+            // an appropriate amount of time since the last invocation.  During device-
+            // wide parole, standby bucketing is ignored.
+            //
+            // Jobs in 'active' apps are not subject to standby, nor are jobs that are
+            // specifically marked as exempt.
+            if (DEBUG_STANDBY) {
+                Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString()
+                        + " parole=" + mInParole + " active=" + job.uidActive
+                        + " exempt=" + job.getJob().isExemptedFromAppStandby());
+            }
+            if (!mInParole
+                    && !job.uidActive
+                    && !job.getJob().isExemptedFromAppStandby()) {
+                final int bucket = job.getStandbyBucket();
+                if (DEBUG_STANDBY) {
+                    Slog.v(TAG, "  bucket=" + bucket + " heartbeat=" + mHeartbeat
+                            + " next=" + mNextBucketHeartbeat[bucket]);
+                }
+                if (mHeartbeat < mNextBucketHeartbeat[bucket]) {
+                    // Only skip this job if the app is still waiting for the end of its nominal
+                    // bucket interval.  Once it's waited that long, we let it go ahead and clear.
+                    // The final (NEVER) bucket is special; we never age those apps' jobs into
+                    // runnability.
+                    final long appLastRan = heartbeatWhenJobsLastRun(job);
+                    if (bucket >= mConstants.STANDBY_BEATS.length
+                            || (mHeartbeat > appLastRan
+                            && mHeartbeat < appLastRan + mConstants.STANDBY_BEATS[bucket])) {
+                        if (job.getWhenStandbyDeferred() == 0) {
+                            if (DEBUG_STANDBY) {
+                                Slog.v(TAG, "Bucket deferral: " + mHeartbeat + " < "
+                                        + (appLastRan + mConstants.STANDBY_BEATS[bucket])
+                                        + " for " + job);
+                            }
+                            job.setWhenStandbyDeferred(sElapsedRealtimeClock.millis());
+                        }
+                        return false;
+                    } else {
+                        if (DEBUG_STANDBY) {
+                            Slog.v(TAG, "Bucket deferred job aged into runnability at "
+                                    + mHeartbeat + " : " + job);
+                        }
+                    }
+                }
+            }
+        }
+
+        // The expensive check: validate that the defined package+service is
+        // still present & viable.
+        return isComponentUsable(job);
+    }
+
+    private boolean isComponentUsable(@NonNull JobStatus job) {
+        final ServiceInfo service;
+        try {
+            // TODO: cache result until we're notified that something in the package changed.
+            service = AppGlobals.getPackageManager().getServiceInfo(
+                    job.getServiceComponent(), PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+                    job.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+
+        if (service == null) {
+            if (DEBUG) {
+                Slog.v(TAG, "isComponentUsable: " + job.toShortString()
+                        + " component not present");
+            }
+            return false;
+        }
+
+        // Everything else checked out so far, so this is the final yes/no check
+        final boolean appIsBad = mActivityManagerInternal.isAppBad(service.applicationInfo);
+        if (DEBUG && appIsBad) {
+            Slog.i(TAG, "App is bad for " + job.toShortString() + " so not runnable");
+        }
+        return !appIsBad;
+    }
+
+    @VisibleForTesting
+    void evaluateControllerStatesLocked(final JobStatus job) {
+        for (int c = mControllers.size() - 1; c >= 0; --c) {
+            final StateController sc = mControllers.get(c);
+            sc.evaluateStateLocked(job);
+        }
+    }
+
+    /**
+     * Returns true if non-job constraint components are in place -- if job.isReady() returns true
+     * and this method returns true, then the job is ready to be executed.
+     */
+    public boolean areComponentsInPlaceLocked(JobStatus job) {
+        // This code is very similar to the code in isReadyToBeExecutedLocked --- it uses the same
+        // conditions.
+
+        final boolean jobExists = mJobs.containsJob(job);
+        final boolean userStarted = areUsersStartedLocked(job);
+
+        if (DEBUG) {
+            Slog.v(TAG, "areComponentsInPlaceLocked: " + job.toShortString()
+                    + " exists=" + jobExists + " userStarted=" + userStarted);
+        }
+
+        // These are also fairly cheap to check, though they typically will not
+        // be conditions we fail.
+        if (!jobExists || !userStarted) {
+            return false;
+        }
+
+        if (isJobThermalConstrainedLocked(job)) {
+            return false;
+        }
+
+        // Job pending/active doesn't affect the readiness of a job.
+
+        // Skipping the heartbeat check as this will only come into play when using the rolling
+        // window quota management system.
+
+        // The expensive check: validate that the defined package+service is
+        // still present & viable.
+        return isComponentUsable(job);
+    }
+
+    /** Returns the maximum amount of time this job could run for. */
+    public long getMaxJobExecutionTimeMs(JobStatus job) {
+        synchronized (mLock) {
+            if (mConstants.USE_HEARTBEATS) {
+                return JobServiceContext.EXECUTING_TIMESLICE_MILLIS;
+            }
+            return Math.min(mQuotaController.getMaxJobExecutionTimeMsLocked(job),
+                    JobServiceContext.EXECUTING_TIMESLICE_MILLIS);
+        }
+    }
+
+    /**
+     * Reconcile jobs in the pending queue against available execution contexts.
+     * A controller can force a job into the pending queue even if it's already running, but
+     * here is where we decide whether to actually execute it.
+     */
+    void maybeRunPendingJobsLocked() {
+        if (DEBUG) {
+            Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs.");
+        }
+        mConcurrencyManager.assignJobsToContextsLocked();
+        reportActiveLocked();
+    }
+
+    private int adjustJobPriority(int curPriority, JobStatus job) {
+        if (curPriority < JobInfo.PRIORITY_TOP_APP) {
+            float factor = mJobPackageTracker.getLoadFactor(job);
+            if (factor >= mConstants.HEAVY_USE_FACTOR) {
+                curPriority += JobInfo.PRIORITY_ADJ_ALWAYS_RUNNING;
+            } else if (factor >= mConstants.MODERATE_USE_FACTOR) {
+                curPriority += JobInfo.PRIORITY_ADJ_OFTEN_RUNNING;
+            }
+        }
+        return curPriority;
+    }
+
+    int evaluateJobPriorityLocked(JobStatus job) {
+        int priority = job.getPriority();
+        if (priority >= JobInfo.PRIORITY_BOUND_FOREGROUND_SERVICE) {
+            return adjustJobPriority(priority, job);
+        }
+        int override = mUidPriorityOverride.get(job.getSourceUid(), 0);
+        if (override != 0) {
+            return adjustJobPriority(override, job);
+        }
+        return adjustJobPriority(priority, job);
+    }
+
+    final class LocalService implements JobSchedulerInternal {
+
+        /**
+         * The current bucket heartbeat ordinal
+         */
+        public long currentHeartbeat() {
+            return getCurrentHeartbeat();
+        }
+
+        /**
+         * Heartbeat ordinal at which the given standby bucket's jobs next become runnable
+         */
+        public long nextHeartbeatForBucket(int bucket) {
+            synchronized (mLock) {
+                return mNextBucketHeartbeat[bucket];
+            }
+        }
+
+        /**
+         * Heartbeat ordinal for the given app.  This is typically the heartbeat at which
+         * the app last ran jobs, so that a newly-scheduled job in an app that hasn't run
+         * jobs in a long time is immediately runnable even if the app is bucketed into
+         * an infrequent time allocation.
+         */
+        public long baseHeartbeatForApp(String packageName, @UserIdInt int userId,
+                final int appStandbyBucket) {
+            if (appStandbyBucket == 0 ||
+                    appStandbyBucket >= mConstants.STANDBY_BEATS.length) {
+                // ACTIVE => everything can be run right away
+                // NEVER => we won't run them anyway, so let them go in the future
+                // as soon as the app enters normal use
+                if (DEBUG_STANDBY) {
+                    Slog.v(TAG, "Base heartbeat forced ZERO for new job in "
+                            + packageName + "/" + userId);
+                }
+                return 0;
+            }
+
+            final long baseHeartbeat = heartbeatWhenJobsLastRun(packageName, userId);
+            if (DEBUG_STANDBY) {
+                Slog.v(TAG, "Base heartbeat " + baseHeartbeat + " for new job in "
+                        + packageName + "/" + userId);
+            }
+            return baseHeartbeat;
+        }
+
+        public void noteJobStart(String packageName, int userId) {
+            synchronized (mLock) {
+                setLastJobHeartbeatLocked(packageName, userId, mHeartbeat);
+            }
+        }
+
+        /**
+         * Returns a list of all pending jobs. A running job is not considered pending. Periodic
+         * jobs are always considered pending.
+         */
+        @Override
+        public List<JobInfo> getSystemScheduledPendingJobs() {
+            synchronized (mLock) {
+                final List<JobInfo> pendingJobs = new ArrayList<JobInfo>();
+                mJobs.forEachJob(Process.SYSTEM_UID, (job) -> {
+                    if (job.getJob().isPeriodic() || !isCurrentlyActiveLocked(job)) {
+                        pendingJobs.add(job.getJob());
+                    }
+                });
+                return pendingJobs;
+            }
+        }
+
+        @Override
+        public void cancelJobsForUid(int uid, String reason) {
+            JobSchedulerService.this.cancelJobsForUid(uid, reason);
+        }
+
+        @Override
+        public void addBackingUpUid(int uid) {
+            synchronized (mLock) {
+                // No need to actually do anything here, since for a full backup the
+                // activity manager will kill the process which will kill the job (and
+                // cause it to restart, but now it can't run).
+                mBackingUpUids.put(uid, uid);
+            }
+        }
+
+        @Override
+        public void removeBackingUpUid(int uid) {
+            synchronized (mLock) {
+                mBackingUpUids.delete(uid);
+                // If there are any jobs for this uid, we need to rebuild the pending list
+                // in case they are now ready to run.
+                if (mJobs.countJobsForUid(uid) > 0) {
+                    mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+                }
+            }
+        }
+
+        @Override
+        public void clearAllBackingUpUids() {
+            synchronized (mLock) {
+                if (mBackingUpUids.size() > 0) {
+                    mBackingUpUids.clear();
+                    mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+                }
+            }
+        }
+
+        @Override
+        public void reportAppUsage(String packageName, int userId) {
+            JobSchedulerService.this.reportAppUsage(packageName, userId);
+        }
+
+        @Override
+        public JobStorePersistStats getPersistStats() {
+            synchronized (mLock) {
+                return new JobStorePersistStats(mJobs.getPersistStats());
+            }
+        }
+    }
+
+    /**
+     * Tracking of app assignments to standby buckets
+     */
+    final class StandbyTracker extends AppIdleStateChangeListener {
+
+        // AppIdleStateChangeListener interface for live updates
+
+        @Override
+        public void onAppIdleStateChanged(final String packageName, final @UserIdInt int userId,
+                boolean idle, int bucket, int reason) {
+            // QuotaController handles this now.
+        }
+
+        @Override
+        public void onParoleStateChanged(boolean isParoleOn) {
+            if (DEBUG_STANDBY) {
+                Slog.i(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
+            }
+            mInParole = isParoleOn;
+        }
+
+        @Override
+        public void onUserInteractionStarted(String packageName, int userId) {
+            final int uid = mLocalPM.getPackageUid(packageName,
+                    PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+            if (uid < 0) {
+                // Quietly ignore; the case is already logged elsewhere
+                return;
+            }
+
+            long sinceLast = mUsageStats.getTimeSinceLastJobRun(packageName, userId);
+            if (sinceLast > 2 * DateUtils.DAY_IN_MILLIS) {
+                // Too long ago, not worth logging
+                sinceLast = 0L;
+            }
+            final DeferredJobCounter counter = new DeferredJobCounter();
+            synchronized (mLock) {
+                mJobs.forEachJobForSourceUid(uid, counter);
+            }
+            if (counter.numDeferred() > 0 || sinceLast > 0) {
+                BatteryStatsInternal mBatteryStatsInternal = LocalServices.getService
+                        (BatteryStatsInternal.class);
+                mBatteryStatsInternal.noteJobsDeferred(uid, counter.numDeferred(), sinceLast);
+                StatsLog.write_non_chained(StatsLog.DEFERRED_JOB_STATS_REPORTED, uid, null,
+                        counter.numDeferred(), sinceLast);
+            }
+        }
+    }
+
+    static class DeferredJobCounter implements Consumer<JobStatus> {
+        private int mDeferred = 0;
+
+        public int numDeferred() {
+            return mDeferred;
+        }
+
+        @Override
+        public void accept(JobStatus job) {
+            if (job.getWhenStandbyDeferred() > 0) {
+                mDeferred++;
+            }
+        }
+    }
+
+    public static int standbyBucketToBucketIndex(int bucket) {
+        // Normalize AppStandby constants to indices into our bookkeeping
+        if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) return NEVER_INDEX;
+        else if (bucket > UsageStatsManager.STANDBY_BUCKET_FREQUENT) return RARE_INDEX;
+        else if (bucket > UsageStatsManager.STANDBY_BUCKET_WORKING_SET) return FREQUENT_INDEX;
+        else if (bucket > UsageStatsManager.STANDBY_BUCKET_ACTIVE) return WORKING_INDEX;
+        else return ACTIVE_INDEX;
+    }
+
+    // Static to support external callers
+    public static int standbyBucketForPackage(String packageName, int userId, long elapsedNow) {
+        UsageStatsManagerInternal usageStats = LocalServices.getService(
+                UsageStatsManagerInternal.class);
+        int bucket = usageStats != null
+                ? usageStats.getAppStandbyBucket(packageName, userId, elapsedNow)
+                : 0;
+
+        bucket = standbyBucketToBucketIndex(bucket);
+
+        if (DEBUG_STANDBY) {
+            Slog.v(TAG, packageName + "/" + userId + " standby bucket index: " + bucket);
+        }
+        return bucket;
+    }
+
+    /**
+     * Binder stub trampoline implementation
+     */
+    final class JobSchedulerStub extends IJobScheduler.Stub {
+        /** Cache determination of whether a given app can persist jobs
+         * key is uid of the calling app; value is undetermined/true/false
+         */
+        private final SparseArray<Boolean> mPersistCache = new SparseArray<Boolean>();
+
+        // Enforce that only the app itself (or shared uid participant) can schedule a
+        // job that runs one of the app's services, as well as verifying that the
+        // named service properly requires the BIND_JOB_SERVICE permission
+        private void enforceValidJobRequest(int uid, JobInfo job) {
+            final IPackageManager pm = AppGlobals.getPackageManager();
+            final ComponentName service = job.getService();
+            try {
+                ServiceInfo si = pm.getServiceInfo(service,
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        UserHandle.getUserId(uid));
+                if (si == null) {
+                    throw new IllegalArgumentException("No such service " + service);
+                }
+                if (si.applicationInfo.uid != uid) {
+                    throw new IllegalArgumentException("uid " + uid +
+                            " cannot schedule job in " + service.getPackageName());
+                }
+                if (!JobService.PERMISSION_BIND.equals(si.permission)) {
+                    throw new IllegalArgumentException("Scheduled service " + service
+                            + " does not require android.permission.BIND_JOB_SERVICE permission");
+                }
+            } catch (RemoteException e) {
+                // Can't happen; the Package Manager is in this same process
+            }
+        }
+
+        private boolean canPersistJobs(int pid, int uid) {
+            // If we get this far we're good to go; all we need to do now is check
+            // whether the app is allowed to persist its scheduled work.
+            final boolean canPersist;
+            synchronized (mPersistCache) {
+                Boolean cached = mPersistCache.get(uid);
+                if (cached != null) {
+                    canPersist = cached.booleanValue();
+                } else {
+                    // Persisting jobs is tantamount to running at boot, so we permit
+                    // it when the app has declared that it uses the RECEIVE_BOOT_COMPLETED
+                    // permission
+                    int result = getContext().checkPermission(
+                            android.Manifest.permission.RECEIVE_BOOT_COMPLETED, pid, uid);
+                    canPersist = (result == PackageManager.PERMISSION_GRANTED);
+                    mPersistCache.put(uid, canPersist);
+                }
+            }
+            return canPersist;
+        }
+
+        private void validateJobFlags(JobInfo job, int callingUid) {
+            if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
+                getContext().enforceCallingOrSelfPermission(
+                        android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
+            }
+            if ((job.getFlags() & JobInfo.FLAG_EXEMPT_FROM_APP_STANDBY) != 0) {
+                if (callingUid != Process.SYSTEM_UID) {
+                    throw new SecurityException("Job has invalid flags");
+                }
+                if (job.isPeriodic()) {
+                    Slog.wtf(TAG, "Periodic jobs mustn't have"
+                            + " FLAG_EXEMPT_FROM_APP_STANDBY. Job=" + job);
+                }
+            }
+        }
+
+        // IJobScheduler implementation
+        @Override
+        public int schedule(JobInfo job) throws RemoteException {
+            if (DEBUG) {
+                Slog.d(TAG, "Scheduling job: " + job.toString());
+            }
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final int userId = UserHandle.getUserId(uid);
+
+            enforceValidJobRequest(uid, job);
+            if (job.isPersisted()) {
+                if (!canPersistJobs(pid, uid)) {
+                    throw new IllegalArgumentException("Error: requested job be persisted without"
+                            + " holding RECEIVE_BOOT_COMPLETED permission.");
+                }
+            }
+
+            validateJobFlags(job, uid);
+
+            long ident = Binder.clearCallingIdentity();
+            try {
+                return JobSchedulerService.this.scheduleAsPackage(job, null, uid, null, userId,
+                        null);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        // IJobScheduler implementation
+        @Override
+        public int enqueue(JobInfo job, JobWorkItem work) throws RemoteException {
+            if (DEBUG) {
+                Slog.d(TAG, "Enqueueing job: " + job.toString() + " work: " + work);
+            }
+            final int uid = Binder.getCallingUid();
+            final int userId = UserHandle.getUserId(uid);
+
+            enforceValidJobRequest(uid, job);
+            if (job.isPersisted()) {
+                throw new IllegalArgumentException("Can't enqueue work for persisted jobs");
+            }
+            if (work == null) {
+                throw new NullPointerException("work is null");
+            }
+
+            validateJobFlags(job, uid);
+
+            long ident = Binder.clearCallingIdentity();
+            try {
+                return JobSchedulerService.this.scheduleAsPackage(job, work, uid, null, userId,
+                        null);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
+        public int scheduleAsPackage(JobInfo job, String packageName, int userId, String tag)
+                throws RemoteException {
+            final int callerUid = Binder.getCallingUid();
+            if (DEBUG) {
+                Slog.d(TAG, "Caller uid " + callerUid + " scheduling job: " + job.toString()
+                        + " on behalf of " + packageName + "/");
+            }
+
+            if (packageName == null) {
+                throw new NullPointerException("Must specify a package for scheduleAsPackage()");
+            }
+
+            int mayScheduleForOthers = getContext().checkCallingOrSelfPermission(
+                    android.Manifest.permission.UPDATE_DEVICE_STATS);
+            if (mayScheduleForOthers != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("Caller uid " + callerUid
+                        + " not permitted to schedule jobs for other apps");
+            }
+
+            validateJobFlags(job, callerUid);
+
+            long ident = Binder.clearCallingIdentity();
+            try {
+                return JobSchedulerService.this.scheduleAsPackage(job, null, callerUid,
+                        packageName, userId, tag);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
+        public ParceledListSlice<JobInfo> getAllPendingJobs() throws RemoteException {
+            final int uid = Binder.getCallingUid();
+
+            long ident = Binder.clearCallingIdentity();
+            try {
+                return new ParceledListSlice<>(JobSchedulerService.this.getPendingJobs(uid));
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
+        public JobInfo getPendingJob(int jobId) throws RemoteException {
+            final int uid = Binder.getCallingUid();
+
+            long ident = Binder.clearCallingIdentity();
+            try {
+                return JobSchedulerService.this.getPendingJob(uid, jobId);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
+        public void cancelAll() throws RemoteException {
+            final int uid = Binder.getCallingUid();
+            long ident = Binder.clearCallingIdentity();
+            try {
+                JobSchedulerService.this.cancelJobsForUid(uid,
+                        "cancelAll() called by app, callingUid=" + uid);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
+        public void cancel(int jobId) throws RemoteException {
+            final int uid = Binder.getCallingUid();
+
+            long ident = Binder.clearCallingIdentity();
+            try {
+                JobSchedulerService.this.cancelJob(uid, jobId, uid);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        /**
+         * "dumpsys" infrastructure
+         */
+        @Override
+        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
+
+            int filterUid = -1;
+            boolean proto = false;
+            if (!ArrayUtils.isEmpty(args)) {
+                int opti = 0;
+                while (opti < args.length) {
+                    String arg = args[opti];
+                    if ("-h".equals(arg)) {
+                        dumpHelp(pw);
+                        return;
+                    } else if ("-a".equals(arg)) {
+                        // Ignore, we always dump all.
+                    } else if ("--proto".equals(arg)) {
+                        proto = true;
+                    } else if (arg.length() > 0 && arg.charAt(0) == '-') {
+                        pw.println("Unknown option: " + arg);
+                        return;
+                    } else {
+                        break;
+                    }
+                    opti++;
+                }
+                if (opti < args.length) {
+                    String pkg = args[opti];
+                    try {
+                        filterUid = getContext().getPackageManager().getPackageUid(pkg,
+                                PackageManager.MATCH_ANY_USER);
+                    } catch (NameNotFoundException ignored) {
+                        pw.println("Invalid package: " + pkg);
+                        return;
+                    }
+                }
+            }
+
+            final long identityToken = Binder.clearCallingIdentity();
+            try {
+                if (proto) {
+                    JobSchedulerService.this.dumpInternalProto(fd, filterUid);
+                } else {
+                    JobSchedulerService.this.dumpInternal(new IndentingPrintWriter(pw, "  "),
+                            filterUid);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identityToken);
+            }
+        }
+
+        @Override
+        public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+                String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+                (new JobSchedulerShellCommand(JobSchedulerService.this)).exec(
+                        this, in, out, err, args, callback, resultReceiver);
+        }
+
+        /**
+         * <b>For internal system user only!</b>
+         * Returns a list of all currently-executing jobs.
+         */
+        @Override
+        public List<JobInfo> getStartedJobs() {
+            final int uid = Binder.getCallingUid();
+            if (uid != Process.SYSTEM_UID) {
+                throw new SecurityException(
+                    "getStartedJobs() is system internal use only.");
+            }
+
+            final ArrayList<JobInfo> runningJobs;
+
+            synchronized (mLock) {
+                runningJobs = new ArrayList<>(mActiveServices.size());
+                for (JobServiceContext jsc : mActiveServices) {
+                    final JobStatus job = jsc.getRunningJobLocked();
+                    if (job != null) {
+                        runningJobs.add(job.getJob());
+                    }
+                }
+            }
+
+            return runningJobs;
+        }
+
+        /**
+         * <b>For internal system user only!</b>
+         * Returns a snapshot of the state of all jobs known to the system.
+         *
+         * <p class="note">This is a slow operation, so it should be called sparingly.
+         */
+        @Override
+        public ParceledListSlice<JobSnapshot> getAllJobSnapshots() {
+            final int uid = Binder.getCallingUid();
+            if (uid != Process.SYSTEM_UID) {
+                throw new SecurityException(
+                    "getAllJobSnapshots() is system internal use only.");
+            }
+            synchronized (mLock) {
+                final ArrayList<JobSnapshot> snapshots = new ArrayList<>(mJobs.size());
+                mJobs.forEachJob((job) -> snapshots.add(
+                        new JobSnapshot(job.getJob(), job.getSatisfiedConstraintFlags(),
+                                isReadyToBeExecutedLocked(job))));
+                return new ParceledListSlice<>(snapshots);
+            }
+        }
+    };
+
+    // Shell command infrastructure: run the given job immediately
+    int executeRunCommand(String pkgName, int userId, int jobId, boolean force) {
+        if (DEBUG) {
+            Slog.v(TAG, "executeRunCommand(): " + pkgName + "/" + userId
+                    + " " + jobId + " f=" + force);
+        }
+
+        try {
+            final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0,
+                    userId != UserHandle.USER_ALL ? userId : UserHandle.USER_SYSTEM);
+            if (uid < 0) {
+                return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE;
+            }
+
+            synchronized (mLock) {
+                final JobStatus js = mJobs.getJobByUidAndJobId(uid, jobId);
+                if (js == null) {
+                    return JobSchedulerShellCommand.CMD_ERR_NO_JOB;
+                }
+
+                js.overrideState = (force) ? JobStatus.OVERRIDE_FULL : JobStatus.OVERRIDE_SOFT;
+                if (!js.isConstraintsSatisfied()) {
+                    js.overrideState = 0;
+                    return JobSchedulerShellCommand.CMD_ERR_CONSTRAINTS;
+                }
+
+                queueReadyJobsForExecutionLocked();
+                maybeRunPendingJobsLocked();
+            }
+        } catch (RemoteException e) {
+            // can't happen
+        }
+        return 0;
+    }
+
+    // Shell command infrastructure: immediately timeout currently executing jobs
+    int executeTimeoutCommand(PrintWriter pw, String pkgName, int userId,
+            boolean hasJobId, int jobId) {
+        if (DEBUG) {
+            Slog.v(TAG, "executeTimeoutCommand(): " + pkgName + "/" + userId + " " + jobId);
+        }
+
+        synchronized (mLock) {
+            boolean foundSome = false;
+            for (int i=0; i<mActiveServices.size(); i++) {
+                final JobServiceContext jc = mActiveServices.get(i);
+                final JobStatus js = jc.getRunningJobLocked();
+                if (jc.timeoutIfExecutingLocked(pkgName, userId, hasJobId, jobId, "shell")) {
+                    foundSome = true;
+                    pw.print("Timing out: ");
+                    js.printUniqueId(pw);
+                    pw.print(" ");
+                    pw.println(js.getServiceComponent().flattenToShortString());
+                }
+            }
+            if (!foundSome) {
+                pw.println("No matching executing jobs found.");
+            }
+        }
+        return 0;
+    }
+
+    // Shell command infrastructure: cancel a scheduled job
+    int executeCancelCommand(PrintWriter pw, String pkgName, int userId,
+            boolean hasJobId, int jobId) {
+        if (DEBUG) {
+            Slog.v(TAG, "executeCancelCommand(): " + pkgName + "/" + userId + " " + jobId);
+        }
+
+        int pkgUid = -1;
+        try {
+            IPackageManager pm = AppGlobals.getPackageManager();
+            pkgUid = pm.getPackageUid(pkgName, 0, userId);
+        } catch (RemoteException e) { /* can't happen */ }
+
+        if (pkgUid < 0) {
+            pw.println("Package " + pkgName + " not found.");
+            return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE;
+        }
+
+        if (!hasJobId) {
+            pw.println("Canceling all jobs for " + pkgName + " in user " + userId);
+            if (!cancelJobsForUid(pkgUid, "cancel shell command for package")) {
+                pw.println("No matching jobs found.");
+            }
+        } else {
+            pw.println("Canceling job " + pkgName + "/#" + jobId + " in user " + userId);
+            if (!cancelJob(pkgUid, jobId, Process.SHELL_UID)) {
+                pw.println("No matching job found.");
+            }
+        }
+
+        return 0;
+    }
+
+    void setMonitorBattery(boolean enabled) {
+        synchronized (mLock) {
+            if (mBatteryController != null) {
+                mBatteryController.getTracker().setMonitorBatteryLocked(enabled);
+            }
+        }
+    }
+
+    int getBatterySeq() {
+        synchronized (mLock) {
+            return mBatteryController != null ? mBatteryController.getTracker().getSeq() : -1;
+        }
+    }
+
+    boolean getBatteryCharging() {
+        synchronized (mLock) {
+            return mBatteryController != null
+                    ? mBatteryController.getTracker().isOnStablePower() : false;
+        }
+    }
+
+    boolean getBatteryNotLow() {
+        synchronized (mLock) {
+            return mBatteryController != null
+                    ? mBatteryController.getTracker().isBatteryNotLow() : false;
+        }
+    }
+
+    int getStorageSeq() {
+        synchronized (mLock) {
+            return mStorageController != null ? mStorageController.getTracker().getSeq() : -1;
+        }
+    }
+
+    boolean getStorageNotLow() {
+        synchronized (mLock) {
+            return mStorageController != null
+                    ? mStorageController.getTracker().isStorageNotLow() : false;
+        }
+    }
+
+    long getCurrentHeartbeat() {
+        synchronized (mLock) {
+            return mHeartbeat;
+        }
+    }
+
+    // Shell command infrastructure
+    int getJobState(PrintWriter pw, String pkgName, int userId, int jobId) {
+        try {
+            final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0,
+                    userId != UserHandle.USER_ALL ? userId : UserHandle.USER_SYSTEM);
+            if (uid < 0) {
+                pw.print("unknown("); pw.print(pkgName); pw.println(")");
+                return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE;
+            }
+
+            synchronized (mLock) {
+                final JobStatus js = mJobs.getJobByUidAndJobId(uid, jobId);
+                if (DEBUG) Slog.d(TAG, "get-job-state " + uid + "/" + jobId + ": " + js);
+                if (js == null) {
+                    pw.print("unknown("); UserHandle.formatUid(pw, uid);
+                    pw.print("/jid"); pw.print(jobId); pw.println(")");
+                    return JobSchedulerShellCommand.CMD_ERR_NO_JOB;
+                }
+
+                boolean printed = false;
+                if (mPendingJobs.contains(js)) {
+                    pw.print("pending");
+                    printed = true;
+                }
+                if (isCurrentlyActiveLocked(js)) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("active");
+                }
+                if (!ArrayUtils.contains(mStartedUsers, js.getUserId())) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("user-stopped");
+                }
+                if (!ArrayUtils.contains(mStartedUsers, js.getSourceUserId())) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("source-user-stopped");
+                }
+                if (mBackingUpUids.indexOfKey(js.getSourceUid()) >= 0) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("backing-up");
+                }
+                boolean componentPresent = false;
+                try {
+                    componentPresent = (AppGlobals.getPackageManager().getServiceInfo(
+                            js.getServiceComponent(),
+                            PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+                            js.getUserId()) != null);
+                } catch (RemoteException e) {
+                }
+                if (!componentPresent) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("no-component");
+                }
+                if (js.isReady()) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("ready");
+                }
+                if (!printed) {
+                    pw.print("waiting");
+                }
+                pw.println();
+            }
+        } catch (RemoteException e) {
+            // can't happen
+        }
+        return 0;
+    }
+
+    // Shell command infrastructure
+    int executeHeartbeatCommand(PrintWriter pw, int numBeats) {
+        if (numBeats < 1) {
+            pw.println(getCurrentHeartbeat());
+            return 0;
+        }
+
+        pw.print("Advancing standby heartbeat by ");
+        pw.println(numBeats);
+        synchronized (mLock) {
+            advanceHeartbeatLocked(numBeats);
+        }
+        return 0;
+    }
+
+    void triggerDockState(boolean idleState) {
+        final Intent dockIntent;
+        if (idleState) {
+            dockIntent = new Intent(Intent.ACTION_DOCK_IDLE);
+        } else {
+            dockIntent = new Intent(Intent.ACTION_DOCK_ACTIVE);
+        }
+        dockIntent.setPackage("android");
+        dockIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+        getContext().sendBroadcastAsUser(dockIntent, UserHandle.ALL);
+    }
+
+    static void dumpHelp(PrintWriter pw) {
+        pw.println("Job Scheduler (jobscheduler) dump options:");
+        pw.println("  [-h] [package] ...");
+        pw.println("    -h: print this help");
+        pw.println("  [package] is an optional package name to limit the output to.");
+    }
+
+    /** Sort jobs by caller UID, then by Job ID. */
+    private static void sortJobs(List<JobStatus> jobs) {
+        Collections.sort(jobs, new Comparator<JobStatus>() {
+            @Override
+            public int compare(JobStatus o1, JobStatus o2) {
+                int uid1 = o1.getUid();
+                int uid2 = o2.getUid();
+                int id1 = o1.getJobId();
+                int id2 = o2.getJobId();
+                if (uid1 != uid2) {
+                    return uid1 < uid2 ? -1 : 1;
+                }
+                return id1 < id2 ? -1 : (id1 > id2 ? 1 : 0);
+            }
+        });
+    }
+
+    void dumpInternal(final IndentingPrintWriter pw, int filterUid) {
+        final int filterUidFinal = UserHandle.getAppId(filterUid);
+        final long now = sSystemClock.millis();
+        final long nowElapsed = sElapsedRealtimeClock.millis();
+        final long nowUptime = sUptimeMillisClock.millis();
+
+        final Predicate<JobStatus> predicate = (js) -> {
+            return filterUidFinal == -1 || UserHandle.getAppId(js.getUid()) == filterUidFinal
+                    || UserHandle.getAppId(js.getSourceUid()) == filterUidFinal;
+        };
+        synchronized (mLock) {
+            mConstants.dump(pw);
+            for (StateController controller : mControllers) {
+                pw.increaseIndent();
+                controller.dumpConstants(pw);
+                pw.decreaseIndent();
+            }
+            pw.println();
+
+            pw.println("  Heartbeat:");
+            pw.print("    Current:    "); pw.println(mHeartbeat);
+            pw.println("    Next");
+            pw.print("      ACTIVE:   "); pw.println(mNextBucketHeartbeat[0]);
+            pw.print("      WORKING:  "); pw.println(mNextBucketHeartbeat[1]);
+            pw.print("      FREQUENT: "); pw.println(mNextBucketHeartbeat[2]);
+            pw.print("      RARE:     "); pw.println(mNextBucketHeartbeat[3]);
+            pw.print("    Last heartbeat: ");
+            TimeUtils.formatDuration(mLastHeartbeatTime, nowElapsed, pw);
+            pw.println();
+            pw.print("    Next heartbeat: ");
+            TimeUtils.formatDuration(mLastHeartbeatTime + mConstants.STANDBY_HEARTBEAT_TIME,
+                    nowElapsed, pw);
+            pw.println();
+            pw.print("    In parole?: ");
+            pw.print(mInParole);
+            pw.println();
+            pw.print("    In thermal throttling?: ");
+            pw.print(mThermalConstraint);
+            pw.println();
+            pw.println();
+
+            pw.println("Started users: " + Arrays.toString(mStartedUsers));
+            pw.print("Registered ");
+            pw.print(mJobs.size());
+            pw.println(" jobs:");
+            if (mJobs.size() > 0) {
+                final List<JobStatus> jobs = mJobs.mJobSet.getAllJobs();
+                sortJobs(jobs);
+                for (JobStatus job : jobs) {
+                    pw.print("  JOB #"); job.printUniqueId(pw); pw.print(": ");
+                    pw.println(job.toShortStringExceptUniqueId());
+
+                    // Skip printing details if the caller requested a filter
+                    if (!predicate.test(job)) {
+                        continue;
+                    }
+
+                    job.dump(pw, "    ", true, nowElapsed);
+                    pw.print("    Last run heartbeat: ");
+                    pw.print(heartbeatWhenJobsLastRun(job));
+                    pw.println();
+
+                    pw.print("    Ready: ");
+                    pw.print(isReadyToBeExecutedLocked(job));
+                    pw.print(" (job=");
+                    pw.print(job.isReady());
+                    pw.print(" user=");
+                    pw.print(areUsersStartedLocked(job));
+                    pw.print(" !pending=");
+                    pw.print(!mPendingJobs.contains(job));
+                    pw.print(" !active=");
+                    pw.print(!isCurrentlyActiveLocked(job));
+                    pw.print(" !backingup=");
+                    pw.print(!(mBackingUpUids.indexOfKey(job.getSourceUid()) >= 0));
+                    pw.print(" comp=");
+                    boolean componentPresent = false;
+                    try {
+                        componentPresent = (AppGlobals.getPackageManager().getServiceInfo(
+                                job.getServiceComponent(),
+                                PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+                                job.getUserId()) != null);
+                    } catch (RemoteException e) {
+                    }
+                    pw.print(componentPresent);
+                    pw.println(")");
+                }
+            } else {
+                pw.println("  None.");
+            }
+            for (int i=0; i<mControllers.size(); i++) {
+                pw.println();
+                pw.println(mControllers.get(i).getClass().getSimpleName() + ":");
+                pw.increaseIndent();
+                mControllers.get(i).dumpControllerStateLocked(pw, predicate);
+                pw.decreaseIndent();
+            }
+            pw.println();
+            pw.println("Uid priority overrides:");
+            for (int i=0; i< mUidPriorityOverride.size(); i++) {
+                int uid = mUidPriorityOverride.keyAt(i);
+                if (filterUidFinal == -1 || filterUidFinal == UserHandle.getAppId(uid)) {
+                    pw.print("  "); pw.print(UserHandle.formatUid(uid));
+                    pw.print(": "); pw.println(mUidPriorityOverride.valueAt(i));
+                }
+            }
+            if (mBackingUpUids.size() > 0) {
+                pw.println();
+                pw.println("Backing up uids:");
+                boolean first = true;
+                for (int i = 0; i < mBackingUpUids.size(); i++) {
+                    int uid = mBackingUpUids.keyAt(i);
+                    if (filterUidFinal == -1 || filterUidFinal == UserHandle.getAppId(uid)) {
+                        if (first) {
+                            pw.print("  ");
+                            first = false;
+                        } else {
+                            pw.print(", ");
+                        }
+                        pw.print(UserHandle.formatUid(uid));
+                    }
+                }
+                pw.println();
+            }
+            pw.println();
+            mJobPackageTracker.dump(pw, "", filterUidFinal);
+            pw.println();
+            if (mJobPackageTracker.dumpHistory(pw, "", filterUidFinal)) {
+                pw.println();
+            }
+            pw.println("Pending queue:");
+            for (int i=0; i<mPendingJobs.size(); i++) {
+                JobStatus job = mPendingJobs.get(i);
+                pw.print("  Pending #"); pw.print(i); pw.print(": ");
+                pw.println(job.toShortString());
+                job.dump(pw, "    ", false, nowElapsed);
+                int priority = evaluateJobPriorityLocked(job);
+                pw.print("    Evaluated priority: ");
+                pw.println(JobInfo.getPriorityString(priority));
+
+                pw.print("    Tag: "); pw.println(job.getTag());
+                pw.print("    Enq: ");
+                TimeUtils.formatDuration(job.madePending - nowUptime, pw);
+                pw.println();
+            }
+            pw.println();
+            pw.println("Active jobs:");
+            for (int i=0; i<mActiveServices.size(); i++) {
+                JobServiceContext jsc = mActiveServices.get(i);
+                pw.print("  Slot #"); pw.print(i); pw.print(": ");
+                final JobStatus job = jsc.getRunningJobLocked();
+                if (job == null) {
+                    if (jsc.mStoppedReason != null) {
+                        pw.print("inactive since ");
+                        TimeUtils.formatDuration(jsc.mStoppedTime, nowElapsed, pw);
+                        pw.print(", stopped because: ");
+                        pw.println(jsc.mStoppedReason);
+                    } else {
+                        pw.println("inactive");
+                    }
+                    continue;
+                } else {
+                    pw.println(job.toShortString());
+                    pw.print("    Running for: ");
+                    TimeUtils.formatDuration(nowElapsed - jsc.getExecutionStartTimeElapsed(), pw);
+                    pw.print(", timeout at: ");
+                    TimeUtils.formatDuration(jsc.getTimeoutElapsed() - nowElapsed, pw);
+                    pw.println();
+                    job.dump(pw, "    ", false, nowElapsed);
+                    int priority = evaluateJobPriorityLocked(jsc.getRunningJobLocked());
+                    pw.print("    Evaluated priority: ");
+                    pw.println(JobInfo.getPriorityString(priority));
+
+                    pw.print("    Active at ");
+                    TimeUtils.formatDuration(job.madeActive - nowUptime, pw);
+                    pw.print(", pending for ");
+                    TimeUtils.formatDuration(job.madeActive - job.madePending, pw);
+                    pw.println();
+                }
+            }
+            if (filterUid == -1) {
+                pw.println();
+                pw.print("mReadyToRock="); pw.println(mReadyToRock);
+                pw.print("mReportedActive="); pw.println(mReportedActive);
+            }
+            pw.println();
+
+            mConcurrencyManager.dumpLocked(pw, now, nowElapsed);
+
+            pw.println();
+            pw.print("PersistStats: ");
+            pw.println(mJobs.getPersistStats());
+        }
+        pw.println();
+    }
+
+    void dumpInternalProto(final FileDescriptor fd, int filterUid) {
+        ProtoOutputStream proto = new ProtoOutputStream(fd);
+        final int filterUidFinal = UserHandle.getAppId(filterUid);
+        final long now = sSystemClock.millis();
+        final long nowElapsed = sElapsedRealtimeClock.millis();
+        final long nowUptime = sUptimeMillisClock.millis();
+        final Predicate<JobStatus> predicate = (js) -> {
+            return filterUidFinal == -1 || UserHandle.getAppId(js.getUid()) == filterUidFinal
+                    || UserHandle.getAppId(js.getSourceUid()) == filterUidFinal;
+        };
+
+        synchronized (mLock) {
+            final long settingsToken = proto.start(JobSchedulerServiceDumpProto.SETTINGS);
+            mConstants.dump(proto);
+            for (StateController controller : mControllers) {
+                controller.dumpConstants(proto);
+            }
+            proto.end(settingsToken);
+
+            proto.write(JobSchedulerServiceDumpProto.CURRENT_HEARTBEAT, mHeartbeat);
+            proto.write(JobSchedulerServiceDumpProto.NEXT_HEARTBEAT, mNextBucketHeartbeat[0]);
+            proto.write(JobSchedulerServiceDumpProto.NEXT_HEARTBEAT, mNextBucketHeartbeat[1]);
+            proto.write(JobSchedulerServiceDumpProto.NEXT_HEARTBEAT, mNextBucketHeartbeat[2]);
+            proto.write(JobSchedulerServiceDumpProto.NEXT_HEARTBEAT, mNextBucketHeartbeat[3]);
+            proto.write(JobSchedulerServiceDumpProto.LAST_HEARTBEAT_TIME_MILLIS,
+                    mLastHeartbeatTime - nowUptime);
+            proto.write(JobSchedulerServiceDumpProto.NEXT_HEARTBEAT_TIME_MILLIS,
+                    mLastHeartbeatTime + mConstants.STANDBY_HEARTBEAT_TIME - nowUptime);
+            proto.write(JobSchedulerServiceDumpProto.IN_PAROLE, mInParole);
+            proto.write(JobSchedulerServiceDumpProto.IN_THERMAL, mThermalConstraint);
+
+            for (int u : mStartedUsers) {
+                proto.write(JobSchedulerServiceDumpProto.STARTED_USERS, u);
+            }
+            if (mJobs.size() > 0) {
+                final List<JobStatus> jobs = mJobs.mJobSet.getAllJobs();
+                sortJobs(jobs);
+                for (JobStatus job : jobs) {
+                    final long rjToken = proto.start(JobSchedulerServiceDumpProto.REGISTERED_JOBS);
+                    job.writeToShortProto(proto, JobSchedulerServiceDumpProto.RegisteredJob.INFO);
+
+                    // Skip printing details if the caller requested a filter
+                    if (!predicate.test(job)) {
+                        continue;
+                    }
+
+                    job.dump(proto, JobSchedulerServiceDumpProto.RegisteredJob.DUMP, true, nowElapsed);
+
+                    // isReadyToBeExecuted
+                    proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_JOB_READY,
+                            job.isReady());
+                    proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_USER_STARTED,
+                            areUsersStartedLocked(job));
+                    proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_JOB_PENDING,
+                            mPendingJobs.contains(job));
+                    proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_JOB_CURRENTLY_ACTIVE,
+                            isCurrentlyActiveLocked(job));
+                    proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_UID_BACKING_UP,
+                            mBackingUpUids.indexOfKey(job.getSourceUid()) >= 0);
+                    boolean componentPresent = false;
+                    try {
+                        componentPresent = (AppGlobals.getPackageManager().getServiceInfo(
+                                job.getServiceComponent(),
+                                PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+                                job.getUserId()) != null);
+                    } catch (RemoteException e) {
+                    }
+                    proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_COMPONENT_PRESENT,
+                            componentPresent);
+                    proto.write(RegisteredJob.LAST_RUN_HEARTBEAT, heartbeatWhenJobsLastRun(job));
+
+                    proto.end(rjToken);
+                }
+            }
+            for (StateController controller : mControllers) {
+                controller.dumpControllerStateLocked(
+                        proto, JobSchedulerServiceDumpProto.CONTROLLERS, predicate);
+            }
+            for (int i=0; i< mUidPriorityOverride.size(); i++) {
+                int uid = mUidPriorityOverride.keyAt(i);
+                if (filterUidFinal == -1 || filterUidFinal == UserHandle.getAppId(uid)) {
+                    long pToken = proto.start(JobSchedulerServiceDumpProto.PRIORITY_OVERRIDES);
+                    proto.write(JobSchedulerServiceDumpProto.PriorityOverride.UID, uid);
+                    proto.write(JobSchedulerServiceDumpProto.PriorityOverride.OVERRIDE_VALUE,
+                            mUidPriorityOverride.valueAt(i));
+                    proto.end(pToken);
+                }
+            }
+            for (int i = 0; i < mBackingUpUids.size(); i++) {
+                int uid = mBackingUpUids.keyAt(i);
+                if (filterUidFinal == -1 || filterUidFinal == UserHandle.getAppId(uid)) {
+                    proto.write(JobSchedulerServiceDumpProto.BACKING_UP_UIDS, uid);
+                }
+            }
+
+            mJobPackageTracker.dump(proto, JobSchedulerServiceDumpProto.PACKAGE_TRACKER,
+                    filterUidFinal);
+            mJobPackageTracker.dumpHistory(proto, JobSchedulerServiceDumpProto.HISTORY,
+                    filterUidFinal);
+
+            for (JobStatus job : mPendingJobs) {
+                final long pjToken = proto.start(JobSchedulerServiceDumpProto.PENDING_JOBS);
+
+                job.writeToShortProto(proto, PendingJob.INFO);
+                job.dump(proto, PendingJob.DUMP, false, nowElapsed);
+                proto.write(PendingJob.EVALUATED_PRIORITY, evaluateJobPriorityLocked(job));
+                proto.write(PendingJob.ENQUEUED_DURATION_MS, nowUptime - job.madePending);
+
+                proto.end(pjToken);
+            }
+            for (JobServiceContext jsc : mActiveServices) {
+                final long ajToken = proto.start(JobSchedulerServiceDumpProto.ACTIVE_JOBS);
+                final JobStatus job = jsc.getRunningJobLocked();
+
+                if (job == null) {
+                    final long ijToken = proto.start(ActiveJob.INACTIVE);
+
+                        proto.write(ActiveJob.InactiveJob.TIME_SINCE_STOPPED_MS,
+                                nowElapsed - jsc.mStoppedTime);
+                    if (jsc.mStoppedReason != null) {
+                        proto.write(ActiveJob.InactiveJob.STOPPED_REASON,
+                                jsc.mStoppedReason);
+                    }
+
+                    proto.end(ijToken);
+                } else {
+                    final long rjToken = proto.start(ActiveJob.RUNNING);
+
+                    job.writeToShortProto(proto, ActiveJob.RunningJob.INFO);
+
+                    proto.write(ActiveJob.RunningJob.RUNNING_DURATION_MS,
+                            nowElapsed - jsc.getExecutionStartTimeElapsed());
+                    proto.write(ActiveJob.RunningJob.TIME_UNTIL_TIMEOUT_MS,
+                            jsc.getTimeoutElapsed() - nowElapsed);
+
+                    job.dump(proto, ActiveJob.RunningJob.DUMP, false, nowElapsed);
+
+                    proto.write(ActiveJob.RunningJob.EVALUATED_PRIORITY,
+                            evaluateJobPriorityLocked(jsc.getRunningJobLocked()));
+
+                    proto.write(ActiveJob.RunningJob.TIME_SINCE_MADE_ACTIVE_MS,
+                            nowUptime - job.madeActive);
+                    proto.write(ActiveJob.RunningJob.PENDING_DURATION_MS,
+                            job.madeActive - job.madePending);
+
+                    proto.end(rjToken);
+                }
+                proto.end(ajToken);
+            }
+            if (filterUid == -1) {
+                proto.write(JobSchedulerServiceDumpProto.IS_READY_TO_ROCK, mReadyToRock);
+                proto.write(JobSchedulerServiceDumpProto.REPORTED_ACTIVE, mReportedActive);
+            }
+            mConcurrencyManager.dumpProtoLocked(proto,
+                    JobSchedulerServiceDumpProto.CONCURRENCY_MANAGER, now, nowElapsed);
+        }
+
+        proto.flush();
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
new file mode 100644
index 0000000..e361441
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job;
+
+import android.app.ActivityManager;
+import android.app.AppGlobals;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+
+import java.io.PrintWriter;
+
+public final class JobSchedulerShellCommand extends ShellCommand {
+    public static final int CMD_ERR_NO_PACKAGE = -1000;
+    public static final int CMD_ERR_NO_JOB = -1001;
+    public static final int CMD_ERR_CONSTRAINTS = -1002;
+
+    JobSchedulerService mInternal;
+    IPackageManager mPM;
+
+    JobSchedulerShellCommand(JobSchedulerService service) {
+        mInternal = service;
+        mPM = AppGlobals.getPackageManager();
+    }
+
+    @Override
+    public int onCommand(String cmd) {
+        final PrintWriter pw = getOutPrintWriter();
+        try {
+            switch (cmd != null ? cmd : "") {
+                case "run":
+                    return runJob(pw);
+                case "timeout":
+                    return timeout(pw);
+                case "cancel":
+                    return cancelJob(pw);
+                case "monitor-battery":
+                    return monitorBattery(pw);
+                case "get-battery-seq":
+                    return getBatterySeq(pw);
+                case "get-battery-charging":
+                    return getBatteryCharging(pw);
+                case "get-battery-not-low":
+                    return getBatteryNotLow(pw);
+                case "get-storage-seq":
+                    return getStorageSeq(pw);
+                case "get-storage-not-low":
+                    return getStorageNotLow(pw);
+                case "get-job-state":
+                    return getJobState(pw);
+                case "heartbeat":
+                    return doHeartbeat(pw);
+                case "trigger-dock-state":
+                    return triggerDockState(pw);
+                default:
+                    return handleDefaultCommands(cmd);
+            }
+        } catch (Exception e) {
+            pw.println("Exception: " + e);
+        }
+        return -1;
+    }
+
+    private void checkPermission(String operation) throws Exception {
+        final int uid = Binder.getCallingUid();
+        if (uid == 0) {
+            // Root can do anything.
+            return;
+        }
+        final int perm = mPM.checkUidPermission(
+                "android.permission.CHANGE_APP_IDLE_STATE", uid);
+        if (perm != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Uid " + uid
+                    + " not permitted to " + operation);
+        }
+    }
+
+    private boolean printError(int errCode, String pkgName, int userId, int jobId) {
+        PrintWriter pw;
+        switch (errCode) {
+            case CMD_ERR_NO_PACKAGE:
+                pw = getErrPrintWriter();
+                pw.print("Package not found: ");
+                pw.print(pkgName);
+                pw.print(" / user ");
+                pw.println(userId);
+                return true;
+
+            case CMD_ERR_NO_JOB:
+                pw = getErrPrintWriter();
+                pw.print("Could not find job ");
+                pw.print(jobId);
+                pw.print(" in package ");
+                pw.print(pkgName);
+                pw.print(" / user ");
+                pw.println(userId);
+                return true;
+
+            case CMD_ERR_CONSTRAINTS:
+                pw = getErrPrintWriter();
+                pw.print("Job ");
+                pw.print(jobId);
+                pw.print(" in package ");
+                pw.print(pkgName);
+                pw.print(" / user ");
+                pw.print(userId);
+                pw.println(" has functional constraints but --force not specified");
+                return true;
+
+            default:
+                return false;
+        }
+    }
+
+    private int runJob(PrintWriter pw) throws Exception {
+        checkPermission("force scheduled jobs");
+
+        boolean force = false;
+        int userId = UserHandle.USER_SYSTEM;
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-f":
+                case "--force":
+                    force = true;
+                    break;
+
+                case "-u":
+                case "--user":
+                    userId = Integer.parseInt(getNextArgRequired());
+                    break;
+
+                default:
+                    pw.println("Error: unknown option '" + opt + "'");
+                    return -1;
+            }
+        }
+
+        final String pkgName = getNextArgRequired();
+        final int jobId = Integer.parseInt(getNextArgRequired());
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force);
+            if (printError(ret, pkgName, userId, jobId)) {
+                return ret;
+            }
+
+            // success!
+            pw.print("Running job");
+            if (force) {
+                pw.print(" [FORCED]");
+            }
+            pw.println();
+
+            return ret;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private int timeout(PrintWriter pw) throws Exception {
+        checkPermission("force timeout jobs");
+
+        int userId = UserHandle.USER_ALL;
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-u":
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+
+                default:
+                    pw.println("Error: unknown option '" + opt + "'");
+                    return -1;
+            }
+        }
+
+        if (userId == UserHandle.USER_CURRENT) {
+            userId = ActivityManager.getCurrentUser();
+        }
+
+        final String pkgName = getNextArg();
+        final String jobIdStr = getNextArg();
+        final int jobId = jobIdStr != null ? Integer.parseInt(jobIdStr) : -1;
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            return mInternal.executeTimeoutCommand(pw, pkgName, userId, jobIdStr != null, jobId);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private int cancelJob(PrintWriter pw) throws Exception {
+        checkPermission("cancel jobs");
+
+        int userId = UserHandle.USER_SYSTEM;
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-u":
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+
+                default:
+                    pw.println("Error: unknown option '" + opt + "'");
+                    return -1;
+            }
+        }
+
+        if (userId < 0) {
+            pw.println("Error: must specify a concrete user ID");
+            return -1;
+        }
+
+        final String pkgName = getNextArg();
+        final String jobIdStr = getNextArg();
+        final int jobId = jobIdStr != null ? Integer.parseInt(jobIdStr) : -1;
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            return mInternal.executeCancelCommand(pw, pkgName, userId, jobIdStr != null, jobId);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private int monitorBattery(PrintWriter pw) throws Exception {
+        checkPermission("change battery monitoring");
+        String opt = getNextArgRequired();
+        boolean enabled;
+        if ("on".equals(opt)) {
+            enabled = true;
+        } else if ("off".equals(opt)) {
+            enabled = false;
+        } else {
+            getErrPrintWriter().println("Error: unknown option " + opt);
+            return 1;
+        }
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            mInternal.setMonitorBattery(enabled);
+            if (enabled) pw.println("Battery monitoring enabled");
+            else pw.println("Battery monitoring disabled");
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+        return 0;
+    }
+
+    private int getBatterySeq(PrintWriter pw) {
+        int seq = mInternal.getBatterySeq();
+        pw.println(seq);
+        return 0;
+    }
+
+    private int getBatteryCharging(PrintWriter pw) {
+        boolean val = mInternal.getBatteryCharging();
+        pw.println(val);
+        return 0;
+    }
+
+    private int getBatteryNotLow(PrintWriter pw) {
+        boolean val = mInternal.getBatteryNotLow();
+        pw.println(val);
+        return 0;
+    }
+
+    private int getStorageSeq(PrintWriter pw) {
+        int seq = mInternal.getStorageSeq();
+        pw.println(seq);
+        return 0;
+    }
+
+    private int getStorageNotLow(PrintWriter pw) {
+        boolean val = mInternal.getStorageNotLow();
+        pw.println(val);
+        return 0;
+    }
+
+    private int getJobState(PrintWriter pw) throws Exception {
+        checkPermission("force timeout jobs");
+
+        int userId = UserHandle.USER_SYSTEM;
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-u":
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+
+                default:
+                    pw.println("Error: unknown option '" + opt + "'");
+                    return -1;
+            }
+        }
+
+        if (userId == UserHandle.USER_CURRENT) {
+            userId = ActivityManager.getCurrentUser();
+        }
+
+        final String pkgName = getNextArgRequired();
+        final String jobIdStr = getNextArgRequired();
+        final int jobId = Integer.parseInt(jobIdStr);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            int ret = mInternal.getJobState(pw, pkgName, userId, jobId);
+            printError(ret, pkgName, userId, jobId);
+            return ret;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private int doHeartbeat(PrintWriter pw) throws Exception {
+        checkPermission("manipulate scheduler heartbeat");
+
+        final String arg = getNextArg();
+        final int numBeats = (arg != null) ? Integer.parseInt(arg) : 0;
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            return mInternal.executeHeartbeatCommand(pw, numBeats);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private int triggerDockState(PrintWriter pw) throws Exception {
+        checkPermission("trigger wireless charging dock state");
+
+        final String opt = getNextArgRequired();
+        boolean idleState;
+        if ("idle".equals(opt)) {
+            idleState = true;
+        } else if ("active".equals(opt)) {
+            idleState = false;
+        } else {
+            getErrPrintWriter().println("Error: unknown option " + opt);
+            return 1;
+        }
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            mInternal.triggerDockState(idleState);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+        return 0;
+    }
+
+    @Override
+    public void onHelp() {
+        final PrintWriter pw = getOutPrintWriter();
+
+        pw.println("Job scheduler (jobscheduler) commands:");
+        pw.println("  help");
+        pw.println("    Print this help text.");
+        pw.println("  run [-f | --force] [-u | --user USER_ID] PACKAGE JOB_ID");
+        pw.println("    Trigger immediate execution of a specific scheduled job.");
+        pw.println("    Options:");
+        pw.println("      -f or --force: run the job even if technical constraints such as");
+        pw.println("         connectivity are not currently met");
+        pw.println("      -u or --user: specify which user's job is to be run; the default is");
+        pw.println("         the primary or system user");
+        pw.println("  timeout [-u | --user USER_ID] [PACKAGE] [JOB_ID]");
+        pw.println("    Trigger immediate timeout of currently executing jobs, as if their.");
+        pw.println("    execution timeout had expired.");
+        pw.println("    Options:");
+        pw.println("      -u or --user: specify which user's job is to be run; the default is");
+        pw.println("         all users");
+        pw.println("  cancel [-u | --user USER_ID] PACKAGE [JOB_ID]");
+        pw.println("    Cancel a scheduled job.  If a job ID is not supplied, all jobs scheduled");
+        pw.println("    by that package will be canceled.  USE WITH CAUTION.");
+        pw.println("    Options:");
+        pw.println("      -u or --user: specify which user's job is to be run; the default is");
+        pw.println("         the primary or system user");
+        pw.println("  heartbeat [num]");
+        pw.println("    With no argument, prints the current standby heartbeat.  With a positive");
+        pw.println("    argument, advances the standby heartbeat by that number.");
+        pw.println("  monitor-battery [on|off]");
+        pw.println("    Control monitoring of all battery changes.  Off by default.  Turning");
+        pw.println("    on makes get-battery-seq useful.");
+        pw.println("  get-battery-seq");
+        pw.println("    Return the last battery update sequence number that was received.");
+        pw.println("  get-battery-charging");
+        pw.println("    Return whether the battery is currently considered to be charging.");
+        pw.println("  get-battery-not-low");
+        pw.println("    Return whether the battery is currently considered to not be low.");
+        pw.println("  get-storage-seq");
+        pw.println("    Return the last storage update sequence number that was received.");
+        pw.println("  get-storage-not-low");
+        pw.println("    Return whether storage is currently considered to not be low.");
+        pw.println("  get-job-state [-u | --user USER_ID] PACKAGE JOB_ID");
+        pw.println("    Return the current state of a job, may be any combination of:");
+        pw.println("      pending: currently on the pending list, waiting to be active");
+        pw.println("      active: job is actively running");
+        pw.println("      user-stopped: job can't run because its user is stopped");
+        pw.println("      backing-up: job can't run because app is currently backing up its data");
+        pw.println("      no-component: job can't run because its component is not available");
+        pw.println("      ready: job is ready to run (all constraints satisfied or bypassed)");
+        pw.println("      waiting: if nothing else above is printed, job not ready to run");
+        pw.println("    Options:");
+        pw.println("      -u or --user: specify which user's job is to be run; the default is");
+        pw.println("         the primary or system user");
+        pw.println("  trigger-dock-state [idle|active]");
+        pw.println("    Trigger wireless charging dock state.  Active by default.");
+        pw.println();
+    }
+
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
new file mode 100644
index 0000000..7da128f
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -0,0 +1,856 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job;
+
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
+import android.app.ActivityManager;
+import android.app.job.IJobCallback;
+import android.app.job.IJobService;
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobWorkItem;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.WorkSource;
+import android.util.EventLog;
+import android.util.Slog;
+import android.util.TimeUtils;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.IBatteryStats;
+import com.android.server.EventLogTags;
+import com.android.server.LocalServices;
+import com.android.server.job.controllers.JobStatus;
+
+/**
+ * Handles client binding and lifecycle of a job. Jobs execute one at a time on an instance of this
+ * class.
+ *
+ * There are two important interactions into this class from the
+ * {@link com.android.server.job.JobSchedulerService}. To execute a job and to cancel a job.
+ * - Execution of a new job is handled by the {@link #mAvailable}. This bit is flipped once when a
+ * job lands, and again when it is complete.
+ * - Cancelling is trickier, because there are also interactions from the client. It's possible
+ * the {@link com.android.server.job.JobServiceContext.JobServiceHandler} tries to process a
+ * {@link #doCancelLocked} after the client has already finished. This is handled by having
+ * {@link com.android.server.job.JobServiceContext.JobServiceHandler#handleCancelLocked} check whether
+ * the context is still valid.
+ * To mitigate this, we avoid sending duplicate onStopJob()
+ * calls to the client after they've specified jobFinished().
+ */
+public final class JobServiceContext implements ServiceConnection {
+    private static final boolean DEBUG = JobSchedulerService.DEBUG;
+    private static final boolean DEBUG_STANDBY = JobSchedulerService.DEBUG_STANDBY;
+
+    private static final String TAG = "JobServiceContext";
+    /** Amount of time a job is allowed to execute for before being considered timed-out. */
+    public static final long EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000;  // 10mins.
+    /** Amount of time the JobScheduler waits for the initial service launch+bind. */
+    private static final long OP_BIND_TIMEOUT_MILLIS = 18 * 1000;
+    /** Amount of time the JobScheduler will wait for a response from an app for a message. */
+    private static final long OP_TIMEOUT_MILLIS = 8 * 1000;
+
+    private static final String[] VERB_STRINGS = {
+            "VERB_BINDING", "VERB_STARTING", "VERB_EXECUTING", "VERB_STOPPING", "VERB_FINISHED"
+    };
+
+    // States that a job occupies while interacting with the client.
+    static final int VERB_BINDING = 0;
+    static final int VERB_STARTING = 1;
+    static final int VERB_EXECUTING = 2;
+    static final int VERB_STOPPING = 3;
+    static final int VERB_FINISHED = 4;
+
+    // Messages that result from interactions with the client service.
+    /** System timed out waiting for a response. */
+    private static final int MSG_TIMEOUT = 0;
+
+    public static final int NO_PREFERRED_UID = -1;
+
+    private final Handler mCallbackHandler;
+    /** Make callbacks to {@link JobSchedulerService} to inform on job completion status. */
+    private final JobCompletedListener mCompletedListener;
+    /** Used for service binding, etc. */
+    private final Context mContext;
+    private final Object mLock;
+    private final IBatteryStats mBatteryStats;
+    private final JobPackageTracker mJobPackageTracker;
+    private PowerManager.WakeLock mWakeLock;
+
+    // Execution state.
+    private JobParameters mParams;
+    @VisibleForTesting
+    int mVerb;
+    private boolean mCancelled;
+
+    /**
+     * All the information maintained about the job currently being executed.
+     *
+     * Any reads (dereferences) not done from the handler thread must be synchronized on
+     * {@link #mLock}.
+     * Writes can only be done from the handler thread, or {@link #executeRunnableJob(JobStatus)}.
+     */
+    private JobStatus mRunningJob;
+    private JobCallback mRunningCallback;
+    /** Used to store next job to run when current job is to be preempted. */
+    private int mPreferredUid;
+    IJobService service;
+
+    /**
+     * Whether this context is free. This is set to false at the start of execution, and reset to
+     * true when execution is complete.
+     */
+    @GuardedBy("mLock")
+    private boolean mAvailable;
+    /** Track start time. */
+    private long mExecutionStartTimeElapsed;
+    /** Track when job will timeout. */
+    private long mTimeoutElapsed;
+
+    // Debugging: reason this job was last stopped.
+    public String mStoppedReason;
+
+    // Debugging: time this job was last stopped.
+    public long mStoppedTime;
+
+    final class JobCallback extends IJobCallback.Stub {
+        public String mStoppedReason;
+        public long mStoppedTime;
+
+        @Override
+        public void acknowledgeStartMessage(int jobId, boolean ongoing) {
+            doAcknowledgeStartMessage(this, jobId, ongoing);
+        }
+
+        @Override
+        public void acknowledgeStopMessage(int jobId, boolean reschedule) {
+            doAcknowledgeStopMessage(this, jobId, reschedule);
+        }
+
+        @Override
+        public JobWorkItem dequeueWork(int jobId) {
+            return doDequeueWork(this, jobId);
+        }
+
+        @Override
+        public boolean completeWork(int jobId, int workId) {
+            return doCompleteWork(this, jobId, workId);
+        }
+
+        @Override
+        public void jobFinished(int jobId, boolean reschedule) {
+            doJobFinished(this, jobId, reschedule);
+        }
+    }
+
+    JobServiceContext(JobSchedulerService service, IBatteryStats batteryStats,
+            JobPackageTracker tracker, Looper looper) {
+        this(service.getContext(), service.getLock(), batteryStats, tracker, service, looper);
+    }
+
+    @VisibleForTesting
+    JobServiceContext(Context context, Object lock, IBatteryStats batteryStats,
+            JobPackageTracker tracker, JobCompletedListener completedListener, Looper looper) {
+        mContext = context;
+        mLock = lock;
+        mBatteryStats = batteryStats;
+        mJobPackageTracker = tracker;
+        mCallbackHandler = new JobServiceHandler(looper);
+        mCompletedListener = completedListener;
+        mAvailable = true;
+        mVerb = VERB_FINISHED;
+        mPreferredUid = NO_PREFERRED_UID;
+    }
+
+    /**
+     * Give a job to this context for execution. Callers must first check {@link #getRunningJobLocked()}
+     * and ensure it is null to make sure this is a valid context.
+     * @param job The status of the job that we are going to run.
+     * @return True if the job is valid and is running. False if the job cannot be executed.
+     */
+    boolean executeRunnableJob(JobStatus job) {
+        synchronized (mLock) {
+            if (!mAvailable) {
+                Slog.e(TAG, "Starting new runnable but context is unavailable > Error.");
+                return false;
+            }
+
+            mPreferredUid = NO_PREFERRED_UID;
+
+            mRunningJob = job;
+            mRunningCallback = new JobCallback();
+            final boolean isDeadlineExpired =
+                    job.hasDeadlineConstraint() &&
+                            (job.getLatestRunTimeElapsed() < sElapsedRealtimeClock.millis());
+            Uri[] triggeredUris = null;
+            if (job.changedUris != null) {
+                triggeredUris = new Uri[job.changedUris.size()];
+                job.changedUris.toArray(triggeredUris);
+            }
+            String[] triggeredAuthorities = null;
+            if (job.changedAuthorities != null) {
+                triggeredAuthorities = new String[job.changedAuthorities.size()];
+                job.changedAuthorities.toArray(triggeredAuthorities);
+            }
+            final JobInfo ji = job.getJob();
+            mParams = new JobParameters(mRunningCallback, job.getJobId(), ji.getExtras(),
+                    ji.getTransientExtras(), ji.getClipData(), ji.getClipGrantFlags(),
+                    isDeadlineExpired, triggeredUris, triggeredAuthorities, job.network);
+            mExecutionStartTimeElapsed = sElapsedRealtimeClock.millis();
+
+            final long whenDeferred = job.getWhenStandbyDeferred();
+            if (whenDeferred > 0) {
+                final long deferral = mExecutionStartTimeElapsed - whenDeferred;
+                EventLog.writeEvent(EventLogTags.JOB_DEFERRED_EXECUTION, deferral);
+                if (DEBUG_STANDBY) {
+                    StringBuilder sb = new StringBuilder(128);
+                    sb.append("Starting job deferred for standby by ");
+                    TimeUtils.formatDuration(deferral, sb);
+                    sb.append(" ms : ");
+                    sb.append(job.toShortString());
+                    Slog.v(TAG, sb.toString());
+                }
+            }
+
+            // Once we'e begun executing a job, we by definition no longer care whether
+            // it was inflated from disk with not-yet-coherent delay/deadline bounds.
+            job.clearPersistedUtcTimes();
+
+            mVerb = VERB_BINDING;
+            scheduleOpTimeOutLocked();
+            final Intent intent = new Intent().setComponent(job.getServiceComponent());
+            boolean binding = false;
+            try {
+                binding = mContext.bindServiceAsUser(intent, this,
+                        Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
+                        | Context.BIND_NOT_PERCEPTIBLE,
+                        new UserHandle(job.getUserId()));
+            } catch (SecurityException e) {
+                // Some permission policy, for example INTERACT_ACROSS_USERS and
+                // android:singleUser, can result in a SecurityException being thrown from
+                // bindServiceAsUser().  If this happens, catch it and fail gracefully.
+                Slog.w(TAG, "Job service " + job.getServiceComponent().getShortClassName()
+                        + " cannot be executed: " + e.getMessage());
+                binding = false;
+            }
+            if (!binding) {
+                if (DEBUG) {
+                    Slog.d(TAG, job.getServiceComponent().getShortClassName() + " unavailable.");
+                }
+                mRunningJob = null;
+                mRunningCallback = null;
+                mParams = null;
+                mExecutionStartTimeElapsed = 0L;
+                mVerb = VERB_FINISHED;
+                removeOpTimeOutLocked();
+                return false;
+            }
+            mJobPackageTracker.noteActive(job);
+            try {
+                mBatteryStats.noteJobStart(job.getBatteryName(), job.getSourceUid(),
+                        job.getStandbyBucket(), job.getJobId());
+            } catch (RemoteException e) {
+                // Whatever.
+            }
+            final String jobPackage = job.getSourcePackageName();
+            final int jobUserId = job.getSourceUserId();
+            UsageStatsManagerInternal usageStats =
+                    LocalServices.getService(UsageStatsManagerInternal.class);
+            usageStats.setLastJobRunTime(jobPackage, jobUserId, mExecutionStartTimeElapsed);
+            JobSchedulerInternal jobScheduler =
+                    LocalServices.getService(JobSchedulerInternal.class);
+            jobScheduler.noteJobStart(jobPackage, jobUserId);
+            mAvailable = false;
+            mStoppedReason = null;
+            mStoppedTime = 0;
+            return true;
+        }
+    }
+
+    /**
+     * Used externally to query the running job. Will return null if there is no job running.
+     */
+    JobStatus getRunningJobLocked() {
+        return mRunningJob;
+    }
+
+    /**
+     * Used only for debugging. Will return <code>"&lt;null&gt;"</code> if there is no job running.
+     */
+    private String getRunningJobNameLocked() {
+        return mRunningJob != null ? mRunningJob.toShortString() : "<null>";
+    }
+
+    /** Called externally when a job that was scheduled for execution should be cancelled. */
+    @GuardedBy("mLock")
+    void cancelExecutingJobLocked(int reason, String debugReason) {
+        doCancelLocked(reason, debugReason);
+    }
+
+    @GuardedBy("mLock")
+    void preemptExecutingJobLocked() {
+        doCancelLocked(JobParameters.REASON_PREEMPT, "cancelled due to preemption");
+    }
+
+    int getPreferredUid() {
+        return mPreferredUid;
+    }
+
+    void clearPreferredUid() {
+        mPreferredUid = NO_PREFERRED_UID;
+    }
+
+    long getExecutionStartTimeElapsed() {
+        return mExecutionStartTimeElapsed;
+    }
+
+    long getTimeoutElapsed() {
+        return mTimeoutElapsed;
+    }
+
+    @GuardedBy("mLock")
+    boolean timeoutIfExecutingLocked(String pkgName, int userId, boolean matchJobId, int jobId,
+            String reason) {
+        final JobStatus executing = getRunningJobLocked();
+        if (executing != null && (userId == UserHandle.USER_ALL || userId == executing.getUserId())
+                && (pkgName == null || pkgName.equals(executing.getSourcePackageName()))
+                && (!matchJobId || jobId == executing.getJobId())) {
+            if (mVerb == VERB_EXECUTING) {
+                mParams.setStopReason(JobParameters.REASON_TIMEOUT, reason);
+                sendStopMessageLocked("force timeout from shell");
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void doJobFinished(JobCallback cb, int jobId, boolean reschedule) {
+        doCallback(cb, reschedule, "app called jobFinished");
+    }
+
+    void doAcknowledgeStopMessage(JobCallback cb, int jobId, boolean reschedule) {
+        doCallback(cb, reschedule, null);
+    }
+
+    void doAcknowledgeStartMessage(JobCallback cb, int jobId, boolean ongoing) {
+        doCallback(cb, ongoing, "finished start");
+    }
+
+    JobWorkItem doDequeueWork(JobCallback cb, int jobId) {
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                assertCallerLocked(cb);
+                if (mVerb == VERB_STOPPING || mVerb == VERB_FINISHED) {
+                    // This job is either all done, or on its way out.  Either way, it
+                    // should not dispatch any more work.  We will pick up any remaining
+                    // work the next time we start the job again.
+                    return null;
+                }
+                final JobWorkItem work = mRunningJob.dequeueWorkLocked();
+                if (work == null && !mRunningJob.hasExecutingWorkLocked()) {
+                    // This will finish the job.
+                    doCallbackLocked(false, "last work dequeued");
+                }
+                return work;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    boolean doCompleteWork(JobCallback cb, int jobId, int workId) {
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                assertCallerLocked(cb);
+                return mRunningJob.completeWorkLocked(ActivityManager.getService(), workId);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    /**
+     * We acquire/release a wakelock on onServiceConnected/unbindService. This mirrors the work
+     * we intend to send to the client - we stop sending work when the service is unbound so until
+     * then we keep the wakelock.
+     * @param name The concrete component name of the service that has been connected.
+     * @param service The IBinder of the Service's communication channel,
+     */
+    @Override
+    public void onServiceConnected(ComponentName name, IBinder service) {
+        JobStatus runningJob;
+        synchronized (mLock) {
+            // This isn't strictly necessary b/c the JobServiceHandler is running on the main
+            // looper and at this point we can't get any binder callbacks from the client. Better
+            // safe than sorry.
+            runningJob = mRunningJob;
+
+            if (runningJob == null || !name.equals(runningJob.getServiceComponent())) {
+                closeAndCleanupJobLocked(true /* needsReschedule */,
+                        "connected for different component");
+                return;
+            }
+            this.service = IJobService.Stub.asInterface(service);
+            final PowerManager pm =
+                    (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+            PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+                    runningJob.getTag());
+            wl.setWorkSource(deriveWorkSource(runningJob));
+            wl.setReferenceCounted(false);
+            wl.acquire();
+
+            // We use a new wakelock instance per job.  In rare cases there is a race between
+            // teardown following job completion/cancellation and new job service spin-up
+            // such that if we simply assign mWakeLock to be the new instance, we orphan
+            // the currently-live lock instead of cleanly replacing it.  Watch for this and
+            // explicitly fast-forward the release if we're in that situation.
+            if (mWakeLock != null) {
+                Slog.w(TAG, "Bound new job " + runningJob + " but live wakelock " + mWakeLock
+                        + " tag=" + mWakeLock.getTag());
+                mWakeLock.release();
+            }
+            mWakeLock = wl;
+            doServiceBoundLocked();
+        }
+    }
+
+    private WorkSource deriveWorkSource(JobStatus runningJob) {
+        final int jobUid = runningJob.getSourceUid();
+        if (WorkSource.isChainedBatteryAttributionEnabled(mContext)) {
+            WorkSource workSource = new WorkSource();
+            workSource.createWorkChain()
+                    .addNode(jobUid, null)
+                    .addNode(android.os.Process.SYSTEM_UID, "JobScheduler");
+            return workSource;
+        } else {
+            return new WorkSource(jobUid);
+        }
+    }
+
+    /** If the client service crashes we reschedule this job and clean up. */
+    @Override
+    public void onServiceDisconnected(ComponentName name) {
+        synchronized (mLock) {
+            closeAndCleanupJobLocked(true /* needsReschedule */, "unexpectedly disconnected");
+        }
+    }
+
+    /**
+     * This class is reused across different clients, and passes itself in as a callback. Check
+     * whether the client exercising the callback is the client we expect.
+     * @return True if the binder calling is coming from the client we expect.
+     */
+    private boolean verifyCallerLocked(JobCallback cb) {
+        if (mRunningCallback != cb) {
+            if (DEBUG) {
+                Slog.d(TAG, "Stale callback received, ignoring.");
+            }
+            return false;
+        }
+        return true;
+    }
+
+    private void assertCallerLocked(JobCallback cb) {
+        if (!verifyCallerLocked(cb)) {
+            StringBuilder sb = new StringBuilder(128);
+            sb.append("Caller no longer running");
+            if (cb.mStoppedReason != null) {
+                sb.append(", last stopped ");
+                TimeUtils.formatDuration(sElapsedRealtimeClock.millis() - cb.mStoppedTime, sb);
+                sb.append(" because: ");
+                sb.append(cb.mStoppedReason);
+            }
+            throw new SecurityException(sb.toString());
+        }
+    }
+
+    /**
+     * Scheduling of async messages (basically timeouts at this point).
+     */
+    private class JobServiceHandler extends Handler {
+        JobServiceHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message message) {
+            switch (message.what) {
+                case MSG_TIMEOUT:
+                    synchronized (mLock) {
+                        if (message.obj == mRunningCallback) {
+                            handleOpTimeoutLocked();
+                        } else {
+                            JobCallback jc = (JobCallback)message.obj;
+                            StringBuilder sb = new StringBuilder(128);
+                            sb.append("Ignoring timeout of no longer active job");
+                            if (jc.mStoppedReason != null) {
+                                sb.append(", stopped ");
+                                TimeUtils.formatDuration(sElapsedRealtimeClock.millis()
+                                        - jc.mStoppedTime, sb);
+                                sb.append(" because: ");
+                                sb.append(jc.mStoppedReason);
+                            }
+                            Slog.w(TAG, sb.toString());
+                        }
+                    }
+                    break;
+                default:
+                    Slog.e(TAG, "Unrecognised message: " + message);
+            }
+        }
+    }
+
+    @GuardedBy("mLock")
+    void doServiceBoundLocked() {
+        removeOpTimeOutLocked();
+        handleServiceBoundLocked();
+    }
+
+    void doCallback(JobCallback cb, boolean reschedule, String reason) {
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                if (!verifyCallerLocked(cb)) {
+                    return;
+                }
+                doCallbackLocked(reschedule, reason);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @GuardedBy("mLock")
+    void doCallbackLocked(boolean reschedule, String reason) {
+        if (DEBUG) {
+            Slog.d(TAG, "doCallback of : " + mRunningJob
+                    + " v:" + VERB_STRINGS[mVerb]);
+        }
+        removeOpTimeOutLocked();
+
+        if (mVerb == VERB_STARTING) {
+            handleStartedLocked(reschedule);
+        } else if (mVerb == VERB_EXECUTING ||
+                mVerb == VERB_STOPPING) {
+            handleFinishedLocked(reschedule, reason);
+        } else {
+            if (DEBUG) {
+                Slog.d(TAG, "Unrecognised callback: " + mRunningJob);
+            }
+        }
+    }
+
+    @GuardedBy("mLock")
+    void doCancelLocked(int arg1, String debugReason) {
+        if (mVerb == VERB_FINISHED) {
+            if (DEBUG) {
+                Slog.d(TAG,
+                        "Trying to process cancel for torn-down context, ignoring.");
+            }
+            return;
+        }
+        mParams.setStopReason(arg1, debugReason);
+        if (arg1 == JobParameters.REASON_PREEMPT) {
+            mPreferredUid = mRunningJob != null ? mRunningJob.getUid() :
+                    NO_PREFERRED_UID;
+        }
+        handleCancelLocked(debugReason);
+    }
+
+    /** Start the job on the service. */
+    @GuardedBy("mLock")
+    private void handleServiceBoundLocked() {
+        if (DEBUG) {
+            Slog.d(TAG, "handleServiceBound for " + getRunningJobNameLocked());
+        }
+        if (mVerb != VERB_BINDING) {
+            Slog.e(TAG, "Sending onStartJob for a job that isn't pending. "
+                    + VERB_STRINGS[mVerb]);
+            closeAndCleanupJobLocked(false /* reschedule */, "started job not pending");
+            return;
+        }
+        if (mCancelled) {
+            if (DEBUG) {
+                Slog.d(TAG, "Job cancelled while waiting for bind to complete. "
+                        + mRunningJob);
+            }
+            closeAndCleanupJobLocked(true /* reschedule */, "cancelled while waiting for bind");
+            return;
+        }
+        try {
+            mVerb = VERB_STARTING;
+            scheduleOpTimeOutLocked();
+            service.startJob(mParams);
+        } catch (Exception e) {
+            // We catch 'Exception' because client-app malice or bugs might induce a wide
+            // range of possible exception-throw outcomes from startJob() and its handling
+            // of the client's ParcelableBundle extras.
+            Slog.e(TAG, "Error sending onStart message to '" +
+                    mRunningJob.getServiceComponent().getShortClassName() + "' ", e);
+        }
+    }
+
+    /**
+     * State behaviours.
+     * VERB_STARTING   -> Successful start, change job to VERB_EXECUTING and post timeout.
+     *     _PENDING    -> Error
+     *     _EXECUTING  -> Error
+     *     _STOPPING   -> Error
+     */
+    @GuardedBy("mLock")
+    private void handleStartedLocked(boolean workOngoing) {
+        switch (mVerb) {
+            case VERB_STARTING:
+                mVerb = VERB_EXECUTING;
+                if (!workOngoing) {
+                    // Job is finished already so fast-forward to handleFinished.
+                    handleFinishedLocked(false, "onStartJob returned false");
+                    return;
+                }
+                if (mCancelled) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Job cancelled while waiting for onStartJob to complete.");
+                    }
+                    // Cancelled *while* waiting for acknowledgeStartMessage from client.
+                    handleCancelLocked(null);
+                    return;
+                }
+                scheduleOpTimeOutLocked();
+                break;
+            default:
+                Slog.e(TAG, "Handling started job but job wasn't starting! Was "
+                        + VERB_STRINGS[mVerb] + ".");
+                return;
+        }
+    }
+
+    /**
+     * VERB_EXECUTING  -> Client called jobFinished(), clean up and notify done.
+     *     _STOPPING   -> Successful finish, clean up and notify done.
+     *     _STARTING   -> Error
+     *     _PENDING    -> Error
+     */
+    @GuardedBy("mLock")
+    private void handleFinishedLocked(boolean reschedule, String reason) {
+        switch (mVerb) {
+            case VERB_EXECUTING:
+            case VERB_STOPPING:
+                closeAndCleanupJobLocked(reschedule, reason);
+                break;
+            default:
+                Slog.e(TAG, "Got an execution complete message for a job that wasn't being" +
+                        "executed. Was " + VERB_STRINGS[mVerb] + ".");
+        }
+    }
+
+    /**
+     * A job can be in various states when a cancel request comes in:
+     * VERB_BINDING    -> Cancelled before bind completed. Mark as cancelled and wait for
+     *                    {@link #onServiceConnected(android.content.ComponentName, android.os.IBinder)}
+     *     _STARTING   -> Mark as cancelled and wait for
+     *                    {@link JobServiceContext#doAcknowledgeStartMessage}
+     *     _EXECUTING  -> call {@link #sendStopMessageLocked}}, but only if there are no callbacks
+     *                      in the message queue.
+     *     _ENDING     -> No point in doing anything here, so we ignore.
+     */
+    @GuardedBy("mLock")
+    private void handleCancelLocked(String reason) {
+        if (JobSchedulerService.DEBUG) {
+            Slog.d(TAG, "Handling cancel for: " + mRunningJob.getJobId() + " "
+                    + VERB_STRINGS[mVerb]);
+        }
+        switch (mVerb) {
+            case VERB_BINDING:
+            case VERB_STARTING:
+                mCancelled = true;
+                applyStoppedReasonLocked(reason);
+                break;
+            case VERB_EXECUTING:
+                sendStopMessageLocked(reason);
+                break;
+            case VERB_STOPPING:
+                // Nada.
+                break;
+            default:
+                Slog.e(TAG, "Cancelling a job without a valid verb: " + mVerb);
+                break;
+        }
+    }
+
+    /** Process MSG_TIMEOUT here. */
+    @GuardedBy("mLock")
+    private void handleOpTimeoutLocked() {
+        switch (mVerb) {
+            case VERB_BINDING:
+                Slog.w(TAG, "Time-out while trying to bind " + getRunningJobNameLocked()
+                        + ", dropping.");
+                closeAndCleanupJobLocked(false /* needsReschedule */, "timed out while binding");
+                break;
+            case VERB_STARTING:
+                // Client unresponsive - wedged or failed to respond in time. We don't really
+                // know what happened so let's log it and notify the JobScheduler
+                // FINISHED/NO-RETRY.
+                Slog.w(TAG, "No response from client for onStartJob "
+                        + getRunningJobNameLocked());
+                closeAndCleanupJobLocked(false /* needsReschedule */, "timed out while starting");
+                break;
+            case VERB_STOPPING:
+                // At least we got somewhere, so fail but ask the JobScheduler to reschedule.
+                Slog.w(TAG, "No response from client for onStopJob "
+                        + getRunningJobNameLocked());
+                closeAndCleanupJobLocked(true /* needsReschedule */, "timed out while stopping");
+                break;
+            case VERB_EXECUTING:
+                // Not an error - client ran out of time.
+                Slog.i(TAG, "Client timed out while executing (no jobFinished received), " +
+                        "sending onStop: " + getRunningJobNameLocked());
+                mParams.setStopReason(JobParameters.REASON_TIMEOUT, "client timed out");
+                sendStopMessageLocked("timeout while executing");
+                break;
+            default:
+                Slog.e(TAG, "Handling timeout for an invalid job state: "
+                        + getRunningJobNameLocked() + ", dropping.");
+                closeAndCleanupJobLocked(false /* needsReschedule */, "invalid timeout");
+        }
+    }
+
+    /**
+     * Already running, need to stop. Will switch {@link #mVerb} from VERB_EXECUTING ->
+     * VERB_STOPPING.
+     */
+    @GuardedBy("mLock")
+    private void sendStopMessageLocked(String reason) {
+        removeOpTimeOutLocked();
+        if (mVerb != VERB_EXECUTING) {
+            Slog.e(TAG, "Sending onStopJob for a job that isn't started. " + mRunningJob);
+            closeAndCleanupJobLocked(false /* reschedule */, reason);
+            return;
+        }
+        try {
+            applyStoppedReasonLocked(reason);
+            mVerb = VERB_STOPPING;
+            scheduleOpTimeOutLocked();
+            service.stopJob(mParams);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Error sending onStopJob to client.", e);
+            // The job's host app apparently crashed during the job, so we should reschedule.
+            closeAndCleanupJobLocked(true /* reschedule */, "host crashed when trying to stop");
+        }
+    }
+
+    /**
+     * The provided job has finished, either by calling
+     * {@link android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean)}
+     * or from acknowledging the stop message we sent. Either way, we're done tracking it and
+     * we want to clean up internally.
+     */
+    @GuardedBy("mLock")
+    private void closeAndCleanupJobLocked(boolean reschedule, String reason) {
+        final JobStatus completedJob;
+        if (mVerb == VERB_FINISHED) {
+            return;
+        }
+        applyStoppedReasonLocked(reason);
+        completedJob = mRunningJob;
+        mJobPackageTracker.noteInactive(completedJob, mParams.getStopReason(), reason);
+        try {
+            mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(),
+                    mRunningJob.getSourceUid(), mParams.getStopReason(),
+                    mRunningJob.getStandbyBucket(), mRunningJob.getJobId());
+        } catch (RemoteException e) {
+            // Whatever.
+        }
+        if (mWakeLock != null) {
+            mWakeLock.release();
+        }
+        mContext.unbindService(JobServiceContext.this);
+        mWakeLock = null;
+        mRunningJob = null;
+        mRunningCallback = null;
+        mParams = null;
+        mVerb = VERB_FINISHED;
+        mCancelled = false;
+        service = null;
+        mAvailable = true;
+        removeOpTimeOutLocked();
+        mCompletedListener.onJobCompletedLocked(completedJob, reschedule);
+    }
+
+    private void applyStoppedReasonLocked(String reason) {
+        if (reason != null && mStoppedReason == null) {
+            mStoppedReason = reason;
+            mStoppedTime = sElapsedRealtimeClock.millis();
+            if (mRunningCallback != null) {
+                mRunningCallback.mStoppedReason = mStoppedReason;
+                mRunningCallback.mStoppedTime = mStoppedTime;
+            }
+        }
+    }
+
+    /**
+     * Called when sending a message to the client, over whose execution we have no control. If
+     * we haven't received a response in a certain amount of time, we want to give up and carry
+     * on with life.
+     */
+    private void scheduleOpTimeOutLocked() {
+        removeOpTimeOutLocked();
+
+        final long timeoutMillis;
+        switch (mVerb) {
+            case VERB_EXECUTING:
+                timeoutMillis = EXECUTING_TIMESLICE_MILLIS;
+                break;
+
+            case VERB_BINDING:
+                timeoutMillis = OP_BIND_TIMEOUT_MILLIS;
+                break;
+
+            default:
+                timeoutMillis = OP_TIMEOUT_MILLIS;
+                break;
+        }
+        if (DEBUG) {
+            Slog.d(TAG, "Scheduling time out for '" +
+                    mRunningJob.getServiceComponent().getShortClassName() + "' jId: " +
+                    mParams.getJobId() + ", in " + (timeoutMillis / 1000) + " s");
+        }
+        Message m = mCallbackHandler.obtainMessage(MSG_TIMEOUT, mRunningCallback);
+        mCallbackHandler.sendMessageDelayed(m, timeoutMillis);
+        mTimeoutElapsed = sElapsedRealtimeClock.millis() + timeoutMillis;
+    }
+
+
+    private void removeOpTimeOutLocked() {
+        mCallbackHandler.removeMessages(MSG_TIMEOUT);
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
new file mode 100644
index 0000000..d69faf3
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
@@ -0,0 +1,1285 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job;
+
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+import static com.android.server.job.JobSchedulerService.sSystemClock;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.IActivityManager;
+import android.app.job.JobInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.net.NetworkRequest;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.PersistableBundle;
+import android.os.Process;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.text.format.DateUtils;
+import android.util.ArraySet;
+import android.util.AtomicFile;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.Xml;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.BitUtils;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.server.IoThread;
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerInternal.JobStorePersistStats;
+import com.android.server.job.controllers.JobStatus;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+/**
+ * Maintains the master list of jobs that the job scheduler is tracking. These jobs are compared by
+ * reference, so none of the functions in this class should make a copy.
+ * Also handles read/write of persisted jobs.
+ *
+ * Note on locking:
+ *      All callers to this class must <strong>lock on the class object they are calling</strong>.
+ *      This is important b/c {@link com.android.server.job.JobStore.WriteJobsMapToDiskRunnable}
+ *      and {@link com.android.server.job.JobStore.ReadJobMapFromDiskRunnable} lock on that
+ *      object.
+ *
+ * Test:
+ * atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+ */
+public final class JobStore {
+    private static final String TAG = "JobStore";
+    private static final boolean DEBUG = JobSchedulerService.DEBUG;
+
+    /** Threshold to adjust how often we want to write to the db. */
+    private static final long JOB_PERSIST_DELAY = 2000L;
+
+    final Object mLock;
+    final Object mWriteScheduleLock;    // used solely for invariants around write scheduling
+    final JobSet mJobSet; // per-caller-uid and per-source-uid tracking
+    final Context mContext;
+
+    // Bookkeeping around incorrect boot-time system clock
+    private final long mXmlTimestamp;
+    private boolean mRtcGood;
+
+    @GuardedBy("mWriteScheduleLock")
+    private boolean mWriteScheduled;
+
+    @GuardedBy("mWriteScheduleLock")
+    private boolean mWriteInProgress;
+
+    private static final Object sSingletonLock = new Object();
+    private final AtomicFile mJobsFile;
+    /** Handler backed by IoThread for writing to disk. */
+    private final Handler mIoHandler = IoThread.getHandler();
+    private static JobStore sSingleton;
+
+    private JobStorePersistStats mPersistInfo = new JobStorePersistStats();
+
+    /** Used by the {@link JobSchedulerService} to instantiate the JobStore. */
+    static JobStore initAndGet(JobSchedulerService jobManagerService) {
+        synchronized (sSingletonLock) {
+            if (sSingleton == null) {
+                sSingleton = new JobStore(jobManagerService.getContext(),
+                        jobManagerService.getLock(), Environment.getDataDirectory());
+            }
+            return sSingleton;
+        }
+    }
+
+    /**
+     * @return A freshly initialized job store object, with no loaded jobs.
+     */
+    @VisibleForTesting
+    public static JobStore initAndGetForTesting(Context context, File dataDir) {
+        JobStore jobStoreUnderTest = new JobStore(context, new Object(), dataDir);
+        jobStoreUnderTest.clear();
+        return jobStoreUnderTest;
+    }
+
+    /**
+     * Construct the instance of the job store. This results in a blocking read from disk.
+     */
+    private JobStore(Context context, Object lock, File dataDir) {
+        mLock = lock;
+        mWriteScheduleLock = new Object();
+        mContext = context;
+
+        File systemDir = new File(dataDir, "system");
+        File jobDir = new File(systemDir, "job");
+        jobDir.mkdirs();
+        mJobsFile = new AtomicFile(new File(jobDir, "jobs.xml"), "jobs");
+
+        mJobSet = new JobSet();
+
+        // If the current RTC is earlier than the timestamp on our persisted jobs file,
+        // we suspect that the RTC is uninitialized and so we cannot draw conclusions
+        // about persisted job scheduling.
+        //
+        // Note that if the persisted jobs file does not exist, we proceed with the
+        // assumption that the RTC is good.  This is less work and is safe: if the
+        // clock updates to sanity then we'll be saving the persisted jobs file in that
+        // correct state, which is normal; or we'll wind up writing the jobs file with
+        // an incorrect historical timestamp.  That's fine; at worst we'll reboot with
+        // a *correct* timestamp, see a bunch of overdue jobs, and run them; then
+        // settle into normal operation.
+        mXmlTimestamp = mJobsFile.getLastModifiedTime();
+        mRtcGood = (sSystemClock.millis() > mXmlTimestamp);
+
+        readJobMapFromDisk(mJobSet, mRtcGood);
+    }
+
+    public boolean jobTimesInflatedValid() {
+        return mRtcGood;
+    }
+
+    public boolean clockNowValidToInflate(long now) {
+        return now >= mXmlTimestamp;
+    }
+
+    /**
+     * Find all the jobs that were affected by RTC clock uncertainty at boot time.  Returns
+     * parallel lists of the existing JobStatus objects and of new, equivalent JobStatus instances
+     * with now-corrected time bounds.
+     */
+    public void getRtcCorrectedJobsLocked(final ArrayList<JobStatus> toAdd,
+            final ArrayList<JobStatus> toRemove) {
+        final long elapsedNow = sElapsedRealtimeClock.millis();
+        final IActivityManager am = ActivityManager.getService();
+
+        // Find the jobs that need to be fixed up, collecting them for post-iteration
+        // replacement with their new versions
+        forEachJob(job -> {
+            final Pair<Long, Long> utcTimes = job.getPersistedUtcTimes();
+            if (utcTimes != null) {
+                Pair<Long, Long> elapsedRuntimes =
+                        convertRtcBoundsToElapsed(utcTimes, elapsedNow);
+                JobStatus newJob = new JobStatus(job, job.getBaseHeartbeat(),
+                        elapsedRuntimes.first, elapsedRuntimes.second,
+                        0, job.getLastSuccessfulRunTime(), job.getLastFailedRunTime());
+                newJob.prepareLocked(am);
+                toAdd.add(newJob);
+                toRemove.add(job);
+            }
+        });
+    }
+
+    /**
+     * Add a job to the master list, persisting it if necessary. If the JobStatus already exists,
+     * it will be replaced.
+     * @param jobStatus Job to add.
+     * @return Whether or not an equivalent JobStatus was replaced by this operation.
+     */
+    public boolean add(JobStatus jobStatus) {
+        boolean replaced = mJobSet.remove(jobStatus);
+        mJobSet.add(jobStatus);
+        if (jobStatus.isPersisted()) {
+            maybeWriteStatusToDiskAsync();
+        }
+        if (DEBUG) {
+            Slog.d(TAG, "Added job status to store: " + jobStatus);
+        }
+        return replaced;
+    }
+
+    boolean containsJob(JobStatus jobStatus) {
+        return mJobSet.contains(jobStatus);
+    }
+
+    public int size() {
+        return mJobSet.size();
+    }
+
+    public JobStorePersistStats getPersistStats() {
+        return mPersistInfo;
+    }
+
+    public int countJobsForUid(int uid) {
+        return mJobSet.countJobsForUid(uid);
+    }
+
+    /**
+     * Remove the provided job. Will also delete the job if it was persisted.
+     * @param removeFromPersisted If true, the job will be removed from the persisted job list
+     *                            immediately (if it was persisted).
+     * @return Whether or not the job existed to be removed.
+     */
+    public boolean remove(JobStatus jobStatus, boolean removeFromPersisted) {
+        boolean removed = mJobSet.remove(jobStatus);
+        if (!removed) {
+            if (DEBUG) {
+                Slog.d(TAG, "Couldn't remove job: didn't exist: " + jobStatus);
+            }
+            return false;
+        }
+        if (removeFromPersisted && jobStatus.isPersisted()) {
+            maybeWriteStatusToDiskAsync();
+        }
+        return removed;
+    }
+
+    /**
+     * Remove the jobs of users not specified in the whitelist.
+     * @param whitelist Array of User IDs whose jobs are not to be removed.
+     */
+    public void removeJobsOfNonUsers(int[] whitelist) {
+        mJobSet.removeJobsOfNonUsers(whitelist);
+    }
+
+    @VisibleForTesting
+    public void clear() {
+        mJobSet.clear();
+        maybeWriteStatusToDiskAsync();
+    }
+
+    /**
+     * @param userHandle User for whom we are querying the list of jobs.
+     * @return A list of all the jobs scheduled for the provided user. Never null.
+     */
+    public List<JobStatus> getJobsByUser(int userHandle) {
+        return mJobSet.getJobsByUser(userHandle);
+    }
+
+    /**
+     * @param uid Uid of the requesting app.
+     * @return All JobStatus objects for a given uid from the master list. Never null.
+     */
+    public List<JobStatus> getJobsByUid(int uid) {
+        return mJobSet.getJobsByUid(uid);
+    }
+
+    /**
+     * @param uid Uid of the requesting app.
+     * @param jobId Job id, specified at schedule-time.
+     * @return the JobStatus that matches the provided uId and jobId, or null if none found.
+     */
+    public JobStatus getJobByUidAndJobId(int uid, int jobId) {
+        return mJobSet.get(uid, jobId);
+    }
+
+    /**
+     * Iterate over the set of all jobs, invoking the supplied functor on each.  This is for
+     * customers who need to examine each job; we'd much rather not have to generate
+     * transient unified collections for them to iterate over and then discard, or creating
+     * iterators every time a client needs to perform a sweep.
+     */
+    public void forEachJob(Consumer<JobStatus> functor) {
+        mJobSet.forEachJob(null, functor);
+    }
+
+    public void forEachJob(@Nullable Predicate<JobStatus> filterPredicate,
+            Consumer<JobStatus> functor) {
+        mJobSet.forEachJob(filterPredicate, functor);
+    }
+
+    public void forEachJob(int uid, Consumer<JobStatus> functor) {
+        mJobSet.forEachJob(uid, functor);
+    }
+
+    public void forEachJobForSourceUid(int sourceUid, Consumer<JobStatus> functor) {
+        mJobSet.forEachJobForSourceUid(sourceUid, functor);
+    }
+
+    /** Version of the db schema. */
+    private static final int JOBS_FILE_VERSION = 0;
+    /** Tag corresponds to constraints this job needs. */
+    private static final String XML_TAG_PARAMS_CONSTRAINTS = "constraints";
+    /** Tag corresponds to execution parameters. */
+    private static final String XML_TAG_PERIODIC = "periodic";
+    private static final String XML_TAG_ONEOFF = "one-off";
+    private static final String XML_TAG_EXTRAS = "extras";
+
+    /**
+     * Every time the state changes we write all the jobs in one swath, instead of trying to
+     * track incremental changes.
+     */
+    private void maybeWriteStatusToDiskAsync() {
+        synchronized (mWriteScheduleLock) {
+            if (!mWriteScheduled) {
+                if (DEBUG) {
+                    Slog.v(TAG, "Scheduling persist of jobs to disk.");
+                }
+                mIoHandler.postDelayed(mWriteRunnable, JOB_PERSIST_DELAY);
+                mWriteScheduled = mWriteInProgress = true;
+            }
+        }
+    }
+
+    @VisibleForTesting
+    public void readJobMapFromDisk(JobSet jobSet, boolean rtcGood) {
+        new ReadJobMapFromDiskRunnable(jobSet, rtcGood).run();
+    }
+
+    /** Write persisted JobStore state to disk synchronously. Should only be used for testing. */
+    @VisibleForTesting
+    public void writeStatusToDiskForTesting() {
+        synchronized (mWriteScheduleLock) {
+            if (mWriteScheduled) {
+                throw new IllegalStateException("An asynchronous write is already scheduled.");
+            }
+
+            mWriteScheduled = mWriteInProgress = true;
+            mWriteRunnable.run();
+        }
+    }
+
+    /**
+     * Wait for any pending write to the persistent store to clear
+     * @param maxWaitMillis Maximum time from present to wait
+     * @return {@code true} if I/O cleared as expected, {@code false} if the wait
+     *     timed out before the pending write completed.
+     */
+    @VisibleForTesting
+    public boolean waitForWriteToCompleteForTesting(long maxWaitMillis) {
+        final long start = SystemClock.uptimeMillis();
+        final long end = start + maxWaitMillis;
+        synchronized (mWriteScheduleLock) {
+            while (mWriteInProgress) {
+                final long now = SystemClock.uptimeMillis();
+                if (now >= end) {
+                    // still not done and we've hit the end; failure
+                    return false;
+                }
+                try {
+                    mWriteScheduleLock.wait(now - start + maxWaitMillis);
+                } catch (InterruptedException e) {
+                    // Spurious; keep waiting
+                    break;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Runnable that writes {@link #mJobSet} out to xml.
+     * NOTE: This Runnable locks on mLock
+     */
+    private final Runnable mWriteRunnable = new Runnable() {
+        @Override
+        public void run() {
+            final long startElapsed = sElapsedRealtimeClock.millis();
+            final List<JobStatus> storeCopy = new ArrayList<JobStatus>();
+            // Intentionally allow new scheduling of a write operation *before* we clone
+            // the job set.  If we reset it to false after cloning, there's a window in
+            // which no new write will be scheduled but mLock is not held, i.e. a new
+            // job might appear and fail to be recognized as needing a persist.  The
+            // potential cost is one redundant write of an identical set of jobs in the
+            // rare case of that specific race, but by doing it this way we avoid quite
+            // a bit of lock contention.
+            synchronized (mWriteScheduleLock) {
+                mWriteScheduled = false;
+            }
+            synchronized (mLock) {
+                // Clone the jobs so we can release the lock before writing.
+                mJobSet.forEachJob(null, (job) -> {
+                    if (job.isPersisted()) {
+                        storeCopy.add(new JobStatus(job));
+                    }
+                });
+            }
+            writeJobsMapImpl(storeCopy);
+            if (DEBUG) {
+                Slog.v(TAG, "Finished writing, took " + (sElapsedRealtimeClock.millis()
+                        - startElapsed) + "ms");
+            }
+            synchronized (mWriteScheduleLock) {
+                mWriteInProgress = false;
+                mWriteScheduleLock.notifyAll();
+            }
+        }
+
+        private void writeJobsMapImpl(List<JobStatus> jobList) {
+            int numJobs = 0;
+            int numSystemJobs = 0;
+            int numSyncJobs = 0;
+            try {
+                final long startTime = SystemClock.uptimeMillis();
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                XmlSerializer out = new FastXmlSerializer();
+                out.setOutput(baos, StandardCharsets.UTF_8.name());
+                out.startDocument(null, true);
+                out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+
+                out.startTag(null, "job-info");
+                out.attribute(null, "version", Integer.toString(JOBS_FILE_VERSION));
+                for (int i=0; i<jobList.size(); i++) {
+                    JobStatus jobStatus = jobList.get(i);
+                    if (DEBUG) {
+                        Slog.d(TAG, "Saving job " + jobStatus.getJobId());
+                    }
+                    out.startTag(null, "job");
+                    addAttributesToJobTag(out, jobStatus);
+                    writeConstraintsToXml(out, jobStatus);
+                    writeExecutionCriteriaToXml(out, jobStatus);
+                    writeBundleToXml(jobStatus.getJob().getExtras(), out);
+                    out.endTag(null, "job");
+
+                    numJobs++;
+                    if (jobStatus.getUid() == Process.SYSTEM_UID) {
+                        numSystemJobs++;
+                        if (isSyncJob(jobStatus)) {
+                            numSyncJobs++;
+                        }
+                    }
+                }
+                out.endTag(null, "job-info");
+                out.endDocument();
+
+                // Write out to disk in one fell swoop.
+                FileOutputStream fos = mJobsFile.startWrite(startTime);
+                fos.write(baos.toByteArray());
+                mJobsFile.finishWrite(fos);
+            } catch (IOException e) {
+                if (DEBUG) {
+                    Slog.v(TAG, "Error writing out job data.", e);
+                }
+            } catch (XmlPullParserException e) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Error persisting bundle.", e);
+                }
+            } finally {
+                mPersistInfo.countAllJobsSaved = numJobs;
+                mPersistInfo.countSystemServerJobsSaved = numSystemJobs;
+                mPersistInfo.countSystemSyncManagerJobsSaved = numSyncJobs;
+            }
+        }
+
+        /** Write out a tag with data comprising the required fields and priority of this job and
+         * its client.
+         */
+        private void addAttributesToJobTag(XmlSerializer out, JobStatus jobStatus)
+                throws IOException {
+            out.attribute(null, "jobid", Integer.toString(jobStatus.getJobId()));
+            out.attribute(null, "package", jobStatus.getServiceComponent().getPackageName());
+            out.attribute(null, "class", jobStatus.getServiceComponent().getClassName());
+            if (jobStatus.getSourcePackageName() != null) {
+                out.attribute(null, "sourcePackageName", jobStatus.getSourcePackageName());
+            }
+            if (jobStatus.getSourceTag() != null) {
+                out.attribute(null, "sourceTag", jobStatus.getSourceTag());
+            }
+            out.attribute(null, "sourceUserId", String.valueOf(jobStatus.getSourceUserId()));
+            out.attribute(null, "uid", Integer.toString(jobStatus.getUid()));
+            out.attribute(null, "priority", String.valueOf(jobStatus.getPriority()));
+            out.attribute(null, "flags", String.valueOf(jobStatus.getFlags()));
+            if (jobStatus.getInternalFlags() != 0) {
+                out.attribute(null, "internalFlags", String.valueOf(jobStatus.getInternalFlags()));
+            }
+
+            out.attribute(null, "lastSuccessfulRunTime",
+                    String.valueOf(jobStatus.getLastSuccessfulRunTime()));
+            out.attribute(null, "lastFailedRunTime",
+                    String.valueOf(jobStatus.getLastFailedRunTime()));
+        }
+
+        private void writeBundleToXml(PersistableBundle extras, XmlSerializer out)
+                throws IOException, XmlPullParserException {
+            out.startTag(null, XML_TAG_EXTRAS);
+            PersistableBundle extrasCopy = deepCopyBundle(extras, 10);
+            extrasCopy.saveToXml(out);
+            out.endTag(null, XML_TAG_EXTRAS);
+        }
+
+        private PersistableBundle deepCopyBundle(PersistableBundle bundle, int maxDepth) {
+            if (maxDepth <= 0) {
+                return null;
+            }
+            PersistableBundle copy = (PersistableBundle) bundle.clone();
+            Set<String> keySet = bundle.keySet();
+            for (String key: keySet) {
+                Object o = copy.get(key);
+                if (o instanceof PersistableBundle) {
+                    PersistableBundle bCopy = deepCopyBundle((PersistableBundle) o, maxDepth-1);
+                    copy.putPersistableBundle(key, bCopy);
+                }
+            }
+            return copy;
+        }
+
+        /**
+         * Write out a tag with data identifying this job's constraints. If the constraint isn't here
+         * it doesn't apply.
+         */
+        private void writeConstraintsToXml(XmlSerializer out, JobStatus jobStatus) throws IOException {
+            out.startTag(null, XML_TAG_PARAMS_CONSTRAINTS);
+            if (jobStatus.hasConnectivityConstraint()) {
+                final NetworkRequest network = jobStatus.getJob().getRequiredNetwork();
+                out.attribute(null, "net-capabilities", Long.toString(
+                        BitUtils.packBits(network.networkCapabilities.getCapabilities())));
+                out.attribute(null, "net-unwanted-capabilities", Long.toString(
+                        BitUtils.packBits(network.networkCapabilities.getUnwantedCapabilities())));
+
+                out.attribute(null, "net-transport-types", Long.toString(
+                        BitUtils.packBits(network.networkCapabilities.getTransportTypes())));
+            }
+            if (jobStatus.hasIdleConstraint()) {
+                out.attribute(null, "idle", Boolean.toString(true));
+            }
+            if (jobStatus.hasChargingConstraint()) {
+                out.attribute(null, "charging", Boolean.toString(true));
+            }
+            if (jobStatus.hasBatteryNotLowConstraint()) {
+                out.attribute(null, "battery-not-low", Boolean.toString(true));
+            }
+            if (jobStatus.hasStorageNotLowConstraint()) {
+                out.attribute(null, "storage-not-low", Boolean.toString(true));
+            }
+            out.endTag(null, XML_TAG_PARAMS_CONSTRAINTS);
+        }
+
+        private void writeExecutionCriteriaToXml(XmlSerializer out, JobStatus jobStatus)
+                throws IOException {
+            final JobInfo job = jobStatus.getJob();
+            if (jobStatus.getJob().isPeriodic()) {
+                out.startTag(null, XML_TAG_PERIODIC);
+                out.attribute(null, "period", Long.toString(job.getIntervalMillis()));
+                out.attribute(null, "flex", Long.toString(job.getFlexMillis()));
+            } else {
+                out.startTag(null, XML_TAG_ONEOFF);
+            }
+
+            // If we still have the persisted times, we need to record those directly because
+            // we haven't yet been able to calculate the usual elapsed-timebase bounds
+            // correctly due to wall-clock uncertainty.
+            Pair <Long, Long> utcJobTimes = jobStatus.getPersistedUtcTimes();
+            if (DEBUG && utcJobTimes != null) {
+                Slog.i(TAG, "storing original UTC timestamps for " + jobStatus);
+            }
+
+            final long nowRTC = sSystemClock.millis();
+            final long nowElapsed = sElapsedRealtimeClock.millis();
+            if (jobStatus.hasDeadlineConstraint()) {
+                // Wall clock deadline.
+                final long deadlineWallclock = (utcJobTimes == null)
+                        ? nowRTC + (jobStatus.getLatestRunTimeElapsed() - nowElapsed)
+                        : utcJobTimes.second;
+                out.attribute(null, "deadline", Long.toString(deadlineWallclock));
+            }
+            if (jobStatus.hasTimingDelayConstraint()) {
+                final long delayWallclock = (utcJobTimes == null)
+                        ? nowRTC + (jobStatus.getEarliestRunTime() - nowElapsed)
+                        : utcJobTimes.first;
+                out.attribute(null, "delay", Long.toString(delayWallclock));
+            }
+
+            // Only write out back-off policy if it differs from the default.
+            // This also helps the case where the job is idle -> these aren't allowed to specify
+            // back-off.
+            if (jobStatus.getJob().getInitialBackoffMillis() != JobInfo.DEFAULT_INITIAL_BACKOFF_MILLIS
+                    || jobStatus.getJob().getBackoffPolicy() != JobInfo.DEFAULT_BACKOFF_POLICY) {
+                out.attribute(null, "backoff-policy", Integer.toString(job.getBackoffPolicy()));
+                out.attribute(null, "initial-backoff", Long.toString(job.getInitialBackoffMillis()));
+            }
+            if (job.isPeriodic()) {
+                out.endTag(null, XML_TAG_PERIODIC);
+            } else {
+                out.endTag(null, XML_TAG_ONEOFF);
+            }
+        }
+    };
+
+    /**
+     * Translate the supplied RTC times to the elapsed timebase, with clamping appropriate
+     * to interpreting them as a job's delay + deadline times for alarm-setting purposes.
+     * @param rtcTimes a Pair<Long, Long> in which {@code first} is the "delay" earliest
+     *     allowable runtime for the job, and {@code second} is the "deadline" time at which
+     *     the job becomes overdue.
+     */
+    private static Pair<Long, Long> convertRtcBoundsToElapsed(Pair<Long, Long> rtcTimes,
+            long nowElapsed) {
+        final long nowWallclock = sSystemClock.millis();
+        final long earliest = (rtcTimes.first > JobStatus.NO_EARLIEST_RUNTIME)
+                ? nowElapsed + Math.max(rtcTimes.first - nowWallclock, 0)
+                : JobStatus.NO_EARLIEST_RUNTIME;
+        final long latest = (rtcTimes.second < JobStatus.NO_LATEST_RUNTIME)
+                ? nowElapsed + Math.max(rtcTimes.second - nowWallclock, 0)
+                : JobStatus.NO_LATEST_RUNTIME;
+        return Pair.create(earliest, latest);
+    }
+
+    private static boolean isSyncJob(JobStatus status) {
+        return com.android.server.content.SyncJobService.class.getName()
+                .equals(status.getServiceComponent().getClassName());
+    }
+
+    /**
+     * Runnable that reads list of persisted job from xml. This is run once at start up, so doesn't
+     * need to go through {@link JobStore#add(com.android.server.job.controllers.JobStatus)}.
+     */
+    private final class ReadJobMapFromDiskRunnable implements Runnable {
+        private final JobSet jobSet;
+        private final boolean rtcGood;
+
+        /**
+         * @param jobSet Reference to the (empty) set of JobStatus objects that back the JobStore,
+         *               so that after disk read we can populate it directly.
+         */
+        ReadJobMapFromDiskRunnable(JobSet jobSet, boolean rtcIsGood) {
+            this.jobSet = jobSet;
+            this.rtcGood = rtcIsGood;
+        }
+
+        @Override
+        public void run() {
+            int numJobs = 0;
+            int numSystemJobs = 0;
+            int numSyncJobs = 0;
+            try {
+                List<JobStatus> jobs;
+                FileInputStream fis = mJobsFile.openRead();
+                synchronized (mLock) {
+                    jobs = readJobMapImpl(fis, rtcGood);
+                    if (jobs != null) {
+                        long now = sElapsedRealtimeClock.millis();
+                        IActivityManager am = ActivityManager.getService();
+                        for (int i=0; i<jobs.size(); i++) {
+                            JobStatus js = jobs.get(i);
+                            js.prepareLocked(am);
+                            js.enqueueTime = now;
+                            this.jobSet.add(js);
+
+                            numJobs++;
+                            if (js.getUid() == Process.SYSTEM_UID) {
+                                numSystemJobs++;
+                                if (isSyncJob(js)) {
+                                    numSyncJobs++;
+                                }
+                            }
+                        }
+                    }
+                }
+                fis.close();
+            } catch (FileNotFoundException e) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Could not find jobs file, probably there was nothing to load.");
+                }
+            } catch (XmlPullParserException | IOException e) {
+                Slog.wtf(TAG, "Error jobstore xml.", e);
+            } finally {
+                if (mPersistInfo.countAllJobsLoaded < 0) { // Only set them once.
+                    mPersistInfo.countAllJobsLoaded = numJobs;
+                    mPersistInfo.countSystemServerJobsLoaded = numSystemJobs;
+                    mPersistInfo.countSystemSyncManagerJobsLoaded = numSyncJobs;
+                }
+            }
+            Slog.i(TAG, "Read " + numJobs + " jobs");
+        }
+
+        private List<JobStatus> readJobMapImpl(FileInputStream fis, boolean rtcIsGood)
+                throws XmlPullParserException, IOException {
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(fis, StandardCharsets.UTF_8.name());
+
+            int eventType = parser.getEventType();
+            while (eventType != XmlPullParser.START_TAG &&
+                    eventType != XmlPullParser.END_DOCUMENT) {
+                eventType = parser.next();
+                Slog.d(TAG, "Start tag: " + parser.getName());
+            }
+            if (eventType == XmlPullParser.END_DOCUMENT) {
+                if (DEBUG) {
+                    Slog.d(TAG, "No persisted jobs.");
+                }
+                return null;
+            }
+
+            String tagName = parser.getName();
+            if ("job-info".equals(tagName)) {
+                final List<JobStatus> jobs = new ArrayList<JobStatus>();
+                // Read in version info.
+                try {
+                    int version = Integer.parseInt(parser.getAttributeValue(null, "version"));
+                    if (version != JOBS_FILE_VERSION) {
+                        Slog.d(TAG, "Invalid version number, aborting jobs file read.");
+                        return null;
+                    }
+                } catch (NumberFormatException e) {
+                    Slog.e(TAG, "Invalid version number, aborting jobs file read.");
+                    return null;
+                }
+                eventType = parser.next();
+                do {
+                    // Read each <job/>
+                    if (eventType == XmlPullParser.START_TAG) {
+                        tagName = parser.getName();
+                        // Start reading job.
+                        if ("job".equals(tagName)) {
+                            JobStatus persistedJob = restoreJobFromXml(rtcIsGood, parser);
+                            if (persistedJob != null) {
+                                if (DEBUG) {
+                                    Slog.d(TAG, "Read out " + persistedJob);
+                                }
+                                jobs.add(persistedJob);
+                            } else {
+                                Slog.d(TAG, "Error reading job from file.");
+                            }
+                        }
+                    }
+                    eventType = parser.next();
+                } while (eventType != XmlPullParser.END_DOCUMENT);
+                return jobs;
+            }
+            return null;
+        }
+
+        /**
+         * @param parser Xml parser at the beginning of a "<job/>" tag. The next "parser.next()" call
+         *               will take the parser into the body of the job tag.
+         * @return Newly instantiated job holding all the information we just read out of the xml tag.
+         */
+        private JobStatus restoreJobFromXml(boolean rtcIsGood, XmlPullParser parser)
+                throws XmlPullParserException, IOException {
+            JobInfo.Builder jobBuilder;
+            int uid, sourceUserId;
+            long lastSuccessfulRunTime;
+            long lastFailedRunTime;
+            int internalFlags = 0;
+
+            // Read out job identifier attributes and priority.
+            try {
+                jobBuilder = buildBuilderFromXml(parser);
+                jobBuilder.setPersisted(true);
+                uid = Integer.parseInt(parser.getAttributeValue(null, "uid"));
+
+                String val = parser.getAttributeValue(null, "priority");
+                if (val != null) {
+                    jobBuilder.setPriority(Integer.parseInt(val));
+                }
+                val = parser.getAttributeValue(null, "flags");
+                if (val != null) {
+                    jobBuilder.setFlags(Integer.parseInt(val));
+                }
+                val = parser.getAttributeValue(null, "internalFlags");
+                if (val != null) {
+                    internalFlags = Integer.parseInt(val);
+                }
+                val = parser.getAttributeValue(null, "sourceUserId");
+                sourceUserId = val == null ? -1 : Integer.parseInt(val);
+
+                val = parser.getAttributeValue(null, "lastSuccessfulRunTime");
+                lastSuccessfulRunTime = val == null ? 0 : Long.parseLong(val);
+
+                val = parser.getAttributeValue(null, "lastFailedRunTime");
+                lastFailedRunTime = val == null ? 0 : Long.parseLong(val);
+            } catch (NumberFormatException e) {
+                Slog.e(TAG, "Error parsing job's required fields, skipping");
+                return null;
+            }
+
+            String sourcePackageName = parser.getAttributeValue(null, "sourcePackageName");
+            final String sourceTag = parser.getAttributeValue(null, "sourceTag");
+
+            int eventType;
+            // Read out constraints tag.
+            do {
+                eventType = parser.next();
+            } while (eventType == XmlPullParser.TEXT);  // Push through to next START_TAG.
+
+            if (!(eventType == XmlPullParser.START_TAG &&
+                    XML_TAG_PARAMS_CONSTRAINTS.equals(parser.getName()))) {
+                // Expecting a <constraints> start tag.
+                return null;
+            }
+            try {
+                buildConstraintsFromXml(jobBuilder, parser);
+            } catch (NumberFormatException e) {
+                Slog.d(TAG, "Error reading constraints, skipping.");
+                return null;
+            }
+            parser.next(); // Consume </constraints>
+
+            // Read out execution parameters tag.
+            do {
+                eventType = parser.next();
+            } while (eventType == XmlPullParser.TEXT);
+            if (eventType != XmlPullParser.START_TAG) {
+                return null;
+            }
+
+            // Tuple of (earliest runtime, latest runtime) in UTC.
+            final Pair<Long, Long> rtcRuntimes;
+            try {
+                rtcRuntimes = buildRtcExecutionTimesFromXml(parser);
+            } catch (NumberFormatException e) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Error parsing execution time parameters, skipping.");
+                }
+                return null;
+            }
+
+            final long elapsedNow = sElapsedRealtimeClock.millis();
+            Pair<Long, Long> elapsedRuntimes = convertRtcBoundsToElapsed(rtcRuntimes, elapsedNow);
+
+            if (XML_TAG_PERIODIC.equals(parser.getName())) {
+                try {
+                    String val = parser.getAttributeValue(null, "period");
+                    final long periodMillis = Long.parseLong(val);
+                    val = parser.getAttributeValue(null, "flex");
+                    final long flexMillis = (val != null) ? Long.valueOf(val) : periodMillis;
+                    jobBuilder.setPeriodic(periodMillis, flexMillis);
+                    // As a sanity check, cap the recreated run time to be no later than flex+period
+                    // from now. This is the latest the periodic could be pushed out. This could
+                    // happen if the periodic ran early (at flex time before period), and then the
+                    // device rebooted.
+                    if (elapsedRuntimes.second > elapsedNow + periodMillis + flexMillis) {
+                        final long clampedLateRuntimeElapsed = elapsedNow + flexMillis
+                                + periodMillis;
+                        final long clampedEarlyRuntimeElapsed = clampedLateRuntimeElapsed
+                                - flexMillis;
+                        Slog.w(TAG,
+                                String.format("Periodic job for uid='%d' persisted run-time is" +
+                                                " too big [%s, %s]. Clamping to [%s,%s]",
+                                        uid,
+                                        DateUtils.formatElapsedTime(elapsedRuntimes.first / 1000),
+                                        DateUtils.formatElapsedTime(elapsedRuntimes.second / 1000),
+                                        DateUtils.formatElapsedTime(
+                                                clampedEarlyRuntimeElapsed / 1000),
+                                        DateUtils.formatElapsedTime(
+                                                clampedLateRuntimeElapsed / 1000))
+                        );
+                        elapsedRuntimes =
+                                Pair.create(clampedEarlyRuntimeElapsed, clampedLateRuntimeElapsed);
+                    }
+                } catch (NumberFormatException e) {
+                    Slog.d(TAG, "Error reading periodic execution criteria, skipping.");
+                    return null;
+                }
+            } else if (XML_TAG_ONEOFF.equals(parser.getName())) {
+                try {
+                    if (elapsedRuntimes.first != JobStatus.NO_EARLIEST_RUNTIME) {
+                        jobBuilder.setMinimumLatency(elapsedRuntimes.first - elapsedNow);
+                    }
+                    if (elapsedRuntimes.second != JobStatus.NO_LATEST_RUNTIME) {
+                        jobBuilder.setOverrideDeadline(
+                                elapsedRuntimes.second - elapsedNow);
+                    }
+                } catch (NumberFormatException e) {
+                    Slog.d(TAG, "Error reading job execution criteria, skipping.");
+                    return null;
+                }
+            } else {
+                if (DEBUG) {
+                    Slog.d(TAG, "Invalid parameter tag, skipping - " + parser.getName());
+                }
+                // Expecting a parameters start tag.
+                return null;
+            }
+            maybeBuildBackoffPolicyFromXml(jobBuilder, parser);
+
+            parser.nextTag(); // Consume parameters end tag.
+
+            // Read out extras Bundle.
+            do {
+                eventType = parser.next();
+            } while (eventType == XmlPullParser.TEXT);
+            if (!(eventType == XmlPullParser.START_TAG
+                    && XML_TAG_EXTRAS.equals(parser.getName()))) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Error reading extras, skipping.");
+                }
+                return null;
+            }
+
+            PersistableBundle extras = PersistableBundle.restoreFromXml(parser);
+            jobBuilder.setExtras(extras);
+            parser.nextTag(); // Consume </extras>
+
+            final JobInfo builtJob;
+            try {
+                builtJob = jobBuilder.build();
+            } catch (Exception e) {
+                Slog.w(TAG, "Unable to build job from XML, ignoring: "
+                        + jobBuilder.summarize());
+                return null;
+            }
+
+            // Migrate sync jobs forward from earlier, incomplete representation
+            if ("android".equals(sourcePackageName)
+                    && extras != null
+                    && extras.getBoolean("SyncManagerJob", false)) {
+                sourcePackageName = extras.getString("owningPackage", sourcePackageName);
+                if (DEBUG) {
+                    Slog.i(TAG, "Fixing up sync job source package name from 'android' to '"
+                            + sourcePackageName + "'");
+                }
+            }
+
+            // And now we're done
+            JobSchedulerInternal service = LocalServices.getService(JobSchedulerInternal.class);
+            final int appBucket = JobSchedulerService.standbyBucketForPackage(sourcePackageName,
+                    sourceUserId, elapsedNow);
+            long currentHeartbeat = service != null ? service.currentHeartbeat() : 0;
+            JobStatus js = new JobStatus(
+                    jobBuilder.build(), uid, sourcePackageName, sourceUserId,
+                    appBucket, currentHeartbeat, sourceTag,
+                    elapsedRuntimes.first, elapsedRuntimes.second,
+                    lastSuccessfulRunTime, lastFailedRunTime,
+                    (rtcIsGood) ? null : rtcRuntimes, internalFlags);
+            return js;
+        }
+
+        private JobInfo.Builder buildBuilderFromXml(XmlPullParser parser) throws NumberFormatException {
+            // Pull out required fields from <job> attributes.
+            int jobId = Integer.parseInt(parser.getAttributeValue(null, "jobid"));
+            String packageName = parser.getAttributeValue(null, "package");
+            String className = parser.getAttributeValue(null, "class");
+            ComponentName cname = new ComponentName(packageName, className);
+
+            return new JobInfo.Builder(jobId, cname);
+        }
+
+        private void buildConstraintsFromXml(JobInfo.Builder jobBuilder, XmlPullParser parser) {
+            String val;
+
+            final String netCapabilities = parser.getAttributeValue(null, "net-capabilities");
+            final String netUnwantedCapabilities = parser.getAttributeValue(
+                    null, "net-unwanted-capabilities");
+            final String netTransportTypes = parser.getAttributeValue(null, "net-transport-types");
+            if (netCapabilities != null && netTransportTypes != null) {
+                final NetworkRequest request = new NetworkRequest.Builder().build();
+                final long unwantedCapabilities = netUnwantedCapabilities != null
+                        ? Long.parseLong(netUnwantedCapabilities)
+                        : BitUtils.packBits(request.networkCapabilities.getUnwantedCapabilities());
+
+                // We're okay throwing NFE here; caught by caller
+                request.networkCapabilities.setCapabilities(
+                        BitUtils.unpackBits(Long.parseLong(netCapabilities)),
+                        BitUtils.unpackBits(unwantedCapabilities));
+                request.networkCapabilities.setTransportTypes(
+                        BitUtils.unpackBits(Long.parseLong(netTransportTypes)));
+                jobBuilder.setRequiredNetwork(request);
+            } else {
+                // Read legacy values
+                val = parser.getAttributeValue(null, "connectivity");
+                if (val != null) {
+                    jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
+                }
+                val = parser.getAttributeValue(null, "metered");
+                if (val != null) {
+                    jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_METERED);
+                }
+                val = parser.getAttributeValue(null, "unmetered");
+                if (val != null) {
+                    jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
+                }
+                val = parser.getAttributeValue(null, "not-roaming");
+                if (val != null) {
+                    jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NOT_ROAMING);
+                }
+            }
+
+            val = parser.getAttributeValue(null, "idle");
+            if (val != null) {
+                jobBuilder.setRequiresDeviceIdle(true);
+            }
+            val = parser.getAttributeValue(null, "charging");
+            if (val != null) {
+                jobBuilder.setRequiresCharging(true);
+            }
+            val = parser.getAttributeValue(null, "battery-not-low");
+            if (val != null) {
+                jobBuilder.setRequiresBatteryNotLow(true);
+            }
+            val = parser.getAttributeValue(null, "storage-not-low");
+            if (val != null) {
+                jobBuilder.setRequiresStorageNotLow(true);
+            }
+        }
+
+        /**
+         * Builds the back-off policy out of the params tag. These attributes may not exist, depending
+         * on whether the back-off was set when the job was first scheduled.
+         */
+        private void maybeBuildBackoffPolicyFromXml(JobInfo.Builder jobBuilder, XmlPullParser parser) {
+            String val = parser.getAttributeValue(null, "initial-backoff");
+            if (val != null) {
+                long initialBackoff = Long.parseLong(val);
+                val = parser.getAttributeValue(null, "backoff-policy");
+                int backoffPolicy = Integer.parseInt(val);  // Will throw NFE which we catch higher up.
+                jobBuilder.setBackoffCriteria(initialBackoff, backoffPolicy);
+            }
+        }
+
+        /**
+         * Extract a job's earliest/latest run time data from XML.  These are returned in
+         * unadjusted UTC wall clock time, because we do not yet know whether the system
+         * clock is reliable for purposes of calculating deltas from 'now'.
+         *
+         * @param parser
+         * @return A Pair of timestamps in UTC wall-clock time.  The first is the earliest
+         *     time at which the job is to become runnable, and the second is the deadline at
+         *     which it becomes overdue to execute.
+         * @throws NumberFormatException
+         */
+        private Pair<Long, Long> buildRtcExecutionTimesFromXml(XmlPullParser parser)
+                throws NumberFormatException {
+            String val;
+            // Pull out execution time data.
+            val = parser.getAttributeValue(null, "delay");
+            final long earliestRunTimeRtc = (val != null)
+                    ? Long.parseLong(val)
+                    : JobStatus.NO_EARLIEST_RUNTIME;
+            val = parser.getAttributeValue(null, "deadline");
+            final long latestRunTimeRtc = (val != null)
+                    ? Long.parseLong(val)
+                    : JobStatus.NO_LATEST_RUNTIME;
+            return Pair.create(earliestRunTimeRtc, latestRunTimeRtc);
+        }
+    }
+
+    /** Set of all tracked jobs. */
+    @VisibleForTesting
+    public static final class JobSet {
+        @VisibleForTesting // Key is the getUid() originator of the jobs in each sheaf
+        final SparseArray<ArraySet<JobStatus>> mJobs;
+
+        @VisibleForTesting // Same data but with the key as getSourceUid() of the jobs in each sheaf
+        final SparseArray<ArraySet<JobStatus>> mJobsPerSourceUid;
+
+        public JobSet() {
+            mJobs = new SparseArray<ArraySet<JobStatus>>();
+            mJobsPerSourceUid = new SparseArray<>();
+        }
+
+        public List<JobStatus> getJobsByUid(int uid) {
+            ArrayList<JobStatus> matchingJobs = new ArrayList<JobStatus>();
+            ArraySet<JobStatus> jobs = mJobs.get(uid);
+            if (jobs != null) {
+                matchingJobs.addAll(jobs);
+            }
+            return matchingJobs;
+        }
+
+        // By user, not by uid, so we need to traverse by key and check
+        public List<JobStatus> getJobsByUser(int userId) {
+            final ArrayList<JobStatus> result = new ArrayList<JobStatus>();
+            for (int i = mJobsPerSourceUid.size() - 1; i >= 0; i--) {
+                if (UserHandle.getUserId(mJobsPerSourceUid.keyAt(i)) == userId) {
+                    final ArraySet<JobStatus> jobs = mJobsPerSourceUid.valueAt(i);
+                    if (jobs != null) {
+                        result.addAll(jobs);
+                    }
+                }
+            }
+            return result;
+        }
+
+        public boolean add(JobStatus job) {
+            final int uid = job.getUid();
+            final int sourceUid = job.getSourceUid();
+            ArraySet<JobStatus> jobs = mJobs.get(uid);
+            if (jobs == null) {
+                jobs = new ArraySet<JobStatus>();
+                mJobs.put(uid, jobs);
+            }
+            ArraySet<JobStatus> jobsForSourceUid = mJobsPerSourceUid.get(sourceUid);
+            if (jobsForSourceUid == null) {
+                jobsForSourceUid = new ArraySet<>();
+                mJobsPerSourceUid.put(sourceUid, jobsForSourceUid);
+            }
+            final boolean added = jobs.add(job);
+            final boolean addedInSource = jobsForSourceUid.add(job);
+            if (added != addedInSource) {
+                Slog.wtf(TAG, "mJobs and mJobsPerSourceUid mismatch; caller= " + added
+                        + " source= " + addedInSource);
+            }
+            return added || addedInSource;
+        }
+
+        public boolean remove(JobStatus job) {
+            final int uid = job.getUid();
+            final ArraySet<JobStatus> jobs = mJobs.get(uid);
+            final int sourceUid = job.getSourceUid();
+            final ArraySet<JobStatus> jobsForSourceUid = mJobsPerSourceUid.get(sourceUid);
+            final boolean didRemove = jobs != null && jobs.remove(job);
+            final boolean sourceRemove = jobsForSourceUid != null && jobsForSourceUid.remove(job);
+            if (didRemove != sourceRemove) {
+                Slog.wtf(TAG, "Job presence mismatch; caller=" + didRemove
+                        + " source=" + sourceRemove);
+            }
+            if (didRemove || sourceRemove) {
+                // no more jobs for this uid?  let the now-empty set objects be GC'd.
+                if (jobs != null && jobs.size() == 0) {
+                    mJobs.remove(uid);
+                }
+                if (jobsForSourceUid != null && jobsForSourceUid.size() == 0) {
+                    mJobsPerSourceUid.remove(sourceUid);
+                }
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * Removes the jobs of all users not specified by the whitelist of user ids.
+         * This will remove jobs scheduled *by* non-existent users as well as jobs scheduled *for*
+         * non-existent users
+         */
+        public void removeJobsOfNonUsers(final int[] whitelist) {
+            final Predicate<JobStatus> noSourceUser =
+                    job -> !ArrayUtils.contains(whitelist, job.getSourceUserId());
+            final Predicate<JobStatus> noCallingUser =
+                    job -> !ArrayUtils.contains(whitelist, job.getUserId());
+            removeAll(noSourceUser.or(noCallingUser));
+        }
+
+        private void removeAll(Predicate<JobStatus> predicate) {
+            for (int jobSetIndex = mJobs.size() - 1; jobSetIndex >= 0; jobSetIndex--) {
+                final ArraySet<JobStatus> jobs = mJobs.valueAt(jobSetIndex);
+                for (int jobIndex = jobs.size() - 1; jobIndex >= 0; jobIndex--) {
+                    if (predicate.test(jobs.valueAt(jobIndex))) {
+                        jobs.removeAt(jobIndex);
+                    }
+                }
+                if (jobs.size() == 0) {
+                    mJobs.removeAt(jobSetIndex);
+                }
+            }
+            for (int jobSetIndex = mJobsPerSourceUid.size() - 1; jobSetIndex >= 0; jobSetIndex--) {
+                final ArraySet<JobStatus> jobs = mJobsPerSourceUid.valueAt(jobSetIndex);
+                for (int jobIndex = jobs.size() - 1; jobIndex >= 0; jobIndex--) {
+                    if (predicate.test(jobs.valueAt(jobIndex))) {
+                        jobs.removeAt(jobIndex);
+                    }
+                }
+                if (jobs.size() == 0) {
+                    mJobsPerSourceUid.removeAt(jobSetIndex);
+                }
+            }
+        }
+
+        public boolean contains(JobStatus job) {
+            final int uid = job.getUid();
+            ArraySet<JobStatus> jobs = mJobs.get(uid);
+            return jobs != null && jobs.contains(job);
+        }
+
+        public JobStatus get(int uid, int jobId) {
+            ArraySet<JobStatus> jobs = mJobs.get(uid);
+            if (jobs != null) {
+                for (int i = jobs.size() - 1; i >= 0; i--) {
+                    JobStatus job = jobs.valueAt(i);
+                    if (job.getJobId() == jobId) {
+                        return job;
+                    }
+                }
+            }
+            return null;
+        }
+
+        // Inefficient; use only for testing
+        public List<JobStatus> getAllJobs() {
+            ArrayList<JobStatus> allJobs = new ArrayList<JobStatus>(size());
+            for (int i = mJobs.size() - 1; i >= 0; i--) {
+                ArraySet<JobStatus> jobs = mJobs.valueAt(i);
+                if (jobs != null) {
+                    // Use a for loop over the ArraySet, so we don't need to make its
+                    // optional collection class iterator implementation or have to go
+                    // through a temporary array from toArray().
+                    for (int j = jobs.size() - 1; j >= 0; j--) {
+                        allJobs.add(jobs.valueAt(j));
+                    }
+                }
+            }
+            return allJobs;
+        }
+
+        public void clear() {
+            mJobs.clear();
+            mJobsPerSourceUid.clear();
+        }
+
+        public int size() {
+            int total = 0;
+            for (int i = mJobs.size() - 1; i >= 0; i--) {
+                total += mJobs.valueAt(i).size();
+            }
+            return total;
+        }
+
+        // We only want to count the jobs that this uid has scheduled on its own
+        // behalf, not those that the app has scheduled on someone else's behalf.
+        public int countJobsForUid(int uid) {
+            int total = 0;
+            ArraySet<JobStatus> jobs = mJobs.get(uid);
+            if (jobs != null) {
+                for (int i = jobs.size() - 1; i >= 0; i--) {
+                    JobStatus job = jobs.valueAt(i);
+                    if (job.getUid() == job.getSourceUid()) {
+                        total++;
+                    }
+                }
+            }
+            return total;
+        }
+
+        public void forEachJob(@Nullable Predicate<JobStatus> filterPredicate,
+                Consumer<JobStatus> functor) {
+            for (int uidIndex = mJobs.size() - 1; uidIndex >= 0; uidIndex--) {
+                ArraySet<JobStatus> jobs = mJobs.valueAt(uidIndex);
+                if (jobs != null) {
+                    for (int i = jobs.size() - 1; i >= 0; i--) {
+                        final JobStatus jobStatus = jobs.valueAt(i);
+                        if ((filterPredicate == null) || filterPredicate.test(jobStatus)) {
+                            functor.accept(jobStatus);
+                        }
+                    }
+                }
+            }
+        }
+
+        public void forEachJob(int callingUid, Consumer<JobStatus> functor) {
+            ArraySet<JobStatus> jobs = mJobs.get(callingUid);
+            if (jobs != null) {
+                for (int i = jobs.size() - 1; i >= 0; i--) {
+                    functor.accept(jobs.valueAt(i));
+                }
+            }
+        }
+
+        public void forEachJobForSourceUid(int sourceUid, Consumer<JobStatus> functor) {
+            final ArraySet<JobStatus> jobs = mJobsPerSourceUid.get(sourceUid);
+            if (jobs != null) {
+                for (int i = jobs.size() - 1; i >= 0; i--) {
+                    functor.accept(jobs.valueAt(i));
+                }
+            }
+        }
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/StateChangedListener.java b/apex/jobscheduler/service/java/com/android/server/job/StateChangedListener.java
new file mode 100644
index 0000000..87bfc27
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/StateChangedListener.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job;
+
+import com.android.server.job.controllers.JobStatus;
+
+/**
+ * Interface through which a {@link com.android.server.job.controllers.StateController} informs
+ * the {@link com.android.server.job.JobSchedulerService} that there are some tasks potentially
+ * ready to be run.
+ */
+public interface StateChangedListener {
+    /**
+     * Called by the controller to notify the JobManager that it should check on the state of a
+     * task.
+     */
+    public void onControllerStateChanged();
+
+    /**
+     * Called by the controller to notify the JobManager that regardless of the state of the task,
+     * it must be run immediately.
+     * @param jobStatus The state of the task which is to be run immediately. <strong>null
+     *                  indicates to the scheduler that any ready jobs should be flushed.</strong>
+     */
+    public void onRunJobNow(JobStatus jobStatus);
+
+    public void onDeviceIdleStateChanged(boolean deviceIdle);
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
new file mode 100644
index 0000000..b698e5b
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers;
+
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
+import com.android.server.AppStateTracker;
+import com.android.server.AppStateTracker.Listener;
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.JobStore;
+import com.android.server.job.StateControllerProto;
+import com.android.server.job.StateControllerProto.BackgroundJobsController.TrackedJob;
+
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+/**
+ * Tracks the following pieces of JobStatus state:
+ *
+ * - the CONSTRAINT_BACKGROUND_NOT_RESTRICTED general constraint bit, which
+ *    is used to selectively permit battery-saver exempted jobs to run; and
+ *
+ * - the uid-active boolean state expressed by the AppStateTracker.  Jobs in 'active'
+ *    uids are inherently eligible to run jobs regardless of the uid's standby bucket.
+ */
+public final class BackgroundJobsController extends StateController {
+    private static final String TAG = "JobScheduler.Background";
+    private static final boolean DEBUG = JobSchedulerService.DEBUG
+            || Log.isLoggable(TAG, Log.DEBUG);
+
+    // Tri-state about possible "is this uid 'active'?" knowledge
+    static final int UNKNOWN = 0;
+    static final int KNOWN_ACTIVE = 1;
+    static final int KNOWN_INACTIVE = 2;
+
+    private final AppStateTracker mAppStateTracker;
+
+    public BackgroundJobsController(JobSchedulerService service) {
+        super(service);
+
+        mAppStateTracker = Preconditions.checkNotNull(
+                LocalServices.getService(AppStateTracker.class));
+        mAppStateTracker.addListener(mForceAppStandbyListener);
+    }
+
+    @Override
+    public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
+        updateSingleJobRestrictionLocked(jobStatus, UNKNOWN);
+    }
+
+    @Override
+    public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
+            boolean forUpdate) {
+    }
+
+    @Override
+    public void dumpControllerStateLocked(final IndentingPrintWriter pw,
+            final Predicate<JobStatus> predicate) {
+        mAppStateTracker.dump(pw);
+        pw.println();
+
+        mService.getJobStore().forEachJob(predicate, (jobStatus) -> {
+            final int uid = jobStatus.getSourceUid();
+            final String sourcePkg = jobStatus.getSourcePackageName();
+            pw.print("#");
+            jobStatus.printUniqueId(pw);
+            pw.print(" from ");
+            UserHandle.formatUid(pw, uid);
+            pw.print(mAppStateTracker.isUidActive(uid) ? " active" : " idle");
+            if (mAppStateTracker.isUidPowerSaveWhitelisted(uid) ||
+                    mAppStateTracker.isUidTempPowerSaveWhitelisted(uid)) {
+                pw.print(", whitelisted");
+            }
+            pw.print(": ");
+            pw.print(sourcePkg);
+
+            pw.print(" [RUN_ANY_IN_BACKGROUND ");
+            pw.print(mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(uid, sourcePkg)
+                    ? "allowed]" : "disallowed]");
+
+            if ((jobStatus.satisfiedConstraints
+                    & JobStatus.CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0) {
+                pw.println(" RUNNABLE");
+            } else {
+                pw.println(" WAITING");
+            }
+        });
+    }
+
+    @Override
+    public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
+            Predicate<JobStatus> predicate) {
+        final long token = proto.start(fieldId);
+        final long mToken = proto.start(StateControllerProto.BACKGROUND);
+
+        mAppStateTracker.dumpProto(proto,
+                StateControllerProto.BackgroundJobsController.FORCE_APP_STANDBY_TRACKER);
+
+        mService.getJobStore().forEachJob(predicate, (jobStatus) -> {
+            final long jsToken =
+                    proto.start(StateControllerProto.BackgroundJobsController.TRACKED_JOBS);
+
+            jobStatus.writeToShortProto(proto,
+                    TrackedJob.INFO);
+            final int sourceUid = jobStatus.getSourceUid();
+            proto.write(TrackedJob.SOURCE_UID, sourceUid);
+            final String sourcePkg = jobStatus.getSourcePackageName();
+            proto.write(TrackedJob.SOURCE_PACKAGE_NAME, sourcePkg);
+
+            proto.write(TrackedJob.IS_IN_FOREGROUND,
+                    mAppStateTracker.isUidActive(sourceUid));
+            proto.write(TrackedJob.IS_WHITELISTED,
+                    mAppStateTracker.isUidPowerSaveWhitelisted(sourceUid) ||
+                    mAppStateTracker.isUidTempPowerSaveWhitelisted(sourceUid));
+
+            proto.write(
+                    TrackedJob.CAN_RUN_ANY_IN_BACKGROUND,
+                    mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(
+                            sourceUid, sourcePkg));
+
+            proto.write(
+                    TrackedJob.ARE_CONSTRAINTS_SATISFIED,
+                    (jobStatus.satisfiedConstraints &
+                            JobStatus.CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0);
+
+            proto.end(jsToken);
+        });
+
+        proto.end(mToken);
+        proto.end(token);
+    }
+
+    private void updateAllJobRestrictionsLocked() {
+        updateJobRestrictionsLocked(/*filterUid=*/ -1, UNKNOWN);
+    }
+
+    private void updateJobRestrictionsForUidLocked(int uid, boolean isActive) {
+        updateJobRestrictionsLocked(uid, (isActive) ? KNOWN_ACTIVE : KNOWN_INACTIVE);
+    }
+
+    private void updateJobRestrictionsLocked(int filterUid, int newActiveState) {
+        final UpdateJobFunctor updateTrackedJobs = new UpdateJobFunctor(newActiveState);
+
+        final long start = DEBUG ? SystemClock.elapsedRealtimeNanos() : 0;
+
+        final JobStore store = mService.getJobStore();
+        if (filterUid > 0) {
+            store.forEachJobForSourceUid(filterUid, updateTrackedJobs);
+        } else {
+            store.forEachJob(updateTrackedJobs);
+        }
+
+        final long time = DEBUG ? (SystemClock.elapsedRealtimeNanos() - start) : 0;
+        if (DEBUG) {
+            Slog.d(TAG, String.format(
+                    "Job status updated: %d/%d checked/total jobs, %d us",
+                    updateTrackedJobs.mCheckedCount,
+                    updateTrackedJobs.mTotalCount,
+                    (time / 1000)
+                    ));
+        }
+
+        if (updateTrackedJobs.mChanged) {
+            mStateChangedListener.onControllerStateChanged();
+        }
+    }
+
+    boolean updateSingleJobRestrictionLocked(JobStatus jobStatus, int activeState) {
+
+        final int uid = jobStatus.getSourceUid();
+        final String packageName = jobStatus.getSourcePackageName();
+
+        final boolean canRun = !mAppStateTracker.areJobsRestricted(uid, packageName,
+                (jobStatus.getInternalFlags() & JobStatus.INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION)
+                        != 0);
+
+        final boolean isActive;
+        if (activeState == UNKNOWN) {
+            isActive = mAppStateTracker.isUidActive(uid);
+        } else {
+            isActive = (activeState == KNOWN_ACTIVE);
+        }
+        boolean didChange = jobStatus.setBackgroundNotRestrictedConstraintSatisfied(canRun);
+        didChange |= jobStatus.setUidActive(isActive);
+        return didChange;
+    }
+
+    private final class UpdateJobFunctor implements Consumer<JobStatus> {
+        final int activeState;
+        boolean mChanged = false;
+        int mTotalCount = 0;
+        int mCheckedCount = 0;
+
+        public UpdateJobFunctor(int newActiveState) {
+            activeState = newActiveState;
+        }
+
+        @Override
+        public void accept(JobStatus jobStatus) {
+            mTotalCount++;
+            mCheckedCount++;
+            if (updateSingleJobRestrictionLocked(jobStatus, activeState)) {
+                mChanged = true;
+            }
+        }
+    }
+
+    private final Listener mForceAppStandbyListener = new Listener() {
+        @Override
+        public void updateAllJobs() {
+            synchronized (mLock) {
+                updateAllJobRestrictionsLocked();
+            }
+        }
+
+        @Override
+        public void updateJobsForUid(int uid, boolean isActive) {
+            synchronized (mLock) {
+                updateJobRestrictionsForUidLocked(uid, isActive);
+            }
+        }
+
+        @Override
+        public void updateJobsForUidPackage(int uid, String packageName, boolean isActive) {
+            synchronized (mLock) {
+                updateJobRestrictionsForUidLocked(uid, isActive);
+            }
+        }
+    };
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
new file mode 100644
index 0000000..46658ad
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers;
+
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+import android.os.BatteryManagerInternal;
+import android.os.UserHandle;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateControllerProto;
+
+import java.util.function.Predicate;
+
+/**
+ * Simple controller that tracks whether the phone is charging or not. The phone is considered to
+ * be charging when it's been plugged in for more than two minutes, and the system has broadcast
+ * ACTION_BATTERY_OK.
+ */
+public final class BatteryController extends StateController {
+    private static final String TAG = "JobScheduler.Battery";
+    private static final boolean DEBUG = JobSchedulerService.DEBUG
+            || Log.isLoggable(TAG, Log.DEBUG);
+
+    private final ArraySet<JobStatus> mTrackedTasks = new ArraySet<>();
+    private ChargingTracker mChargeTracker;
+
+    @VisibleForTesting
+    public ChargingTracker getTracker() {
+        return mChargeTracker;
+    }
+
+    public BatteryController(JobSchedulerService service) {
+        super(service);
+        mChargeTracker = new ChargingTracker();
+        mChargeTracker.startTracking();
+    }
+
+    @Override
+    public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
+        if (taskStatus.hasPowerConstraint()) {
+            mTrackedTasks.add(taskStatus);
+            taskStatus.setTrackingController(JobStatus.TRACKING_BATTERY);
+            taskStatus.setChargingConstraintSatisfied(mChargeTracker.isOnStablePower());
+            taskStatus.setBatteryNotLowConstraintSatisfied(mChargeTracker.isBatteryNotLow());
+        }
+    }
+
+    @Override
+    public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob, boolean forUpdate) {
+        if (taskStatus.clearTrackingController(JobStatus.TRACKING_BATTERY)) {
+            mTrackedTasks.remove(taskStatus);
+        }
+    }
+
+    private void maybeReportNewChargingStateLocked() {
+        final boolean stablePower = mChargeTracker.isOnStablePower();
+        final boolean batteryNotLow = mChargeTracker.isBatteryNotLow();
+        if (DEBUG) {
+            Slog.d(TAG, "maybeReportNewChargingStateLocked: " + stablePower);
+        }
+        boolean reportChange = false;
+        for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
+            final JobStatus ts = mTrackedTasks.valueAt(i);
+            boolean previous = ts.setChargingConstraintSatisfied(stablePower);
+            if (previous != stablePower) {
+                reportChange = true;
+            }
+            previous = ts.setBatteryNotLowConstraintSatisfied(batteryNotLow);
+            if (previous != batteryNotLow) {
+                reportChange = true;
+            }
+        }
+        if (stablePower || batteryNotLow) {
+            // If one of our conditions has been satisfied, always schedule any newly ready jobs.
+            mStateChangedListener.onRunJobNow(null);
+        } else if (reportChange) {
+            // Otherwise, just let the job scheduler know the state has changed and take care of it
+            // as it thinks is best.
+            mStateChangedListener.onControllerStateChanged();
+        }
+    }
+
+    public final class ChargingTracker extends BroadcastReceiver {
+        /**
+         * Track whether we're "charging", where charging means that we're ready to commit to
+         * doing work.
+         */
+        private boolean mCharging;
+        /** Keep track of whether the battery is charged enough that we want to do work. */
+        private boolean mBatteryHealthy;
+        /** Sequence number of last broadcast. */
+        private int mLastBatterySeq = -1;
+
+        private BroadcastReceiver mMonitor;
+
+        public ChargingTracker() {
+        }
+
+        public void startTracking() {
+            IntentFilter filter = new IntentFilter();
+
+            // Battery health.
+            filter.addAction(Intent.ACTION_BATTERY_LOW);
+            filter.addAction(Intent.ACTION_BATTERY_OKAY);
+            // Charging/not charging.
+            filter.addAction(BatteryManager.ACTION_CHARGING);
+            filter.addAction(BatteryManager.ACTION_DISCHARGING);
+            mContext.registerReceiver(this, filter);
+
+            // Initialise tracker state.
+            BatteryManagerInternal batteryManagerInternal =
+                    LocalServices.getService(BatteryManagerInternal.class);
+            mBatteryHealthy = !batteryManagerInternal.getBatteryLevelLow();
+            mCharging = batteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
+        }
+
+        public void setMonitorBatteryLocked(boolean enabled) {
+            if (enabled) {
+                if (mMonitor == null) {
+                    mMonitor = new BroadcastReceiver() {
+                        @Override public void onReceive(Context context, Intent intent) {
+                            ChargingTracker.this.onReceive(context, intent);
+                        }
+                    };
+                    IntentFilter filter = new IntentFilter();
+                    filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+                    mContext.registerReceiver(mMonitor, filter);
+                }
+            } else {
+                if (mMonitor != null) {
+                    mContext.unregisterReceiver(mMonitor);
+                    mMonitor = null;
+                }
+            }
+        }
+
+        public boolean isOnStablePower() {
+            return mCharging && mBatteryHealthy;
+        }
+
+        public boolean isBatteryNotLow() {
+            return mBatteryHealthy;
+        }
+
+        public boolean isMonitoring() {
+            return mMonitor != null;
+        }
+
+        public int getSeq() {
+            return mLastBatterySeq;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            onReceiveInternal(intent);
+        }
+
+        @VisibleForTesting
+        public void onReceiveInternal(Intent intent) {
+            synchronized (mLock) {
+                final String action = intent.getAction();
+                if (Intent.ACTION_BATTERY_LOW.equals(action)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Battery life too low to do work. @ "
+                                + sElapsedRealtimeClock.millis());
+                    }
+                    // If we get this action, the battery is discharging => it isn't plugged in so
+                    // there's no work to cancel. We track this variable for the case where it is
+                    // charging, but hasn't been for long enough to be healthy.
+                    mBatteryHealthy = false;
+                    maybeReportNewChargingStateLocked();
+                } else if (Intent.ACTION_BATTERY_OKAY.equals(action)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Battery life healthy enough to do work. @ "
+                                + sElapsedRealtimeClock.millis());
+                    }
+                    mBatteryHealthy = true;
+                    maybeReportNewChargingStateLocked();
+                } else if (BatteryManager.ACTION_CHARGING.equals(action)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Received charging intent, fired @ "
+                                + sElapsedRealtimeClock.millis());
+                    }
+                    mCharging = true;
+                    maybeReportNewChargingStateLocked();
+                } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Disconnected from power.");
+                    }
+                    mCharging = false;
+                    maybeReportNewChargingStateLocked();
+                }
+                mLastBatterySeq = intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE,
+                        mLastBatterySeq);
+            }
+        }
+    }
+
+    @Override
+    public void dumpControllerStateLocked(IndentingPrintWriter pw,
+            Predicate<JobStatus> predicate) {
+        pw.println("Stable power: " + mChargeTracker.isOnStablePower());
+        pw.println("Not low: " + mChargeTracker.isBatteryNotLow());
+
+        if (mChargeTracker.isMonitoring()) {
+            pw.print("MONITORING: seq=");
+            pw.println(mChargeTracker.getSeq());
+        }
+        pw.println();
+
+        for (int i = 0; i < mTrackedTasks.size(); i++) {
+            final JobStatus js = mTrackedTasks.valueAt(i);
+            if (!predicate.test(js)) {
+                continue;
+            }
+            pw.print("#");
+            js.printUniqueId(pw);
+            pw.print(" from ");
+            UserHandle.formatUid(pw, js.getSourceUid());
+            pw.println();
+        }
+    }
+
+    @Override
+    public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
+            Predicate<JobStatus> predicate) {
+        final long token = proto.start(fieldId);
+        final long mToken = proto.start(StateControllerProto.BATTERY);
+
+        proto.write(StateControllerProto.BatteryController.IS_ON_STABLE_POWER,
+                mChargeTracker.isOnStablePower());
+        proto.write(StateControllerProto.BatteryController.IS_BATTERY_NOT_LOW,
+                mChargeTracker.isBatteryNotLow());
+
+        proto.write(StateControllerProto.BatteryController.IS_MONITORING,
+                mChargeTracker.isMonitoring());
+        proto.write(StateControllerProto.BatteryController.LAST_BROADCAST_SEQUENCE_NUMBER,
+                mChargeTracker.getSeq());
+
+        for (int i = 0; i < mTrackedTasks.size(); i++) {
+            final JobStatus js = mTrackedTasks.valueAt(i);
+            if (!predicate.test(js)) {
+                continue;
+            }
+            final long jsToken = proto.start(StateControllerProto.BatteryController.TRACKED_JOBS);
+            js.writeToShortProto(proto, StateControllerProto.BatteryController.TrackedJob.INFO);
+            proto.write(StateControllerProto.BatteryController.TrackedJob.SOURCE_UID,
+                    js.getSourceUid());
+            proto.end(jsToken);
+        }
+
+        proto.end(mToken);
+        proto.end(token);
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
new file mode 100644
index 0000000..f8cf6ae
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -0,0 +1,694 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers;
+
+import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+
+import android.app.job.JobInfo;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.INetworkPolicyListener;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkPolicyManager;
+import android.net.NetworkRequest;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.UserHandle;
+import android.text.format.DateUtils;
+import android.util.ArraySet;
+import android.util.DataUnit;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.JobSchedulerService.Constants;
+import com.android.server.job.JobServiceContext;
+import com.android.server.job.StateControllerProto;
+import com.android.server.net.NetworkPolicyManagerInternal;
+
+import java.util.Objects;
+import java.util.function.Predicate;
+
+/**
+ * Handles changes in connectivity.
+ * <p>
+ * Each app can have a different default networks or different connectivity
+ * status due to user-requested network policies, so we need to check
+ * constraints on a per-UID basis.
+ *
+ * Test: atest com.android.server.job.controllers.ConnectivityControllerTest
+ */
+public final class ConnectivityController extends StateController implements
+        ConnectivityManager.OnNetworkActiveListener {
+    private static final String TAG = "JobScheduler.Connectivity";
+    private static final boolean DEBUG = JobSchedulerService.DEBUG
+            || Log.isLoggable(TAG, Log.DEBUG);
+
+    private final ConnectivityManager mConnManager;
+    private final NetworkPolicyManager mNetPolicyManager;
+    private final NetworkPolicyManagerInternal mNetPolicyManagerInternal;
+
+    /** List of tracked jobs keyed by source UID. */
+    @GuardedBy("mLock")
+    private final SparseArray<ArraySet<JobStatus>> mTrackedJobs = new SparseArray<>();
+
+    /**
+     * Keep track of all the UID's jobs that the controller has requested that NetworkPolicyManager
+     * grant an exception to in the app standby chain.
+     */
+    @GuardedBy("mLock")
+    private final SparseArray<ArraySet<JobStatus>> mRequestedWhitelistJobs = new SparseArray<>();
+
+    /** List of currently available networks. */
+    @GuardedBy("mLock")
+    private final ArraySet<Network> mAvailableNetworks = new ArraySet<>();
+
+    private boolean mUseQuotaLimit;
+
+    private static final int MSG_DATA_SAVER_TOGGLED = 0;
+    private static final int MSG_UID_RULES_CHANGES = 1;
+    private static final int MSG_REEVALUATE_JOBS = 2;
+
+    private final Handler mHandler;
+
+    public ConnectivityController(JobSchedulerService service) {
+        super(service);
+        mHandler = new CcHandler(mContext.getMainLooper());
+
+        mConnManager = mContext.getSystemService(ConnectivityManager.class);
+        mNetPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
+        mNetPolicyManagerInternal = LocalServices.getService(NetworkPolicyManagerInternal.class);
+
+        // We're interested in all network changes; internally we match these
+        // network changes against the active network for each UID with jobs.
+        final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
+        mConnManager.registerNetworkCallback(request, mNetworkCallback);
+
+        mNetPolicyManager.registerListener(mNetPolicyListener);
+
+        mUseQuotaLimit = !mConstants.USE_HEARTBEATS;
+    }
+
+    @GuardedBy("mLock")
+    @Override
+    public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
+        if (jobStatus.hasConnectivityConstraint()) {
+            updateConstraintsSatisfied(jobStatus);
+            ArraySet<JobStatus> jobs = mTrackedJobs.get(jobStatus.getSourceUid());
+            if (jobs == null) {
+                jobs = new ArraySet<>();
+                mTrackedJobs.put(jobStatus.getSourceUid(), jobs);
+            }
+            jobs.add(jobStatus);
+            jobStatus.setTrackingController(JobStatus.TRACKING_CONNECTIVITY);
+        }
+    }
+
+    @GuardedBy("mLock")
+    @Override
+    public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
+            boolean forUpdate) {
+        if (jobStatus.clearTrackingController(JobStatus.TRACKING_CONNECTIVITY)) {
+            ArraySet<JobStatus> jobs = mTrackedJobs.get(jobStatus.getSourceUid());
+            if (jobs != null) {
+                jobs.remove(jobStatus);
+            }
+            maybeRevokeStandbyExceptionLocked(jobStatus);
+        }
+    }
+
+    @GuardedBy("mLock")
+    @Override
+    public void onConstantsUpdatedLocked() {
+        if (mConstants.USE_HEARTBEATS) {
+            // App idle exceptions are only requested for the rolling quota system.
+            if (DEBUG) Slog.i(TAG, "Revoking all standby exceptions");
+            for (int i = 0; i < mRequestedWhitelistJobs.size(); ++i) {
+                int uid = mRequestedWhitelistJobs.keyAt(i);
+                mNetPolicyManagerInternal.setAppIdleWhitelist(uid, false);
+            }
+            mRequestedWhitelistJobs.clear();
+        }
+        if (mUseQuotaLimit == mConstants.USE_HEARTBEATS) {
+            mUseQuotaLimit = !mConstants.USE_HEARTBEATS;
+            mHandler.obtainMessage(MSG_REEVALUATE_JOBS).sendToTarget();
+        }
+    }
+
+    /**
+     * Returns true if the job's requested network is available. This DOES NOT necesarilly mean
+     * that the UID has been granted access to the network.
+     */
+    public boolean isNetworkAvailable(JobStatus job) {
+        synchronized (mLock) {
+            for (int i = 0; i < mAvailableNetworks.size(); ++i) {
+                final Network network = mAvailableNetworks.valueAt(i);
+                final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(
+                        network);
+                final boolean satisfied = isSatisfied(job, network, capabilities, mConstants);
+                if (DEBUG) {
+                    Slog.v(TAG, "isNetworkAvailable(" + job + ") with network " + network
+                            + " and capabilities " + capabilities + ". Satisfied=" + satisfied);
+                }
+                if (satisfied) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Request that NetworkPolicyManager grant an exception to the uid from its standby policy
+     * chain.
+     */
+    @VisibleForTesting
+    @GuardedBy("mLock")
+    void requestStandbyExceptionLocked(JobStatus job) {
+        final int uid = job.getSourceUid();
+        // Need to call this before adding the job.
+        final boolean isExceptionRequested = isStandbyExceptionRequestedLocked(uid);
+        ArraySet<JobStatus> jobs = mRequestedWhitelistJobs.get(uid);
+        if (jobs == null) {
+            jobs = new ArraySet<JobStatus>();
+            mRequestedWhitelistJobs.put(uid, jobs);
+        }
+        if (!jobs.add(job) || isExceptionRequested) {
+            if (DEBUG) {
+                Slog.i(TAG, "requestStandbyExceptionLocked found exception already requested.");
+            }
+            return;
+        }
+        if (DEBUG) Slog.i(TAG, "Requesting standby exception for UID: " + uid);
+        mNetPolicyManagerInternal.setAppIdleWhitelist(uid, true);
+    }
+
+    /** Returns whether a standby exception has been requested for the UID. */
+    @VisibleForTesting
+    @GuardedBy("mLock")
+    boolean isStandbyExceptionRequestedLocked(final int uid) {
+        ArraySet jobs = mRequestedWhitelistJobs.get(uid);
+        return jobs != null && jobs.size() > 0;
+    }
+
+    @VisibleForTesting
+    @GuardedBy("mLock")
+    boolean wouldBeReadyWithConnectivityLocked(JobStatus jobStatus) {
+        final boolean networkAvailable = isNetworkAvailable(jobStatus);
+        if (DEBUG) {
+            Slog.v(TAG, "wouldBeReadyWithConnectivityLocked: " + jobStatus.toShortString()
+                    + " networkAvailable=" + networkAvailable);
+        }
+        // If the network isn't available, then requesting an exception won't help.
+
+        return networkAvailable && wouldBeReadyWithConstraintLocked(jobStatus,
+                JobStatus.CONSTRAINT_CONNECTIVITY);
+    }
+
+    /**
+     * Tell NetworkPolicyManager not to block a UID's network connection if that's the only
+     * thing stopping a job from running.
+     */
+    @GuardedBy("mLock")
+    @Override
+    public void evaluateStateLocked(JobStatus jobStatus) {
+        if (mConstants.USE_HEARTBEATS) {
+            // This should only be used for the rolling quota system.
+            return;
+        }
+
+        if (!jobStatus.hasConnectivityConstraint()) {
+            return;
+        }
+
+        // Always check the full job readiness stat in case the component has been disabled.
+        if (wouldBeReadyWithConnectivityLocked(jobStatus)) {
+            if (DEBUG) {
+                Slog.i(TAG, "evaluateStateLocked finds job " + jobStatus + " would be ready.");
+            }
+            requestStandbyExceptionLocked(jobStatus);
+        } else {
+            if (DEBUG) {
+                Slog.i(TAG, "evaluateStateLocked finds job " + jobStatus + " would not be ready.");
+            }
+            maybeRevokeStandbyExceptionLocked(jobStatus);
+        }
+    }
+
+    @GuardedBy("mLock")
+    @Override
+    public void reevaluateStateLocked(final int uid) {
+        if (mConstants.USE_HEARTBEATS) {
+            return;
+        }
+        // Check if we still need a connectivity exception in case the JobService was disabled.
+        ArraySet<JobStatus> jobs = mTrackedJobs.get(uid);
+        if (jobs == null) {
+            return;
+        }
+        for (int i = jobs.size() - 1; i >= 0; i--) {
+            evaluateStateLocked(jobs.valueAt(i));
+        }
+    }
+
+    /** Cancel the requested standby exception if none of the jobs would be ready to run anyway. */
+    @VisibleForTesting
+    @GuardedBy("mLock")
+    void maybeRevokeStandbyExceptionLocked(final JobStatus job) {
+        final int uid = job.getSourceUid();
+        if (!isStandbyExceptionRequestedLocked(uid)) {
+            return;
+        }
+        ArraySet<JobStatus> jobs = mRequestedWhitelistJobs.get(uid);
+        if (jobs == null) {
+            Slog.wtf(TAG,
+                    "maybeRevokeStandbyExceptionLocked found null jobs array even though a "
+                            + "standby exception has been requested.");
+            return;
+        }
+        if (!jobs.remove(job) || jobs.size() > 0) {
+            if (DEBUG) {
+                Slog.i(TAG,
+                        "maybeRevokeStandbyExceptionLocked not revoking because there are still "
+                                + jobs.size() + " jobs left.");
+            }
+            return;
+        }
+        // No more jobs that need an exception.
+        revokeStandbyExceptionLocked(uid);
+    }
+
+    /**
+     * Tell NetworkPolicyManager to revoke any exception it granted from its standby policy chain
+     * for the uid.
+     */
+    @GuardedBy("mLock")
+    private void revokeStandbyExceptionLocked(final int uid) {
+        if (DEBUG) Slog.i(TAG, "Revoking standby exception for UID: " + uid);
+        mNetPolicyManagerInternal.setAppIdleWhitelist(uid, false);
+        mRequestedWhitelistJobs.remove(uid);
+    }
+
+    @GuardedBy("mLock")
+    @Override
+    public void onAppRemovedLocked(String pkgName, int uid) {
+        mTrackedJobs.delete(uid);
+    }
+
+    /**
+     * Test to see if running the given job on the given network is insane.
+     * <p>
+     * For example, if a job is trying to send 10MB over a 128Kbps EDGE
+     * connection, it would take 10.4 minutes, and has no chance of succeeding
+     * before the job times out, so we'd be insane to try running it.
+     */
+    private boolean isInsane(JobStatus jobStatus, Network network,
+            NetworkCapabilities capabilities, Constants constants) {
+        final long maxJobExecutionTimeMs = mUseQuotaLimit
+                ? mService.getMaxJobExecutionTimeMs(jobStatus)
+                : JobServiceContext.EXECUTING_TIMESLICE_MILLIS;
+
+        final long downloadBytes = jobStatus.getEstimatedNetworkDownloadBytes();
+        if (downloadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
+            final long bandwidth = capabilities.getLinkDownstreamBandwidthKbps();
+            // If we don't know the bandwidth, all we can do is hope the job finishes in time.
+            if (bandwidth != LINK_BANDWIDTH_UNSPECIFIED) {
+                // Divide by 8 to convert bits to bytes.
+                final long estimatedMillis = ((downloadBytes * DateUtils.SECOND_IN_MILLIS)
+                        / (DataUnit.KIBIBYTES.toBytes(bandwidth) / 8));
+                if (estimatedMillis > maxJobExecutionTimeMs) {
+                    // If we'd never finish before the timeout, we'd be insane!
+                    Slog.w(TAG, "Estimated " + downloadBytes + " download bytes over " + bandwidth
+                            + " kbps network would take " + estimatedMillis + "ms and job has "
+                            + maxJobExecutionTimeMs + "ms to run; that's insane!");
+                    return true;
+                }
+            }
+        }
+
+        final long uploadBytes = jobStatus.getEstimatedNetworkUploadBytes();
+        if (uploadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
+            final long bandwidth = capabilities.getLinkUpstreamBandwidthKbps();
+            // If we don't know the bandwidth, all we can do is hope the job finishes in time.
+            if (bandwidth != LINK_BANDWIDTH_UNSPECIFIED) {
+                // Divide by 8 to convert bits to bytes.
+                final long estimatedMillis = ((uploadBytes * DateUtils.SECOND_IN_MILLIS)
+                        / (DataUnit.KIBIBYTES.toBytes(bandwidth) / 8));
+                if (estimatedMillis > maxJobExecutionTimeMs) {
+                    // If we'd never finish before the timeout, we'd be insane!
+                    Slog.w(TAG, "Estimated " + uploadBytes + " upload bytes over " + bandwidth
+                            + " kbps network would take " + estimatedMillis + "ms and job has "
+                            + maxJobExecutionTimeMs + "ms to run; that's insane!");
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    private static boolean isCongestionDelayed(JobStatus jobStatus, Network network,
+            NetworkCapabilities capabilities, Constants constants) {
+        // If network is congested, and job is less than 50% through the
+        // developer-requested window, then we're okay delaying the job.
+        if (!capabilities.hasCapability(NET_CAPABILITY_NOT_CONGESTED)) {
+            return jobStatus.getFractionRunTime() < constants.CONN_CONGESTION_DELAY_FRAC;
+        } else {
+            return false;
+        }
+    }
+
+    private static boolean isStrictSatisfied(JobStatus jobStatus, Network network,
+            NetworkCapabilities capabilities, Constants constants) {
+        return jobStatus.getJob().getRequiredNetwork().networkCapabilities
+                .satisfiedByNetworkCapabilities(capabilities);
+    }
+
+    private static boolean isRelaxedSatisfied(JobStatus jobStatus, Network network,
+            NetworkCapabilities capabilities, Constants constants) {
+        // Only consider doing this for prefetching jobs
+        if (!jobStatus.getJob().isPrefetch()) {
+            return false;
+        }
+
+        // See if we match after relaxing any unmetered request
+        final NetworkCapabilities relaxed = new NetworkCapabilities(
+                jobStatus.getJob().getRequiredNetwork().networkCapabilities)
+                        .removeCapability(NET_CAPABILITY_NOT_METERED);
+        if (relaxed.satisfiedByNetworkCapabilities(capabilities)) {
+            // TODO: treat this as "maybe" response; need to check quotas
+            return jobStatus.getFractionRunTime() > constants.CONN_PREFETCH_RELAX_FRAC;
+        } else {
+            return false;
+        }
+    }
+
+    @VisibleForTesting
+    boolean isSatisfied(JobStatus jobStatus, Network network,
+            NetworkCapabilities capabilities, Constants constants) {
+        // Zeroth, we gotta have a network to think about being satisfied
+        if (network == null || capabilities == null) return false;
+
+        // First, are we insane?
+        if (isInsane(jobStatus, network, capabilities, constants)) return false;
+
+        // Second, is the network congested?
+        if (isCongestionDelayed(jobStatus, network, capabilities, constants)) return false;
+
+        // Third, is the network a strict match?
+        if (isStrictSatisfied(jobStatus, network, capabilities, constants)) return true;
+
+        // Third, is the network a relaxed match?
+        if (isRelaxedSatisfied(jobStatus, network, capabilities, constants)) return true;
+
+        return false;
+    }
+
+    private boolean updateConstraintsSatisfied(JobStatus jobStatus) {
+        final Network network = mConnManager.getActiveNetworkForUid(jobStatus.getSourceUid());
+        final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(network);
+        return updateConstraintsSatisfied(jobStatus, network, capabilities);
+    }
+
+    private boolean updateConstraintsSatisfied(JobStatus jobStatus, Network network,
+            NetworkCapabilities capabilities) {
+        // TODO: consider matching against non-active networks
+
+        final boolean ignoreBlocked = (jobStatus.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
+        final NetworkInfo info = mConnManager.getNetworkInfoForUid(network,
+                jobStatus.getSourceUid(), ignoreBlocked);
+
+        final boolean connected = (info != null) && info.isConnected();
+        final boolean satisfied = isSatisfied(jobStatus, network, capabilities, mConstants);
+
+        final boolean changed = jobStatus
+                .setConnectivityConstraintSatisfied(connected && satisfied);
+
+        // Pass along the evaluated network for job to use; prevents race
+        // conditions as default routes change over time, and opens the door to
+        // using non-default routes.
+        jobStatus.network = network;
+
+        if (DEBUG) {
+            Slog.i(TAG, "Connectivity " + (changed ? "CHANGED" : "unchanged")
+                    + " for " + jobStatus + ": connected=" + connected
+                    + " satisfied=" + satisfied);
+        }
+        return changed;
+    }
+
+    /**
+     * Update any jobs tracked by this controller that match given filters.
+     *
+     * @param filterUid     only update jobs belonging to this UID, or {@code -1} to
+     *                      update all tracked jobs.
+     * @param filterNetwork only update jobs that would use this
+     *                      {@link Network}, or {@code null} to update all tracked jobs.
+     */
+    private void updateTrackedJobs(int filterUid, Network filterNetwork) {
+        synchronized (mLock) {
+            // Since this is a really hot codepath, temporarily cache any
+            // answers that we get from ConnectivityManager.
+            final SparseArray<NetworkCapabilities> networkToCapabilities = new SparseArray<>();
+
+            boolean changed = false;
+            if (filterUid == -1) {
+                for (int i = mTrackedJobs.size() - 1; i >= 0; i--) {
+                    changed |= updateTrackedJobsLocked(mTrackedJobs.valueAt(i),
+                            filterNetwork, networkToCapabilities);
+                }
+            } else {
+                changed = updateTrackedJobsLocked(mTrackedJobs.get(filterUid),
+                        filterNetwork, networkToCapabilities);
+            }
+            if (changed) {
+                mStateChangedListener.onControllerStateChanged();
+            }
+        }
+    }
+
+    private boolean updateTrackedJobsLocked(ArraySet<JobStatus> jobs, Network filterNetwork,
+            SparseArray<NetworkCapabilities> networkToCapabilities) {
+        if (jobs == null || jobs.size() == 0) {
+            return false;
+        }
+
+        final Network network = mConnManager.getActiveNetworkForUid(jobs.valueAt(0).getSourceUid());
+        final int netId = network != null ? network.netId : -1;
+        NetworkCapabilities capabilities = networkToCapabilities.get(netId);
+        if (capabilities == null) {
+            capabilities = mConnManager.getNetworkCapabilities(network);
+            networkToCapabilities.put(netId, capabilities);
+        }
+        final boolean networkMatch = (filterNetwork == null
+                || Objects.equals(filterNetwork, network));
+
+        boolean changed = false;
+        for (int i = jobs.size() - 1; i >= 0; i--) {
+            final JobStatus js = jobs.valueAt(i);
+
+            // Update either when we have a network match, or when the
+            // job hasn't yet been evaluated against the currently
+            // active network; typically when we just lost a network.
+            if (networkMatch || !Objects.equals(js.network, network)) {
+                changed |= updateConstraintsSatisfied(js, network, capabilities);
+            }
+        }
+        return changed;
+    }
+
+    /**
+     * We know the network has just come up. We want to run any jobs that are ready.
+     */
+    @Override
+    public void onNetworkActive() {
+        synchronized (mLock) {
+            for (int i = mTrackedJobs.size()-1; i >= 0; i--) {
+                final ArraySet<JobStatus> jobs = mTrackedJobs.valueAt(i);
+                for (int j = jobs.size() - 1; j >= 0; j--) {
+                    final JobStatus js = jobs.valueAt(j);
+                    if (js.isReady()) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "Running " + js + " due to network activity.");
+                        }
+                        mStateChangedListener.onRunJobNow(js);
+                    }
+                }
+            }
+        }
+    }
+
+    private final NetworkCallback mNetworkCallback = new NetworkCallback() {
+        @Override
+        public void onAvailable(Network network) {
+            if (DEBUG) Slog.v(TAG, "onAvailable: " + network);
+            synchronized (mLock) {
+                mAvailableNetworks.add(network);
+            }
+        }
+
+        @Override
+        public void onCapabilitiesChanged(Network network, NetworkCapabilities capabilities) {
+            if (DEBUG) {
+                Slog.v(TAG, "onCapabilitiesChanged: " + network);
+            }
+            updateTrackedJobs(-1, network);
+        }
+
+        @Override
+        public void onLost(Network network) {
+            if (DEBUG) {
+                Slog.v(TAG, "onLost: " + network);
+            }
+            synchronized (mLock) {
+                mAvailableNetworks.remove(network);
+            }
+            updateTrackedJobs(-1, network);
+        }
+    };
+
+    private final INetworkPolicyListener mNetPolicyListener = new NetworkPolicyManager.Listener() {
+        @Override
+        public void onRestrictBackgroundChanged(boolean restrictBackground) {
+            if (DEBUG) {
+                Slog.v(TAG, "onRestrictBackgroundChanged: " + restrictBackground);
+            }
+            mHandler.obtainMessage(MSG_DATA_SAVER_TOGGLED).sendToTarget();
+        }
+
+        @Override
+        public void onUidRulesChanged(int uid, int uidRules) {
+            if (DEBUG) {
+                Slog.v(TAG, "onUidRulesChanged: " + uid);
+            }
+            mHandler.obtainMessage(MSG_UID_RULES_CHANGES, uid, 0).sendToTarget();
+        }
+    };
+
+    private class CcHandler extends Handler {
+        CcHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            synchronized (mLock) {
+                switch (msg.what) {
+                    case MSG_DATA_SAVER_TOGGLED:
+                        updateTrackedJobs(-1, null);
+                        break;
+                    case MSG_UID_RULES_CHANGES:
+                        updateTrackedJobs(msg.arg1, null);
+                        break;
+                    case MSG_REEVALUATE_JOBS:
+                        updateTrackedJobs(-1, null);
+                        break;
+                }
+            }
+        }
+    };
+
+    @GuardedBy("mLock")
+    @Override
+    public void dumpControllerStateLocked(IndentingPrintWriter pw,
+            Predicate<JobStatus> predicate) {
+        pw.print("mUseQuotaLimit="); pw.println(mUseQuotaLimit);
+
+        if (mRequestedWhitelistJobs.size() > 0) {
+            pw.print("Requested standby exceptions:");
+            for (int i = 0; i < mRequestedWhitelistJobs.size(); i++) {
+                pw.print(" ");
+                pw.print(mRequestedWhitelistJobs.keyAt(i));
+                pw.print(" (");
+                pw.print(mRequestedWhitelistJobs.valueAt(i).size());
+                pw.print(" jobs)");
+            }
+            pw.println();
+        }
+        if (mAvailableNetworks.size() > 0) {
+            pw.println("Available networks:");
+            pw.increaseIndent();
+            for (int i = 0; i < mAvailableNetworks.size(); i++) {
+                pw.println(mAvailableNetworks.valueAt(i));
+            }
+            pw.decreaseIndent();
+        } else {
+            pw.println("No available networks");
+        }
+        for (int i = 0; i < mTrackedJobs.size(); i++) {
+            final ArraySet<JobStatus> jobs = mTrackedJobs.valueAt(i);
+            for (int j = 0; j < jobs.size(); j++) {
+                final JobStatus js = jobs.valueAt(j);
+                if (!predicate.test(js)) {
+                    continue;
+                }
+                pw.print("#");
+                js.printUniqueId(pw);
+                pw.print(" from ");
+                UserHandle.formatUid(pw, js.getSourceUid());
+                pw.print(": ");
+                pw.print(js.getJob().getRequiredNetwork());
+                pw.println();
+            }
+        }
+    }
+
+    @GuardedBy("mLock")
+    @Override
+    public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
+            Predicate<JobStatus> predicate) {
+        final long token = proto.start(fieldId);
+        final long mToken = proto.start(StateControllerProto.CONNECTIVITY);
+
+        for (int i = 0; i < mTrackedJobs.size(); i++) {
+            final ArraySet<JobStatus> jobs = mTrackedJobs.valueAt(i);
+            for (int j = 0; j < jobs.size(); j++) {
+                final JobStatus js = jobs.valueAt(j);
+                if (!predicate.test(js)) {
+                    continue;
+                }
+                final long jsToken = proto.start(
+                        StateControllerProto.ConnectivityController.TRACKED_JOBS);
+                js.writeToShortProto(proto,
+                        StateControllerProto.ConnectivityController.TrackedJob.INFO);
+                proto.write(StateControllerProto.ConnectivityController.TrackedJob.SOURCE_UID,
+                        js.getSourceUid());
+                NetworkRequest rn = js.getJob().getRequiredNetwork();
+                if (rn != null) {
+                    rn.writeToProto(proto,
+                            StateControllerProto.ConnectivityController.TrackedJob
+                                    .REQUIRED_NETWORK);
+                }
+                proto.end(jsToken);
+            }
+        }
+
+        proto.end(mToken);
+        proto.end(token);
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java
new file mode 100644
index 0000000..a775cf5
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers;
+
+import android.annotation.UserIdInt;
+import android.app.job.JobInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateControllerProto;
+import com.android.server.job.StateControllerProto.ContentObserverController.Observer.TriggerContentData;
+
+import java.util.ArrayList;
+import java.util.function.Predicate;
+
+/**
+ * Controller for monitoring changes to content URIs through a ContentObserver.
+ */
+public final class ContentObserverController extends StateController {
+    private static final String TAG = "JobScheduler.ContentObserver";
+    private static final boolean DEBUG = JobSchedulerService.DEBUG
+            || Log.isLoggable(TAG, Log.DEBUG);
+
+    /**
+     * Maximum number of changing URIs we will batch together to report.
+     * XXX Should be smarter about this, restricting it by the maximum number
+     * of characters we will retain.
+     */
+    private static final int MAX_URIS_REPORTED = 50;
+
+    /**
+     * At this point we consider it urgent to schedule the job ASAP.
+     */
+    private static final int URIS_URGENT_THRESHOLD = 40;
+
+    final private ArraySet<JobStatus> mTrackedTasks = new ArraySet<>();
+    /**
+     * Per-userid {@link JobInfo.TriggerContentUri} keyed ContentObserver cache.
+     */
+    final SparseArray<ArrayMap<JobInfo.TriggerContentUri, ObserverInstance>> mObservers =
+            new SparseArray<>();
+    final Handler mHandler;
+
+    public ContentObserverController(JobSchedulerService service) {
+        super(service);
+        mHandler = new Handler(mContext.getMainLooper());
+    }
+
+    @Override
+    public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
+        if (taskStatus.hasContentTriggerConstraint()) {
+            if (taskStatus.contentObserverJobInstance == null) {
+                taskStatus.contentObserverJobInstance = new JobInstance(taskStatus);
+            }
+            if (DEBUG) {
+                Slog.i(TAG, "Tracking content-trigger job " + taskStatus);
+            }
+            mTrackedTasks.add(taskStatus);
+            taskStatus.setTrackingController(JobStatus.TRACKING_CONTENT);
+            boolean havePendingUris = false;
+            // If there is a previous job associated with the new job, propagate over
+            // any pending content URI trigger reports.
+            if (taskStatus.contentObserverJobInstance.mChangedAuthorities != null) {
+                havePendingUris = true;
+            }
+            // If we have previously reported changed authorities/uris, then we failed
+            // to complete the job with them so will re-record them to report again.
+            if (taskStatus.changedAuthorities != null) {
+                havePendingUris = true;
+                if (taskStatus.contentObserverJobInstance.mChangedAuthorities == null) {
+                    taskStatus.contentObserverJobInstance.mChangedAuthorities
+                            = new ArraySet<>();
+                }
+                for (String auth : taskStatus.changedAuthorities) {
+                    taskStatus.contentObserverJobInstance.mChangedAuthorities.add(auth);
+                }
+                if (taskStatus.changedUris != null) {
+                    if (taskStatus.contentObserverJobInstance.mChangedUris == null) {
+                        taskStatus.contentObserverJobInstance.mChangedUris = new ArraySet<>();
+                    }
+                    for (Uri uri : taskStatus.changedUris) {
+                        taskStatus.contentObserverJobInstance.mChangedUris.add(uri);
+                    }
+                }
+                taskStatus.changedAuthorities = null;
+                taskStatus.changedUris = null;
+            }
+            taskStatus.changedAuthorities = null;
+            taskStatus.changedUris = null;
+            taskStatus.setContentTriggerConstraintSatisfied(havePendingUris);
+        }
+        if (lastJob != null && lastJob.contentObserverJobInstance != null) {
+            // And now we can detach the instance state from the last job.
+            lastJob.contentObserverJobInstance.detachLocked();
+            lastJob.contentObserverJobInstance = null;
+        }
+    }
+
+    @Override
+    public void prepareForExecutionLocked(JobStatus taskStatus) {
+        if (taskStatus.hasContentTriggerConstraint()) {
+            if (taskStatus.contentObserverJobInstance != null) {
+                taskStatus.changedUris = taskStatus.contentObserverJobInstance.mChangedUris;
+                taskStatus.changedAuthorities
+                        = taskStatus.contentObserverJobInstance.mChangedAuthorities;
+                taskStatus.contentObserverJobInstance.mChangedUris = null;
+                taskStatus.contentObserverJobInstance.mChangedAuthorities = null;
+            }
+        }
+    }
+
+    @Override
+    public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob,
+            boolean forUpdate) {
+        if (taskStatus.clearTrackingController(JobStatus.TRACKING_CONTENT)) {
+            mTrackedTasks.remove(taskStatus);
+            if (taskStatus.contentObserverJobInstance != null) {
+                taskStatus.contentObserverJobInstance.unscheduleLocked();
+                if (incomingJob != null) {
+                    if (taskStatus.contentObserverJobInstance != null
+                            && taskStatus.contentObserverJobInstance.mChangedAuthorities != null) {
+                        // We are stopping this job, but it is going to be replaced by this given
+                        // incoming job.  We want to propagate our state over to it, so we don't
+                        // lose any content changes that had happened since the last one started.
+                        // If there is a previous job associated with the new job, propagate over
+                        // any pending content URI trigger reports.
+                        if (incomingJob.contentObserverJobInstance == null) {
+                            incomingJob.contentObserverJobInstance = new JobInstance(incomingJob);
+                        }
+                        incomingJob.contentObserverJobInstance.mChangedAuthorities
+                                = taskStatus.contentObserverJobInstance.mChangedAuthorities;
+                        incomingJob.contentObserverJobInstance.mChangedUris
+                                = taskStatus.contentObserverJobInstance.mChangedUris;
+                        taskStatus.contentObserverJobInstance.mChangedAuthorities = null;
+                        taskStatus.contentObserverJobInstance.mChangedUris = null;
+                    }
+                    // We won't detach the content observers here, because we want to
+                    // allow them to continue monitoring so we don't miss anything...  and
+                    // since we are giving an incomingJob here, we know this will be
+                    // immediately followed by a start tracking of that job.
+                } else {
+                    // But here there is no incomingJob, so nothing coming up, so time to detach.
+                    taskStatus.contentObserverJobInstance.detachLocked();
+                    taskStatus.contentObserverJobInstance = null;
+                }
+            }
+            if (DEBUG) {
+                Slog.i(TAG, "No longer tracking job " + taskStatus);
+            }
+        }
+    }
+
+    @Override
+    public void rescheduleForFailureLocked(JobStatus newJob, JobStatus failureToReschedule) {
+        if (failureToReschedule.hasContentTriggerConstraint()
+                && newJob.hasContentTriggerConstraint()) {
+            // Our job has failed, and we are scheduling a new job for it.
+            // Copy the last reported content changes in to the new job, so when
+            // we schedule the new one we will pick them up and report them again.
+            newJob.changedAuthorities = failureToReschedule.changedAuthorities;
+            newJob.changedUris = failureToReschedule.changedUris;
+        }
+    }
+
+    final class ObserverInstance extends ContentObserver {
+        final JobInfo.TriggerContentUri mUri;
+        final @UserIdInt int mUserId;
+        final ArraySet<JobInstance> mJobs = new ArraySet<>();
+
+        public ObserverInstance(Handler handler, JobInfo.TriggerContentUri uri,
+                @UserIdInt int userId) {
+            super(handler);
+            mUri = uri;
+            mUserId = userId;
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            if (DEBUG) {
+                Slog.i(TAG, "onChange(self=" + selfChange + ") for " + uri
+                        + " when mUri=" + mUri + " mUserId=" + mUserId);
+            }
+            synchronized (mLock) {
+                final int N = mJobs.size();
+                for (int i=0; i<N; i++) {
+                    JobInstance inst = mJobs.valueAt(i);
+                    if (inst.mChangedUris == null) {
+                        inst.mChangedUris = new ArraySet<>();
+                    }
+                    if (inst.mChangedUris.size() < MAX_URIS_REPORTED) {
+                        inst.mChangedUris.add(uri);
+                    }
+                    if (inst.mChangedAuthorities == null) {
+                        inst.mChangedAuthorities = new ArraySet<>();
+                    }
+                    inst.mChangedAuthorities.add(uri.getAuthority());
+                    inst.scheduleLocked();
+                }
+            }
+        }
+    }
+
+    static final class TriggerRunnable implements Runnable {
+        final JobInstance mInstance;
+
+        TriggerRunnable(JobInstance instance) {
+            mInstance = instance;
+        }
+
+        @Override public void run() {
+            mInstance.trigger();
+        }
+    }
+
+    final class JobInstance {
+        final ArrayList<ObserverInstance> mMyObservers = new ArrayList<>();
+        final JobStatus mJobStatus;
+        final Runnable mExecuteRunner;
+        final Runnable mTimeoutRunner;
+        ArraySet<Uri> mChangedUris;
+        ArraySet<String> mChangedAuthorities;
+
+        boolean mTriggerPending;
+
+        // This constructor must be called with the master job scheduler lock held.
+        JobInstance(JobStatus jobStatus) {
+            mJobStatus = jobStatus;
+            mExecuteRunner = new TriggerRunnable(this);
+            mTimeoutRunner = new TriggerRunnable(this);
+            final JobInfo.TriggerContentUri[] uris = jobStatus.getJob().getTriggerContentUris();
+            final int sourceUserId = jobStatus.getSourceUserId();
+            ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observersOfUser =
+                    mObservers.get(sourceUserId);
+            if (observersOfUser == null) {
+                observersOfUser = new ArrayMap<>();
+                mObservers.put(sourceUserId, observersOfUser);
+            }
+            if (uris != null) {
+                for (JobInfo.TriggerContentUri uri : uris) {
+                    ObserverInstance obs = observersOfUser.get(uri);
+                    if (obs == null) {
+                        obs = new ObserverInstance(mHandler, uri, jobStatus.getSourceUserId());
+                        observersOfUser.put(uri, obs);
+                        final boolean andDescendants = (uri.getFlags() &
+                                JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS) != 0;
+                        if (DEBUG) {
+                            Slog.v(TAG, "New observer " + obs + " for " + uri.getUri()
+                                    + " andDescendants=" + andDescendants
+                                    + " sourceUserId=" + sourceUserId);
+                        }
+                        mContext.getContentResolver().registerContentObserver(
+                                uri.getUri(),
+                                andDescendants,
+                                obs,
+                                sourceUserId
+                        );
+                    } else {
+                        if (DEBUG) {
+                            final boolean andDescendants = (uri.getFlags() &
+                                    JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS) != 0;
+                            Slog.v(TAG, "Reusing existing observer " + obs + " for " + uri.getUri()
+                                    + " andDescendants=" + andDescendants);
+                        }
+                    }
+                    obs.mJobs.add(this);
+                    mMyObservers.add(obs);
+                }
+            }
+        }
+
+        void trigger() {
+            boolean reportChange = false;
+            synchronized (mLock) {
+                if (mTriggerPending) {
+                    if (mJobStatus.setContentTriggerConstraintSatisfied(true)) {
+                        reportChange = true;
+                    }
+                    unscheduleLocked();
+                }
+            }
+            // Let the scheduler know that state has changed. This may or may not result in an
+            // execution.
+            if (reportChange) {
+                mStateChangedListener.onControllerStateChanged();
+            }
+        }
+
+        void scheduleLocked() {
+            if (!mTriggerPending) {
+                mTriggerPending = true;
+                mHandler.postDelayed(mTimeoutRunner, mJobStatus.getTriggerContentMaxDelay());
+            }
+            mHandler.removeCallbacks(mExecuteRunner);
+            if (mChangedUris.size() >= URIS_URGENT_THRESHOLD) {
+                // If we start getting near the limit, GO NOW!
+                mHandler.post(mExecuteRunner);
+            } else {
+                mHandler.postDelayed(mExecuteRunner, mJobStatus.getTriggerContentUpdateDelay());
+            }
+        }
+
+        void unscheduleLocked() {
+            if (mTriggerPending) {
+                mHandler.removeCallbacks(mExecuteRunner);
+                mHandler.removeCallbacks(mTimeoutRunner);
+                mTriggerPending = false;
+            }
+        }
+
+        void detachLocked() {
+            final int N = mMyObservers.size();
+            for (int i=0; i<N; i++) {
+                final ObserverInstance obs = mMyObservers.get(i);
+                obs.mJobs.remove(this);
+                if (obs.mJobs.size() == 0) {
+                    if (DEBUG) {
+                        Slog.i(TAG, "Unregistering observer " + obs + " for " + obs.mUri.getUri());
+                    }
+                    mContext.getContentResolver().unregisterContentObserver(obs);
+                    ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observerOfUser =
+                            mObservers.get(obs.mUserId);
+                    if (observerOfUser !=  null) {
+                        observerOfUser.remove(obs.mUri);
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void dumpControllerStateLocked(IndentingPrintWriter pw,
+            Predicate<JobStatus> predicate) {
+        for (int i = 0; i < mTrackedTasks.size(); i++) {
+            JobStatus js = mTrackedTasks.valueAt(i);
+            if (!predicate.test(js)) {
+                continue;
+            }
+            pw.print("#");
+            js.printUniqueId(pw);
+            pw.print(" from ");
+            UserHandle.formatUid(pw, js.getSourceUid());
+            pw.println();
+        }
+        pw.println();
+
+        int N = mObservers.size();
+        if (N > 0) {
+            pw.println("Observers:");
+            pw.increaseIndent();
+            for (int userIdx = 0; userIdx < N; userIdx++) {
+                final int userId = mObservers.keyAt(userIdx);
+                ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observersOfUser =
+                        mObservers.get(userId);
+                int numbOfObserversPerUser = observersOfUser.size();
+                for (int observerIdx = 0 ; observerIdx < numbOfObserversPerUser; observerIdx++) {
+                    ObserverInstance obs = observersOfUser.valueAt(observerIdx);
+                    int M = obs.mJobs.size();
+                    boolean shouldDump = false;
+                    for (int j = 0; j < M; j++) {
+                        JobInstance inst = obs.mJobs.valueAt(j);
+                        if (predicate.test(inst.mJobStatus)) {
+                            shouldDump = true;
+                            break;
+                        }
+                    }
+                    if (!shouldDump) {
+                        continue;
+                    }
+                    JobInfo.TriggerContentUri trigger = observersOfUser.keyAt(observerIdx);
+                    pw.print(trigger.getUri());
+                    pw.print(" 0x");
+                    pw.print(Integer.toHexString(trigger.getFlags()));
+                    pw.print(" (");
+                    pw.print(System.identityHashCode(obs));
+                    pw.println("):");
+                    pw.increaseIndent();
+                    pw.println("Jobs:");
+                    pw.increaseIndent();
+                    for (int j = 0; j < M; j++) {
+                        JobInstance inst = obs.mJobs.valueAt(j);
+                        pw.print("#");
+                        inst.mJobStatus.printUniqueId(pw);
+                        pw.print(" from ");
+                        UserHandle.formatUid(pw, inst.mJobStatus.getSourceUid());
+                        if (inst.mChangedAuthorities != null) {
+                            pw.println(":");
+                            pw.increaseIndent();
+                            if (inst.mTriggerPending) {
+                                pw.print("Trigger pending: update=");
+                                TimeUtils.formatDuration(
+                                        inst.mJobStatus.getTriggerContentUpdateDelay(), pw);
+                                pw.print(", max=");
+                                TimeUtils.formatDuration(
+                                        inst.mJobStatus.getTriggerContentMaxDelay(), pw);
+                                pw.println();
+                            }
+                            pw.println("Changed Authorities:");
+                            for (int k = 0; k < inst.mChangedAuthorities.size(); k++) {
+                                pw.println(inst.mChangedAuthorities.valueAt(k));
+                            }
+                            if (inst.mChangedUris != null) {
+                                pw.println("          Changed URIs:");
+                                for (int k = 0; k < inst.mChangedUris.size(); k++) {
+                                    pw.println(inst.mChangedUris.valueAt(k));
+                                }
+                            }
+                            pw.decreaseIndent();
+                        } else {
+                            pw.println();
+                        }
+                    }
+                    pw.decreaseIndent();
+                    pw.decreaseIndent();
+                }
+            }
+            pw.decreaseIndent();
+        }
+    }
+
+    @Override
+    public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
+            Predicate<JobStatus> predicate) {
+        final long token = proto.start(fieldId);
+        final long mToken = proto.start(StateControllerProto.CONTENT_OBSERVER);
+
+        for (int i = 0; i < mTrackedTasks.size(); i++) {
+            JobStatus js = mTrackedTasks.valueAt(i);
+            if (!predicate.test(js)) {
+                continue;
+            }
+            final long jsToken =
+                    proto.start(StateControllerProto.ContentObserverController.TRACKED_JOBS);
+            js.writeToShortProto(proto,
+                    StateControllerProto.ContentObserverController.TrackedJob.INFO);
+            proto.write(StateControllerProto.ContentObserverController.TrackedJob.SOURCE_UID,
+                    js.getSourceUid());
+            proto.end(jsToken);
+        }
+
+        final int n = mObservers.size();
+        for (int userIdx = 0; userIdx < n; userIdx++) {
+            final long oToken =
+                    proto.start(StateControllerProto.ContentObserverController.OBSERVERS);
+            final int userId = mObservers.keyAt(userIdx);
+
+            proto.write(StateControllerProto.ContentObserverController.Observer.USER_ID, userId);
+
+            ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observersOfUser =
+                    mObservers.get(userId);
+            int numbOfObserversPerUser = observersOfUser.size();
+            for (int observerIdx = 0 ; observerIdx < numbOfObserversPerUser; observerIdx++) {
+                ObserverInstance obs = observersOfUser.valueAt(observerIdx);
+                int m = obs.mJobs.size();
+                boolean shouldDump = false;
+                for (int j = 0; j < m; j++) {
+                    JobInstance inst = obs.mJobs.valueAt(j);
+                    if (predicate.test(inst.mJobStatus)) {
+                        shouldDump = true;
+                        break;
+                    }
+                }
+                if (!shouldDump) {
+                    continue;
+                }
+                final long tToken = proto.start(
+                        StateControllerProto.ContentObserverController.Observer.TRIGGERS);
+
+                JobInfo.TriggerContentUri trigger = observersOfUser.keyAt(observerIdx);
+                Uri u = trigger.getUri();
+                if (u != null) {
+                    proto.write(TriggerContentData.URI, u.toString());
+                }
+                proto.write(TriggerContentData.FLAGS, trigger.getFlags());
+
+                for (int j = 0; j < m; j++) {
+                    final long jToken = proto.start(TriggerContentData.JOBS);
+                    JobInstance inst = obs.mJobs.valueAt(j);
+
+                    inst.mJobStatus.writeToShortProto(proto, TriggerContentData.JobInstance.INFO);
+                    proto.write(TriggerContentData.JobInstance.SOURCE_UID,
+                            inst.mJobStatus.getSourceUid());
+
+                    if (inst.mChangedAuthorities == null) {
+                        proto.end(jToken);
+                        continue;
+                    }
+                    if (inst.mTriggerPending) {
+                        proto.write(TriggerContentData.JobInstance.TRIGGER_CONTENT_UPDATE_DELAY_MS,
+                                inst.mJobStatus.getTriggerContentUpdateDelay());
+                        proto.write(TriggerContentData.JobInstance.TRIGGER_CONTENT_MAX_DELAY_MS,
+                                inst.mJobStatus.getTriggerContentMaxDelay());
+                    }
+                    for (int k = 0; k < inst.mChangedAuthorities.size(); k++) {
+                        proto.write(TriggerContentData.JobInstance.CHANGED_AUTHORITIES,
+                                inst.mChangedAuthorities.valueAt(k));
+                    }
+                    if (inst.mChangedUris != null) {
+                        for (int k = 0; k < inst.mChangedUris.size(); k++) {
+                            u = inst.mChangedUris.valueAt(k);
+                            if (u != null) {
+                                proto.write(TriggerContentData.JobInstance.CHANGED_URIS,
+                                        u.toString());
+                            }
+                        }
+                    }
+
+                    proto.end(jToken);
+                }
+
+                proto.end(tToken);
+            }
+
+            proto.end(oToken);
+        }
+
+        proto.end(mToken);
+        proto.end(token);
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
new file mode 100644
index 0000000..127a5c8
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers;
+
+import android.app.job.JobInfo;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.UserHandle;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseBooleanArray;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.DeviceIdleController;
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateControllerProto;
+import com.android.server.job.StateControllerProto.DeviceIdleJobsController.TrackedJob;
+
+import java.util.Arrays;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+/**
+ * When device is dozing, set constraint for all jobs, except whitelisted apps, as not satisfied.
+ * When device is not dozing, set constraint for all jobs as satisfied.
+ */
+public final class DeviceIdleJobsController extends StateController {
+    private static final String TAG = "JobScheduler.DeviceIdle";
+    private static final boolean DEBUG = JobSchedulerService.DEBUG
+            || Log.isLoggable(TAG, Log.DEBUG);
+
+    private static final long BACKGROUND_JOBS_DELAY = 3000;
+
+    static final int PROCESS_BACKGROUND_JOBS = 1;
+
+    /**
+     * These are jobs added with a special flag to indicate that they should be exempted from doze
+     * when the app is temp whitelisted or in the foreground.
+     */
+    private final ArraySet<JobStatus> mAllowInIdleJobs;
+    private final SparseBooleanArray mForegroundUids;
+    private final DeviceIdleUpdateFunctor mDeviceIdleUpdateFunctor;
+    private final DeviceIdleJobsDelayHandler mHandler;
+    private final PowerManager mPowerManager;
+    private final DeviceIdleController.LocalService mLocalDeviceIdleController;
+
+    /**
+     * True when in device idle mode, so we don't want to schedule any jobs.
+     */
+    private boolean mDeviceIdleMode;
+    private int[] mDeviceIdleWhitelistAppIds;
+    private int[] mPowerSaveTempWhitelistAppIds;
+
+    // onReceive
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED:
+                case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED:
+                    updateIdleMode(mPowerManager != null && (mPowerManager.isDeviceIdleMode()
+                            || mPowerManager.isLightDeviceIdleMode()));
+                    break;
+                case PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED:
+                    synchronized (mLock) {
+                        mDeviceIdleWhitelistAppIds =
+                                mLocalDeviceIdleController.getPowerSaveWhitelistUserAppIds();
+                        if (DEBUG) {
+                            Slog.d(TAG, "Got whitelist "
+                                    + Arrays.toString(mDeviceIdleWhitelistAppIds));
+                        }
+                    }
+                    break;
+                case PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED:
+                    synchronized (mLock) {
+                        mPowerSaveTempWhitelistAppIds =
+                                mLocalDeviceIdleController.getPowerSaveTempWhitelistAppIds();
+                        if (DEBUG) {
+                            Slog.d(TAG, "Got temp whitelist "
+                                    + Arrays.toString(mPowerSaveTempWhitelistAppIds));
+                        }
+                        boolean changed = false;
+                        for (int i = 0; i < mAllowInIdleJobs.size(); i++) {
+                            changed |= updateTaskStateLocked(mAllowInIdleJobs.valueAt(i));
+                        }
+                        if (changed) {
+                            mStateChangedListener.onControllerStateChanged();
+                        }
+                    }
+                    break;
+            }
+        }
+    };
+
+    public DeviceIdleJobsController(JobSchedulerService service) {
+        super(service);
+
+        mHandler = new DeviceIdleJobsDelayHandler(mContext.getMainLooper());
+        // Register for device idle mode changes
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        mLocalDeviceIdleController =
+                LocalServices.getService(DeviceIdleController.LocalService.class);
+        mDeviceIdleWhitelistAppIds = mLocalDeviceIdleController.getPowerSaveWhitelistUserAppIds();
+        mPowerSaveTempWhitelistAppIds =
+                mLocalDeviceIdleController.getPowerSaveTempWhitelistAppIds();
+        mDeviceIdleUpdateFunctor = new DeviceIdleUpdateFunctor();
+        mAllowInIdleJobs = new ArraySet<>();
+        mForegroundUids = new SparseBooleanArray();
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+        filter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
+        filter.addAction(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
+        filter.addAction(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
+        mContext.registerReceiverAsUser(
+                mBroadcastReceiver, UserHandle.ALL, filter, null, null);
+    }
+
+    void updateIdleMode(boolean enabled) {
+        boolean changed = false;
+        synchronized (mLock) {
+            if (mDeviceIdleMode != enabled) {
+                changed = true;
+            }
+            mDeviceIdleMode = enabled;
+            if (DEBUG) Slog.d(TAG, "mDeviceIdleMode=" + mDeviceIdleMode);
+            if (enabled) {
+                mHandler.removeMessages(PROCESS_BACKGROUND_JOBS);
+                mService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor);
+            } else {
+                // When coming out of doze, process all foreground uids immediately, while others
+                // will be processed after a delay of 3 seconds.
+                for (int i = 0; i < mForegroundUids.size(); i++) {
+                    if (mForegroundUids.valueAt(i)) {
+                        mService.getJobStore().forEachJobForSourceUid(
+                                mForegroundUids.keyAt(i), mDeviceIdleUpdateFunctor);
+                    }
+                }
+                mHandler.sendEmptyMessageDelayed(PROCESS_BACKGROUND_JOBS, BACKGROUND_JOBS_DELAY);
+            }
+        }
+        // Inform the job scheduler service about idle mode changes
+        if (changed) {
+            mStateChangedListener.onDeviceIdleStateChanged(enabled);
+        }
+    }
+
+    /**
+     *  Called by jobscheduler service to report uid state changes between active and idle
+     */
+    public void setUidActiveLocked(int uid, boolean active) {
+        final boolean changed = (active != mForegroundUids.get(uid));
+        if (!changed) {
+            return;
+        }
+        if (DEBUG) {
+            Slog.d(TAG, "uid " + uid + " going " + (active ? "active" : "inactive"));
+        }
+        mForegroundUids.put(uid, active);
+        mDeviceIdleUpdateFunctor.mChanged = false;
+        mService.getJobStore().forEachJobForSourceUid(uid, mDeviceIdleUpdateFunctor);
+        if (mDeviceIdleUpdateFunctor.mChanged) {
+            mStateChangedListener.onControllerStateChanged();
+        }
+    }
+
+    /**
+     * Checks if the given job's scheduling app id exists in the device idle user whitelist.
+     */
+    boolean isWhitelistedLocked(JobStatus job) {
+        return Arrays.binarySearch(mDeviceIdleWhitelistAppIds,
+                UserHandle.getAppId(job.getSourceUid())) >= 0;
+    }
+
+    /**
+     * Checks if the given job's scheduling app id exists in the device idle temp whitelist.
+     */
+    boolean isTempWhitelistedLocked(JobStatus job) {
+        return ArrayUtils.contains(mPowerSaveTempWhitelistAppIds,
+                UserHandle.getAppId(job.getSourceUid()));
+    }
+
+    private boolean updateTaskStateLocked(JobStatus task) {
+        final boolean allowInIdle = ((task.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0)
+                && (mForegroundUids.get(task.getSourceUid()) || isTempWhitelistedLocked(task));
+        final boolean whitelisted = isWhitelistedLocked(task);
+        final boolean enableTask = !mDeviceIdleMode || whitelisted || allowInIdle;
+        return task.setDeviceNotDozingConstraintSatisfied(enableTask, whitelisted);
+    }
+
+    @Override
+    public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
+        if ((jobStatus.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0) {
+            mAllowInIdleJobs.add(jobStatus);
+        }
+        updateTaskStateLocked(jobStatus);
+    }
+
+    @Override
+    public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
+            boolean forUpdate) {
+        if ((jobStatus.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0) {
+            mAllowInIdleJobs.remove(jobStatus);
+        }
+    }
+
+    @Override
+    public void dumpControllerStateLocked(final IndentingPrintWriter pw,
+            final Predicate<JobStatus> predicate) {
+        pw.println("Idle mode: " + mDeviceIdleMode);
+        pw.println();
+
+        mService.getJobStore().forEachJob(predicate, (jobStatus) -> {
+            pw.print("#");
+            jobStatus.printUniqueId(pw);
+            pw.print(" from ");
+            UserHandle.formatUid(pw, jobStatus.getSourceUid());
+            pw.print(": ");
+            pw.print(jobStatus.getSourcePackageName());
+            pw.print((jobStatus.satisfiedConstraints
+                    & JobStatus.CONSTRAINT_DEVICE_NOT_DOZING) != 0
+                            ? " RUNNABLE" : " WAITING");
+            if (jobStatus.dozeWhitelisted) {
+                pw.print(" WHITELISTED");
+            }
+            if (mAllowInIdleJobs.contains(jobStatus)) {
+                pw.print(" ALLOWED_IN_DOZE");
+            }
+            pw.println();
+        });
+    }
+
+    @Override
+    public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
+            Predicate<JobStatus> predicate) {
+        final long token = proto.start(fieldId);
+        final long mToken = proto.start(StateControllerProto.DEVICE_IDLE);
+
+        proto.write(StateControllerProto.DeviceIdleJobsController.IS_DEVICE_IDLE_MODE,
+                mDeviceIdleMode);
+        mService.getJobStore().forEachJob(predicate, (jobStatus) -> {
+            final long jsToken =
+                    proto.start(StateControllerProto.DeviceIdleJobsController.TRACKED_JOBS);
+
+            jobStatus.writeToShortProto(proto, TrackedJob.INFO);
+            proto.write(TrackedJob.SOURCE_UID, jobStatus.getSourceUid());
+            proto.write(TrackedJob.SOURCE_PACKAGE_NAME, jobStatus.getSourcePackageName());
+            proto.write(TrackedJob.ARE_CONSTRAINTS_SATISFIED,
+                    (jobStatus.satisfiedConstraints &
+                        JobStatus.CONSTRAINT_DEVICE_NOT_DOZING) != 0);
+            proto.write(TrackedJob.IS_DOZE_WHITELISTED, jobStatus.dozeWhitelisted);
+            proto.write(TrackedJob.IS_ALLOWED_IN_DOZE, mAllowInIdleJobs.contains(jobStatus));
+
+            proto.end(jsToken);
+        });
+
+        proto.end(mToken);
+        proto.end(token);
+    }
+
+    final class DeviceIdleUpdateFunctor implements Consumer<JobStatus> {
+        boolean mChanged;
+
+        @Override
+        public void accept(JobStatus jobStatus) {
+            mChanged |= updateTaskStateLocked(jobStatus);
+        }
+    }
+
+    final class DeviceIdleJobsDelayHandler extends Handler {
+        public DeviceIdleJobsDelayHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case PROCESS_BACKGROUND_JOBS:
+                    // Just process all the jobs, the ones in foreground should already be running.
+                    synchronized (mLock) {
+                        mDeviceIdleUpdateFunctor.mChanged = false;
+                        mService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor);
+                        if (mDeviceIdleUpdateFunctor.mChanged) {
+                            mStateChangedListener.onControllerStateChanged();
+                        }
+                    }
+                    break;
+            }
+        }
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
new file mode 100644
index 0000000..e3c311f
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.util.ArraySet;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateControllerProto;
+import com.android.server.job.controllers.idle.CarIdlenessTracker;
+import com.android.server.job.controllers.idle.DeviceIdlenessTracker;
+import com.android.server.job.controllers.idle.IdlenessListener;
+import com.android.server.job.controllers.idle.IdlenessTracker;
+
+import java.util.function.Predicate;
+
+public final class IdleController extends StateController implements IdlenessListener {
+    private static final String TAG = "JobScheduler.IdleController";
+    // Policy: we decide that we're "idle" if the device has been unused /
+    // screen off or dreaming or wireless charging dock idle for at least this long
+    final ArraySet<JobStatus> mTrackedTasks = new ArraySet<>();
+    IdlenessTracker mIdleTracker;
+
+    public IdleController(JobSchedulerService service) {
+        super(service);
+        initIdleStateTracking(mContext);
+    }
+
+    /**
+     * StateController interface
+     */
+    @Override
+    public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
+        if (taskStatus.hasIdleConstraint()) {
+            mTrackedTasks.add(taskStatus);
+            taskStatus.setTrackingController(JobStatus.TRACKING_IDLE);
+            taskStatus.setIdleConstraintSatisfied(mIdleTracker.isIdle());
+        }
+    }
+
+    @Override
+    public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob,
+            boolean forUpdate) {
+        if (taskStatus.clearTrackingController(JobStatus.TRACKING_IDLE)) {
+            mTrackedTasks.remove(taskStatus);
+        }
+    }
+
+    /**
+     * State-change notifications from the idleness tracker
+     */
+    @Override
+    public void reportNewIdleState(boolean isIdle) {
+        synchronized (mLock) {
+            for (int i = mTrackedTasks.size()-1; i >= 0; i--) {
+                mTrackedTasks.valueAt(i).setIdleConstraintSatisfied(isIdle);
+            }
+        }
+        mStateChangedListener.onControllerStateChanged();
+    }
+
+    /**
+     * Idle state tracking, and messaging with the task manager when
+     * significant state changes occur
+     */
+    private void initIdleStateTracking(Context ctx) {
+        final boolean isCar = mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_AUTOMOTIVE);
+        if (isCar) {
+            mIdleTracker = new CarIdlenessTracker();
+        } else {
+            mIdleTracker = new DeviceIdlenessTracker();
+        }
+        mIdleTracker.startTracking(ctx, this);
+    }
+
+    @Override
+    public void dumpControllerStateLocked(IndentingPrintWriter pw,
+            Predicate<JobStatus> predicate) {
+        pw.println("Currently idle: " + mIdleTracker.isIdle());
+        pw.println("Idleness tracker:"); mIdleTracker.dump(pw);
+        pw.println();
+
+        for (int i = 0; i < mTrackedTasks.size(); i++) {
+            final JobStatus js = mTrackedTasks.valueAt(i);
+            if (!predicate.test(js)) {
+                continue;
+            }
+            pw.print("#");
+            js.printUniqueId(pw);
+            pw.print(" from ");
+            UserHandle.formatUid(pw, js.getSourceUid());
+            pw.println();
+        }
+    }
+
+    @Override
+    public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
+            Predicate<JobStatus> predicate) {
+        final long token = proto.start(fieldId);
+        final long mToken = proto.start(StateControllerProto.IDLE);
+
+        proto.write(StateControllerProto.IdleController.IS_IDLE, mIdleTracker.isIdle());
+
+        for (int i = 0; i < mTrackedTasks.size(); i++) {
+            final JobStatus js = mTrackedTasks.valueAt(i);
+            if (!predicate.test(js)) {
+                continue;
+            }
+            final long jsToken = proto.start(StateControllerProto.IdleController.TRACKED_JOBS);
+            js.writeToShortProto(proto, StateControllerProto.IdleController.TrackedJob.INFO);
+            proto.write(StateControllerProto.IdleController.TrackedJob.SOURCE_UID,
+                    js.getSourceUid());
+            proto.end(jsToken);
+        }
+
+        proto.end(mToken);
+        proto.end(token);
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
new file mode 100644
index 0000000..6f2b334
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -0,0 +1,1861 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers;
+
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
+import android.app.AppGlobals;
+import android.app.IActivityManager;
+import android.app.job.JobInfo;
+import android.app.job.JobWorkItem;
+import android.content.ClipData;
+import android.content.ComponentName;
+import android.net.Network;
+import android.net.Uri;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.text.format.TimeMigrationUtils;
+import android.util.ArraySet;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.StatsLog;
+import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.server.LocalServices;
+import com.android.server.job.GrantedUriPermissions;
+import com.android.server.job.JobSchedulerInternal;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.JobServerProtoEnums;
+import com.android.server.job.JobStatusDumpProto;
+import com.android.server.job.JobStatusShortInfoProto;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.function.Predicate;
+
+/**
+ * Uniquely identifies a job internally.
+ * Created from the public {@link android.app.job.JobInfo} object when it lands on the scheduler.
+ * Contains current state of the requirements of the job, as well as a function to evaluate
+ * whether it's ready to run.
+ * This object is shared among the various controllers - hence why the different fields are atomic.
+ * This isn't strictly necessary because each controller is only interested in a specific field,
+ * and the receivers that are listening for global state change will all run on the main looper,
+ * but we don't enforce that so this is safer.
+ *
+ * Test: atest com.android.server.job.controllers.JobStatusTest
+ * @hide
+ */
+public final class JobStatus {
+    static final String TAG = "JobSchedulerService";
+    static final boolean DEBUG = JobSchedulerService.DEBUG;
+
+    public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
+    public static final long NO_EARLIEST_RUNTIME = 0L;
+
+    static final int CONSTRAINT_CHARGING = JobInfo.CONSTRAINT_FLAG_CHARGING; // 1 < 0
+    static final int CONSTRAINT_IDLE = JobInfo.CONSTRAINT_FLAG_DEVICE_IDLE;  // 1 << 2
+    static final int CONSTRAINT_BATTERY_NOT_LOW = JobInfo.CONSTRAINT_FLAG_BATTERY_NOT_LOW; // 1 << 1
+    static final int CONSTRAINT_STORAGE_NOT_LOW = JobInfo.CONSTRAINT_FLAG_STORAGE_NOT_LOW; // 1 << 3
+    static final int CONSTRAINT_TIMING_DELAY = 1<<31;
+    static final int CONSTRAINT_DEADLINE = 1<<30;
+    static final int CONSTRAINT_CONNECTIVITY = 1<<28;
+    static final int CONSTRAINT_CONTENT_TRIGGER = 1<<26;
+    static final int CONSTRAINT_DEVICE_NOT_DOZING = 1 << 25; // Implicit constraint
+    static final int CONSTRAINT_WITHIN_QUOTA = 1 << 24;      // Implicit constraint
+    static final int CONSTRAINT_BACKGROUND_NOT_RESTRICTED = 1 << 22; // Implicit constraint
+
+    /**
+     * The constraints that we want to log to statsd.
+     *
+     * Constraints that can be inferred from other atoms have been excluded to avoid logging too
+     * much information and to reduce redundancy:
+     *
+     * * CONSTRAINT_CHARGING can be inferred with PluggedStateChanged (Atom #32)
+     * * CONSTRAINT_BATTERY_NOT_LOW can be inferred with BatteryLevelChanged (Atom #30)
+     * * CONSTRAINT_CONNECTIVITY can be partially inferred with ConnectivityStateChanged
+     * (Atom #98) and BatterySaverModeStateChanged (Atom #20).
+     * * CONSTRAINT_DEVICE_NOT_DOZING can be mostly inferred with DeviceIdleModeStateChanged
+     * (Atom #21)
+     * * CONSTRAINT_BACKGROUND_NOT_RESTRICTED can be inferred with BatterySaverModeStateChanged
+     * (Atom #20)
+     */
+    private static final int STATSD_CONSTRAINTS_TO_LOG = CONSTRAINT_CONTENT_TRIGGER
+            | CONSTRAINT_DEADLINE
+            | CONSTRAINT_IDLE
+            | CONSTRAINT_STORAGE_NOT_LOW
+            | CONSTRAINT_TIMING_DELAY
+            | CONSTRAINT_WITHIN_QUOTA;
+
+    // TODO(b/129954980)
+    private static final boolean STATS_LOG_ENABLED = false;
+
+    // Soft override: ignore constraints like time that don't affect API availability
+    public static final int OVERRIDE_SOFT = 1;
+    // Full override: ignore all constraints including API-affecting like connectivity
+    public static final int OVERRIDE_FULL = 2;
+
+    /** If not specified, trigger update delay is 10 seconds. */
+    public static final long DEFAULT_TRIGGER_UPDATE_DELAY = 10*1000;
+
+    /** The minimum possible update delay is 1/2 second. */
+    public static final long MIN_TRIGGER_UPDATE_DELAY = 500;
+
+    /** If not specified, trigger maxumum delay is 2 minutes. */
+    public static final long DEFAULT_TRIGGER_MAX_DELAY = 2*60*1000;
+
+    /** The minimum possible update delay is 1 second. */
+    public static final long MIN_TRIGGER_MAX_DELAY = 1000;
+
+    final JobInfo job;
+    /**
+     * Uid of the package requesting this job.  This can differ from the "source"
+     * uid when the job was scheduled on the app's behalf, such as with the jobs
+     * that underly Sync Manager operation.
+     */
+    final int callingUid;
+    final String batteryName;
+
+    /**
+     * Identity of the app in which the job is hosted.
+     */
+    final String sourcePackageName;
+    final int sourceUserId;
+    final int sourceUid;
+    final String sourceTag;
+
+    final String tag;
+
+    private GrantedUriPermissions uriPerms;
+    private boolean prepared;
+
+    static final boolean DEBUG_PREPARE = true;
+    private Throwable unpreparedPoint = null;
+
+    /**
+     * Earliest point in the future at which this job will be eligible to run. A value of 0
+     * indicates there is no delay constraint. See {@link #hasTimingDelayConstraint()}.
+     */
+    private final long earliestRunTimeElapsedMillis;
+    /**
+     * Latest point in the future at which this job must be run. A value of {@link Long#MAX_VALUE}
+     * indicates there is no deadline constraint. See {@link #hasDeadlineConstraint()}.
+     */
+    private final long latestRunTimeElapsedMillis;
+
+    /**
+     * Valid only for periodic jobs. The original latest point in the future at which this
+     * job was expected to run.
+     */
+    private long mOriginalLatestRunTimeElapsedMillis;
+
+    /** How many times this job has failed, used to compute back-off. */
+    private final int numFailures;
+
+    /**
+     * Current standby heartbeat when this job was scheduled or last ran.  Used to
+     * pin the runnability check regardless of the job's app moving between buckets.
+     */
+    private final long baseHeartbeat;
+
+    /**
+     * Which app standby bucket this job's app is in.  Updated when the app is moved to a
+     * different bucket.
+     */
+    private int standbyBucket;
+
+    /**
+     * Debugging: timestamp if we ever defer this job based on standby bucketing, this
+     * is when we did so.
+     */
+    private long whenStandbyDeferred;
+
+    /** The first time this job was force batched. */
+    private long mFirstForceBatchedTimeElapsed;
+
+    // Constraints.
+    final int requiredConstraints;
+    private final int mRequiredConstraintsOfInterest;
+    int satisfiedConstraints = 0;
+    private int mSatisfiedConstraintsOfInterest = 0;
+
+    // Set to true if doze constraint was satisfied due to app being whitelisted.
+    public boolean dozeWhitelisted;
+
+    // Set to true when the app is "active" per AppStateTracker
+    public boolean uidActive;
+
+    /**
+     * Flag for {@link #trackingControllers}: the battery controller is currently tracking this job.
+     */
+    public static final int TRACKING_BATTERY = 1<<0;
+    /**
+     * Flag for {@link #trackingControllers}: the network connectivity controller is currently
+     * tracking this job.
+     */
+    public static final int TRACKING_CONNECTIVITY = 1<<1;
+    /**
+     * Flag for {@link #trackingControllers}: the content observer controller is currently
+     * tracking this job.
+     */
+    public static final int TRACKING_CONTENT = 1<<2;
+    /**
+     * Flag for {@link #trackingControllers}: the idle controller is currently tracking this job.
+     */
+    public static final int TRACKING_IDLE = 1<<3;
+    /**
+     * Flag for {@link #trackingControllers}: the storage controller is currently tracking this job.
+     */
+    public static final int TRACKING_STORAGE = 1<<4;
+    /**
+     * Flag for {@link #trackingControllers}: the time controller is currently tracking this job.
+     */
+    public static final int TRACKING_TIME = 1<<5;
+    /**
+     * Flag for {@link #trackingControllers}: the quota controller is currently tracking this job.
+     */
+    public static final int TRACKING_QUOTA = 1 << 6;
+
+    /**
+     * Bit mask of controllers that are currently tracking the job.
+     */
+    private int trackingControllers;
+
+    /**
+     * Flag for {@link #mInternalFlags}: this job was scheduled when the app that owns the job
+     * service (not necessarily the caller) was in the foreground and the job has no time
+     * constraints, which makes it exempted from the battery saver job restriction.
+     *
+     * @hide
+     */
+    public static final int INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION = 1 << 0;
+
+    /**
+     * Versatile, persistable flags for a job that's updated within the system server,
+     * as opposed to {@link JobInfo#flags} that's set by callers.
+     */
+    private int mInternalFlags;
+
+    // These are filled in by controllers when preparing for execution.
+    public ArraySet<Uri> changedUris;
+    public ArraySet<String> changedAuthorities;
+    public Network network;
+
+    public int lastEvaluatedPriority;
+
+    // If non-null, this is work that has been enqueued for the job.
+    public ArrayList<JobWorkItem> pendingWork;
+
+    // If non-null, this is work that is currently being executed.
+    public ArrayList<JobWorkItem> executingWork;
+
+    public int nextPendingWorkId = 1;
+
+    // Used by shell commands
+    public int overrideState = 0;
+
+    // When this job was enqueued, for ordering.  (in elapsedRealtimeMillis)
+    public long enqueueTime;
+
+    // Metrics about queue latency.  (in uptimeMillis)
+    public long madePending;
+    public long madeActive;
+
+    /**
+     * Last time a job finished successfully for a periodic job, in the currentTimeMillis time,
+     * for dumpsys.
+     */
+    private long mLastSuccessfulRunTime;
+
+    /**
+     * Last time a job finished unsuccessfully, in the currentTimeMillis time, for dumpsys.
+     */
+    private long mLastFailedRunTime;
+
+    /**
+     * Transient: when a job is inflated from disk before we have a reliable RTC clock time,
+     * we retain the canonical (delay, deadline) scheduling tuple read out of the persistent
+     * store in UTC so that we can fix up the job's scheduling criteria once we get a good
+     * wall-clock time.  If we have to persist the job again before the clock has been updated,
+     * we record these times again rather than calculating based on the earliest/latest elapsed
+     * time base figures.
+     *
+     * 'first' is the earliest/delay time, and 'second' is the latest/deadline time.
+     */
+    private Pair<Long, Long> mPersistedUtcTimes;
+
+    /**
+     * For use only by ContentObserverController: state it is maintaining about content URIs
+     * being observed.
+     */
+    ContentObserverController.JobInstance contentObserverJobInstance;
+
+    private long mTotalNetworkDownloadBytes = JobInfo.NETWORK_BYTES_UNKNOWN;
+    private long mTotalNetworkUploadBytes = JobInfo.NETWORK_BYTES_UNKNOWN;
+
+    /////// Booleans that track if a job is ready to run. They should be updated whenever dependent
+    /////// states change.
+
+    /**
+     * The deadline for the job has passed. This is only good for non-periodic jobs. A periodic job
+     * should only run if its constraints are satisfied.
+     * Computed as: NOT periodic AND has deadline constraint AND deadline constraint satisfied.
+     */
+    private boolean mReadyDeadlineSatisfied;
+
+    /**
+     * The device isn't Dozing or this job will be in the foreground. This implicit constraint must
+     * be satisfied.
+     */
+    private boolean mReadyNotDozing;
+
+    /**
+     * The job is not restricted from running in the background (due to Battery Saver). This
+     * implicit constraint must be satisfied.
+     */
+    private boolean mReadyNotRestrictedInBg;
+
+    /** The job is within its quota based on its standby bucket. */
+    private boolean mReadyWithinQuota;
+
+    /** Provide a handle to the service that this job will be run on. */
+    public int getServiceToken() {
+        return callingUid;
+    }
+
+    /**
+     * Core constructor for JobStatus instances.  All other ctors funnel down to this one.
+     *
+     * @param job The actual requested parameters for the job
+     * @param callingUid Identity of the app that is scheduling the job.  This may not be the
+     *     app in which the job is implemented; such as with sync jobs.
+     * @param sourcePackageName The package name of the app in which the job will run.
+     * @param sourceUserId The user in which the job will run
+     * @param standbyBucket The standby bucket that the source package is currently assigned to,
+     *     cached here for speed of handling during runnability evaluations (and updated when bucket
+     *     assignments are changed)
+     * @param heartbeat Timestamp of when the job was created, in the standby-related
+     *     timebase.
+     * @param tag A string associated with the job for debugging/logging purposes.
+     * @param numFailures Count of how many times this job has requested a reschedule because
+     *     its work was not yet finished.
+     * @param earliestRunTimeElapsedMillis Milestone: earliest point in time at which the job
+     *     is to be considered runnable
+     * @param latestRunTimeElapsedMillis Milestone: point in time at which the job will be
+     *     considered overdue
+     * @param lastSuccessfulRunTime When did we last run this job to completion?
+     * @param lastFailedRunTime When did we last run this job only to have it stop incomplete?
+     * @param internalFlags Non-API property flags about this job
+     */
+    private JobStatus(JobInfo job, int callingUid, String sourcePackageName,
+            int sourceUserId, int standbyBucket, long heartbeat, String tag, int numFailures,
+            long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis,
+            long lastSuccessfulRunTime, long lastFailedRunTime, int internalFlags) {
+        this.job = job;
+        this.callingUid = callingUid;
+        this.standbyBucket = standbyBucket;
+        this.baseHeartbeat = heartbeat;
+
+        int tempSourceUid = -1;
+        if (sourceUserId != -1 && sourcePackageName != null) {
+            try {
+                tempSourceUid = AppGlobals.getPackageManager().getPackageUid(sourcePackageName, 0,
+                        sourceUserId);
+            } catch (RemoteException ex) {
+                // Can't happen, PackageManager runs in the same process.
+            }
+        }
+        if (tempSourceUid == -1) {
+            this.sourceUid = callingUid;
+            this.sourceUserId = UserHandle.getUserId(callingUid);
+            this.sourcePackageName = job.getService().getPackageName();
+            this.sourceTag = null;
+        } else {
+            this.sourceUid = tempSourceUid;
+            this.sourceUserId = sourceUserId;
+            this.sourcePackageName = sourcePackageName;
+            this.sourceTag = tag;
+        }
+
+        this.batteryName = this.sourceTag != null
+                ? this.sourceTag + ":" + job.getService().getPackageName()
+                : job.getService().flattenToShortString();
+        this.tag = "*job*/" + this.batteryName;
+
+        this.earliestRunTimeElapsedMillis = earliestRunTimeElapsedMillis;
+        this.latestRunTimeElapsedMillis = latestRunTimeElapsedMillis;
+        this.mOriginalLatestRunTimeElapsedMillis = latestRunTimeElapsedMillis;
+        this.numFailures = numFailures;
+
+        int requiredConstraints = job.getConstraintFlags();
+        if (job.getRequiredNetwork() != null) {
+            requiredConstraints |= CONSTRAINT_CONNECTIVITY;
+        }
+        if (earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME) {
+            requiredConstraints |= CONSTRAINT_TIMING_DELAY;
+        }
+        if (latestRunTimeElapsedMillis != NO_LATEST_RUNTIME) {
+            requiredConstraints |= CONSTRAINT_DEADLINE;
+        }
+        if (job.getTriggerContentUris() != null) {
+            requiredConstraints |= CONSTRAINT_CONTENT_TRIGGER;
+        }
+        this.requiredConstraints = requiredConstraints;
+        mRequiredConstraintsOfInterest = requiredConstraints & CONSTRAINTS_OF_INTEREST;
+        mReadyNotDozing = (job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
+
+        mLastSuccessfulRunTime = lastSuccessfulRunTime;
+        mLastFailedRunTime = lastFailedRunTime;
+
+        mInternalFlags = internalFlags;
+
+        updateEstimatedNetworkBytesLocked();
+
+        if (job.getRequiredNetwork() != null) {
+            // Later, when we check if a given network satisfies the required
+            // network, we need to know the UID that is requesting it, so push
+            // our source UID into place.
+            job.getRequiredNetwork().networkCapabilities.setSingleUid(this.sourceUid);
+        }
+    }
+
+    /** Copy constructor: used specifically when cloning JobStatus objects for persistence,
+     *   so we preserve RTC window bounds if the source object has them. */
+    public JobStatus(JobStatus jobStatus) {
+        this(jobStatus.getJob(), jobStatus.getUid(),
+                jobStatus.getSourcePackageName(), jobStatus.getSourceUserId(),
+                jobStatus.getStandbyBucket(), jobStatus.getBaseHeartbeat(),
+                jobStatus.getSourceTag(), jobStatus.getNumFailures(),
+                jobStatus.getEarliestRunTime(), jobStatus.getLatestRunTimeElapsed(),
+                jobStatus.getLastSuccessfulRunTime(), jobStatus.getLastFailedRunTime(),
+                jobStatus.getInternalFlags());
+        mPersistedUtcTimes = jobStatus.mPersistedUtcTimes;
+        if (jobStatus.mPersistedUtcTimes != null) {
+            if (DEBUG) {
+                Slog.i(TAG, "Cloning job with persisted run times", new RuntimeException("here"));
+            }
+        }
+    }
+
+    /**
+     * Create a new JobStatus that was loaded from disk. We ignore the provided
+     * {@link android.app.job.JobInfo} time criteria because we can load a persisted periodic job
+     * from the {@link com.android.server.job.JobStore} and still want to respect its
+     * wallclock runtime rather than resetting it on every boot.
+     * We consider a freshly loaded job to no longer be in back-off, and the associated
+     * standby bucket is whatever the OS thinks it should be at this moment.
+     */
+    public JobStatus(JobInfo job, int callingUid, String sourcePkgName, int sourceUserId,
+            int standbyBucket, long baseHeartbeat, String sourceTag,
+            long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis,
+            long lastSuccessfulRunTime, long lastFailedRunTime,
+            Pair<Long, Long> persistedExecutionTimesUTC,
+            int innerFlags) {
+        this(job, callingUid, sourcePkgName, sourceUserId,
+                standbyBucket, baseHeartbeat,
+                sourceTag, 0,
+                earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis,
+                lastSuccessfulRunTime, lastFailedRunTime, innerFlags);
+
+        // Only during initial inflation do we record the UTC-timebase execution bounds
+        // read from the persistent store.  If we ever have to recreate the JobStatus on
+        // the fly, it means we're rescheduling the job; and this means that the calculated
+        // elapsed timebase bounds intrinsically become correct.
+        this.mPersistedUtcTimes = persistedExecutionTimesUTC;
+        if (persistedExecutionTimesUTC != null) {
+            if (DEBUG) {
+                Slog.i(TAG, "+ restored job with RTC times because of bad boot clock");
+            }
+        }
+    }
+
+    /** Create a new job to be rescheduled with the provided parameters. */
+    public JobStatus(JobStatus rescheduling, long newBaseHeartbeat,
+            long newEarliestRuntimeElapsedMillis,
+            long newLatestRuntimeElapsedMillis, int backoffAttempt,
+            long lastSuccessfulRunTime, long lastFailedRunTime) {
+        this(rescheduling.job, rescheduling.getUid(),
+                rescheduling.getSourcePackageName(), rescheduling.getSourceUserId(),
+                rescheduling.getStandbyBucket(), newBaseHeartbeat,
+                rescheduling.getSourceTag(), backoffAttempt, newEarliestRuntimeElapsedMillis,
+                newLatestRuntimeElapsedMillis,
+                lastSuccessfulRunTime, lastFailedRunTime, rescheduling.getInternalFlags());
+    }
+
+    /**
+     * Create a newly scheduled job.
+     * @param callingUid Uid of the package that scheduled this job.
+     * @param sourcePkg Package name of the app that will actually run the job.  Null indicates
+     *     that the calling package is the source.
+     * @param sourceUserId User id for whom this job is scheduled. -1 indicates this is same as the
+     *     caller.
+     */
+    public static JobStatus createFromJobInfo(JobInfo job, int callingUid, String sourcePkg,
+            int sourceUserId, String tag) {
+        final long elapsedNow = sElapsedRealtimeClock.millis();
+        final long earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis;
+        if (job.isPeriodic()) {
+            // Make sure period is in the interval [min_possible_period, max_possible_period].
+            final long period = Math.max(JobInfo.getMinPeriodMillis(),
+                    Math.min(JobSchedulerService.MAX_ALLOWED_PERIOD_MS, job.getIntervalMillis()));
+            latestRunTimeElapsedMillis = elapsedNow + period;
+            earliestRunTimeElapsedMillis = latestRunTimeElapsedMillis
+                    // Make sure flex is in the interval [min_possible_flex, period].
+                    - Math.max(JobInfo.getMinFlexMillis(), Math.min(period, job.getFlexMillis()));
+        } else {
+            earliestRunTimeElapsedMillis = job.hasEarlyConstraint() ?
+                    elapsedNow + job.getMinLatencyMillis() : NO_EARLIEST_RUNTIME;
+            latestRunTimeElapsedMillis = job.hasLateConstraint() ?
+                    elapsedNow + job.getMaxExecutionDelayMillis() : NO_LATEST_RUNTIME;
+        }
+        String jobPackage = (sourcePkg != null) ? sourcePkg : job.getService().getPackageName();
+
+        int standbyBucket = JobSchedulerService.standbyBucketForPackage(jobPackage,
+                sourceUserId, elapsedNow);
+        JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class);
+        long currentHeartbeat = js != null
+                ? js.baseHeartbeatForApp(jobPackage, sourceUserId, standbyBucket)
+                : 0;
+        return new JobStatus(job, callingUid, sourcePkg, sourceUserId,
+                standbyBucket, currentHeartbeat, tag, 0,
+                earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis,
+                0 /* lastSuccessfulRunTime */, 0 /* lastFailedRunTime */,
+                /*innerFlags=*/ 0);
+    }
+
+    public void enqueueWorkLocked(IActivityManager am, JobWorkItem work) {
+        if (pendingWork == null) {
+            pendingWork = new ArrayList<>();
+        }
+        work.setWorkId(nextPendingWorkId);
+        nextPendingWorkId++;
+        if (work.getIntent() != null
+                && GrantedUriPermissions.checkGrantFlags(work.getIntent().getFlags())) {
+            work.setGrants(GrantedUriPermissions.createFromIntent(am, work.getIntent(), sourceUid,
+                    sourcePackageName, sourceUserId, toShortString()));
+        }
+        pendingWork.add(work);
+        updateEstimatedNetworkBytesLocked();
+    }
+
+    public JobWorkItem dequeueWorkLocked() {
+        if (pendingWork != null && pendingWork.size() > 0) {
+            JobWorkItem work = pendingWork.remove(0);
+            if (work != null) {
+                if (executingWork == null) {
+                    executingWork = new ArrayList<>();
+                }
+                executingWork.add(work);
+                work.bumpDeliveryCount();
+            }
+            updateEstimatedNetworkBytesLocked();
+            return work;
+        }
+        return null;
+    }
+
+    public boolean hasWorkLocked() {
+        return (pendingWork != null && pendingWork.size() > 0) || hasExecutingWorkLocked();
+    }
+
+    public boolean hasExecutingWorkLocked() {
+        return executingWork != null && executingWork.size() > 0;
+    }
+
+    private static void ungrantWorkItem(IActivityManager am, JobWorkItem work) {
+        if (work.getGrants() != null) {
+            ((GrantedUriPermissions)work.getGrants()).revoke(am);
+        }
+    }
+
+    public boolean completeWorkLocked(IActivityManager am, int workId) {
+        if (executingWork != null) {
+            final int N = executingWork.size();
+            for (int i = 0; i < N; i++) {
+                JobWorkItem work = executingWork.get(i);
+                if (work.getWorkId() == workId) {
+                    executingWork.remove(i);
+                    ungrantWorkItem(am, work);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private static void ungrantWorkList(IActivityManager am, ArrayList<JobWorkItem> list) {
+        if (list != null) {
+            final int N = list.size();
+            for (int i = 0; i < N; i++) {
+                ungrantWorkItem(am, list.get(i));
+            }
+        }
+    }
+
+    public void stopTrackingJobLocked(IActivityManager am, JobStatus incomingJob) {
+        if (incomingJob != null) {
+            // We are replacing with a new job -- transfer the work!  We do any executing
+            // work first, since that was originally at the front of the pending work.
+            if (executingWork != null && executingWork.size() > 0) {
+                incomingJob.pendingWork = executingWork;
+            }
+            if (incomingJob.pendingWork == null) {
+                incomingJob.pendingWork = pendingWork;
+            } else if (pendingWork != null && pendingWork.size() > 0) {
+                incomingJob.pendingWork.addAll(pendingWork);
+            }
+            pendingWork = null;
+            executingWork = null;
+            incomingJob.nextPendingWorkId = nextPendingWorkId;
+            incomingJob.updateEstimatedNetworkBytesLocked();
+        } else {
+            // We are completely stopping the job...  need to clean up work.
+            ungrantWorkList(am, pendingWork);
+            pendingWork = null;
+            ungrantWorkList(am, executingWork);
+            executingWork = null;
+        }
+        updateEstimatedNetworkBytesLocked();
+    }
+
+    public void prepareLocked(IActivityManager am) {
+        if (prepared) {
+            Slog.wtf(TAG, "Already prepared: " + this);
+            return;
+        }
+        prepared = true;
+        if (DEBUG_PREPARE) {
+            unpreparedPoint = null;
+        }
+        final ClipData clip = job.getClipData();
+        if (clip != null) {
+            uriPerms = GrantedUriPermissions.createFromClip(am, clip, sourceUid, sourcePackageName,
+                    sourceUserId, job.getClipGrantFlags(), toShortString());
+        }
+    }
+
+    public void unprepareLocked(IActivityManager am) {
+        if (!prepared) {
+            Slog.wtf(TAG, "Hasn't been prepared: " + this);
+            if (DEBUG_PREPARE && unpreparedPoint != null) {
+                Slog.e(TAG, "Was already unprepared at ", unpreparedPoint);
+            }
+            return;
+        }
+        prepared = false;
+        if (DEBUG_PREPARE) {
+            unpreparedPoint = new Throwable().fillInStackTrace();
+        }
+        if (uriPerms != null) {
+            uriPerms.revoke(am);
+            uriPerms = null;
+        }
+    }
+
+    public boolean isPreparedLocked() {
+        return prepared;
+    }
+
+    public JobInfo getJob() {
+        return job;
+    }
+
+    public int getJobId() {
+        return job.getId();
+    }
+
+    public void printUniqueId(PrintWriter pw) {
+        UserHandle.formatUid(pw, callingUid);
+        pw.print("/");
+        pw.print(job.getId());
+    }
+
+    public int getNumFailures() {
+        return numFailures;
+    }
+
+    public ComponentName getServiceComponent() {
+        return job.getService();
+    }
+
+    public String getSourcePackageName() {
+        return sourcePackageName;
+    }
+
+    public int getSourceUid() {
+        return sourceUid;
+    }
+
+    public int getSourceUserId() {
+        return sourceUserId;
+    }
+
+    public int getUserId() {
+        return UserHandle.getUserId(callingUid);
+    }
+
+    public int getStandbyBucket() {
+        return standbyBucket;
+    }
+
+    public long getBaseHeartbeat() {
+        return baseHeartbeat;
+    }
+
+    public void setStandbyBucket(int newBucket) {
+        standbyBucket = newBucket;
+    }
+
+    // Called only by the standby monitoring code
+    public long getWhenStandbyDeferred() {
+        return whenStandbyDeferred;
+    }
+
+    // Called only by the standby monitoring code
+    public void setWhenStandbyDeferred(long now) {
+        whenStandbyDeferred = now;
+    }
+
+    /**
+     * Returns the first time this job was force batched, in the elapsed realtime timebase. Will be
+     * 0 if this job was never force batched.
+     */
+    public long getFirstForceBatchedTimeElapsed() {
+        return mFirstForceBatchedTimeElapsed;
+    }
+
+    public void setFirstForceBatchedTimeElapsed(long now) {
+        mFirstForceBatchedTimeElapsed = now;
+    }
+
+    public String getSourceTag() {
+        return sourceTag;
+    }
+
+    public int getUid() {
+        return callingUid;
+    }
+
+    public String getBatteryName() {
+        return batteryName;
+    }
+
+    public String getTag() {
+        return tag;
+    }
+
+    public int getPriority() {
+        return job.getPriority();
+    }
+
+    public int getFlags() {
+        return job.getFlags();
+    }
+
+    public int getInternalFlags() {
+        return mInternalFlags;
+    }
+
+    public void addInternalFlags(int flags) {
+        mInternalFlags |= flags;
+    }
+
+    public int getSatisfiedConstraintFlags() {
+        return satisfiedConstraints;
+    }
+
+    public void maybeAddForegroundExemption(Predicate<Integer> uidForegroundChecker) {
+        // Jobs with time constraints shouldn't be exempted.
+        if (job.hasEarlyConstraint() || job.hasLateConstraint()) {
+            return;
+        }
+        // Already exempted, skip the foreground check.
+        if ((mInternalFlags & INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION) != 0) {
+            return;
+        }
+        if (uidForegroundChecker.test(getSourceUid())) {
+            addInternalFlags(INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION);
+        }
+    }
+
+    private void updateEstimatedNetworkBytesLocked() {
+        mTotalNetworkDownloadBytes = job.getEstimatedNetworkDownloadBytes();
+        mTotalNetworkUploadBytes = job.getEstimatedNetworkUploadBytes();
+
+        if (pendingWork != null) {
+            for (int i = 0; i < pendingWork.size(); i++) {
+                if (mTotalNetworkDownloadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
+                    // If any component of the job has unknown usage, we don't have a
+                    // complete picture of what data will be used, and we have to treat the
+                    // entire up/download as unknown.
+                    long downloadBytes = pendingWork.get(i).getEstimatedNetworkDownloadBytes();
+                    if (downloadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
+                        mTotalNetworkDownloadBytes += downloadBytes;
+                    }
+                }
+                if (mTotalNetworkUploadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
+                    // If any component of the job has unknown usage, we don't have a
+                    // complete picture of what data will be used, and we have to treat the
+                    // entire up/download as unknown.
+                    long uploadBytes = pendingWork.get(i).getEstimatedNetworkUploadBytes();
+                    if (uploadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
+                        mTotalNetworkUploadBytes += uploadBytes;
+                    }
+                }
+            }
+        }
+    }
+
+    public long getEstimatedNetworkDownloadBytes() {
+        return mTotalNetworkDownloadBytes;
+    }
+
+    public long getEstimatedNetworkUploadBytes() {
+        return mTotalNetworkUploadBytes;
+    }
+
+    /** Does this job have any sort of networking constraint? */
+    public boolean hasConnectivityConstraint() {
+        return (requiredConstraints&CONSTRAINT_CONNECTIVITY) != 0;
+    }
+
+    public boolean hasChargingConstraint() {
+        return (requiredConstraints&CONSTRAINT_CHARGING) != 0;
+    }
+
+    public boolean hasBatteryNotLowConstraint() {
+        return (requiredConstraints&CONSTRAINT_BATTERY_NOT_LOW) != 0;
+    }
+
+    public boolean hasPowerConstraint() {
+        return (requiredConstraints&(CONSTRAINT_CHARGING|CONSTRAINT_BATTERY_NOT_LOW)) != 0;
+    }
+
+    public boolean hasStorageNotLowConstraint() {
+        return (requiredConstraints&CONSTRAINT_STORAGE_NOT_LOW) != 0;
+    }
+
+    public boolean hasTimingDelayConstraint() {
+        return (requiredConstraints&CONSTRAINT_TIMING_DELAY) != 0;
+    }
+
+    public boolean hasDeadlineConstraint() {
+        return (requiredConstraints&CONSTRAINT_DEADLINE) != 0;
+    }
+
+    public boolean hasIdleConstraint() {
+        return (requiredConstraints&CONSTRAINT_IDLE) != 0;
+    }
+
+    public boolean hasContentTriggerConstraint() {
+        return (requiredConstraints&CONSTRAINT_CONTENT_TRIGGER) != 0;
+    }
+
+    public long getTriggerContentUpdateDelay() {
+        long time = job.getTriggerContentUpdateDelay();
+        if (time < 0) {
+            return DEFAULT_TRIGGER_UPDATE_DELAY;
+        }
+        return Math.max(time, MIN_TRIGGER_UPDATE_DELAY);
+    }
+
+    public long getTriggerContentMaxDelay() {
+        long time = job.getTriggerContentMaxDelay();
+        if (time < 0) {
+            return DEFAULT_TRIGGER_MAX_DELAY;
+        }
+        return Math.max(time, MIN_TRIGGER_MAX_DELAY);
+    }
+
+    public boolean isPersisted() {
+        return job.isPersisted();
+    }
+
+    public long getEarliestRunTime() {
+        return earliestRunTimeElapsedMillis;
+    }
+
+    public long getLatestRunTimeElapsed() {
+        return latestRunTimeElapsedMillis;
+    }
+
+    public long getOriginalLatestRunTimeElapsed() {
+        return mOriginalLatestRunTimeElapsedMillis;
+    }
+
+    public void setOriginalLatestRunTimeElapsed(long latestRunTimeElapsed) {
+        mOriginalLatestRunTimeElapsedMillis = latestRunTimeElapsed;
+    }
+
+    /**
+     * Return the fractional position of "now" within the "run time" window of
+     * this job.
+     * <p>
+     * For example, if the earliest run time was 10 minutes ago, and the latest
+     * run time is 30 minutes from now, this would return 0.25.
+     * <p>
+     * If the job has no window defined, returns 1. When only an earliest or
+     * latest time is defined, it's treated as an infinitely small window at
+     * that time.
+     */
+    public float getFractionRunTime() {
+        final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
+        if (earliestRunTimeElapsedMillis == 0 && latestRunTimeElapsedMillis == Long.MAX_VALUE) {
+            return 1;
+        } else if (earliestRunTimeElapsedMillis == 0) {
+            return now >= latestRunTimeElapsedMillis ? 1 : 0;
+        } else if (latestRunTimeElapsedMillis == Long.MAX_VALUE) {
+            return now >= earliestRunTimeElapsedMillis ? 1 : 0;
+        } else {
+            if (now <= earliestRunTimeElapsedMillis) {
+                return 0;
+            } else if (now >= latestRunTimeElapsedMillis) {
+                return 1;
+            } else {
+                return (float) (now - earliestRunTimeElapsedMillis)
+                        / (float) (latestRunTimeElapsedMillis - earliestRunTimeElapsedMillis);
+            }
+        }
+    }
+
+    public Pair<Long, Long> getPersistedUtcTimes() {
+        return mPersistedUtcTimes;
+    }
+
+    public void clearPersistedUtcTimes() {
+        mPersistedUtcTimes = null;
+    }
+
+    /** @return true if the constraint was changed, false otherwise. */
+    boolean setChargingConstraintSatisfied(boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_CHARGING, state);
+    }
+
+    /** @return true if the constraint was changed, false otherwise. */
+    boolean setBatteryNotLowConstraintSatisfied(boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, state);
+    }
+
+    /** @return true if the constraint was changed, false otherwise. */
+    boolean setStorageNotLowConstraintSatisfied(boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_STORAGE_NOT_LOW, state);
+    }
+
+    /** @return true if the constraint was changed, false otherwise. */
+    boolean setTimingDelayConstraintSatisfied(boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, state);
+    }
+
+    /** @return true if the constraint was changed, false otherwise. */
+    boolean setDeadlineConstraintSatisfied(boolean state) {
+        if (setConstraintSatisfied(CONSTRAINT_DEADLINE, state)) {
+            // The constraint was changed. Update the ready flag.
+            mReadyDeadlineSatisfied = !job.isPeriodic() && hasDeadlineConstraint() && state;
+            return true;
+        }
+        return false;
+    }
+
+    /** @return true if the constraint was changed, false otherwise. */
+    boolean setIdleConstraintSatisfied(boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_IDLE, state);
+    }
+
+    /** @return true if the constraint was changed, false otherwise. */
+    boolean setConnectivityConstraintSatisfied(boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, state);
+    }
+
+    /** @return true if the constraint was changed, false otherwise. */
+    boolean setContentTriggerConstraintSatisfied(boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, state);
+    }
+
+    /** @return true if the constraint was changed, false otherwise. */
+    boolean setDeviceNotDozingConstraintSatisfied(boolean state, boolean whitelisted) {
+        dozeWhitelisted = whitelisted;
+        if (setConstraintSatisfied(CONSTRAINT_DEVICE_NOT_DOZING, state)) {
+            // The constraint was changed. Update the ready flag.
+            mReadyNotDozing = state || (job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
+            return true;
+        }
+        return false;
+    }
+
+    /** @return true if the constraint was changed, false otherwise. */
+    boolean setBackgroundNotRestrictedConstraintSatisfied(boolean state) {
+        if (setConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED, state)) {
+            // The constraint was changed. Update the ready flag.
+            mReadyNotRestrictedInBg = state;
+            return true;
+        }
+        return false;
+    }
+
+    /** @return true if the constraint was changed, false otherwise. */
+    boolean setQuotaConstraintSatisfied(boolean state) {
+        if (setConstraintSatisfied(CONSTRAINT_WITHIN_QUOTA, state)) {
+            // The constraint was changed. Update the ready flag.
+            mReadyWithinQuota = state;
+            return true;
+        }
+        return false;
+    }
+
+    /** @return true if the state was changed, false otherwise. */
+    boolean setUidActive(final boolean newActiveState) {
+        if (newActiveState != uidActive) {
+            uidActive = newActiveState;
+            return true;
+        }
+        return false; /* unchanged */
+    }
+
+    /** @return true if the constraint was changed, false otherwise. */
+    boolean setConstraintSatisfied(int constraint, boolean state) {
+        boolean old = (satisfiedConstraints&constraint) != 0;
+        if (old == state) {
+            return false;
+        }
+        satisfiedConstraints = (satisfiedConstraints&~constraint) | (state ? constraint : 0);
+        mSatisfiedConstraintsOfInterest = satisfiedConstraints & CONSTRAINTS_OF_INTEREST;
+        if (STATS_LOG_ENABLED && (STATSD_CONSTRAINTS_TO_LOG & constraint) != 0) {
+            StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_CONSTRAINT_CHANGED,
+                    sourceUid, null, getBatteryName(), getProtoConstraint(constraint),
+                    state ? StatsLog.SCHEDULED_JOB_CONSTRAINT_CHANGED__STATE__SATISFIED
+                            : StatsLog.SCHEDULED_JOB_CONSTRAINT_CHANGED__STATE__UNSATISFIED);
+        }
+        return true;
+    }
+
+    boolean isConstraintSatisfied(int constraint) {
+        return (satisfiedConstraints&constraint) != 0;
+    }
+
+    boolean clearTrackingController(int which) {
+        if ((trackingControllers&which) != 0) {
+            trackingControllers &= ~which;
+            return true;
+        }
+        return false;
+    }
+
+    void setTrackingController(int which) {
+        trackingControllers |= which;
+    }
+
+    public long getLastSuccessfulRunTime() {
+        return mLastSuccessfulRunTime;
+    }
+
+    public long getLastFailedRunTime() {
+        return mLastFailedRunTime;
+    }
+
+    /**
+     * @return Whether or not this job is ready to run, based on its requirements.
+     */
+    public boolean isReady() {
+        return isReady(mSatisfiedConstraintsOfInterest);
+    }
+
+    /**
+     * @return Whether or not this job would be ready to run if it had the specified constraint
+     * granted, based on its requirements.
+     */
+    boolean wouldBeReadyWithConstraint(int constraint) {
+        boolean oldValue = false;
+        int satisfied = mSatisfiedConstraintsOfInterest;
+        switch (constraint) {
+            case CONSTRAINT_BACKGROUND_NOT_RESTRICTED:
+                oldValue = mReadyNotRestrictedInBg;
+                mReadyNotRestrictedInBg = true;
+                break;
+            case CONSTRAINT_DEADLINE:
+                oldValue = mReadyDeadlineSatisfied;
+                mReadyDeadlineSatisfied = true;
+                break;
+            case CONSTRAINT_DEVICE_NOT_DOZING:
+                oldValue = mReadyNotDozing;
+                mReadyNotDozing = true;
+                break;
+            case CONSTRAINT_WITHIN_QUOTA:
+                oldValue = mReadyWithinQuota;
+                mReadyWithinQuota = true;
+                break;
+            default:
+                satisfied |= constraint;
+                break;
+        }
+
+        boolean toReturn = isReady(satisfied);
+
+        switch (constraint) {
+            case CONSTRAINT_BACKGROUND_NOT_RESTRICTED:
+                mReadyNotRestrictedInBg = oldValue;
+                break;
+            case CONSTRAINT_DEADLINE:
+                mReadyDeadlineSatisfied = oldValue;
+                break;
+            case CONSTRAINT_DEVICE_NOT_DOZING:
+                mReadyNotDozing = oldValue;
+                break;
+            case CONSTRAINT_WITHIN_QUOTA:
+                mReadyWithinQuota = oldValue;
+                break;
+        }
+        return toReturn;
+    }
+
+    private boolean isReady(int satisfiedConstraints) {
+        // Quota constraints trumps all other constraints.
+        if (!mReadyWithinQuota) {
+            return false;
+        }
+        // Deadline constraint trumps other constraints besides quota (except for periodic jobs
+        // where deadline is an implementation detail. A periodic job should only run if its
+        // constraints are satisfied).
+        // DeviceNotDozing implicit constraint must be satisfied
+        // NotRestrictedInBackground implicit constraint must be satisfied
+        return mReadyNotDozing && mReadyNotRestrictedInBg && (mReadyDeadlineSatisfied
+                || isConstraintsSatisfied(satisfiedConstraints));
+    }
+
+    static final int CONSTRAINTS_OF_INTEREST = CONSTRAINT_CHARGING | CONSTRAINT_BATTERY_NOT_LOW
+            | CONSTRAINT_STORAGE_NOT_LOW | CONSTRAINT_TIMING_DELAY | CONSTRAINT_CONNECTIVITY
+            | CONSTRAINT_IDLE | CONSTRAINT_CONTENT_TRIGGER;
+
+    // Soft override covers all non-"functional" constraints
+    static final int SOFT_OVERRIDE_CONSTRAINTS =
+            CONSTRAINT_CHARGING | CONSTRAINT_BATTERY_NOT_LOW | CONSTRAINT_STORAGE_NOT_LOW
+                    | CONSTRAINT_TIMING_DELAY | CONSTRAINT_IDLE;
+
+    /**
+     * @return Whether the constraints set on this job are satisfied.
+     */
+    public boolean isConstraintsSatisfied() {
+        return isConstraintsSatisfied(mSatisfiedConstraintsOfInterest);
+    }
+
+    private boolean isConstraintsSatisfied(int satisfiedConstraints) {
+        if (overrideState == OVERRIDE_FULL) {
+            // force override: the job is always runnable
+            return true;
+        }
+
+        int sat = satisfiedConstraints;
+        if (overrideState == OVERRIDE_SOFT) {
+            // override: pretend all 'soft' requirements are satisfied
+            sat |= (requiredConstraints & SOFT_OVERRIDE_CONSTRAINTS);
+        }
+
+        return (sat & mRequiredConstraintsOfInterest) == mRequiredConstraintsOfInterest;
+    }
+
+    public boolean matches(int uid, int jobId) {
+        return this.job.getId() == jobId && this.callingUid == uid;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("JobStatus{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(" #");
+        UserHandle.formatUid(sb, callingUid);
+        sb.append("/");
+        sb.append(job.getId());
+        sb.append(' ');
+        sb.append(batteryName);
+        sb.append(" u=");
+        sb.append(getUserId());
+        sb.append(" s=");
+        sb.append(getSourceUid());
+        if (earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME
+                || latestRunTimeElapsedMillis != NO_LATEST_RUNTIME) {
+            long now = sElapsedRealtimeClock.millis();
+            sb.append(" TIME=");
+            formatRunTime(sb, earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME, now);
+            sb.append(":");
+            formatRunTime(sb, latestRunTimeElapsedMillis, NO_LATEST_RUNTIME, now);
+        }
+        if (job.getRequiredNetwork() != null) {
+            sb.append(" NET");
+        }
+        if (job.isRequireCharging()) {
+            sb.append(" CHARGING");
+        }
+        if (job.isRequireBatteryNotLow()) {
+            sb.append(" BATNOTLOW");
+        }
+        if (job.isRequireStorageNotLow()) {
+            sb.append(" STORENOTLOW");
+        }
+        if (job.isRequireDeviceIdle()) {
+            sb.append(" IDLE");
+        }
+        if (job.isPeriodic()) {
+            sb.append(" PERIODIC");
+        }
+        if (job.isPersisted()) {
+            sb.append(" PERSISTED");
+        }
+        if ((satisfiedConstraints&CONSTRAINT_DEVICE_NOT_DOZING) == 0) {
+            sb.append(" WAIT:DEV_NOT_DOZING");
+        }
+        if (job.getTriggerContentUris() != null) {
+            sb.append(" URIS=");
+            sb.append(Arrays.toString(job.getTriggerContentUris()));
+        }
+        if (numFailures != 0) {
+            sb.append(" failures=");
+            sb.append(numFailures);
+        }
+        if (isReady()) {
+            sb.append(" READY");
+        }
+        sb.append("}");
+        return sb.toString();
+    }
+
+    private void formatRunTime(PrintWriter pw, long runtime, long  defaultValue, long now) {
+        if (runtime == defaultValue) {
+            pw.print("none");
+        } else {
+            TimeUtils.formatDuration(runtime - now, pw);
+        }
+    }
+
+    private void formatRunTime(StringBuilder sb, long runtime, long  defaultValue, long now) {
+        if (runtime == defaultValue) {
+            sb.append("none");
+        } else {
+            TimeUtils.formatDuration(runtime - now, sb);
+        }
+    }
+
+    /**
+     * Convenience function to identify a job uniquely without pulling all the data that
+     * {@link #toString()} returns.
+     */
+    public String toShortString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(" #");
+        UserHandle.formatUid(sb, callingUid);
+        sb.append("/");
+        sb.append(job.getId());
+        sb.append(' ');
+        sb.append(batteryName);
+        return sb.toString();
+    }
+
+    /**
+     * Convenience function to identify a job uniquely without pulling all the data that
+     * {@link #toString()} returns.
+     */
+    public String toShortStringExceptUniqueId() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(batteryName);
+        return sb.toString();
+    }
+
+    /**
+     * Convenience function to dump data that identifies a job uniquely to proto. This is intended
+     * to mimic {@link #toShortString}.
+     */
+    public void writeToShortProto(ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+
+        proto.write(JobStatusShortInfoProto.CALLING_UID, callingUid);
+        proto.write(JobStatusShortInfoProto.JOB_ID, job.getId());
+        proto.write(JobStatusShortInfoProto.BATTERY_NAME, batteryName);
+
+        proto.end(token);
+    }
+
+    void dumpConstraints(PrintWriter pw, int constraints) {
+        if ((constraints&CONSTRAINT_CHARGING) != 0) {
+            pw.print(" CHARGING");
+        }
+        if ((constraints& CONSTRAINT_BATTERY_NOT_LOW) != 0) {
+            pw.print(" BATTERY_NOT_LOW");
+        }
+        if ((constraints& CONSTRAINT_STORAGE_NOT_LOW) != 0) {
+            pw.print(" STORAGE_NOT_LOW");
+        }
+        if ((constraints&CONSTRAINT_TIMING_DELAY) != 0) {
+            pw.print(" TIMING_DELAY");
+        }
+        if ((constraints&CONSTRAINT_DEADLINE) != 0) {
+            pw.print(" DEADLINE");
+        }
+        if ((constraints&CONSTRAINT_IDLE) != 0) {
+            pw.print(" IDLE");
+        }
+        if ((constraints&CONSTRAINT_CONNECTIVITY) != 0) {
+            pw.print(" CONNECTIVITY");
+        }
+        if ((constraints&CONSTRAINT_CONTENT_TRIGGER) != 0) {
+            pw.print(" CONTENT_TRIGGER");
+        }
+        if ((constraints&CONSTRAINT_DEVICE_NOT_DOZING) != 0) {
+            pw.print(" DEVICE_NOT_DOZING");
+        }
+        if ((constraints&CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0) {
+            pw.print(" BACKGROUND_NOT_RESTRICTED");
+        }
+        if ((constraints & CONSTRAINT_WITHIN_QUOTA) != 0) {
+            pw.print(" WITHIN_QUOTA");
+        }
+        if (constraints != 0) {
+            pw.print(" [0x");
+            pw.print(Integer.toHexString(constraints));
+            pw.print("]");
+        }
+    }
+
+    /** Returns a {@link JobServerProtoEnums.Constraint} enum value for the given constraint. */
+    private int getProtoConstraint(int constraint) {
+        switch (constraint) {
+            case CONSTRAINT_BACKGROUND_NOT_RESTRICTED:
+                return JobServerProtoEnums.CONSTRAINT_BACKGROUND_NOT_RESTRICTED;
+            case CONSTRAINT_BATTERY_NOT_LOW:
+                return JobServerProtoEnums.CONSTRAINT_BATTERY_NOT_LOW;
+            case CONSTRAINT_CHARGING:
+                return JobServerProtoEnums.CONSTRAINT_CHARGING;
+            case CONSTRAINT_CONNECTIVITY:
+                return JobServerProtoEnums.CONSTRAINT_CONNECTIVITY;
+            case CONSTRAINT_CONTENT_TRIGGER:
+                return JobServerProtoEnums.CONSTRAINT_CONTENT_TRIGGER;
+            case CONSTRAINT_DEADLINE:
+                return JobServerProtoEnums.CONSTRAINT_DEADLINE;
+            case CONSTRAINT_DEVICE_NOT_DOZING:
+                return JobServerProtoEnums.CONSTRAINT_DEVICE_NOT_DOZING;
+            case CONSTRAINT_IDLE:
+                return JobServerProtoEnums.CONSTRAINT_IDLE;
+            case CONSTRAINT_STORAGE_NOT_LOW:
+                return JobServerProtoEnums.CONSTRAINT_STORAGE_NOT_LOW;
+            case CONSTRAINT_TIMING_DELAY:
+                return JobServerProtoEnums.CONSTRAINT_TIMING_DELAY;
+            case CONSTRAINT_WITHIN_QUOTA:
+                return JobServerProtoEnums.CONSTRAINT_WITHIN_QUOTA;
+            default:
+                return JobServerProtoEnums.CONSTRAINT_UNKNOWN;
+        }
+    }
+
+    /** Writes constraints to the given repeating proto field. */
+    void dumpConstraints(ProtoOutputStream proto, long fieldId, int constraints) {
+        if ((constraints & CONSTRAINT_CHARGING) != 0) {
+            proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_CHARGING);
+        }
+        if ((constraints & CONSTRAINT_BATTERY_NOT_LOW) != 0) {
+            proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_BATTERY_NOT_LOW);
+        }
+        if ((constraints & CONSTRAINT_STORAGE_NOT_LOW) != 0) {
+            proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_STORAGE_NOT_LOW);
+        }
+        if ((constraints & CONSTRAINT_TIMING_DELAY) != 0) {
+            proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_TIMING_DELAY);
+        }
+        if ((constraints & CONSTRAINT_DEADLINE) != 0) {
+            proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_DEADLINE);
+        }
+        if ((constraints & CONSTRAINT_IDLE) != 0) {
+            proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_IDLE);
+        }
+        if ((constraints & CONSTRAINT_CONNECTIVITY) != 0) {
+            proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_CONNECTIVITY);
+        }
+        if ((constraints & CONSTRAINT_CONTENT_TRIGGER) != 0) {
+            proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_CONTENT_TRIGGER);
+        }
+        if ((constraints & CONSTRAINT_DEVICE_NOT_DOZING) != 0) {
+            proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_DEVICE_NOT_DOZING);
+        }
+        if ((constraints & CONSTRAINT_WITHIN_QUOTA) != 0) {
+            proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_WITHIN_QUOTA);
+        }
+        if ((constraints & CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0) {
+            proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_BACKGROUND_NOT_RESTRICTED);
+        }
+    }
+
+    private void dumpJobWorkItem(PrintWriter pw, String prefix, JobWorkItem work, int index) {
+        pw.print(prefix); pw.print("  #"); pw.print(index); pw.print(": #");
+        pw.print(work.getWorkId()); pw.print(" "); pw.print(work.getDeliveryCount());
+        pw.print("x "); pw.println(work.getIntent());
+        if (work.getGrants() != null) {
+            pw.print(prefix); pw.println("  URI grants:");
+            ((GrantedUriPermissions)work.getGrants()).dump(pw, prefix + "    ");
+        }
+    }
+
+    private void dumpJobWorkItem(ProtoOutputStream proto, long fieldId, JobWorkItem work) {
+        final long token = proto.start(fieldId);
+
+        proto.write(JobStatusDumpProto.JobWorkItem.WORK_ID, work.getWorkId());
+        proto.write(JobStatusDumpProto.JobWorkItem.DELIVERY_COUNT, work.getDeliveryCount());
+        if (work.getIntent() != null) {
+            work.getIntent().writeToProto(proto, JobStatusDumpProto.JobWorkItem.INTENT);
+        }
+        Object grants = work.getGrants();
+        if (grants != null) {
+            ((GrantedUriPermissions) grants).dump(proto, JobStatusDumpProto.JobWorkItem.URI_GRANTS);
+        }
+
+        proto.end(token);
+    }
+
+    /**
+     * Returns a bucket name based on the normalized bucket indices, not the AppStandby constants.
+     */
+    String getBucketName() {
+        return bucketName(standbyBucket);
+    }
+
+    /**
+     * Returns a bucket name based on the normalized bucket indices, not the AppStandby constants.
+     */
+    static String bucketName(int standbyBucket) {
+        switch (standbyBucket) {
+            case 0: return "ACTIVE";
+            case 1: return "WORKING_SET";
+            case 2: return "FREQUENT";
+            case 3: return "RARE";
+            case 4: return "NEVER";
+            default:
+                return "Unknown: " + standbyBucket;
+        }
+    }
+
+    // Dumpsys infrastructure
+    public void dump(PrintWriter pw, String prefix, boolean full, long elapsedRealtimeMillis) {
+        pw.print(prefix); UserHandle.formatUid(pw, callingUid);
+        pw.print(" tag="); pw.println(tag);
+        pw.print(prefix);
+        pw.print("Source: uid="); UserHandle.formatUid(pw, getSourceUid());
+        pw.print(" user="); pw.print(getSourceUserId());
+        pw.print(" pkg="); pw.println(getSourcePackageName());
+        if (full) {
+            pw.print(prefix); pw.println("JobInfo:");
+            pw.print(prefix); pw.print("  Service: ");
+            pw.println(job.getService().flattenToShortString());
+            if (job.isPeriodic()) {
+                pw.print(prefix); pw.print("  PERIODIC: interval=");
+                TimeUtils.formatDuration(job.getIntervalMillis(), pw);
+                pw.print(" flex="); TimeUtils.formatDuration(job.getFlexMillis(), pw);
+                pw.println();
+            }
+            if (job.isPersisted()) {
+                pw.print(prefix); pw.println("  PERSISTED");
+            }
+            if (job.getPriority() != 0) {
+                pw.print(prefix); pw.print("  Priority: ");
+                pw.println(JobInfo.getPriorityString(job.getPriority()));
+            }
+            if (job.getFlags() != 0) {
+                pw.print(prefix); pw.print("  Flags: ");
+                pw.println(Integer.toHexString(job.getFlags()));
+            }
+            if (getInternalFlags() != 0) {
+                pw.print(prefix); pw.print("  Internal flags: ");
+                pw.print(Integer.toHexString(getInternalFlags()));
+
+                if ((getInternalFlags()&INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION) != 0) {
+                    pw.print(" HAS_FOREGROUND_EXEMPTION");
+                }
+                pw.println();
+            }
+            pw.print(prefix); pw.print("  Requires: charging=");
+            pw.print(job.isRequireCharging()); pw.print(" batteryNotLow=");
+            pw.print(job.isRequireBatteryNotLow()); pw.print(" deviceIdle=");
+            pw.println(job.isRequireDeviceIdle());
+            if (job.getTriggerContentUris() != null) {
+                pw.print(prefix); pw.println("  Trigger content URIs:");
+                for (int i = 0; i < job.getTriggerContentUris().length; i++) {
+                    JobInfo.TriggerContentUri trig = job.getTriggerContentUris()[i];
+                    pw.print(prefix); pw.print("    ");
+                    pw.print(Integer.toHexString(trig.getFlags()));
+                    pw.print(' '); pw.println(trig.getUri());
+                }
+                if (job.getTriggerContentUpdateDelay() >= 0) {
+                    pw.print(prefix); pw.print("  Trigger update delay: ");
+                    TimeUtils.formatDuration(job.getTriggerContentUpdateDelay(), pw);
+                    pw.println();
+                }
+                if (job.getTriggerContentMaxDelay() >= 0) {
+                    pw.print(prefix); pw.print("  Trigger max delay: ");
+                    TimeUtils.formatDuration(job.getTriggerContentMaxDelay(), pw);
+                    pw.println();
+                }
+            }
+            if (job.getExtras() != null && !job.getExtras().maybeIsEmpty()) {
+                pw.print(prefix); pw.print("  Extras: ");
+                pw.println(job.getExtras().toShortString());
+            }
+            if (job.getTransientExtras() != null && !job.getTransientExtras().maybeIsEmpty()) {
+                pw.print(prefix); pw.print("  Transient extras: ");
+                pw.println(job.getTransientExtras().toShortString());
+            }
+            if (job.getClipData() != null) {
+                pw.print(prefix); pw.print("  Clip data: ");
+                StringBuilder b = new StringBuilder(128);
+                job.getClipData().toShortString(b);
+                pw.println(b);
+            }
+            if (uriPerms != null) {
+                pw.print(prefix); pw.println("  Granted URI permissions:");
+                uriPerms.dump(pw, prefix + "  ");
+            }
+            if (job.getRequiredNetwork() != null) {
+                pw.print(prefix); pw.print("  Network type: ");
+                pw.println(job.getRequiredNetwork());
+            }
+            if (mTotalNetworkDownloadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
+                pw.print(prefix); pw.print("  Network download bytes: ");
+                pw.println(mTotalNetworkDownloadBytes);
+            }
+            if (mTotalNetworkUploadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
+                pw.print(prefix); pw.print("  Network upload bytes: ");
+                pw.println(mTotalNetworkUploadBytes);
+            }
+            if (job.getMinLatencyMillis() != 0) {
+                pw.print(prefix); pw.print("  Minimum latency: ");
+                TimeUtils.formatDuration(job.getMinLatencyMillis(), pw);
+                pw.println();
+            }
+            if (job.getMaxExecutionDelayMillis() != 0) {
+                pw.print(prefix); pw.print("  Max execution delay: ");
+                TimeUtils.formatDuration(job.getMaxExecutionDelayMillis(), pw);
+                pw.println();
+            }
+            pw.print(prefix); pw.print("  Backoff: policy="); pw.print(job.getBackoffPolicy());
+            pw.print(" initial="); TimeUtils.formatDuration(job.getInitialBackoffMillis(), pw);
+            pw.println();
+            if (job.hasEarlyConstraint()) {
+                pw.print(prefix); pw.println("  Has early constraint");
+            }
+            if (job.hasLateConstraint()) {
+                pw.print(prefix); pw.println("  Has late constraint");
+            }
+        }
+        pw.print(prefix); pw.print("Required constraints:");
+        dumpConstraints(pw, requiredConstraints);
+        pw.println();
+        if (full) {
+            pw.print(prefix); pw.print("Satisfied constraints:");
+            dumpConstraints(pw, satisfiedConstraints);
+            pw.println();
+            pw.print(prefix); pw.print("Unsatisfied constraints:");
+            dumpConstraints(pw,
+                    ((requiredConstraints | CONSTRAINT_WITHIN_QUOTA) & ~satisfiedConstraints));
+            pw.println();
+            if (dozeWhitelisted) {
+                pw.print(prefix); pw.println("Doze whitelisted: true");
+            }
+            if (uidActive) {
+                pw.print(prefix); pw.println("Uid: active");
+            }
+            if (job.isExemptedFromAppStandby()) {
+                pw.print(prefix); pw.println("Is exempted from app standby");
+            }
+        }
+        if (trackingControllers != 0) {
+            pw.print(prefix); pw.print("Tracking:");
+            if ((trackingControllers&TRACKING_BATTERY) != 0) pw.print(" BATTERY");
+            if ((trackingControllers&TRACKING_CONNECTIVITY) != 0) pw.print(" CONNECTIVITY");
+            if ((trackingControllers&TRACKING_CONTENT) != 0) pw.print(" CONTENT");
+            if ((trackingControllers&TRACKING_IDLE) != 0) pw.print(" IDLE");
+            if ((trackingControllers&TRACKING_STORAGE) != 0) pw.print(" STORAGE");
+            if ((trackingControllers&TRACKING_TIME) != 0) pw.print(" TIME");
+            if ((trackingControllers & TRACKING_QUOTA) != 0) pw.print(" QUOTA");
+            pw.println();
+        }
+
+        pw.print(prefix); pw.println("Implicit constraints:");
+        pw.print(prefix); pw.print("  readyNotDozing: ");
+        pw.println(mReadyNotDozing);
+        pw.print(prefix); pw.print("  readyNotRestrictedInBg: ");
+        pw.println(mReadyNotRestrictedInBg);
+        if (!job.isPeriodic() && hasDeadlineConstraint()) {
+            pw.print(prefix); pw.print("  readyDeadlineSatisfied: ");
+            pw.println(mReadyDeadlineSatisfied);
+        }
+
+        if (changedAuthorities != null) {
+            pw.print(prefix); pw.println("Changed authorities:");
+            for (int i=0; i<changedAuthorities.size(); i++) {
+                pw.print(prefix); pw.print("  "); pw.println(changedAuthorities.valueAt(i));
+            }
+            if (changedUris != null) {
+                pw.print(prefix); pw.println("Changed URIs:");
+                for (int i=0; i<changedUris.size(); i++) {
+                    pw.print(prefix); pw.print("  "); pw.println(changedUris.valueAt(i));
+                }
+            }
+        }
+        if (network != null) {
+            pw.print(prefix); pw.print("Network: "); pw.println(network);
+        }
+        if (pendingWork != null && pendingWork.size() > 0) {
+            pw.print(prefix); pw.println("Pending work:");
+            for (int i = 0; i < pendingWork.size(); i++) {
+                dumpJobWorkItem(pw, prefix, pendingWork.get(i), i);
+            }
+        }
+        if (executingWork != null && executingWork.size() > 0) {
+            pw.print(prefix); pw.println("Executing work:");
+            for (int i = 0; i < executingWork.size(); i++) {
+                dumpJobWorkItem(pw, prefix, executingWork.get(i), i);
+            }
+        }
+        pw.print(prefix); pw.print("Standby bucket: ");
+        pw.println(getBucketName());
+        if (standbyBucket > 0) {
+            pw.print(prefix); pw.print("Base heartbeat: ");
+            pw.println(baseHeartbeat);
+        }
+        if (whenStandbyDeferred != 0) {
+            pw.print(prefix); pw.print("  Deferred since: ");
+            TimeUtils.formatDuration(whenStandbyDeferred, elapsedRealtimeMillis, pw);
+            pw.println();
+        }
+        if (mFirstForceBatchedTimeElapsed != 0) {
+            pw.print(prefix);
+            pw.print("  Time since first force batch attempt: ");
+            TimeUtils.formatDuration(mFirstForceBatchedTimeElapsed, elapsedRealtimeMillis, pw);
+            pw.println();
+        }
+        pw.print(prefix); pw.print("Enqueue time: ");
+        TimeUtils.formatDuration(enqueueTime, elapsedRealtimeMillis, pw);
+        pw.println();
+        pw.print(prefix); pw.print("Run time: earliest=");
+        formatRunTime(pw, earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME, elapsedRealtimeMillis);
+        pw.print(", latest=");
+        formatRunTime(pw, latestRunTimeElapsedMillis, NO_LATEST_RUNTIME, elapsedRealtimeMillis);
+        pw.print(", original latest=");
+        formatRunTime(pw, mOriginalLatestRunTimeElapsedMillis,
+                NO_LATEST_RUNTIME, elapsedRealtimeMillis);
+        pw.println();
+        if (numFailures != 0) {
+            pw.print(prefix); pw.print("Num failures: "); pw.println(numFailures);
+        }
+        if (mLastSuccessfulRunTime != 0) {
+            pw.print(prefix); pw.print("Last successful run: ");
+            pw.println(TimeMigrationUtils.formatMillisWithFixedFormat(mLastSuccessfulRunTime));
+        }
+        if (mLastFailedRunTime != 0) {
+            pw.print(prefix); pw.print("Last failed run: ");
+            pw.println(TimeMigrationUtils.formatMillisWithFixedFormat(mLastFailedRunTime));
+        }
+    }
+
+    public void dump(ProtoOutputStream proto, long fieldId, boolean full, long elapsedRealtimeMillis) {
+        final long token = proto.start(fieldId);
+
+        proto.write(JobStatusDumpProto.CALLING_UID, callingUid);
+        proto.write(JobStatusDumpProto.TAG, tag);
+        proto.write(JobStatusDumpProto.SOURCE_UID, getSourceUid());
+        proto.write(JobStatusDumpProto.SOURCE_USER_ID, getSourceUserId());
+        proto.write(JobStatusDumpProto.SOURCE_PACKAGE_NAME, getSourcePackageName());
+        proto.write(JobStatusDumpProto.INTERNAL_FLAGS, getInternalFlags());
+
+        if (full) {
+            final long jiToken = proto.start(JobStatusDumpProto.JOB_INFO);
+
+            job.getService().writeToProto(proto, JobStatusDumpProto.JobInfo.SERVICE);
+
+            proto.write(JobStatusDumpProto.JobInfo.IS_PERIODIC, job.isPeriodic());
+            proto.write(JobStatusDumpProto.JobInfo.PERIOD_INTERVAL_MS, job.getIntervalMillis());
+            proto.write(JobStatusDumpProto.JobInfo.PERIOD_FLEX_MS, job.getFlexMillis());
+
+            proto.write(JobStatusDumpProto.JobInfo.IS_PERSISTED, job.isPersisted());
+            proto.write(JobStatusDumpProto.JobInfo.PRIORITY, job.getPriority());
+            proto.write(JobStatusDumpProto.JobInfo.FLAGS, job.getFlags());
+
+            proto.write(JobStatusDumpProto.JobInfo.REQUIRES_CHARGING, job.isRequireCharging());
+            proto.write(JobStatusDumpProto.JobInfo.REQUIRES_BATTERY_NOT_LOW, job.isRequireBatteryNotLow());
+            proto.write(JobStatusDumpProto.JobInfo.REQUIRES_DEVICE_IDLE, job.isRequireDeviceIdle());
+
+            if (job.getTriggerContentUris() != null) {
+                for (int i = 0; i < job.getTriggerContentUris().length; i++) {
+                    final long tcuToken = proto.start(JobStatusDumpProto.JobInfo.TRIGGER_CONTENT_URIS);
+                    JobInfo.TriggerContentUri trig = job.getTriggerContentUris()[i];
+
+                    proto.write(JobStatusDumpProto.JobInfo.TriggerContentUri.FLAGS, trig.getFlags());
+                    Uri u = trig.getUri();
+                    if (u != null) {
+                        proto.write(JobStatusDumpProto.JobInfo.TriggerContentUri.URI, u.toString());
+                    }
+
+                    proto.end(tcuToken);
+                }
+                if (job.getTriggerContentUpdateDelay() >= 0) {
+                    proto.write(JobStatusDumpProto.JobInfo.TRIGGER_CONTENT_UPDATE_DELAY_MS,
+                            job.getTriggerContentUpdateDelay());
+                }
+                if (job.getTriggerContentMaxDelay() >= 0) {
+                    proto.write(JobStatusDumpProto.JobInfo.TRIGGER_CONTENT_MAX_DELAY_MS,
+                            job.getTriggerContentMaxDelay());
+                }
+            }
+            if (job.getExtras() != null && !job.getExtras().maybeIsEmpty()) {
+                job.getExtras().writeToProto(proto, JobStatusDumpProto.JobInfo.EXTRAS);
+            }
+            if (job.getTransientExtras() != null && !job.getTransientExtras().maybeIsEmpty()) {
+                job.getTransientExtras().writeToProto(proto, JobStatusDumpProto.JobInfo.TRANSIENT_EXTRAS);
+            }
+            if (job.getClipData() != null) {
+                job.getClipData().writeToProto(proto, JobStatusDumpProto.JobInfo.CLIP_DATA);
+            }
+            if (uriPerms != null) {
+                uriPerms.dump(proto, JobStatusDumpProto.JobInfo.GRANTED_URI_PERMISSIONS);
+            }
+            if (job.getRequiredNetwork() != null) {
+                job.getRequiredNetwork().writeToProto(proto, JobStatusDumpProto.JobInfo.REQUIRED_NETWORK);
+            }
+            if (mTotalNetworkDownloadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
+                proto.write(JobStatusDumpProto.JobInfo.TOTAL_NETWORK_DOWNLOAD_BYTES,
+                        mTotalNetworkDownloadBytes);
+            }
+            if (mTotalNetworkUploadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
+                proto.write(JobStatusDumpProto.JobInfo.TOTAL_NETWORK_UPLOAD_BYTES,
+                        mTotalNetworkUploadBytes);
+            }
+            proto.write(JobStatusDumpProto.JobInfo.MIN_LATENCY_MS, job.getMinLatencyMillis());
+            proto.write(JobStatusDumpProto.JobInfo.MAX_EXECUTION_DELAY_MS, job.getMaxExecutionDelayMillis());
+
+            final long bpToken = proto.start(JobStatusDumpProto.JobInfo.BACKOFF_POLICY);
+            proto.write(JobStatusDumpProto.JobInfo.Backoff.POLICY, job.getBackoffPolicy());
+            proto.write(JobStatusDumpProto.JobInfo.Backoff.INITIAL_BACKOFF_MS,
+                    job.getInitialBackoffMillis());
+            proto.end(bpToken);
+
+            proto.write(JobStatusDumpProto.JobInfo.HAS_EARLY_CONSTRAINT, job.hasEarlyConstraint());
+            proto.write(JobStatusDumpProto.JobInfo.HAS_LATE_CONSTRAINT, job.hasLateConstraint());
+
+            proto.end(jiToken);
+        }
+
+        dumpConstraints(proto, JobStatusDumpProto.REQUIRED_CONSTRAINTS, requiredConstraints);
+        if (full) {
+            dumpConstraints(proto, JobStatusDumpProto.SATISFIED_CONSTRAINTS, satisfiedConstraints);
+            dumpConstraints(proto, JobStatusDumpProto.UNSATISFIED_CONSTRAINTS,
+                    ((requiredConstraints | CONSTRAINT_WITHIN_QUOTA) & ~satisfiedConstraints));
+            proto.write(JobStatusDumpProto.IS_DOZE_WHITELISTED, dozeWhitelisted);
+            proto.write(JobStatusDumpProto.IS_UID_ACTIVE, uidActive);
+            proto.write(JobStatusDumpProto.IS_EXEMPTED_FROM_APP_STANDBY,
+                    job.isExemptedFromAppStandby());
+        }
+
+        // Tracking controllers
+        if ((trackingControllers&TRACKING_BATTERY) != 0) {
+            proto.write(JobStatusDumpProto.TRACKING_CONTROLLERS,
+                    JobStatusDumpProto.TRACKING_BATTERY);
+        }
+        if ((trackingControllers&TRACKING_CONNECTIVITY) != 0) {
+            proto.write(JobStatusDumpProto.TRACKING_CONTROLLERS,
+                    JobStatusDumpProto.TRACKING_CONNECTIVITY);
+        }
+        if ((trackingControllers&TRACKING_CONTENT) != 0) {
+            proto.write(JobStatusDumpProto.TRACKING_CONTROLLERS,
+                    JobStatusDumpProto.TRACKING_CONTENT);
+        }
+        if ((trackingControllers&TRACKING_IDLE) != 0) {
+            proto.write(JobStatusDumpProto.TRACKING_CONTROLLERS,
+                    JobStatusDumpProto.TRACKING_IDLE);
+        }
+        if ((trackingControllers&TRACKING_STORAGE) != 0) {
+            proto.write(JobStatusDumpProto.TRACKING_CONTROLLERS,
+                    JobStatusDumpProto.TRACKING_STORAGE);
+        }
+        if ((trackingControllers&TRACKING_TIME) != 0) {
+            proto.write(JobStatusDumpProto.TRACKING_CONTROLLERS,
+                    JobStatusDumpProto.TRACKING_TIME);
+        }
+        if ((trackingControllers & TRACKING_QUOTA) != 0) {
+            proto.write(JobStatusDumpProto.TRACKING_CONTROLLERS,
+                    JobStatusDumpProto.TRACKING_QUOTA);
+        }
+
+        // Implicit constraints
+        final long icToken = proto.start(JobStatusDumpProto.IMPLICIT_CONSTRAINTS);
+        proto.write(JobStatusDumpProto.ImplicitConstraints.IS_NOT_DOZING, mReadyNotDozing);
+        proto.write(JobStatusDumpProto.ImplicitConstraints.IS_NOT_RESTRICTED_IN_BG,
+                mReadyNotRestrictedInBg);
+        proto.end(icToken);
+
+        if (changedAuthorities != null) {
+            for (int k = 0; k < changedAuthorities.size(); k++) {
+                proto.write(JobStatusDumpProto.CHANGED_AUTHORITIES, changedAuthorities.valueAt(k));
+            }
+        }
+        if (changedUris != null) {
+            for (int i = 0; i < changedUris.size(); i++) {
+                Uri u = changedUris.valueAt(i);
+                proto.write(JobStatusDumpProto.CHANGED_URIS, u.toString());
+            }
+        }
+
+        if (network != null) {
+            network.writeToProto(proto, JobStatusDumpProto.NETWORK);
+        }
+
+        if (pendingWork != null && pendingWork.size() > 0) {
+            for (int i = 0; i < pendingWork.size(); i++) {
+                dumpJobWorkItem(proto, JobStatusDumpProto.PENDING_WORK, pendingWork.get(i));
+            }
+        }
+        if (executingWork != null && executingWork.size() > 0) {
+            for (int i = 0; i < executingWork.size(); i++) {
+                dumpJobWorkItem(proto, JobStatusDumpProto.EXECUTING_WORK, executingWork.get(i));
+            }
+        }
+
+        proto.write(JobStatusDumpProto.STANDBY_BUCKET, standbyBucket);
+        proto.write(JobStatusDumpProto.ENQUEUE_DURATION_MS, elapsedRealtimeMillis - enqueueTime);
+        proto.write(JobStatusDumpProto.TIME_SINCE_FIRST_DEFERRAL_MS,
+                whenStandbyDeferred == 0 ? 0 : elapsedRealtimeMillis - whenStandbyDeferred);
+        proto.write(JobStatusDumpProto.TIME_SINCE_FIRST_FORCE_BATCH_ATTEMPT_MS,
+                mFirstForceBatchedTimeElapsed == 0
+                        ? 0 : elapsedRealtimeMillis - mFirstForceBatchedTimeElapsed);
+        if (earliestRunTimeElapsedMillis == NO_EARLIEST_RUNTIME) {
+            proto.write(JobStatusDumpProto.TIME_UNTIL_EARLIEST_RUNTIME_MS, 0);
+        } else {
+            proto.write(JobStatusDumpProto.TIME_UNTIL_EARLIEST_RUNTIME_MS,
+                    earliestRunTimeElapsedMillis - elapsedRealtimeMillis);
+        }
+        if (latestRunTimeElapsedMillis == NO_LATEST_RUNTIME) {
+            proto.write(JobStatusDumpProto.TIME_UNTIL_LATEST_RUNTIME_MS, 0);
+        } else {
+            proto.write(JobStatusDumpProto.TIME_UNTIL_LATEST_RUNTIME_MS,
+                    latestRunTimeElapsedMillis - elapsedRealtimeMillis);
+        }
+
+        proto.write(JobStatusDumpProto.NUM_FAILURES, numFailures);
+        proto.write(JobStatusDumpProto.LAST_SUCCESSFUL_RUN_TIME, mLastSuccessfulRunTime);
+        proto.write(JobStatusDumpProto.LAST_FAILED_RUN_TIME, mLastFailedRunTime);
+
+        proto.end(token);
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
new file mode 100644
index 0000000..b8cfac4
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -0,0 +1,2829 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.job.controllers;
+
+import static android.text.format.DateUtils.HOUR_IN_MILLIS;
+import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static android.text.format.DateUtils.SECOND_IN_MILLIS;
+
+import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
+import static com.android.server.job.JobSchedulerService.FREQUENT_INDEX;
+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.WORKING_INDEX;
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
+import android.app.AlarmManager;
+import android.app.AppGlobals;
+import android.app.IUidObserver;
+import android.app.usage.UsageStatsManagerInternal;
+import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.BatteryManager;
+import android.os.BatteryManagerInternal;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.KeyValueListParser;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
+import android.util.SparseSetArray;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.LocalServices;
+import com.android.server.job.ConstantsProto;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.JobServiceContext;
+import com.android.server.job.StateControllerProto;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+/**
+ * Controller that tracks whether an app has exceeded its standby bucket quota.
+ *
+ * With initial defaults, each app in each bucket is given 10 minutes to run within its respective
+ * time window. Active jobs can run indefinitely, working set jobs can run for 10 minutes within a
+ * 2 hour window, frequent jobs get to run 10 minutes in an 8 hour window, and rare jobs get to run
+ * 10 minutes in a 24 hour window. The windows are rolling, so as soon as a job would have some
+ * quota based on its bucket, it will be eligible to run. When a job's bucket changes, its new
+ * quota is immediately applied to it.
+ *
+ * Job and session count limits are included to prevent abuse/spam. Each bucket has its own limit on
+ * the number of jobs or sessions that can run within the window. Regardless of bucket, apps will
+ * not be allowed to run more than 20 jobs within the past 10 minutes.
+ *
+ * Jobs are throttled while an app is not in a foreground state. All jobs are allowed to run
+ * freely when an app enters the foreground state and are restricted when the app leaves the
+ * foreground state. However, jobs that are started while the app is in the TOP state do not count
+ * towards any quota and are not restricted regardless of the app's state change.
+ *
+ * Jobs will not be throttled when the device is charging. The device is considered to be charging
+ * once the {@link BatteryManager#ACTION_CHARGING} intent has been broadcast.
+ *
+ * Note: all limits are enforced per bucket window unless explicitly stated otherwise.
+ * All stated values are configurable and subject to change. See {@link QcConstants} for current
+ * defaults.
+ *
+ * Test: atest com.android.server.job.controllers.QuotaControllerTest
+ */
+public final class QuotaController extends StateController {
+    private static final String TAG = "JobScheduler.Quota";
+    private static final boolean DEBUG = JobSchedulerService.DEBUG
+            || Log.isLoggable(TAG, Log.DEBUG);
+
+    private static final String ALARM_TAG_CLEANUP = "*job.cleanup*";
+    private static final String ALARM_TAG_QUOTA_CHECK = "*job.quota_check*";
+
+    /**
+     * A sparse array of ArrayMaps, which is suitable for holding (userId, packageName)->object
+     * associations.
+     */
+    private static class UserPackageMap<T> {
+        private final SparseArray<ArrayMap<String, T>> mData = new SparseArray<>();
+
+        public void add(int userId, @NonNull String packageName, @Nullable T obj) {
+            ArrayMap<String, T> data = mData.get(userId);
+            if (data == null) {
+                data = new ArrayMap<String, T>();
+                mData.put(userId, data);
+            }
+            data.put(packageName, obj);
+        }
+
+        public void clear() {
+            for (int i = 0; i < mData.size(); ++i) {
+                mData.valueAt(i).clear();
+            }
+        }
+
+        /** Removes all the data for the user, if there was any. */
+        public void delete(int userId) {
+            mData.delete(userId);
+        }
+
+        /** Removes the data for the user and package, if there was any. */
+        public void delete(int userId, @NonNull String packageName) {
+            ArrayMap<String, T> data = mData.get(userId);
+            if (data != null) {
+                data.remove(packageName);
+            }
+        }
+
+        @Nullable
+        public T get(int userId, @NonNull String packageName) {
+            ArrayMap<String, T> data = mData.get(userId);
+            if (data != null) {
+                return data.get(packageName);
+            }
+            return null;
+        }
+
+        /** @see SparseArray#indexOfKey */
+        public int indexOfKey(int userId) {
+            return mData.indexOfKey(userId);
+        }
+
+        /** Returns the userId at the given index. */
+        public int keyAt(int index) {
+            return mData.keyAt(index);
+        }
+
+        /** Returns the package name at the given index. */
+        @NonNull
+        public String keyAt(int userIndex, int packageIndex) {
+            return mData.valueAt(userIndex).keyAt(packageIndex);
+        }
+
+        /** Returns the size of the outer (userId) array. */
+        public int numUsers() {
+            return mData.size();
+        }
+
+        public int numPackagesForUser(int userId) {
+            ArrayMap<String, T> data = mData.get(userId);
+            return data == null ? 0 : data.size();
+        }
+
+        /** Returns the value T at the given user and index. */
+        @Nullable
+        public T valueAt(int userIndex, int packageIndex) {
+            return mData.valueAt(userIndex).valueAt(packageIndex);
+        }
+
+        public void forEach(Consumer<T> consumer) {
+            for (int i = numUsers() - 1; i >= 0; --i) {
+                ArrayMap<String, T> data = mData.valueAt(i);
+                for (int j = data.size() - 1; j >= 0; --j) {
+                    consumer.accept(data.valueAt(j));
+                }
+            }
+        }
+    }
+
+    /**
+     * Standardize the output of userId-packageName combo.
+     */
+    private static String string(int userId, String packageName) {
+        return "<" + userId + ">" + packageName;
+    }
+
+    private static final class Package {
+        public final String packageName;
+        public final int userId;
+
+        Package(int userId, String packageName) {
+            this.userId = userId;
+            this.packageName = packageName;
+        }
+
+        @Override
+        public String toString() {
+            return string(userId, packageName);
+        }
+
+        public void writeToProto(ProtoOutputStream proto, long fieldId) {
+            final long token = proto.start(fieldId);
+
+            proto.write(StateControllerProto.QuotaController.Package.USER_ID, userId);
+            proto.write(StateControllerProto.QuotaController.Package.NAME, packageName);
+
+            proto.end(token);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Package) {
+                Package other = (Package) obj;
+                return userId == other.userId && Objects.equals(packageName, other.packageName);
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            return packageName.hashCode() + userId;
+        }
+    }
+
+    private static int hashLong(long val) {
+        return (int) (val ^ (val >>> 32));
+    }
+
+    @VisibleForTesting
+    static class ExecutionStats {
+        /**
+         * The time after which this record should be considered invalid (out of date), in the
+         * elapsed realtime timebase.
+         */
+        public long expirationTimeElapsed;
+
+        public long windowSizeMs;
+        public int jobCountLimit;
+        public int sessionCountLimit;
+
+        /** The total amount of time the app ran in its respective bucket window size. */
+        public long executionTimeInWindowMs;
+        public int bgJobCountInWindow;
+
+        /** The total amount of time the app ran in the last {@link #MAX_PERIOD_MS}. */
+        public long executionTimeInMaxPeriodMs;
+        public int bgJobCountInMaxPeriod;
+
+        /**
+         * The number of {@link TimingSession}s within the bucket window size. This will include
+         * sessions that started before the window as long as they end within the window.
+         */
+        public int sessionCountInWindow;
+
+        /**
+         * The time after which the app will be under the bucket quota and can start running jobs
+         * again. This is only valid if
+         * {@link #executionTimeInWindowMs} >= {@link #mAllowedTimePerPeriodMs},
+         * {@link #executionTimeInMaxPeriodMs} >= {@link #mMaxExecutionTimeMs},
+         * {@link #bgJobCountInWindow} >= {@link #jobCountLimit}, or
+         * {@link #sessionCountInWindow} >= {@link #sessionCountLimit}.
+         */
+        public long inQuotaTimeElapsed;
+
+        /**
+         * The time after which {@link #jobCountInRateLimitingWindow} should be considered invalid,
+         * in the elapsed realtime timebase.
+         */
+        public long jobRateLimitExpirationTimeElapsed;
+
+        /**
+         * The number of jobs that ran in at least the last {@link #mRateLimitingWindowMs}.
+         * It may contain a few stale entries since cleanup won't happen exactly every
+         * {@link #mRateLimitingWindowMs}.
+         */
+        public int jobCountInRateLimitingWindow;
+
+        /**
+         * The time after which {@link #sessionCountInRateLimitingWindow} should be considered
+         * invalid, in the elapsed realtime timebase.
+         */
+        public long sessionRateLimitExpirationTimeElapsed;
+
+        /**
+         * The number of {@link TimingSession}s that ran in at least the last
+         * {@link #mRateLimitingWindowMs}. It may contain a few stale entries since cleanup won't
+         * happen exactly every {@link #mRateLimitingWindowMs}. This should only be considered
+         * valid before elapsed realtime has reached {@link #sessionRateLimitExpirationTimeElapsed}.
+         */
+        public int sessionCountInRateLimitingWindow;
+
+        @Override
+        public String toString() {
+            return "expirationTime=" + expirationTimeElapsed + ", "
+                    + "windowSizeMs=" + windowSizeMs + ", "
+                    + "jobCountLimit=" + jobCountLimit + ", "
+                    + "sessionCountLimit=" + sessionCountLimit + ", "
+                    + "executionTimeInWindow=" + executionTimeInWindowMs + ", "
+                    + "bgJobCountInWindow=" + bgJobCountInWindow + ", "
+                    + "executionTimeInMaxPeriod=" + executionTimeInMaxPeriodMs + ", "
+                    + "bgJobCountInMaxPeriod=" + bgJobCountInMaxPeriod + ", "
+                    + "sessionCountInWindow=" + sessionCountInWindow + ", "
+                    + "inQuotaTime=" + inQuotaTimeElapsed + ", "
+                    + "jobCountExpirationTime=" + jobRateLimitExpirationTimeElapsed + ", "
+                    + "jobCountInRateLimitingWindow=" + jobCountInRateLimitingWindow + ", "
+                    + "sessionCountExpirationTime=" + sessionRateLimitExpirationTimeElapsed + ", "
+                    + "sessionCountInRateLimitingWindow=" + sessionCountInRateLimitingWindow;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof ExecutionStats) {
+                ExecutionStats other = (ExecutionStats) obj;
+                return this.expirationTimeElapsed == other.expirationTimeElapsed
+                        && this.windowSizeMs == other.windowSizeMs
+                        && this.jobCountLimit == other.jobCountLimit
+                        && this.sessionCountLimit == other.sessionCountLimit
+                        && this.executionTimeInWindowMs == other.executionTimeInWindowMs
+                        && this.bgJobCountInWindow == other.bgJobCountInWindow
+                        && this.executionTimeInMaxPeriodMs == other.executionTimeInMaxPeriodMs
+                        && this.sessionCountInWindow == other.sessionCountInWindow
+                        && this.bgJobCountInMaxPeriod == other.bgJobCountInMaxPeriod
+                        && this.inQuotaTimeElapsed == other.inQuotaTimeElapsed
+                        && this.jobRateLimitExpirationTimeElapsed
+                                == other.jobRateLimitExpirationTimeElapsed
+                        && this.jobCountInRateLimitingWindow == other.jobCountInRateLimitingWindow
+                        && this.sessionRateLimitExpirationTimeElapsed
+                                == other.sessionRateLimitExpirationTimeElapsed
+                        && this.sessionCountInRateLimitingWindow
+                                == other.sessionCountInRateLimitingWindow;
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            int result = 0;
+            result = 31 * result + hashLong(expirationTimeElapsed);
+            result = 31 * result + hashLong(windowSizeMs);
+            result = 31 * result + hashLong(jobCountLimit);
+            result = 31 * result + hashLong(sessionCountLimit);
+            result = 31 * result + hashLong(executionTimeInWindowMs);
+            result = 31 * result + bgJobCountInWindow;
+            result = 31 * result + hashLong(executionTimeInMaxPeriodMs);
+            result = 31 * result + bgJobCountInMaxPeriod;
+            result = 31 * result + sessionCountInWindow;
+            result = 31 * result + hashLong(inQuotaTimeElapsed);
+            result = 31 * result + hashLong(jobRateLimitExpirationTimeElapsed);
+            result = 31 * result + jobCountInRateLimitingWindow;
+            result = 31 * result + hashLong(sessionRateLimitExpirationTimeElapsed);
+            result = 31 * result + sessionCountInRateLimitingWindow;
+            return result;
+        }
+    }
+
+    /** List of all tracked jobs keyed by source package-userId combo. */
+    private final UserPackageMap<ArraySet<JobStatus>> mTrackedJobs = new UserPackageMap<>();
+
+    /** Timer for each package-userId combo. */
+    private final UserPackageMap<Timer> mPkgTimers = new UserPackageMap<>();
+
+    /** List of all timing sessions for a package-userId combo, in chronological order. */
+    private final UserPackageMap<List<TimingSession>> mTimingSessions = new UserPackageMap<>();
+
+    /**
+     * List of alarm listeners for each package that listen for when each package comes back within
+     * quota.
+     */
+    private final UserPackageMap<QcAlarmListener> mInQuotaAlarmListeners = new UserPackageMap<>();
+
+    /** Cached calculation results for each app, with the standby buckets as the array indices. */
+    private final UserPackageMap<ExecutionStats[]> mExecutionStatsCache = new UserPackageMap<>();
+
+    /** List of UIDs currently in the foreground. */
+    private final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
+
+    /** Cached mapping of UIDs (for all users) to a list of packages in the UID. */
+    private final SparseSetArray<String> mUidToPackageCache = new SparseSetArray<>();
+
+    /**
+     * List of jobs that started while the UID was in the TOP state. There will be no more than
+     * 16 ({@link JobSchedulerService#MAX_JOB_CONTEXTS_COUNT}) running at once, so an ArraySet is
+     * fine.
+     */
+    private final ArraySet<JobStatus> mTopStartedJobs = new ArraySet<>();
+
+    private final ActivityManagerInternal mActivityManagerInternal;
+    private final AlarmManager mAlarmManager;
+    private final ChargingTracker mChargeTracker;
+    private final Handler mHandler;
+    private final QcConstants mQcConstants;
+
+    private volatile boolean mInParole;
+
+    /**
+     * If the QuotaController should throttle apps based on their standby bucket and job activity.
+     * If false, all jobs will have their CONSTRAINT_WITHIN_QUOTA bit set to true immediately and
+     * indefinitely.
+     */
+    private boolean mShouldThrottle;
+
+    /** How much time each app will have to run jobs within their standby bucket window. */
+    private long mAllowedTimePerPeriodMs = QcConstants.DEFAULT_ALLOWED_TIME_PER_PERIOD_MS;
+
+    /**
+     * The maximum amount of time an app can have its jobs running within a {@link #MAX_PERIOD_MS}
+     * window.
+     */
+    private long mMaxExecutionTimeMs = QcConstants.DEFAULT_MAX_EXECUTION_TIME_MS;
+
+    /**
+     * How much time the app should have before transitioning from out-of-quota to in-quota.
+     * This should not affect processing if the app is already in-quota.
+     */
+    private long mQuotaBufferMs = QcConstants.DEFAULT_IN_QUOTA_BUFFER_MS;
+
+    /**
+     * {@link #mAllowedTimePerPeriodMs} - {@link #mQuotaBufferMs}. This can be used to determine
+     * when an app will have enough quota to transition from out-of-quota to in-quota.
+     */
+    private long mAllowedTimeIntoQuotaMs = mAllowedTimePerPeriodMs - mQuotaBufferMs;
+
+    /**
+     * {@link #mMaxExecutionTimeMs} - {@link #mQuotaBufferMs}. This can be used to determine when an
+     * app will have enough quota to transition from out-of-quota to in-quota.
+     */
+    private long mMaxExecutionTimeIntoQuotaMs = mMaxExecutionTimeMs - mQuotaBufferMs;
+
+    /** The period of time used to rate limit recently run jobs. */
+    private long mRateLimitingWindowMs = QcConstants.DEFAULT_RATE_LIMITING_WINDOW_MS;
+
+    /** The maximum number of jobs that can run within the past {@link #mRateLimitingWindowMs}. */
+    private int mMaxJobCountPerRateLimitingWindow =
+            QcConstants.DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW;
+
+    /**
+     * The maximum number of {@link TimingSession}s that can run within the past {@link
+     * #mRateLimitingWindowMs}.
+     */
+    private int mMaxSessionCountPerRateLimitingWindow =
+            QcConstants.DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW;
+
+    private long mNextCleanupTimeElapsed = 0;
+    private final AlarmManager.OnAlarmListener mSessionCleanupAlarmListener =
+            new AlarmManager.OnAlarmListener() {
+                @Override
+                public void onAlarm() {
+                    mHandler.obtainMessage(MSG_CLEAN_UP_SESSIONS).sendToTarget();
+                }
+            };
+
+    private final IUidObserver mUidObserver = new IUidObserver.Stub() {
+        @Override
+        public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+            mHandler.obtainMessage(MSG_UID_PROCESS_STATE_CHANGED, uid, procState).sendToTarget();
+        }
+
+        @Override
+        public void onUidGone(int uid, boolean disabled) {
+        }
+
+        @Override
+        public void onUidActive(int uid) {
+        }
+
+        @Override
+        public void onUidIdle(int uid, boolean disabled) {
+        }
+
+        @Override
+        public void onUidCachedChanged(int uid, boolean cached) {
+        }
+    };
+
+    private final BroadcastReceiver mPackageAddedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent == null) {
+                return;
+            }
+            if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+                return;
+            }
+            final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+            synchronized (mLock) {
+                mUidToPackageCache.remove(uid);
+            }
+        }
+    };
+
+    /**
+     * The rolling window size for each standby bucket. Within each window, an app will have 10
+     * minutes to run its jobs.
+     */
+    private final long[] mBucketPeriodsMs = new long[]{
+            QcConstants.DEFAULT_WINDOW_SIZE_ACTIVE_MS,
+            QcConstants.DEFAULT_WINDOW_SIZE_WORKING_MS,
+            QcConstants.DEFAULT_WINDOW_SIZE_FREQUENT_MS,
+            QcConstants.DEFAULT_WINDOW_SIZE_RARE_MS
+    };
+
+    /** The maximum period any bucket can have. */
+    private static final long MAX_PERIOD_MS = 24 * 60 * MINUTE_IN_MILLIS;
+
+    /**
+     * The maximum number of jobs based on its standby bucket. For each max value count in the
+     * array, the app will not be allowed to run more than that many number of jobs within the
+     * latest time interval of its rolling window size.
+     *
+     * @see #mBucketPeriodsMs
+     */
+    private final int[] mMaxBucketJobCounts = new int[]{
+            QcConstants.DEFAULT_MAX_JOB_COUNT_ACTIVE,
+            QcConstants.DEFAULT_MAX_JOB_COUNT_WORKING,
+            QcConstants.DEFAULT_MAX_JOB_COUNT_FREQUENT,
+            QcConstants.DEFAULT_MAX_JOB_COUNT_RARE
+    };
+
+    /**
+     * The maximum number of {@link TimingSession}s based on its standby bucket. For each max value
+     * count in the array, the app will not be allowed to have more than that many number of
+     * {@link TimingSession}s within the latest time interval of its rolling window size.
+     *
+     * @see #mBucketPeriodsMs
+     */
+    private final int[] mMaxBucketSessionCounts = new int[]{
+            QcConstants.DEFAULT_MAX_SESSION_COUNT_ACTIVE,
+            QcConstants.DEFAULT_MAX_SESSION_COUNT_WORKING,
+            QcConstants.DEFAULT_MAX_SESSION_COUNT_FREQUENT,
+            QcConstants.DEFAULT_MAX_SESSION_COUNT_RARE
+    };
+
+    /**
+     * Treat two distinct {@link TimingSession}s as the same if they start and end within this
+     * amount of time of each other.
+     */
+    private long mTimingSessionCoalescingDurationMs =
+            QcConstants.DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS;
+
+    /** An app has reached its quota. The message should contain a {@link Package} object. */
+    private static final int MSG_REACHED_QUOTA = 0;
+    /** Drop any old timing sessions. */
+    private static final int MSG_CLEAN_UP_SESSIONS = 1;
+    /** Check if a package is now within its quota. */
+    private static final int MSG_CHECK_PACKAGE = 2;
+    /** Process state for a UID has changed. */
+    private static final int MSG_UID_PROCESS_STATE_CHANGED = 3;
+
+    public QuotaController(JobSchedulerService service) {
+        super(service);
+        mHandler = new QcHandler(mContext.getMainLooper());
+        mChargeTracker = new ChargingTracker();
+        mChargeTracker.startTracking();
+        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
+        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+        mQcConstants = new QcConstants(mHandler);
+
+        final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+        mContext.registerReceiverAsUser(mPackageAddedReceiver, UserHandle.ALL, filter, null, null);
+
+        // Set up the app standby bucketing tracker
+        UsageStatsManagerInternal usageStats = LocalServices.getService(
+                UsageStatsManagerInternal.class);
+        usageStats.addAppIdleStateChangeListener(new StandbyTracker());
+
+        try {
+            ActivityManager.getService().registerUidObserver(mUidObserver,
+                    ActivityManager.UID_OBSERVER_PROCSTATE,
+                    ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, null);
+        } catch (RemoteException e) {
+            // ignored; both services live in system_server
+        }
+
+        mShouldThrottle = !mConstants.USE_HEARTBEATS;
+    }
+
+    @Override
+    public void onSystemServicesReady() {
+        mQcConstants.start(mContext.getContentResolver());
+    }
+
+    @Override
+    public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
+        final int userId = jobStatus.getSourceUserId();
+        final String pkgName = jobStatus.getSourcePackageName();
+        // Still need to track jobs even if mShouldThrottle is false in case it's set to true at
+        // some point.
+        ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, pkgName);
+        if (jobs == null) {
+            jobs = new ArraySet<>();
+            mTrackedJobs.add(userId, pkgName, jobs);
+        }
+        jobs.add(jobStatus);
+        jobStatus.setTrackingController(JobStatus.TRACKING_QUOTA);
+        if (mShouldThrottle) {
+            final boolean isWithinQuota = isWithinQuotaLocked(jobStatus);
+            setConstraintSatisfied(jobStatus, isWithinQuota);
+            if (!isWithinQuota) {
+                maybeScheduleStartAlarmLocked(userId, pkgName,
+                        getEffectiveStandbyBucket(jobStatus));
+            }
+        } else {
+            // QuotaController isn't throttling, so always set to true.
+            jobStatus.setQuotaConstraintSatisfied(true);
+        }
+    }
+
+    @Override
+    public void prepareForExecutionLocked(JobStatus jobStatus) {
+        if (DEBUG) {
+            Slog.d(TAG, "Prepping for " + jobStatus.toShortString());
+        }
+
+        final int uid = jobStatus.getSourceUid();
+        if (mActivityManagerInternal.getUidProcessState(uid) <= ActivityManager.PROCESS_STATE_TOP) {
+            if (DEBUG) {
+                Slog.d(TAG, jobStatus.toShortString() + " is top started job");
+            }
+            mTopStartedJobs.add(jobStatus);
+            // Top jobs won't count towards quota so there's no need to involve the Timer.
+            return;
+        }
+
+        final int userId = jobStatus.getSourceUserId();
+        final String packageName = jobStatus.getSourcePackageName();
+        Timer timer = mPkgTimers.get(userId, packageName);
+        if (timer == null) {
+            timer = new Timer(uid, userId, packageName);
+            mPkgTimers.add(userId, packageName, timer);
+        }
+        timer.startTrackingJobLocked(jobStatus);
+    }
+
+    @Override
+    public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
+            boolean forUpdate) {
+        if (jobStatus.clearTrackingController(JobStatus.TRACKING_QUOTA)) {
+            Timer timer = mPkgTimers.get(jobStatus.getSourceUserId(),
+                    jobStatus.getSourcePackageName());
+            if (timer != null) {
+                timer.stopTrackingJob(jobStatus);
+            }
+            ArraySet<JobStatus> jobs = mTrackedJobs.get(jobStatus.getSourceUserId(),
+                    jobStatus.getSourcePackageName());
+            if (jobs != null) {
+                jobs.remove(jobStatus);
+            }
+            mTopStartedJobs.remove(jobStatus);
+        }
+    }
+
+    @Override
+    public void onConstantsUpdatedLocked() {
+        if (mShouldThrottle == mConstants.USE_HEARTBEATS) {
+            mShouldThrottle = !mConstants.USE_HEARTBEATS;
+
+            // Update job bookkeeping out of band.
+            BackgroundThread.getHandler().post(() -> {
+                synchronized (mLock) {
+                    maybeUpdateAllConstraintsLocked();
+                }
+            });
+        }
+    }
+
+    @Override
+    public void onAppRemovedLocked(String packageName, int uid) {
+        if (packageName == null) {
+            Slog.wtf(TAG, "Told app removed but given null package name.");
+            return;
+        }
+        final int userId = UserHandle.getUserId(uid);
+        mTrackedJobs.delete(userId, packageName);
+        Timer timer = mPkgTimers.get(userId, packageName);
+        if (timer != null) {
+            if (timer.isActive()) {
+                Slog.wtf(TAG, "onAppRemovedLocked called before Timer turned off.");
+                timer.dropEverythingLocked();
+            }
+            mPkgTimers.delete(userId, packageName);
+        }
+        mTimingSessions.delete(userId, packageName);
+        QcAlarmListener alarmListener = mInQuotaAlarmListeners.get(userId, packageName);
+        if (alarmListener != null) {
+            mAlarmManager.cancel(alarmListener);
+            mInQuotaAlarmListeners.delete(userId, packageName);
+        }
+        mExecutionStatsCache.delete(userId, packageName);
+        mForegroundUids.delete(uid);
+        mUidToPackageCache.remove(uid);
+    }
+
+    @Override
+    public void onUserRemovedLocked(int userId) {
+        mTrackedJobs.delete(userId);
+        mPkgTimers.delete(userId);
+        mTimingSessions.delete(userId);
+        mInQuotaAlarmListeners.delete(userId);
+        mExecutionStatsCache.delete(userId);
+        mUidToPackageCache.clear();
+    }
+
+    private boolean isUidInForeground(int uid) {
+        if (UserHandle.isCore(uid)) {
+            return true;
+        }
+        synchronized (mLock) {
+            return mForegroundUids.get(uid);
+        }
+    }
+
+    /** @return true if the job was started while the app was in the TOP state. */
+    private boolean isTopStartedJobLocked(@NonNull final JobStatus jobStatus) {
+        return mTopStartedJobs.contains(jobStatus);
+    }
+
+    /** Returns the maximum amount of time this job could run for. */
+    public long getMaxJobExecutionTimeMsLocked(@NonNull final JobStatus jobStatus) {
+        // If quota is currently "free", then the job can run for the full amount of time.
+        if (mChargeTracker.isCharging()
+                || mInParole
+                || isTopStartedJobLocked(jobStatus)
+                || isUidInForeground(jobStatus.getSourceUid())) {
+            return JobServiceContext.EXECUTING_TIMESLICE_MILLIS;
+        }
+        return getRemainingExecutionTimeLocked(jobStatus);
+    }
+
+    /**
+     * Returns an appropriate standby bucket for the job, taking into account any standby
+     * exemptions.
+     */
+    private int getEffectiveStandbyBucket(@NonNull final JobStatus jobStatus) {
+        if (jobStatus.uidActive || jobStatus.getJob().isExemptedFromAppStandby()) {
+            // Treat these cases as if they're in the ACTIVE bucket so that they get throttled
+            // like other ACTIVE apps.
+            return ACTIVE_INDEX;
+        }
+        return jobStatus.getStandbyBucket();
+    }
+
+    @VisibleForTesting
+    boolean isWithinQuotaLocked(@NonNull final JobStatus jobStatus) {
+        final int standbyBucket = getEffectiveStandbyBucket(jobStatus);
+        // A job is within quota if one of the following is true:
+        //   1. it was started while the app was in the TOP state
+        //   2. the app is currently in the foreground
+        //   3. the app overall is within its quota
+        return isTopStartedJobLocked(jobStatus)
+                || isUidInForeground(jobStatus.getSourceUid())
+                || isWithinQuotaLocked(
+                jobStatus.getSourceUserId(), jobStatus.getSourcePackageName(), standbyBucket);
+    }
+
+    @VisibleForTesting
+    boolean isWithinQuotaLocked(final int userId, @NonNull final String packageName,
+            final int standbyBucket) {
+        if (standbyBucket == NEVER_INDEX) return false;
+        // This check is needed in case the flag is toggled after a job has been registered.
+        if (!mShouldThrottle) return true;
+
+        // Quota constraint is not enforced while charging or when parole is on.
+        if (mChargeTracker.isCharging() || mInParole) {
+            return true;
+        }
+
+        ExecutionStats stats = getExecutionStatsLocked(userId, packageName, standbyBucket);
+        return getRemainingExecutionTimeLocked(stats) > 0
+                && isUnderJobCountQuotaLocked(stats, standbyBucket)
+                && isUnderSessionCountQuotaLocked(stats, standbyBucket);
+    }
+
+    private boolean isUnderJobCountQuotaLocked(@NonNull ExecutionStats stats,
+            final int standbyBucket) {
+        final long now = sElapsedRealtimeClock.millis();
+        final boolean isUnderAllowedTimeQuota =
+                (stats.jobRateLimitExpirationTimeElapsed <= now
+                        || stats.jobCountInRateLimitingWindow < mMaxJobCountPerRateLimitingWindow);
+        return isUnderAllowedTimeQuota
+                && (stats.bgJobCountInWindow < mMaxBucketJobCounts[standbyBucket]);
+    }
+
+    private boolean isUnderSessionCountQuotaLocked(@NonNull ExecutionStats stats,
+            final int standbyBucket) {
+        final long now = sElapsedRealtimeClock.millis();
+        final boolean isUnderAllowedTimeQuota = (stats.sessionRateLimitExpirationTimeElapsed <= now
+                || stats.sessionCountInRateLimitingWindow < mMaxSessionCountPerRateLimitingWindow);
+        return isUnderAllowedTimeQuota
+                && stats.sessionCountInWindow < mMaxBucketSessionCounts[standbyBucket];
+    }
+
+    @VisibleForTesting
+    long getRemainingExecutionTimeLocked(@NonNull final JobStatus jobStatus) {
+        return getRemainingExecutionTimeLocked(jobStatus.getSourceUserId(),
+                jobStatus.getSourcePackageName(),
+                getEffectiveStandbyBucket(jobStatus));
+    }
+
+    @VisibleForTesting
+    long getRemainingExecutionTimeLocked(final int userId, @NonNull final String packageName) {
+        final int standbyBucket = JobSchedulerService.standbyBucketForPackage(packageName,
+                userId, sElapsedRealtimeClock.millis());
+        return getRemainingExecutionTimeLocked(userId, packageName, standbyBucket);
+    }
+
+    /**
+     * Returns the amount of time, in milliseconds, that this job has remaining to run based on its
+     * current standby bucket. Time remaining could be negative if the app was moved from a less
+     * restricted to a more restricted bucket.
+     */
+    private long getRemainingExecutionTimeLocked(final int userId,
+            @NonNull final String packageName, final int standbyBucket) {
+        if (standbyBucket == NEVER_INDEX) {
+            return 0;
+        }
+        return getRemainingExecutionTimeLocked(
+                getExecutionStatsLocked(userId, packageName, standbyBucket));
+    }
+
+    private long getRemainingExecutionTimeLocked(@NonNull ExecutionStats stats) {
+        return Math.min(mAllowedTimePerPeriodMs - stats.executionTimeInWindowMs,
+                mMaxExecutionTimeMs - stats.executionTimeInMaxPeriodMs);
+    }
+
+    /**
+     * Returns the amount of time, in milliseconds, until the package would have reached its
+     * duration quota, assuming it has a job counting towards its quota the entire time. This takes
+     * into account any {@link TimingSession}s that may roll out of the window as the job is
+     * running.
+     */
+    @VisibleForTesting
+    long getTimeUntilQuotaConsumedLocked(final int userId, @NonNull final String packageName) {
+        final long nowElapsed = sElapsedRealtimeClock.millis();
+        final int standbyBucket = JobSchedulerService.standbyBucketForPackage(
+                packageName, userId, nowElapsed);
+        if (standbyBucket == NEVER_INDEX) {
+            return 0;
+        }
+        List<TimingSession> sessions = mTimingSessions.get(userId, packageName);
+        if (sessions == null || sessions.size() == 0) {
+            return mAllowedTimePerPeriodMs;
+        }
+
+        final ExecutionStats stats = getExecutionStatsLocked(userId, packageName, standbyBucket);
+        final long startWindowElapsed = nowElapsed - stats.windowSizeMs;
+        final long startMaxElapsed = nowElapsed - MAX_PERIOD_MS;
+        final long allowedTimeRemainingMs = mAllowedTimePerPeriodMs - stats.executionTimeInWindowMs;
+        final long maxExecutionTimeRemainingMs =
+                mMaxExecutionTimeMs - stats.executionTimeInMaxPeriodMs;
+
+        // Regular ACTIVE case. Since the bucket size equals the allowed time, the app jobs can
+        // essentially run until they reach the maximum limit.
+        if (stats.windowSizeMs == mAllowedTimePerPeriodMs) {
+            return calculateTimeUntilQuotaConsumedLocked(
+                    sessions, startMaxElapsed, maxExecutionTimeRemainingMs);
+        }
+
+        // Need to check both max time and period time in case one is less than the other.
+        // For example, max time remaining could be less than bucket time remaining, but sessions
+        // contributing to the max time remaining could phase out enough that we'd want to use the
+        // bucket value.
+        return Math.min(
+                calculateTimeUntilQuotaConsumedLocked(
+                        sessions, startMaxElapsed, maxExecutionTimeRemainingMs),
+                calculateTimeUntilQuotaConsumedLocked(
+                        sessions, startWindowElapsed, allowedTimeRemainingMs));
+    }
+
+    /**
+     * Calculates how much time it will take, in milliseconds, until the quota is fully consumed.
+     *
+     * @param windowStartElapsed The start of the window, in the elapsed realtime timebase.
+     * @param deadSpaceMs        How much time can be allowed to count towards the quota
+     */
+    private long calculateTimeUntilQuotaConsumedLocked(@NonNull List<TimingSession> sessions,
+            final long windowStartElapsed, long deadSpaceMs) {
+        long timeUntilQuotaConsumedMs = 0;
+        long start = windowStartElapsed;
+        for (int i = 0; i < sessions.size(); ++i) {
+            TimingSession session = sessions.get(i);
+
+            if (session.endTimeElapsed < windowStartElapsed) {
+                // Outside of window. Ignore.
+                continue;
+            } else if (session.startTimeElapsed <= windowStartElapsed) {
+                // Overlapping session. Can extend time by portion of session in window.
+                timeUntilQuotaConsumedMs += session.endTimeElapsed - windowStartElapsed;
+                start = session.endTimeElapsed;
+            } else {
+                // Completely within the window. Can only consider if there's enough dead space
+                // to get to the start of the session.
+                long diff = session.startTimeElapsed - start;
+                if (diff > deadSpaceMs) {
+                    break;
+                }
+                timeUntilQuotaConsumedMs += diff
+                        + (session.endTimeElapsed - session.startTimeElapsed);
+                deadSpaceMs -= diff;
+                start = session.endTimeElapsed;
+            }
+        }
+        // Will be non-zero if the loop didn't look at any sessions.
+        timeUntilQuotaConsumedMs += deadSpaceMs;
+        if (timeUntilQuotaConsumedMs > mMaxExecutionTimeMs) {
+            Slog.wtf(TAG, "Calculated quota consumed time too high: " + timeUntilQuotaConsumedMs);
+        }
+        return timeUntilQuotaConsumedMs;
+    }
+
+    /** Returns the execution stats of the app in the most recent window. */
+    @VisibleForTesting
+    @NonNull
+    ExecutionStats getExecutionStatsLocked(final int userId, @NonNull final String packageName,
+            final int standbyBucket) {
+        return getExecutionStatsLocked(userId, packageName, standbyBucket, true);
+    }
+
+    @NonNull
+    private ExecutionStats getExecutionStatsLocked(final int userId,
+            @NonNull final String packageName, final int standbyBucket,
+            final boolean refreshStatsIfOld) {
+        if (standbyBucket == NEVER_INDEX) {
+            Slog.wtf(TAG, "getExecutionStatsLocked called for a NEVER app.");
+            return new ExecutionStats();
+        }
+        ExecutionStats[] appStats = mExecutionStatsCache.get(userId, packageName);
+        if (appStats == null) {
+            appStats = new ExecutionStats[mBucketPeriodsMs.length];
+            mExecutionStatsCache.add(userId, packageName, appStats);
+        }
+        ExecutionStats stats = appStats[standbyBucket];
+        if (stats == null) {
+            stats = new ExecutionStats();
+            appStats[standbyBucket] = stats;
+        }
+        if (refreshStatsIfOld) {
+            final long bucketWindowSizeMs = mBucketPeriodsMs[standbyBucket];
+            final int jobCountLimit = mMaxBucketJobCounts[standbyBucket];
+            final int sessionCountLimit = mMaxBucketSessionCounts[standbyBucket];
+            Timer timer = mPkgTimers.get(userId, packageName);
+            if ((timer != null && timer.isActive())
+                    || stats.expirationTimeElapsed <= sElapsedRealtimeClock.millis()
+                    || stats.windowSizeMs != bucketWindowSizeMs
+                    || stats.jobCountLimit != jobCountLimit
+                    || stats.sessionCountLimit != sessionCountLimit) {
+                // The stats are no longer valid.
+                stats.windowSizeMs = bucketWindowSizeMs;
+                stats.jobCountLimit = jobCountLimit;
+                stats.sessionCountLimit = sessionCountLimit;
+                updateExecutionStatsLocked(userId, packageName, stats);
+            }
+        }
+
+        return stats;
+    }
+
+    @VisibleForTesting
+    void updateExecutionStatsLocked(final int userId, @NonNull final String packageName,
+            @NonNull ExecutionStats stats) {
+        stats.executionTimeInWindowMs = 0;
+        stats.bgJobCountInWindow = 0;
+        stats.executionTimeInMaxPeriodMs = 0;
+        stats.bgJobCountInMaxPeriod = 0;
+        stats.sessionCountInWindow = 0;
+        stats.inQuotaTimeElapsed = 0;
+
+        Timer timer = mPkgTimers.get(userId, packageName);
+        final long nowElapsed = sElapsedRealtimeClock.millis();
+        stats.expirationTimeElapsed = nowElapsed + MAX_PERIOD_MS;
+        if (timer != null && timer.isActive()) {
+            stats.executionTimeInWindowMs =
+                    stats.executionTimeInMaxPeriodMs = timer.getCurrentDuration(nowElapsed);
+            stats.bgJobCountInWindow = stats.bgJobCountInMaxPeriod = timer.getBgJobCount();
+            // If the timer is active, the value will be stale at the next method call, so
+            // invalidate now.
+            stats.expirationTimeElapsed = nowElapsed;
+            if (stats.executionTimeInWindowMs >= mAllowedTimeIntoQuotaMs) {
+                stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
+                        nowElapsed - mAllowedTimeIntoQuotaMs + stats.windowSizeMs);
+            }
+            if (stats.executionTimeInMaxPeriodMs >= mMaxExecutionTimeIntoQuotaMs) {
+                stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
+                        nowElapsed - mMaxExecutionTimeIntoQuotaMs + MAX_PERIOD_MS);
+            }
+        }
+
+        List<TimingSession> sessions = mTimingSessions.get(userId, packageName);
+        if (sessions == null || sessions.size() == 0) {
+            return;
+        }
+
+        final long startWindowElapsed = nowElapsed - stats.windowSizeMs;
+        final long startMaxElapsed = nowElapsed - MAX_PERIOD_MS;
+        int sessionCountInWindow = 0;
+        // The minimum time between the start time and the beginning of the sessions that were
+        // looked at --> how much time the stats will be valid for.
+        long emptyTimeMs = Long.MAX_VALUE;
+        // Sessions are non-overlapping and in order of occurrence, so iterating backwards will get
+        // the most recent ones.
+        final int loopStart = sessions.size() - 1;
+        for (int i = loopStart; i >= 0; --i) {
+            TimingSession session = sessions.get(i);
+
+            // Window management.
+            if (startWindowElapsed < session.endTimeElapsed) {
+                final long start;
+                if (startWindowElapsed < session.startTimeElapsed) {
+                    start = session.startTimeElapsed;
+                    emptyTimeMs =
+                            Math.min(emptyTimeMs, session.startTimeElapsed - startWindowElapsed);
+                } else {
+                    // The session started before the window but ended within the window. Only
+                    // include the portion that was within the window.
+                    start = startWindowElapsed;
+                    emptyTimeMs = 0;
+                }
+
+                stats.executionTimeInWindowMs += session.endTimeElapsed - start;
+                stats.bgJobCountInWindow += session.bgJobCount;
+                if (stats.executionTimeInWindowMs >= mAllowedTimeIntoQuotaMs) {
+                    stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
+                            start + stats.executionTimeInWindowMs - mAllowedTimeIntoQuotaMs
+                                    + stats.windowSizeMs);
+                }
+                if (stats.bgJobCountInWindow >= stats.jobCountLimit) {
+                    stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
+                            session.endTimeElapsed + stats.windowSizeMs);
+                }
+                if (i == loopStart
+                        || (sessions.get(i + 1).startTimeElapsed - session.endTimeElapsed)
+                                > mTimingSessionCoalescingDurationMs) {
+                    // Coalesce sessions if they are very close to each other in time
+                    sessionCountInWindow++;
+
+                    if (sessionCountInWindow >= stats.sessionCountLimit) {
+                        stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
+                                session.endTimeElapsed + stats.windowSizeMs);
+                    }
+                }
+            }
+
+            // Max period check.
+            if (startMaxElapsed < session.startTimeElapsed) {
+                stats.executionTimeInMaxPeriodMs +=
+                        session.endTimeElapsed - session.startTimeElapsed;
+                stats.bgJobCountInMaxPeriod += session.bgJobCount;
+                emptyTimeMs = Math.min(emptyTimeMs, session.startTimeElapsed - startMaxElapsed);
+                if (stats.executionTimeInMaxPeriodMs >= mMaxExecutionTimeIntoQuotaMs) {
+                    stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
+                            session.startTimeElapsed + stats.executionTimeInMaxPeriodMs
+                                    - mMaxExecutionTimeIntoQuotaMs + MAX_PERIOD_MS);
+                }
+            } else if (startMaxElapsed < session.endTimeElapsed) {
+                // The session started before the window but ended within the window. Only include
+                // the portion that was within the window.
+                stats.executionTimeInMaxPeriodMs += session.endTimeElapsed - startMaxElapsed;
+                stats.bgJobCountInMaxPeriod += session.bgJobCount;
+                emptyTimeMs = 0;
+                if (stats.executionTimeInMaxPeriodMs >= mMaxExecutionTimeIntoQuotaMs) {
+                    stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
+                            startMaxElapsed + stats.executionTimeInMaxPeriodMs
+                                    - mMaxExecutionTimeIntoQuotaMs + MAX_PERIOD_MS);
+                }
+            } else {
+                // This session ended before the window. No point in going any further.
+                break;
+            }
+        }
+        stats.expirationTimeElapsed = nowElapsed + emptyTimeMs;
+        stats.sessionCountInWindow = sessionCountInWindow;
+    }
+
+    /** Invalidate ExecutionStats for all apps. */
+    @VisibleForTesting
+    void invalidateAllExecutionStatsLocked() {
+        final long nowElapsed = sElapsedRealtimeClock.millis();
+        mExecutionStatsCache.forEach((appStats) -> {
+            if (appStats != null) {
+                for (int i = 0; i < appStats.length; ++i) {
+                    ExecutionStats stats = appStats[i];
+                    if (stats != null) {
+                        stats.expirationTimeElapsed = nowElapsed;
+                    }
+                }
+            }
+        });
+    }
+
+    @VisibleForTesting
+    void invalidateAllExecutionStatsLocked(final int userId,
+            @NonNull final String packageName) {
+        ExecutionStats[] appStats = mExecutionStatsCache.get(userId, packageName);
+        if (appStats != null) {
+            final long nowElapsed = sElapsedRealtimeClock.millis();
+            for (int i = 0; i < appStats.length; ++i) {
+                ExecutionStats stats = appStats[i];
+                if (stats != null) {
+                    stats.expirationTimeElapsed = nowElapsed;
+                }
+            }
+        }
+    }
+
+    @VisibleForTesting
+    void incrementJobCount(final int userId, @NonNull final String packageName, int count) {
+        final long now = sElapsedRealtimeClock.millis();
+        ExecutionStats[] appStats = mExecutionStatsCache.get(userId, packageName);
+        if (appStats == null) {
+            appStats = new ExecutionStats[mBucketPeriodsMs.length];
+            mExecutionStatsCache.add(userId, packageName, appStats);
+        }
+        for (int i = 0; i < appStats.length; ++i) {
+            ExecutionStats stats = appStats[i];
+            if (stats == null) {
+                stats = new ExecutionStats();
+                appStats[i] = stats;
+            }
+            if (stats.jobRateLimitExpirationTimeElapsed <= now) {
+                stats.jobRateLimitExpirationTimeElapsed = now + mRateLimitingWindowMs;
+                stats.jobCountInRateLimitingWindow = 0;
+            }
+            stats.jobCountInRateLimitingWindow += count;
+        }
+    }
+
+    private void incrementTimingSessionCount(final int userId, @NonNull final String packageName) {
+        final long now = sElapsedRealtimeClock.millis();
+        ExecutionStats[] appStats = mExecutionStatsCache.get(userId, packageName);
+        if (appStats == null) {
+            appStats = new ExecutionStats[mBucketPeriodsMs.length];
+            mExecutionStatsCache.add(userId, packageName, appStats);
+        }
+        for (int i = 0; i < appStats.length; ++i) {
+            ExecutionStats stats = appStats[i];
+            if (stats == null) {
+                stats = new ExecutionStats();
+                appStats[i] = stats;
+            }
+            if (stats.sessionRateLimitExpirationTimeElapsed <= now) {
+                stats.sessionRateLimitExpirationTimeElapsed = now + mRateLimitingWindowMs;
+                stats.sessionCountInRateLimitingWindow = 0;
+            }
+            stats.sessionCountInRateLimitingWindow++;
+        }
+    }
+
+    @VisibleForTesting
+    void saveTimingSession(final int userId, @NonNull final String packageName,
+            @NonNull final TimingSession session) {
+        synchronized (mLock) {
+            List<TimingSession> sessions = mTimingSessions.get(userId, packageName);
+            if (sessions == null) {
+                sessions = new ArrayList<>();
+                mTimingSessions.add(userId, packageName, sessions);
+            }
+            sessions.add(session);
+            // Adding a new session means that the current stats are now incorrect.
+            invalidateAllExecutionStatsLocked(userId, packageName);
+
+            maybeScheduleCleanupAlarmLocked();
+        }
+    }
+
+    private final class EarliestEndTimeFunctor implements Consumer<List<TimingSession>> {
+        public long earliestEndElapsed = Long.MAX_VALUE;
+
+        @Override
+        public void accept(List<TimingSession> sessions) {
+            if (sessions != null && sessions.size() > 0) {
+                earliestEndElapsed = Math.min(earliestEndElapsed, sessions.get(0).endTimeElapsed);
+            }
+        }
+
+        void reset() {
+            earliestEndElapsed = Long.MAX_VALUE;
+        }
+    }
+
+    private final EarliestEndTimeFunctor mEarliestEndTimeFunctor = new EarliestEndTimeFunctor();
+
+    /** Schedule a cleanup alarm if necessary and there isn't already one scheduled. */
+    @VisibleForTesting
+    void maybeScheduleCleanupAlarmLocked() {
+        if (mNextCleanupTimeElapsed > sElapsedRealtimeClock.millis()) {
+            // There's already an alarm scheduled. Just stick with that one. There's no way we'll
+            // end up scheduling an earlier alarm.
+            if (DEBUG) {
+                Slog.v(TAG, "Not scheduling cleanup since there's already one at "
+                        + mNextCleanupTimeElapsed + " (in " + (mNextCleanupTimeElapsed
+                        - sElapsedRealtimeClock.millis()) + "ms)");
+            }
+            return;
+        }
+        mEarliestEndTimeFunctor.reset();
+        mTimingSessions.forEach(mEarliestEndTimeFunctor);
+        final long earliestEndElapsed = mEarliestEndTimeFunctor.earliestEndElapsed;
+        if (earliestEndElapsed == Long.MAX_VALUE) {
+            // Couldn't find a good time to clean up. Maybe this was called after we deleted all
+            // timing sessions.
+            if (DEBUG) {
+                Slog.d(TAG, "Didn't find a time to schedule cleanup");
+            }
+            return;
+        }
+        // Need to keep sessions for all apps up to the max period, regardless of their current
+        // standby bucket.
+        long nextCleanupElapsed = earliestEndElapsed + MAX_PERIOD_MS;
+        if (nextCleanupElapsed - mNextCleanupTimeElapsed <= 10 * MINUTE_IN_MILLIS) {
+            // No need to clean up too often. Delay the alarm if the next cleanup would be too soon
+            // after it.
+            nextCleanupElapsed += 10 * MINUTE_IN_MILLIS;
+        }
+        mNextCleanupTimeElapsed = nextCleanupElapsed;
+        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextCleanupElapsed, ALARM_TAG_CLEANUP,
+                mSessionCleanupAlarmListener, mHandler);
+        if (DEBUG) {
+            Slog.d(TAG, "Scheduled next cleanup for " + mNextCleanupTimeElapsed);
+        }
+    }
+
+    private void handleNewChargingStateLocked() {
+        final long nowElapsed = sElapsedRealtimeClock.millis();
+        final boolean isCharging = mChargeTracker.isCharging();
+        if (DEBUG) {
+            Slog.d(TAG, "handleNewChargingStateLocked: " + isCharging);
+        }
+        // Deal with Timers first.
+        mPkgTimers.forEach((t) -> t.onStateChangedLocked(nowElapsed, isCharging));
+        // Now update jobs.
+        maybeUpdateAllConstraintsLocked();
+    }
+
+    private void maybeUpdateAllConstraintsLocked() {
+        boolean changed = false;
+        for (int u = 0; u < mTrackedJobs.numUsers(); ++u) {
+            final int userId = mTrackedJobs.keyAt(u);
+            for (int p = 0; p < mTrackedJobs.numPackagesForUser(userId); ++p) {
+                final String packageName = mTrackedJobs.keyAt(u, p);
+                changed |= maybeUpdateConstraintForPkgLocked(userId, packageName);
+            }
+        }
+        if (changed) {
+            mStateChangedListener.onControllerStateChanged();
+        }
+    }
+
+    /**
+     * Update the CONSTRAINT_WITHIN_QUOTA bit for all of the Jobs for a given package.
+     *
+     * @return true if at least one job had its bit changed
+     */
+    private boolean maybeUpdateConstraintForPkgLocked(final int userId,
+            @NonNull final String packageName) {
+        ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, packageName);
+        if (jobs == null || jobs.size() == 0) {
+            return false;
+        }
+
+        // Quota is the same for all jobs within a package.
+        final int realStandbyBucket = jobs.valueAt(0).getStandbyBucket();
+        final boolean realInQuota = isWithinQuotaLocked(userId, packageName, realStandbyBucket);
+        boolean changed = false;
+        for (int i = jobs.size() - 1; i >= 0; --i) {
+            final JobStatus js = jobs.valueAt(i);
+            if (isTopStartedJobLocked(js)) {
+                // Job was started while the app was in the TOP state so we should allow it to
+                // finish.
+                changed |= js.setQuotaConstraintSatisfied(true);
+            } else if (realStandbyBucket != ACTIVE_INDEX
+                    && realStandbyBucket == getEffectiveStandbyBucket(js)) {
+                // An app in the ACTIVE bucket may be out of quota while the job could be in quota
+                // for some reason. Therefore, avoid setting the real value here and check each job
+                // individually.
+                changed |= setConstraintSatisfied(js, realInQuota);
+            } else {
+                // This job is somehow exempted. Need to determine its own quota status.
+                changed |= setConstraintSatisfied(js, isWithinQuotaLocked(js));
+            }
+        }
+        if (!realInQuota) {
+            // Don't want to use the effective standby bucket here since that bump the bucket to
+            // ACTIVE for one of the jobs, which doesn't help with other jobs that aren't
+            // exempted.
+            maybeScheduleStartAlarmLocked(userId, packageName, realStandbyBucket);
+        } else {
+            QcAlarmListener alarmListener = mInQuotaAlarmListeners.get(userId, packageName);
+            if (alarmListener != null && alarmListener.isWaiting()) {
+                mAlarmManager.cancel(alarmListener);
+                // Set the trigger time to 0 so that the alarm doesn't think it's still waiting.
+                alarmListener.setTriggerTime(0);
+            }
+        }
+        return changed;
+    }
+
+    private class UidConstraintUpdater implements Consumer<JobStatus> {
+        private final UserPackageMap<Integer> mToScheduleStartAlarms = new UserPackageMap<>();
+        public boolean wasJobChanged;
+
+        @Override
+        public void accept(JobStatus jobStatus) {
+            wasJobChanged |= setConstraintSatisfied(jobStatus, isWithinQuotaLocked(jobStatus));
+            final int userId = jobStatus.getSourceUserId();
+            final String packageName = jobStatus.getSourcePackageName();
+            final int realStandbyBucket = jobStatus.getStandbyBucket();
+            if (isWithinQuotaLocked(userId, packageName, realStandbyBucket)) {
+                QcAlarmListener alarmListener = mInQuotaAlarmListeners.get(userId, packageName);
+                if (alarmListener != null && alarmListener.isWaiting()) {
+                    mAlarmManager.cancel(alarmListener);
+                    // Set the trigger time to 0 so that the alarm doesn't think it's still waiting.
+                    alarmListener.setTriggerTime(0);
+                }
+            } else {
+                mToScheduleStartAlarms.add(userId, packageName, realStandbyBucket);
+            }
+        }
+
+        void postProcess() {
+            for (int u = 0; u < mToScheduleStartAlarms.numUsers(); ++u) {
+                final int userId = mToScheduleStartAlarms.keyAt(u);
+                for (int p = 0; p < mToScheduleStartAlarms.numPackagesForUser(userId); ++p) {
+                    final String packageName = mToScheduleStartAlarms.keyAt(u, p);
+                    final int standbyBucket = mToScheduleStartAlarms.get(userId, packageName);
+                    maybeScheduleStartAlarmLocked(userId, packageName, standbyBucket);
+                }
+            }
+        }
+
+        void reset() {
+            wasJobChanged = false;
+            mToScheduleStartAlarms.clear();
+        }
+    }
+
+    private final UidConstraintUpdater mUpdateUidConstraints = new UidConstraintUpdater();
+
+    private boolean maybeUpdateConstraintForUidLocked(final int uid) {
+        mService.getJobStore().forEachJobForSourceUid(uid, mUpdateUidConstraints);
+
+        mUpdateUidConstraints.postProcess();
+        boolean changed = mUpdateUidConstraints.wasJobChanged;
+        mUpdateUidConstraints.reset();
+        return changed;
+    }
+
+    /**
+     * Maybe schedule a non-wakeup alarm for the next time this package will have quota to run
+     * again. This should only be called if the package is already out of quota.
+     */
+    @VisibleForTesting
+    void maybeScheduleStartAlarmLocked(final int userId, @NonNull final String packageName,
+            final int standbyBucket) {
+        if (standbyBucket == NEVER_INDEX) {
+            return;
+        }
+
+        final String pkgString = string(userId, packageName);
+        ExecutionStats stats = getExecutionStatsLocked(userId, packageName, standbyBucket);
+        final boolean isUnderJobCountQuota = isUnderJobCountQuotaLocked(stats, standbyBucket);
+        final boolean isUnderTimingSessionCountQuota = isUnderSessionCountQuotaLocked(stats,
+                standbyBucket);
+
+        QcAlarmListener alarmListener = mInQuotaAlarmListeners.get(userId, packageName);
+        if (stats.executionTimeInWindowMs < mAllowedTimePerPeriodMs
+                && stats.executionTimeInMaxPeriodMs < mMaxExecutionTimeMs
+                && isUnderJobCountQuota
+                && isUnderTimingSessionCountQuota) {
+            // Already in quota. Why was this method called?
+            if (DEBUG) {
+                Slog.e(TAG, "maybeScheduleStartAlarmLocked called for " + pkgString
+                        + " even though it already has "
+                        + getRemainingExecutionTimeLocked(userId, packageName, standbyBucket)
+                        + "ms in its quota.");
+            }
+            if (alarmListener != null) {
+                // Cancel any pending alarm.
+                mAlarmManager.cancel(alarmListener);
+                // Set the trigger time to 0 so that the alarm doesn't think it's still waiting.
+                alarmListener.setTriggerTime(0);
+            }
+            mHandler.obtainMessage(MSG_CHECK_PACKAGE, userId, 0, packageName).sendToTarget();
+            return;
+        }
+
+        if (alarmListener == null) {
+            alarmListener = new QcAlarmListener(userId, packageName);
+            mInQuotaAlarmListeners.add(userId, packageName, alarmListener);
+        }
+
+        // The time this app will have quota again.
+        long inQuotaTimeElapsed = stats.inQuotaTimeElapsed;
+        if (!isUnderJobCountQuota && stats.bgJobCountInWindow < stats.jobCountLimit) {
+            // App hit the rate limit.
+            inQuotaTimeElapsed = Math.max(inQuotaTimeElapsed,
+                    stats.jobRateLimitExpirationTimeElapsed);
+        }
+        if (!isUnderTimingSessionCountQuota
+                && stats.sessionCountInWindow < stats.sessionCountLimit) {
+            // App hit the rate limit.
+            inQuotaTimeElapsed = Math.max(inQuotaTimeElapsed,
+                    stats.sessionRateLimitExpirationTimeElapsed);
+        }
+        // Only schedule the alarm if:
+        // 1. There isn't one currently scheduled
+        // 2. The new alarm is significantly earlier than the previous alarm (which could be the
+        // case if the package moves into a higher standby bucket). If it's earlier but not
+        // significantly so, then we essentially delay the job a few extra minutes.
+        // 3. The alarm is after the current alarm by more than the quota buffer.
+        // TODO: this might be overengineering. Simplify if proven safe.
+        if (!alarmListener.isWaiting()
+                || inQuotaTimeElapsed < alarmListener.getTriggerTimeElapsed() - 3 * MINUTE_IN_MILLIS
+                || alarmListener.getTriggerTimeElapsed() < inQuotaTimeElapsed) {
+            if (DEBUG) {
+                Slog.d(TAG, "Scheduling start alarm for " + pkgString);
+            }
+            // If the next time this app will have quota is at least 3 minutes before the
+            // alarm is supposed to go off, reschedule the alarm.
+            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, inQuotaTimeElapsed,
+                    ALARM_TAG_QUOTA_CHECK, alarmListener, mHandler);
+            alarmListener.setTriggerTime(inQuotaTimeElapsed);
+        } else if (DEBUG) {
+            Slog.d(TAG, "No need to schedule start alarm for " + pkgString);
+        }
+    }
+
+    private boolean setConstraintSatisfied(@NonNull JobStatus jobStatus, boolean isWithinQuota) {
+        if (!isWithinQuota && jobStatus.getWhenStandbyDeferred() == 0) {
+            // Mark that the job is being deferred due to buckets.
+            jobStatus.setWhenStandbyDeferred(sElapsedRealtimeClock.millis());
+        }
+        return jobStatus.setQuotaConstraintSatisfied(isWithinQuota);
+    }
+
+    private final class ChargingTracker extends BroadcastReceiver {
+        /**
+         * Track whether we're charging. This has a slightly different definition than that of
+         * BatteryController.
+         */
+        private boolean mCharging;
+
+        ChargingTracker() {
+        }
+
+        public void startTracking() {
+            IntentFilter filter = new IntentFilter();
+
+            // Charging/not charging.
+            filter.addAction(BatteryManager.ACTION_CHARGING);
+            filter.addAction(BatteryManager.ACTION_DISCHARGING);
+            mContext.registerReceiver(this, filter);
+
+            // Initialise tracker state.
+            BatteryManagerInternal batteryManagerInternal =
+                    LocalServices.getService(BatteryManagerInternal.class);
+            mCharging = batteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
+        }
+
+        public boolean isCharging() {
+            return mCharging;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            synchronized (mLock) {
+                final String action = intent.getAction();
+                if (BatteryManager.ACTION_CHARGING.equals(action)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Received charging intent, fired @ "
+                                + sElapsedRealtimeClock.millis());
+                    }
+                    mCharging = true;
+                    handleNewChargingStateLocked();
+                } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Disconnected from power.");
+                    }
+                    mCharging = false;
+                    handleNewChargingStateLocked();
+                }
+            }
+        }
+    }
+
+    @VisibleForTesting
+    static final class TimingSession {
+        // Start timestamp in elapsed realtime timebase.
+        public final long startTimeElapsed;
+        // End timestamp in elapsed realtime timebase.
+        public final long endTimeElapsed;
+        // How many background jobs ran during this session.
+        public final int bgJobCount;
+
+        private final int mHashCode;
+
+        TimingSession(long startElapsed, long endElapsed, int bgJobCount) {
+            this.startTimeElapsed = startElapsed;
+            this.endTimeElapsed = endElapsed;
+            this.bgJobCount = bgJobCount;
+
+            int hashCode = 0;
+            hashCode = 31 * hashCode + hashLong(startTimeElapsed);
+            hashCode = 31 * hashCode + hashLong(endTimeElapsed);
+            hashCode = 31 * hashCode + bgJobCount;
+            mHashCode = hashCode;
+        }
+
+        @Override
+        public String toString() {
+            return "TimingSession{" + startTimeElapsed + "->" + endTimeElapsed + ", " + bgJobCount
+                    + "}";
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof TimingSession) {
+                TimingSession other = (TimingSession) obj;
+                return startTimeElapsed == other.startTimeElapsed
+                        && endTimeElapsed == other.endTimeElapsed
+                        && bgJobCount == other.bgJobCount;
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            return mHashCode;
+        }
+
+        public void dump(IndentingPrintWriter pw) {
+            pw.print(startTimeElapsed);
+            pw.print(" -> ");
+            pw.print(endTimeElapsed);
+            pw.print(" (");
+            pw.print(endTimeElapsed - startTimeElapsed);
+            pw.print("), ");
+            pw.print(bgJobCount);
+            pw.print(" bg jobs.");
+            pw.println();
+        }
+
+        public void dump(@NonNull ProtoOutputStream proto, long fieldId) {
+            final long token = proto.start(fieldId);
+
+            proto.write(StateControllerProto.QuotaController.TimingSession.START_TIME_ELAPSED,
+                    startTimeElapsed);
+            proto.write(StateControllerProto.QuotaController.TimingSession.END_TIME_ELAPSED,
+                    endTimeElapsed);
+            proto.write(StateControllerProto.QuotaController.TimingSession.BG_JOB_COUNT,
+                    bgJobCount);
+
+            proto.end(token);
+        }
+    }
+
+    private final class Timer {
+        private final Package mPkg;
+        private final int mUid;
+
+        // List of jobs currently running for this app that started when the app wasn't in the
+        // foreground.
+        private final ArraySet<JobStatus> mRunningBgJobs = new ArraySet<>();
+        private long mStartTimeElapsed;
+        private int mBgJobCount;
+
+        Timer(int uid, int userId, String packageName) {
+            mPkg = new Package(userId, packageName);
+            mUid = uid;
+        }
+
+        void startTrackingJobLocked(@NonNull JobStatus jobStatus) {
+            if (isTopStartedJobLocked(jobStatus)) {
+                // We intentionally don't pay attention to fg state changes after a TOP job has
+                // started.
+                if (DEBUG) {
+                    Slog.v(TAG,
+                            "Timer ignoring " + jobStatus.toShortString() + " because isTop");
+                }
+                return;
+            }
+            if (DEBUG) {
+                Slog.v(TAG, "Starting to track " + jobStatus.toShortString());
+            }
+            // Always track jobs, even when charging.
+            mRunningBgJobs.add(jobStatus);
+            if (shouldTrackLocked()) {
+                mBgJobCount++;
+                incrementJobCount(mPkg.userId, mPkg.packageName, 1);
+                if (mRunningBgJobs.size() == 1) {
+                    // Started tracking the first job.
+                    mStartTimeElapsed = sElapsedRealtimeClock.millis();
+                    // Starting the timer means that all cached execution stats are now incorrect.
+                    invalidateAllExecutionStatsLocked(mPkg.userId, mPkg.packageName);
+                    scheduleCutoff();
+                }
+            }
+        }
+
+        void stopTrackingJob(@NonNull JobStatus jobStatus) {
+            if (DEBUG) {
+                Slog.v(TAG, "Stopping tracking of " + jobStatus.toShortString());
+            }
+            synchronized (mLock) {
+                if (mRunningBgJobs.size() == 0) {
+                    // maybeStopTrackingJobLocked can be called when an app cancels a job, so a
+                    // timer may not be running when it's asked to stop tracking a job.
+                    if (DEBUG) {
+                        Slog.d(TAG, "Timer isn't tracking any jobs but still told to stop");
+                    }
+                    return;
+                }
+                if (mRunningBgJobs.remove(jobStatus)
+                        && !mChargeTracker.isCharging() && mRunningBgJobs.size() == 0) {
+                    emitSessionLocked(sElapsedRealtimeClock.millis());
+                    cancelCutoff();
+                }
+            }
+        }
+
+        /**
+         * Stops tracking all jobs and cancels any pending alarms. This should only be called if
+         * the Timer is not going to be used anymore.
+         */
+        void dropEverythingLocked() {
+            mRunningBgJobs.clear();
+            cancelCutoff();
+        }
+
+        private void emitSessionLocked(long nowElapsed) {
+            if (mBgJobCount <= 0) {
+                // Nothing to emit.
+                return;
+            }
+            TimingSession ts = new TimingSession(mStartTimeElapsed, nowElapsed, mBgJobCount);
+            saveTimingSession(mPkg.userId, mPkg.packageName, ts);
+            mBgJobCount = 0;
+            // Don't reset the tracked jobs list as we need to keep tracking the current number
+            // of jobs.
+            // However, cancel the currently scheduled cutoff since it's not currently useful.
+            cancelCutoff();
+            incrementTimingSessionCount(mPkg.userId, mPkg.packageName);
+        }
+
+        /**
+         * Returns true if the Timer is actively tracking, as opposed to passively ref counting
+         * during charging.
+         */
+        public boolean isActive() {
+            synchronized (mLock) {
+                return mBgJobCount > 0;
+            }
+        }
+
+        boolean isRunning(JobStatus jobStatus) {
+            return mRunningBgJobs.contains(jobStatus);
+        }
+
+        long getCurrentDuration(long nowElapsed) {
+            synchronized (mLock) {
+                return !isActive() ? 0 : nowElapsed - mStartTimeElapsed;
+            }
+        }
+
+        int getBgJobCount() {
+            synchronized (mLock) {
+                return mBgJobCount;
+            }
+        }
+
+        private boolean shouldTrackLocked() {
+            return !mChargeTracker.isCharging() && !mForegroundUids.get(mUid);
+        }
+
+        void onStateChangedLocked(long nowElapsed, boolean isQuotaFree) {
+            if (isQuotaFree) {
+                emitSessionLocked(nowElapsed);
+            } else if (!isActive() && shouldTrackLocked()) {
+                // Start timing from unplug.
+                if (mRunningBgJobs.size() > 0) {
+                    mStartTimeElapsed = nowElapsed;
+                    // NOTE: this does have the unfortunate consequence that if the device is
+                    // repeatedly plugged in and unplugged, or an app changes foreground state
+                    // very frequently, the job count for a package may be artificially high.
+                    mBgJobCount = mRunningBgJobs.size();
+                    incrementJobCount(mPkg.userId, mPkg.packageName, mBgJobCount);
+                    // Starting the timer means that all cached execution stats are now
+                    // incorrect.
+                    invalidateAllExecutionStatsLocked(mPkg.userId, mPkg.packageName);
+                    // Schedule cutoff since we're now actively tracking for quotas again.
+                    scheduleCutoff();
+                }
+            }
+        }
+
+        void rescheduleCutoff() {
+            cancelCutoff();
+            scheduleCutoff();
+        }
+
+        private void scheduleCutoff() {
+            // Each package can only be in one standby bucket, so we only need to have one
+            // message per timer. We only need to reschedule when restarting timer or when
+            // standby bucket changes.
+            synchronized (mLock) {
+                if (!isActive()) {
+                    return;
+                }
+                Message msg = mHandler.obtainMessage(MSG_REACHED_QUOTA, mPkg);
+                final long timeRemainingMs = getTimeUntilQuotaConsumedLocked(mPkg.userId,
+                        mPkg.packageName);
+                if (DEBUG) {
+                    Slog.i(TAG, "Job for " + mPkg + " has " + timeRemainingMs + "ms left.");
+                }
+                // If the job was running the entire time, then the system would be up, so it's
+                // fine to use uptime millis for these messages.
+                mHandler.sendMessageDelayed(msg, timeRemainingMs);
+            }
+        }
+
+        private void cancelCutoff() {
+            mHandler.removeMessages(MSG_REACHED_QUOTA, mPkg);
+        }
+
+        public void dump(IndentingPrintWriter pw, Predicate<JobStatus> predicate) {
+            pw.print("Timer{");
+            pw.print(mPkg);
+            pw.print("} ");
+            if (isActive()) {
+                pw.print("started at ");
+                pw.print(mStartTimeElapsed);
+                pw.print(" (");
+                pw.print(sElapsedRealtimeClock.millis() - mStartTimeElapsed);
+                pw.print("ms ago)");
+            } else {
+                pw.print("NOT active");
+            }
+            pw.print(", ");
+            pw.print(mBgJobCount);
+            pw.print(" running bg jobs");
+            pw.println();
+            pw.increaseIndent();
+            for (int i = 0; i < mRunningBgJobs.size(); i++) {
+                JobStatus js = mRunningBgJobs.valueAt(i);
+                if (predicate.test(js)) {
+                    pw.println(js.toShortString());
+                }
+            }
+            pw.decreaseIndent();
+        }
+
+        public void dump(ProtoOutputStream proto, long fieldId, Predicate<JobStatus> predicate) {
+            final long token = proto.start(fieldId);
+
+            mPkg.writeToProto(proto, StateControllerProto.QuotaController.Timer.PKG);
+            proto.write(StateControllerProto.QuotaController.Timer.IS_ACTIVE, isActive());
+            proto.write(StateControllerProto.QuotaController.Timer.START_TIME_ELAPSED,
+                    mStartTimeElapsed);
+            proto.write(StateControllerProto.QuotaController.Timer.BG_JOB_COUNT, mBgJobCount);
+            for (int i = 0; i < mRunningBgJobs.size(); i++) {
+                JobStatus js = mRunningBgJobs.valueAt(i);
+                if (predicate.test(js)) {
+                    js.writeToShortProto(proto,
+                            StateControllerProto.QuotaController.Timer.RUNNING_JOBS);
+                }
+            }
+
+            proto.end(token);
+        }
+    }
+
+    /**
+     * Tracking of app assignments to standby buckets
+     */
+    final class StandbyTracker extends AppIdleStateChangeListener {
+
+        @Override
+        public void onAppIdleStateChanged(final String packageName, final @UserIdInt int userId,
+                boolean idle, int bucket, int reason) {
+            // Update job bookkeeping out of band.
+            BackgroundThread.getHandler().post(() -> {
+                final int bucketIndex = JobSchedulerService.standbyBucketToBucketIndex(bucket);
+                if (DEBUG) {
+                    Slog.i(TAG, "Moving pkg " + string(userId, packageName) + " to bucketIndex "
+                            + bucketIndex);
+                }
+                synchronized (mLock) {
+                    ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, packageName);
+                    if (jobs == null || jobs.size() == 0) {
+                        return;
+                    }
+                    for (int i = jobs.size() - 1; i >= 0; i--) {
+                        JobStatus js = jobs.valueAt(i);
+                        js.setStandbyBucket(bucketIndex);
+                    }
+                    Timer timer = mPkgTimers.get(userId, packageName);
+                    if (timer != null && timer.isActive()) {
+                        timer.rescheduleCutoff();
+                    }
+                    if (!mShouldThrottle || maybeUpdateConstraintForPkgLocked(userId,
+                            packageName)) {
+                        mStateChangedListener.onControllerStateChanged();
+                    }
+                }
+            });
+        }
+
+        @Override
+        public void onParoleStateChanged(final boolean isParoleOn) {
+            mInParole = isParoleOn;
+            if (DEBUG) {
+                Slog.i(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
+            }
+            // Update job bookkeeping out of band.
+            BackgroundThread.getHandler().post(() -> {
+                synchronized (mLock) {
+                    maybeUpdateAllConstraintsLocked();
+                }
+            });
+        }
+    }
+
+    private final class DeleteTimingSessionsFunctor implements Consumer<List<TimingSession>> {
+        private final Predicate<TimingSession> mTooOld = new Predicate<TimingSession>() {
+            public boolean test(TimingSession ts) {
+                return ts.endTimeElapsed <= sElapsedRealtimeClock.millis() - MAX_PERIOD_MS;
+            }
+        };
+
+        @Override
+        public void accept(List<TimingSession> sessions) {
+            if (sessions != null) {
+                // Remove everything older than MAX_PERIOD_MS time ago.
+                sessions.removeIf(mTooOld);
+            }
+        }
+    }
+
+    private final DeleteTimingSessionsFunctor mDeleteOldSessionsFunctor =
+            new DeleteTimingSessionsFunctor();
+
+    @VisibleForTesting
+    void deleteObsoleteSessionsLocked() {
+        mTimingSessions.forEach(mDeleteOldSessionsFunctor);
+    }
+
+    private class QcHandler extends Handler {
+        QcHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            synchronized (mLock) {
+                switch (msg.what) {
+                    case MSG_REACHED_QUOTA: {
+                        Package pkg = (Package) msg.obj;
+                        if (DEBUG) {
+                            Slog.d(TAG, "Checking if " + pkg + " has reached its quota.");
+                        }
+
+                        long timeRemainingMs = getRemainingExecutionTimeLocked(pkg.userId,
+                                pkg.packageName);
+                        if (timeRemainingMs <= 50) {
+                            // Less than 50 milliseconds left. Start process of shutting down jobs.
+                            if (DEBUG) Slog.d(TAG, pkg + " has reached its quota.");
+                            if (maybeUpdateConstraintForPkgLocked(pkg.userId, pkg.packageName)) {
+                                mStateChangedListener.onControllerStateChanged();
+                            }
+                        } else {
+                            // This could potentially happen if an old session phases out while a
+                            // job is currently running.
+                            // Reschedule message
+                            Message rescheduleMsg = obtainMessage(MSG_REACHED_QUOTA, pkg);
+                            timeRemainingMs = getTimeUntilQuotaConsumedLocked(pkg.userId,
+                                    pkg.packageName);
+                            if (DEBUG) {
+                                Slog.d(TAG, pkg + " has " + timeRemainingMs + "ms left.");
+                            }
+                            sendMessageDelayed(rescheduleMsg, timeRemainingMs);
+                        }
+                        break;
+                    }
+                    case MSG_CLEAN_UP_SESSIONS:
+                        if (DEBUG) {
+                            Slog.d(TAG, "Cleaning up timing sessions.");
+                        }
+                        deleteObsoleteSessionsLocked();
+                        maybeScheduleCleanupAlarmLocked();
+
+                        break;
+                    case MSG_CHECK_PACKAGE: {
+                        String packageName = (String) msg.obj;
+                        int userId = msg.arg1;
+                        if (DEBUG) {
+                            Slog.d(TAG, "Checking pkg " + string(userId, packageName));
+                        }
+                        if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
+                            mStateChangedListener.onControllerStateChanged();
+                        }
+                        break;
+                    }
+                    case MSG_UID_PROCESS_STATE_CHANGED: {
+                        final int uid = msg.arg1;
+                        final int procState = msg.arg2;
+                        final int userId = UserHandle.getUserId(uid);
+                        final long nowElapsed = sElapsedRealtimeClock.millis();
+
+                        synchronized (mLock) {
+                            boolean isQuotaFree;
+                            if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
+                                mForegroundUids.put(uid, true);
+                                isQuotaFree = true;
+                            } else {
+                                mForegroundUids.delete(uid);
+                                isQuotaFree = false;
+                            }
+                            // Update Timers first.
+                            if (mPkgTimers.indexOfKey(userId) >= 0) {
+                                ArraySet<String> packages = mUidToPackageCache.get(uid);
+                                if (packages == null) {
+                                    try {
+                                        String[] pkgs = AppGlobals.getPackageManager()
+                                                .getPackagesForUid(uid);
+                                        if (pkgs != null) {
+                                            for (String pkg : pkgs) {
+                                                mUidToPackageCache.add(uid, pkg);
+                                            }
+                                            packages = mUidToPackageCache.get(uid);
+                                        }
+                                    } catch (RemoteException e) {
+                                        Slog.wtf(TAG, "Failed to get package list", e);
+                                    }
+                                }
+                                if (packages != null) {
+                                    for (int i = packages.size() - 1; i >= 0; --i) {
+                                        Timer t = mPkgTimers.get(userId, packages.valueAt(i));
+                                        if (t != null) {
+                                            t.onStateChangedLocked(nowElapsed, isQuotaFree);
+                                        }
+                                    }
+                                }
+                            }
+                            if (maybeUpdateConstraintForUidLocked(uid)) {
+                                mStateChangedListener.onControllerStateChanged();
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    private class QcAlarmListener implements AlarmManager.OnAlarmListener {
+        private final int mUserId;
+        private final String mPackageName;
+        private volatile long mTriggerTimeElapsed;
+
+        QcAlarmListener(int userId, String packageName) {
+            mUserId = userId;
+            mPackageName = packageName;
+        }
+
+        boolean isWaiting() {
+            return mTriggerTimeElapsed > 0;
+        }
+
+        void setTriggerTime(long timeElapsed) {
+            mTriggerTimeElapsed = timeElapsed;
+        }
+
+        long getTriggerTimeElapsed() {
+            return mTriggerTimeElapsed;
+        }
+
+        @Override
+        public void onAlarm() {
+            mHandler.obtainMessage(MSG_CHECK_PACKAGE, mUserId, 0, mPackageName).sendToTarget();
+            mTriggerTimeElapsed = 0;
+        }
+    }
+
+    @VisibleForTesting
+    class QcConstants extends ContentObserver {
+        private ContentResolver mResolver;
+        private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+        private static final String KEY_ALLOWED_TIME_PER_PERIOD_MS = "allowed_time_per_period_ms";
+        private static final String KEY_IN_QUOTA_BUFFER_MS = "in_quota_buffer_ms";
+        private static final String KEY_WINDOW_SIZE_ACTIVE_MS = "window_size_active_ms";
+        private static final String KEY_WINDOW_SIZE_WORKING_MS = "window_size_working_ms";
+        private static final String KEY_WINDOW_SIZE_FREQUENT_MS = "window_size_frequent_ms";
+        private static final String KEY_WINDOW_SIZE_RARE_MS = "window_size_rare_ms";
+        private static final String KEY_MAX_EXECUTION_TIME_MS = "max_execution_time_ms";
+        private static final String KEY_MAX_JOB_COUNT_ACTIVE = "max_job_count_active";
+        private static final String KEY_MAX_JOB_COUNT_WORKING = "max_job_count_working";
+        private static final String KEY_MAX_JOB_COUNT_FREQUENT = "max_job_count_frequent";
+        private static final String KEY_MAX_JOB_COUNT_RARE = "max_job_count_rare";
+        private static final String KEY_RATE_LIMITING_WINDOW_MS = "rate_limiting_window_ms";
+        private static final String KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW =
+                "max_job_count_per_rate_limiting_window";
+        private static final String KEY_MAX_SESSION_COUNT_ACTIVE = "max_session_count_active";
+        private static final String KEY_MAX_SESSION_COUNT_WORKING = "max_session_count_working";
+        private static final String KEY_MAX_SESSION_COUNT_FREQUENT = "max_session_count_frequent";
+        private static final String KEY_MAX_SESSION_COUNT_RARE = "max_session_count_rare";
+        private static final String KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW =
+                "max_session_count_per_rate_limiting_window";
+        private static final String KEY_TIMING_SESSION_COALESCING_DURATION_MS =
+                "timing_session_coalescing_duration_ms";
+
+        private static final long DEFAULT_ALLOWED_TIME_PER_PERIOD_MS =
+                10 * 60 * 1000L; // 10 minutes
+        private static final long DEFAULT_IN_QUOTA_BUFFER_MS =
+                30 * 1000L; // 30 seconds
+        private static final long DEFAULT_WINDOW_SIZE_ACTIVE_MS =
+                DEFAULT_ALLOWED_TIME_PER_PERIOD_MS; // ACTIVE apps can run jobs at any time
+        private static final long DEFAULT_WINDOW_SIZE_WORKING_MS =
+                2 * 60 * 60 * 1000L; // 2 hours
+        private static final long DEFAULT_WINDOW_SIZE_FREQUENT_MS =
+                8 * 60 * 60 * 1000L; // 8 hours
+        private static final long DEFAULT_WINDOW_SIZE_RARE_MS =
+                24 * 60 * 60 * 1000L; // 24 hours
+        private static final long DEFAULT_MAX_EXECUTION_TIME_MS =
+                4 * HOUR_IN_MILLIS;
+        private static final long DEFAULT_RATE_LIMITING_WINDOW_MS =
+                10 * MINUTE_IN_MILLIS;
+        private static final int DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW = 20;
+        private static final int DEFAULT_MAX_JOB_COUNT_ACTIVE = // 20/window = 120/hr = 1/session
+                DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW;
+        private static final int DEFAULT_MAX_JOB_COUNT_WORKING = // 120/window = 60/hr = 12/session
+                (int) (60.0 * DEFAULT_WINDOW_SIZE_WORKING_MS / HOUR_IN_MILLIS);
+        private static final int DEFAULT_MAX_JOB_COUNT_FREQUENT = // 200/window = 25/hr = 25/session
+                (int) (25.0 * DEFAULT_WINDOW_SIZE_FREQUENT_MS / HOUR_IN_MILLIS);
+        private static final int DEFAULT_MAX_JOB_COUNT_RARE = // 48/window = 2/hr = 16/session
+                (int) (2.0 * DEFAULT_WINDOW_SIZE_RARE_MS / HOUR_IN_MILLIS);
+        private static final int DEFAULT_MAX_SESSION_COUNT_ACTIVE =
+                20; // 120/hr
+        private static final int DEFAULT_MAX_SESSION_COUNT_WORKING =
+                10; // 5/hr
+        private static final int DEFAULT_MAX_SESSION_COUNT_FREQUENT =
+                8; // 1/hr
+        private static final int DEFAULT_MAX_SESSION_COUNT_RARE =
+                3; // .125/hr
+        private static final int DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = 20;
+        private static final long DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS = 5000; // 5 seconds
+
+        /** How much time each app will have to run jobs within their standby bucket window. */
+        public long ALLOWED_TIME_PER_PERIOD_MS = DEFAULT_ALLOWED_TIME_PER_PERIOD_MS;
+
+        /**
+         * How much time the package should have before transitioning from out-of-quota to in-quota.
+         * This should not affect processing if the package is already in-quota.
+         */
+        public long IN_QUOTA_BUFFER_MS = DEFAULT_IN_QUOTA_BUFFER_MS;
+
+        /**
+         * The quota window size of the particular standby bucket. Apps in this standby bucket are
+         * expected to run only {@link #ALLOWED_TIME_PER_PERIOD_MS} within the past
+         * WINDOW_SIZE_MS.
+         */
+        public long WINDOW_SIZE_ACTIVE_MS = DEFAULT_WINDOW_SIZE_ACTIVE_MS;
+
+        /**
+         * The quota window size of the particular standby bucket. Apps in this standby bucket are
+         * expected to run only {@link #ALLOWED_TIME_PER_PERIOD_MS} within the past
+         * WINDOW_SIZE_MS.
+         */
+        public long WINDOW_SIZE_WORKING_MS = DEFAULT_WINDOW_SIZE_WORKING_MS;
+
+        /**
+         * The quota window size of the particular standby bucket. Apps in this standby bucket are
+         * expected to run only {@link #ALLOWED_TIME_PER_PERIOD_MS} within the past
+         * WINDOW_SIZE_MS.
+         */
+        public long WINDOW_SIZE_FREQUENT_MS = DEFAULT_WINDOW_SIZE_FREQUENT_MS;
+
+        /**
+         * The quota window size of the particular standby bucket. Apps in this standby bucket are
+         * expected to run only {@link #ALLOWED_TIME_PER_PERIOD_MS} within the past
+         * WINDOW_SIZE_MS.
+         */
+        public long WINDOW_SIZE_RARE_MS = DEFAULT_WINDOW_SIZE_RARE_MS;
+
+        /**
+         * The maximum amount of time an app can have its jobs running within a 24 hour window.
+         */
+        public long MAX_EXECUTION_TIME_MS = DEFAULT_MAX_EXECUTION_TIME_MS;
+
+        /**
+         * The maximum number of jobs an app can run within this particular standby bucket's
+         * window size.
+         */
+        public int MAX_JOB_COUNT_ACTIVE = DEFAULT_MAX_JOB_COUNT_ACTIVE;
+
+        /**
+         * The maximum number of jobs an app can run within this particular standby bucket's
+         * window size.
+         */
+        public int MAX_JOB_COUNT_WORKING = DEFAULT_MAX_JOB_COUNT_WORKING;
+
+        /**
+         * The maximum number of jobs an app can run within this particular standby bucket's
+         * window size.
+         */
+        public int MAX_JOB_COUNT_FREQUENT = DEFAULT_MAX_JOB_COUNT_FREQUENT;
+
+        /**
+         * The maximum number of jobs an app can run within this particular standby bucket's
+         * window size.
+         */
+        public int MAX_JOB_COUNT_RARE = DEFAULT_MAX_JOB_COUNT_RARE;
+
+        /** The period of time used to rate limit recently run jobs. */
+        public long RATE_LIMITING_WINDOW_MS = DEFAULT_RATE_LIMITING_WINDOW_MS;
+
+        /**
+         * The maximum number of jobs that can run within the past {@link #RATE_LIMITING_WINDOW_MS}.
+         */
+        public int MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW =
+                DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW;
+
+        /**
+         * The maximum number of {@link TimingSession}s an app can run within this particular
+         * standby bucket's window size.
+         */
+        public int MAX_SESSION_COUNT_ACTIVE = DEFAULT_MAX_SESSION_COUNT_ACTIVE;
+
+        /**
+         * The maximum number of {@link TimingSession}s an app can run within this particular
+         * standby bucket's window size.
+         */
+        public int MAX_SESSION_COUNT_WORKING = DEFAULT_MAX_SESSION_COUNT_WORKING;
+
+        /**
+         * The maximum number of {@link TimingSession}s an app can run within this particular
+         * standby bucket's window size.
+         */
+        public int MAX_SESSION_COUNT_FREQUENT = DEFAULT_MAX_SESSION_COUNT_FREQUENT;
+
+        /**
+         * The maximum number of {@link TimingSession}s an app can run within this particular
+         * standby bucket's window size.
+         */
+        public int MAX_SESSION_COUNT_RARE = DEFAULT_MAX_SESSION_COUNT_RARE;
+
+        /**
+         * The maximum number of {@link TimingSession}s that can run within the past
+         * {@link #ALLOWED_TIME_PER_PERIOD_MS}.
+         */
+        public int MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW =
+                DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW;
+
+        /**
+         * Treat two distinct {@link TimingSession}s as the same if they start and end within this
+         * amount of time of each other.
+         */
+        public long TIMING_SESSION_COALESCING_DURATION_MS =
+                DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS;
+
+        // Safeguards
+
+        /** The minimum number of jobs that any bucket will be allowed to run within its window. */
+        private static final int MIN_BUCKET_JOB_COUNT = 10;
+
+        /**
+         * The minimum number of {@link TimingSession}s that any bucket will be allowed to run
+         * within its window.
+         */
+        private static final int MIN_BUCKET_SESSION_COUNT = 1;
+
+        /** The minimum value that {@link #MAX_EXECUTION_TIME_MS} can have. */
+        private static final long MIN_MAX_EXECUTION_TIME_MS = 60 * MINUTE_IN_MILLIS;
+
+        /** The minimum value that {@link #MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW} can have. */
+        private static final int MIN_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW = 10;
+
+        /** The minimum value that {@link #MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW} can have. */
+        private static final int MIN_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = 10;
+
+        /** The minimum value that {@link #RATE_LIMITING_WINDOW_MS} can have. */
+        private static final long MIN_RATE_LIMITING_WINDOW_MS = 30 * SECOND_IN_MILLIS;
+
+        QcConstants(Handler handler) {
+            super(handler);
+        }
+
+        private void start(ContentResolver resolver) {
+            mResolver = resolver;
+            mResolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS), false, this);
+            updateConstants();
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            final String constants = Settings.Global.getString(
+                    mResolver, Settings.Global.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS);
+
+            try {
+                mParser.setString(constants);
+            } catch (Exception e) {
+                // Failed to parse the settings string, log this and move on with defaults.
+                Slog.e(TAG, "Bad jobscheduler quota controller settings", e);
+            }
+
+            ALLOWED_TIME_PER_PERIOD_MS = mParser.getDurationMillis(
+                    KEY_ALLOWED_TIME_PER_PERIOD_MS, DEFAULT_ALLOWED_TIME_PER_PERIOD_MS);
+            IN_QUOTA_BUFFER_MS = mParser.getDurationMillis(
+                    KEY_IN_QUOTA_BUFFER_MS, DEFAULT_IN_QUOTA_BUFFER_MS);
+            WINDOW_SIZE_ACTIVE_MS = mParser.getDurationMillis(
+                    KEY_WINDOW_SIZE_ACTIVE_MS, DEFAULT_WINDOW_SIZE_ACTIVE_MS);
+            WINDOW_SIZE_WORKING_MS = mParser.getDurationMillis(
+                    KEY_WINDOW_SIZE_WORKING_MS, DEFAULT_WINDOW_SIZE_WORKING_MS);
+            WINDOW_SIZE_FREQUENT_MS = mParser.getDurationMillis(
+                    KEY_WINDOW_SIZE_FREQUENT_MS, DEFAULT_WINDOW_SIZE_FREQUENT_MS);
+            WINDOW_SIZE_RARE_MS = mParser.getDurationMillis(
+                    KEY_WINDOW_SIZE_RARE_MS, DEFAULT_WINDOW_SIZE_RARE_MS);
+            MAX_EXECUTION_TIME_MS = mParser.getDurationMillis(
+                    KEY_MAX_EXECUTION_TIME_MS, DEFAULT_MAX_EXECUTION_TIME_MS);
+            MAX_JOB_COUNT_ACTIVE = mParser.getInt(
+                    KEY_MAX_JOB_COUNT_ACTIVE, DEFAULT_MAX_JOB_COUNT_ACTIVE);
+            MAX_JOB_COUNT_WORKING = mParser.getInt(
+                    KEY_MAX_JOB_COUNT_WORKING, DEFAULT_MAX_JOB_COUNT_WORKING);
+            MAX_JOB_COUNT_FREQUENT = mParser.getInt(
+                    KEY_MAX_JOB_COUNT_FREQUENT, DEFAULT_MAX_JOB_COUNT_FREQUENT);
+            MAX_JOB_COUNT_RARE = mParser.getInt(
+                    KEY_MAX_JOB_COUNT_RARE, DEFAULT_MAX_JOB_COUNT_RARE);
+            RATE_LIMITING_WINDOW_MS = mParser.getLong(
+                    KEY_RATE_LIMITING_WINDOW_MS, DEFAULT_RATE_LIMITING_WINDOW_MS);
+            MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW = mParser.getInt(
+                    KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW,
+                    DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW);
+            MAX_SESSION_COUNT_ACTIVE = mParser.getInt(
+                    KEY_MAX_SESSION_COUNT_ACTIVE, DEFAULT_MAX_SESSION_COUNT_ACTIVE);
+            MAX_SESSION_COUNT_WORKING = mParser.getInt(
+                    KEY_MAX_SESSION_COUNT_WORKING, DEFAULT_MAX_SESSION_COUNT_WORKING);
+            MAX_SESSION_COUNT_FREQUENT = mParser.getInt(
+                    KEY_MAX_SESSION_COUNT_FREQUENT, DEFAULT_MAX_SESSION_COUNT_FREQUENT);
+            MAX_SESSION_COUNT_RARE = mParser.getInt(
+                    KEY_MAX_SESSION_COUNT_RARE, DEFAULT_MAX_SESSION_COUNT_RARE);
+            MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = mParser.getInt(
+                    KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW,
+                    DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW);
+            TIMING_SESSION_COALESCING_DURATION_MS = mParser.getLong(
+                    KEY_TIMING_SESSION_COALESCING_DURATION_MS,
+                    DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS);
+
+            updateConstants();
+        }
+
+        @VisibleForTesting
+        void updateConstants() {
+            synchronized (mLock) {
+                boolean changed = false;
+
+                long newMaxExecutionTimeMs = Math.max(MIN_MAX_EXECUTION_TIME_MS,
+                        Math.min(MAX_PERIOD_MS, MAX_EXECUTION_TIME_MS));
+                if (mMaxExecutionTimeMs != newMaxExecutionTimeMs) {
+                    mMaxExecutionTimeMs = newMaxExecutionTimeMs;
+                    mMaxExecutionTimeIntoQuotaMs = mMaxExecutionTimeMs - mQuotaBufferMs;
+                    changed = true;
+                }
+                long newAllowedTimeMs = Math.min(mMaxExecutionTimeMs,
+                        Math.max(MINUTE_IN_MILLIS, ALLOWED_TIME_PER_PERIOD_MS));
+                if (mAllowedTimePerPeriodMs != newAllowedTimeMs) {
+                    mAllowedTimePerPeriodMs = newAllowedTimeMs;
+                    mAllowedTimeIntoQuotaMs = mAllowedTimePerPeriodMs - mQuotaBufferMs;
+                    changed = true;
+                }
+                // Make sure quota buffer is non-negative, not greater than allowed time per period,
+                // and no more than 5 minutes.
+                long newQuotaBufferMs = Math.max(0, Math.min(mAllowedTimePerPeriodMs,
+                        Math.min(5 * MINUTE_IN_MILLIS, IN_QUOTA_BUFFER_MS)));
+                if (mQuotaBufferMs != newQuotaBufferMs) {
+                    mQuotaBufferMs = newQuotaBufferMs;
+                    mAllowedTimeIntoQuotaMs = mAllowedTimePerPeriodMs - mQuotaBufferMs;
+                    mMaxExecutionTimeIntoQuotaMs = mMaxExecutionTimeMs - mQuotaBufferMs;
+                    changed = true;
+                }
+                long newActivePeriodMs = Math.max(mAllowedTimePerPeriodMs,
+                        Math.min(MAX_PERIOD_MS, WINDOW_SIZE_ACTIVE_MS));
+                if (mBucketPeriodsMs[ACTIVE_INDEX] != newActivePeriodMs) {
+                    mBucketPeriodsMs[ACTIVE_INDEX] = newActivePeriodMs;
+                    changed = true;
+                }
+                long newWorkingPeriodMs = Math.max(mAllowedTimePerPeriodMs,
+                        Math.min(MAX_PERIOD_MS, WINDOW_SIZE_WORKING_MS));
+                if (mBucketPeriodsMs[WORKING_INDEX] != newWorkingPeriodMs) {
+                    mBucketPeriodsMs[WORKING_INDEX] = newWorkingPeriodMs;
+                    changed = true;
+                }
+                long newFrequentPeriodMs = Math.max(mAllowedTimePerPeriodMs,
+                        Math.min(MAX_PERIOD_MS, WINDOW_SIZE_FREQUENT_MS));
+                if (mBucketPeriodsMs[FREQUENT_INDEX] != newFrequentPeriodMs) {
+                    mBucketPeriodsMs[FREQUENT_INDEX] = newFrequentPeriodMs;
+                    changed = true;
+                }
+                long newRarePeriodMs = Math.max(mAllowedTimePerPeriodMs,
+                        Math.min(MAX_PERIOD_MS, WINDOW_SIZE_RARE_MS));
+                if (mBucketPeriodsMs[RARE_INDEX] != newRarePeriodMs) {
+                    mBucketPeriodsMs[RARE_INDEX] = newRarePeriodMs;
+                    changed = true;
+                }
+                long newRateLimitingWindowMs = Math.min(MAX_PERIOD_MS,
+                        Math.max(MIN_RATE_LIMITING_WINDOW_MS, RATE_LIMITING_WINDOW_MS));
+                if (mRateLimitingWindowMs != newRateLimitingWindowMs) {
+                    mRateLimitingWindowMs = newRateLimitingWindowMs;
+                    changed = true;
+                }
+                int newMaxJobCountPerRateLimitingWindow = Math.max(
+                        MIN_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW,
+                        MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW);
+                if (mMaxJobCountPerRateLimitingWindow != newMaxJobCountPerRateLimitingWindow) {
+                    mMaxJobCountPerRateLimitingWindow = newMaxJobCountPerRateLimitingWindow;
+                    changed = true;
+                }
+                int newActiveMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_ACTIVE);
+                if (mMaxBucketJobCounts[ACTIVE_INDEX] != newActiveMaxJobCount) {
+                    mMaxBucketJobCounts[ACTIVE_INDEX] = newActiveMaxJobCount;
+                    changed = true;
+                }
+                int newWorkingMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_WORKING);
+                if (mMaxBucketJobCounts[WORKING_INDEX] != newWorkingMaxJobCount) {
+                    mMaxBucketJobCounts[WORKING_INDEX] = newWorkingMaxJobCount;
+                    changed = true;
+                }
+                int newFrequentMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_FREQUENT);
+                if (mMaxBucketJobCounts[FREQUENT_INDEX] != newFrequentMaxJobCount) {
+                    mMaxBucketJobCounts[FREQUENT_INDEX] = newFrequentMaxJobCount;
+                    changed = true;
+                }
+                int newRareMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_RARE);
+                if (mMaxBucketJobCounts[RARE_INDEX] != newRareMaxJobCount) {
+                    mMaxBucketJobCounts[RARE_INDEX] = newRareMaxJobCount;
+                    changed = true;
+                }
+                int newMaxSessionCountPerRateLimitPeriod = Math.max(
+                        MIN_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW,
+                        MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW);
+                if (mMaxSessionCountPerRateLimitingWindow != newMaxSessionCountPerRateLimitPeriod) {
+                    mMaxSessionCountPerRateLimitingWindow = newMaxSessionCountPerRateLimitPeriod;
+                    changed = true;
+                }
+                int newActiveMaxSessionCount =
+                        Math.max(MIN_BUCKET_SESSION_COUNT, MAX_SESSION_COUNT_ACTIVE);
+                if (mMaxBucketSessionCounts[ACTIVE_INDEX] != newActiveMaxSessionCount) {
+                    mMaxBucketSessionCounts[ACTIVE_INDEX] = newActiveMaxSessionCount;
+                    changed = true;
+                }
+                int newWorkingMaxSessionCount =
+                        Math.max(MIN_BUCKET_SESSION_COUNT, MAX_SESSION_COUNT_WORKING);
+                if (mMaxBucketSessionCounts[WORKING_INDEX] != newWorkingMaxSessionCount) {
+                    mMaxBucketSessionCounts[WORKING_INDEX] = newWorkingMaxSessionCount;
+                    changed = true;
+                }
+                int newFrequentMaxSessionCount =
+                        Math.max(MIN_BUCKET_SESSION_COUNT, MAX_SESSION_COUNT_FREQUENT);
+                if (mMaxBucketSessionCounts[FREQUENT_INDEX] != newFrequentMaxSessionCount) {
+                    mMaxBucketSessionCounts[FREQUENT_INDEX] = newFrequentMaxSessionCount;
+                    changed = true;
+                }
+                int newRareMaxSessionCount =
+                        Math.max(MIN_BUCKET_SESSION_COUNT, MAX_SESSION_COUNT_RARE);
+                if (mMaxBucketSessionCounts[RARE_INDEX] != newRareMaxSessionCount) {
+                    mMaxBucketSessionCounts[RARE_INDEX] = newRareMaxSessionCount;
+                    changed = true;
+                }
+                long newSessionCoalescingDurationMs = Math.min(15 * MINUTE_IN_MILLIS,
+                        Math.max(0, TIMING_SESSION_COALESCING_DURATION_MS));
+                if (mTimingSessionCoalescingDurationMs != newSessionCoalescingDurationMs) {
+                    mTimingSessionCoalescingDurationMs = newSessionCoalescingDurationMs;
+                    changed = true;
+                }
+
+                if (changed && mShouldThrottle) {
+                    // Update job bookkeeping out of band.
+                    BackgroundThread.getHandler().post(() -> {
+                        synchronized (mLock) {
+                            invalidateAllExecutionStatsLocked();
+                            maybeUpdateAllConstraintsLocked();
+                        }
+                    });
+                }
+            }
+        }
+
+        private void dump(IndentingPrintWriter pw) {
+            pw.println();
+            pw.println("QuotaController:");
+            pw.increaseIndent();
+            pw.printPair(KEY_ALLOWED_TIME_PER_PERIOD_MS, ALLOWED_TIME_PER_PERIOD_MS).println();
+            pw.printPair(KEY_IN_QUOTA_BUFFER_MS, IN_QUOTA_BUFFER_MS).println();
+            pw.printPair(KEY_WINDOW_SIZE_ACTIVE_MS, WINDOW_SIZE_ACTIVE_MS).println();
+            pw.printPair(KEY_WINDOW_SIZE_WORKING_MS, WINDOW_SIZE_WORKING_MS).println();
+            pw.printPair(KEY_WINDOW_SIZE_FREQUENT_MS, WINDOW_SIZE_FREQUENT_MS).println();
+            pw.printPair(KEY_WINDOW_SIZE_RARE_MS, WINDOW_SIZE_RARE_MS).println();
+            pw.printPair(KEY_MAX_EXECUTION_TIME_MS, MAX_EXECUTION_TIME_MS).println();
+            pw.printPair(KEY_MAX_JOB_COUNT_ACTIVE, MAX_JOB_COUNT_ACTIVE).println();
+            pw.printPair(KEY_MAX_JOB_COUNT_WORKING, MAX_JOB_COUNT_WORKING).println();
+            pw.printPair(KEY_MAX_JOB_COUNT_FREQUENT, MAX_JOB_COUNT_FREQUENT).println();
+            pw.printPair(KEY_MAX_JOB_COUNT_RARE, MAX_JOB_COUNT_RARE).println();
+            pw.printPair(KEY_RATE_LIMITING_WINDOW_MS, RATE_LIMITING_WINDOW_MS).println();
+            pw.printPair(KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW,
+                    MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW).println();
+            pw.printPair(KEY_MAX_SESSION_COUNT_ACTIVE, MAX_SESSION_COUNT_ACTIVE).println();
+            pw.printPair(KEY_MAX_SESSION_COUNT_WORKING, MAX_SESSION_COUNT_WORKING).println();
+            pw.printPair(KEY_MAX_SESSION_COUNT_FREQUENT, MAX_SESSION_COUNT_FREQUENT).println();
+            pw.printPair(KEY_MAX_SESSION_COUNT_RARE, MAX_SESSION_COUNT_RARE).println();
+            pw.printPair(KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW,
+                    MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW).println();
+            pw.printPair(KEY_TIMING_SESSION_COALESCING_DURATION_MS,
+                    TIMING_SESSION_COALESCING_DURATION_MS).println();
+            pw.decreaseIndent();
+        }
+
+        private void dump(ProtoOutputStream proto) {
+            final long qcToken = proto.start(ConstantsProto.QUOTA_CONTROLLER);
+            proto.write(ConstantsProto.QuotaController.ALLOWED_TIME_PER_PERIOD_MS,
+                    ALLOWED_TIME_PER_PERIOD_MS);
+            proto.write(ConstantsProto.QuotaController.IN_QUOTA_BUFFER_MS, IN_QUOTA_BUFFER_MS);
+            proto.write(ConstantsProto.QuotaController.ACTIVE_WINDOW_SIZE_MS,
+                    WINDOW_SIZE_ACTIVE_MS);
+            proto.write(ConstantsProto.QuotaController.WORKING_WINDOW_SIZE_MS,
+                    WINDOW_SIZE_WORKING_MS);
+            proto.write(ConstantsProto.QuotaController.FREQUENT_WINDOW_SIZE_MS,
+                    WINDOW_SIZE_FREQUENT_MS);
+            proto.write(ConstantsProto.QuotaController.RARE_WINDOW_SIZE_MS, WINDOW_SIZE_RARE_MS);
+            proto.write(ConstantsProto.QuotaController.MAX_EXECUTION_TIME_MS,
+                    MAX_EXECUTION_TIME_MS);
+            proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_ACTIVE, MAX_JOB_COUNT_ACTIVE);
+            proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_WORKING,
+                    MAX_JOB_COUNT_WORKING);
+            proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_FREQUENT,
+                    MAX_JOB_COUNT_FREQUENT);
+            proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_RARE, MAX_JOB_COUNT_RARE);
+            proto.write(ConstantsProto.QuotaController.RATE_LIMITING_WINDOW_MS,
+                    RATE_LIMITING_WINDOW_MS);
+            proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW,
+                    MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW);
+            proto.write(ConstantsProto.QuotaController.MAX_SESSION_COUNT_ACTIVE,
+                    MAX_SESSION_COUNT_ACTIVE);
+            proto.write(ConstantsProto.QuotaController.MAX_SESSION_COUNT_WORKING,
+                    MAX_SESSION_COUNT_WORKING);
+            proto.write(ConstantsProto.QuotaController.MAX_SESSION_COUNT_FREQUENT,
+                    MAX_SESSION_COUNT_FREQUENT);
+            proto.write(ConstantsProto.QuotaController.MAX_SESSION_COUNT_RARE,
+                    MAX_SESSION_COUNT_RARE);
+            proto.write(ConstantsProto.QuotaController.MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW,
+                    MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW);
+            proto.write(ConstantsProto.QuotaController.TIMING_SESSION_COALESCING_DURATION_MS,
+                    TIMING_SESSION_COALESCING_DURATION_MS);
+            proto.end(qcToken);
+        }
+    }
+
+    //////////////////////// TESTING HELPERS /////////////////////////////
+
+    @VisibleForTesting
+    long getAllowedTimePerPeriodMs() {
+        return mAllowedTimePerPeriodMs;
+    }
+
+    @VisibleForTesting
+    @NonNull
+    int[] getBucketMaxJobCounts() {
+        return mMaxBucketJobCounts;
+    }
+
+    @VisibleForTesting
+    @NonNull
+    int[] getBucketMaxSessionCounts() {
+        return mMaxBucketSessionCounts;
+    }
+
+    @VisibleForTesting
+    @NonNull
+    long[] getBucketWindowSizes() {
+        return mBucketPeriodsMs;
+    }
+
+    @VisibleForTesting
+    @NonNull
+    SparseBooleanArray getForegroundUids() {
+        return mForegroundUids;
+    }
+
+    @VisibleForTesting
+    @NonNull
+    Handler getHandler() {
+        return mHandler;
+    }
+
+    @VisibleForTesting
+    long getInQuotaBufferMs() {
+        return mQuotaBufferMs;
+    }
+
+    @VisibleForTesting
+    long getMaxExecutionTimeMs() {
+        return mMaxExecutionTimeMs;
+    }
+
+    @VisibleForTesting
+    int getMaxJobCountPerRateLimitingWindow() {
+        return mMaxJobCountPerRateLimitingWindow;
+    }
+
+    @VisibleForTesting
+    int getMaxSessionCountPerRateLimitingWindow() {
+        return mMaxSessionCountPerRateLimitingWindow;
+    }
+
+    @VisibleForTesting
+    long getRateLimitingWindowMs() {
+        return mRateLimitingWindowMs;
+    }
+
+    @VisibleForTesting
+    long getTimingSessionCoalescingDurationMs() {
+        return mTimingSessionCoalescingDurationMs;
+    }
+
+    @VisibleForTesting
+    @Nullable
+    List<TimingSession> getTimingSessions(int userId, String packageName) {
+        return mTimingSessions.get(userId, packageName);
+    }
+
+    @VisibleForTesting
+    @NonNull
+    QcConstants getQcConstants() {
+        return mQcConstants;
+    }
+
+    //////////////////////////// DATA DUMP //////////////////////////////
+
+    @Override
+    public void dumpControllerStateLocked(final IndentingPrintWriter pw,
+            final Predicate<JobStatus> predicate) {
+        pw.println("Is throttling: " + mShouldThrottle);
+        pw.println("Is charging: " + mChargeTracker.isCharging());
+        pw.println("In parole: " + mInParole);
+        pw.println("Current elapsed time: " + sElapsedRealtimeClock.millis());
+        pw.println();
+
+        pw.print("Foreground UIDs: ");
+        pw.println(mForegroundUids.toString());
+        pw.println();
+
+        pw.println("Cached UID->package map:");
+        pw.increaseIndent();
+        for (int i = 0; i < mUidToPackageCache.size(); ++i) {
+            final int uid = mUidToPackageCache.keyAt(i);
+            pw.print(uid);
+            pw.print(": ");
+            pw.println(mUidToPackageCache.get(uid));
+        }
+        pw.decreaseIndent();
+        pw.println();
+
+        mTrackedJobs.forEach((jobs) -> {
+            for (int j = 0; j < jobs.size(); j++) {
+                final JobStatus js = jobs.valueAt(j);
+                if (!predicate.test(js)) {
+                    continue;
+                }
+                pw.print("#");
+                js.printUniqueId(pw);
+                pw.print(" from ");
+                UserHandle.formatUid(pw, js.getSourceUid());
+                if (mTopStartedJobs.contains(js)) {
+                    pw.print(" (TOP)");
+                }
+                pw.println();
+
+                pw.increaseIndent();
+                pw.print(JobStatus.bucketName(getEffectiveStandbyBucket(js)));
+                pw.print(", ");
+                if (js.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA)) {
+                    pw.print("within quota");
+                } else {
+                    pw.print("not within quota");
+                }
+                pw.print(", ");
+                pw.print(getRemainingExecutionTimeLocked(js));
+                pw.print("ms remaining in quota");
+                pw.decreaseIndent();
+                pw.println();
+            }
+        });
+
+        pw.println();
+        for (int u = 0; u < mPkgTimers.numUsers(); ++u) {
+            final int userId = mPkgTimers.keyAt(u);
+            for (int p = 0; p < mPkgTimers.numPackagesForUser(userId); ++p) {
+                final String pkgName = mPkgTimers.keyAt(u, p);
+                mPkgTimers.valueAt(u, p).dump(pw, predicate);
+                pw.println();
+                List<TimingSession> sessions = mTimingSessions.get(userId, pkgName);
+                if (sessions != null) {
+                    pw.increaseIndent();
+                    pw.println("Saved sessions:");
+                    pw.increaseIndent();
+                    for (int j = sessions.size() - 1; j >= 0; j--) {
+                        TimingSession session = sessions.get(j);
+                        session.dump(pw);
+                    }
+                    pw.decreaseIndent();
+                    pw.decreaseIndent();
+                    pw.println();
+                }
+            }
+        }
+
+        pw.println("Cached execution stats:");
+        pw.increaseIndent();
+        for (int u = 0; u < mExecutionStatsCache.numUsers(); ++u) {
+            final int userId = mExecutionStatsCache.keyAt(u);
+            for (int p = 0; p < mExecutionStatsCache.numPackagesForUser(userId); ++p) {
+                final String pkgName = mExecutionStatsCache.keyAt(u, p);
+                ExecutionStats[] stats = mExecutionStatsCache.valueAt(u, p);
+
+                pw.println(string(userId, pkgName));
+                pw.increaseIndent();
+                for (int i = 0; i < stats.length; ++i) {
+                    ExecutionStats executionStats = stats[i];
+                    if (executionStats != null) {
+                        pw.print(JobStatus.bucketName(i));
+                        pw.print(": ");
+                        pw.println(executionStats);
+                    }
+                }
+                pw.decreaseIndent();
+            }
+        }
+        pw.decreaseIndent();
+
+        pw.println();
+        pw.println("In quota alarms:");
+        pw.increaseIndent();
+        for (int u = 0; u < mInQuotaAlarmListeners.numUsers(); ++u) {
+            final int userId = mInQuotaAlarmListeners.keyAt(u);
+            for (int p = 0; p < mInQuotaAlarmListeners.numPackagesForUser(userId); ++p) {
+                final String pkgName = mInQuotaAlarmListeners.keyAt(u, p);
+                QcAlarmListener alarmListener = mInQuotaAlarmListeners.valueAt(u, p);
+
+                pw.print(string(userId, pkgName));
+                pw.print(": ");
+                if (alarmListener.isWaiting()) {
+                    pw.println(alarmListener.getTriggerTimeElapsed());
+                } else {
+                    pw.println("NOT WAITING");
+                }
+            }
+        }
+        pw.decreaseIndent();
+    }
+
+    @Override
+    public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
+            Predicate<JobStatus> predicate) {
+        final long token = proto.start(fieldId);
+        final long mToken = proto.start(StateControllerProto.QUOTA);
+
+        proto.write(StateControllerProto.QuotaController.IS_CHARGING, mChargeTracker.isCharging());
+        proto.write(StateControllerProto.QuotaController.IS_IN_PAROLE, mInParole);
+        proto.write(StateControllerProto.QuotaController.ELAPSED_REALTIME,
+                sElapsedRealtimeClock.millis());
+
+        for (int i = 0; i < mForegroundUids.size(); ++i) {
+            proto.write(StateControllerProto.QuotaController.FOREGROUND_UIDS,
+                    mForegroundUids.keyAt(i));
+        }
+
+        mTrackedJobs.forEach((jobs) -> {
+            for (int j = 0; j < jobs.size(); j++) {
+                final JobStatus js = jobs.valueAt(j);
+                if (!predicate.test(js)) {
+                    continue;
+                }
+                final long jsToken = proto.start(
+                        StateControllerProto.QuotaController.TRACKED_JOBS);
+                js.writeToShortProto(proto,
+                        StateControllerProto.QuotaController.TrackedJob.INFO);
+                proto.write(StateControllerProto.QuotaController.TrackedJob.SOURCE_UID,
+                        js.getSourceUid());
+                proto.write(
+                        StateControllerProto.QuotaController.TrackedJob.EFFECTIVE_STANDBY_BUCKET,
+                        getEffectiveStandbyBucket(js));
+                proto.write(StateControllerProto.QuotaController.TrackedJob.IS_TOP_STARTED_JOB,
+                        mTopStartedJobs.contains(js));
+                proto.write(StateControllerProto.QuotaController.TrackedJob.HAS_QUOTA,
+                        js.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+                proto.write(StateControllerProto.QuotaController.TrackedJob.REMAINING_QUOTA_MS,
+                        getRemainingExecutionTimeLocked(js));
+                proto.end(jsToken);
+            }
+        });
+
+        for (int u = 0; u < mPkgTimers.numUsers(); ++u) {
+            final int userId = mPkgTimers.keyAt(u);
+            for (int p = 0; p < mPkgTimers.numPackagesForUser(userId); ++p) {
+                final String pkgName = mPkgTimers.keyAt(u, p);
+                final long psToken = proto.start(
+                        StateControllerProto.QuotaController.PACKAGE_STATS);
+                mPkgTimers.valueAt(u, p).dump(proto,
+                        StateControllerProto.QuotaController.PackageStats.TIMER, predicate);
+
+                List<TimingSession> sessions = mTimingSessions.get(userId, pkgName);
+                if (sessions != null) {
+                    for (int j = sessions.size() - 1; j >= 0; j--) {
+                        TimingSession session = sessions.get(j);
+                        session.dump(proto,
+                                StateControllerProto.QuotaController.PackageStats.SAVED_SESSIONS);
+                    }
+                }
+
+                ExecutionStats[] stats = mExecutionStatsCache.get(userId, pkgName);
+                if (stats != null) {
+                    for (int bucketIndex = 0; bucketIndex < stats.length; ++bucketIndex) {
+                        ExecutionStats es = stats[bucketIndex];
+                        if (es == null) {
+                            continue;
+                        }
+                        final long esToken = proto.start(
+                                StateControllerProto.QuotaController.PackageStats.EXECUTION_STATS);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.STANDBY_BUCKET,
+                                bucketIndex);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.EXPIRATION_TIME_ELAPSED,
+                                es.expirationTimeElapsed);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.WINDOW_SIZE_MS,
+                                es.windowSizeMs);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.JOB_COUNT_LIMIT,
+                                es.jobCountLimit);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.SESSION_COUNT_LIMIT,
+                                es.sessionCountLimit);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.EXECUTION_TIME_IN_WINDOW_MS,
+                                es.executionTimeInWindowMs);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.BG_JOB_COUNT_IN_WINDOW,
+                                es.bgJobCountInWindow);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.EXECUTION_TIME_IN_MAX_PERIOD_MS,
+                                es.executionTimeInMaxPeriodMs);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.BG_JOB_COUNT_IN_MAX_PERIOD,
+                                es.bgJobCountInMaxPeriod);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.SESSION_COUNT_IN_WINDOW,
+                                es.sessionCountInWindow);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.IN_QUOTA_TIME_ELAPSED,
+                                es.inQuotaTimeElapsed);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.JOB_COUNT_EXPIRATION_TIME_ELAPSED,
+                                es.jobRateLimitExpirationTimeElapsed);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.JOB_COUNT_IN_RATE_LIMITING_WINDOW,
+                                es.jobCountInRateLimitingWindow);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.SESSION_COUNT_EXPIRATION_TIME_ELAPSED,
+                                es.sessionRateLimitExpirationTimeElapsed);
+                        proto.write(
+                                StateControllerProto.QuotaController.ExecutionStats.SESSION_COUNT_IN_RATE_LIMITING_WINDOW,
+                                es.sessionCountInRateLimitingWindow);
+                        proto.end(esToken);
+                    }
+                }
+
+                QcAlarmListener alarmListener = mInQuotaAlarmListeners.get(userId, pkgName);
+                if (alarmListener != null) {
+                    final long alToken = proto.start(
+                            StateControllerProto.QuotaController.PackageStats.IN_QUOTA_ALARM_LISTENER);
+                    proto.write(StateControllerProto.QuotaController.AlarmListener.IS_WAITING,
+                            alarmListener.isWaiting());
+                    proto.write(
+                            StateControllerProto.QuotaController.AlarmListener.TRIGGER_TIME_ELAPSED,
+                            alarmListener.getTriggerTimeElapsed());
+                    proto.end(alToken);
+                }
+
+                proto.end(psToken);
+            }
+        }
+
+        proto.end(mToken);
+        proto.end(token);
+    }
+
+    @Override
+    public void dumpConstants(IndentingPrintWriter pw) {
+        mQcConstants.dump(pw);
+    }
+
+    @Override
+    public void dumpConstants(ProtoOutputStream proto) {
+        mQcConstants.dump(proto);
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
new file mode 100644
index 0000000..51be38b
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers;
+
+import static com.android.server.job.JobSchedulerService.DEBUG;
+
+import android.content.Context;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.JobSchedulerService.Constants;
+import com.android.server.job.StateChangedListener;
+
+import java.util.function.Predicate;
+
+/**
+ * Incorporates shared controller logic between the various controllers of the JobManager.
+ * These are solely responsible for tracking a list of jobs, and notifying the JM when these
+ * are ready to run, or whether they must be stopped.
+ */
+public abstract class StateController {
+    private static final String TAG = "JobScheduler.SC";
+
+    protected final JobSchedulerService mService;
+    protected final StateChangedListener mStateChangedListener;
+    protected final Context mContext;
+    protected final Object mLock;
+    protected final Constants mConstants;
+
+    StateController(JobSchedulerService service) {
+        mService = service;
+        mStateChangedListener = service;
+        mContext = service.getTestableContext();
+        mLock = service.getLock();
+        mConstants = service.getConstants();
+    }
+
+    /**
+     * Called when the system boot phase has reached
+     * {@link com.android.server.SystemService#PHASE_SYSTEM_SERVICES_READY}.
+     */
+    public void onSystemServicesReady() {
+    }
+
+    /**
+     * Implement the logic here to decide whether a job should be tracked by this controller.
+     * This logic is put here so the JobManager can be completely agnostic of Controller logic.
+     * Also called when updating a task, so implementing controllers have to be aware of
+     * preexisting tasks.
+     */
+    public abstract void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob);
+
+    /**
+     * Optionally implement logic here to prepare the job to be executed.
+     */
+    public void prepareForExecutionLocked(JobStatus jobStatus) {
+    }
+
+    /**
+     * Remove task - this will happen if the task is cancelled, completed, etc.
+     */
+    public abstract void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
+            boolean forUpdate);
+
+    /**
+     * Called when a new job is being created to reschedule an old failed job.
+     */
+    public void rescheduleForFailureLocked(JobStatus newJob, JobStatus failureToReschedule) {
+    }
+
+    /**
+     * Called when the JobScheduler.Constants are updated.
+     */
+    public void onConstantsUpdatedLocked() {
+    }
+
+    /** Called when a package is uninstalled from the device (not for an update). */
+    public void onAppRemovedLocked(String packageName, int uid) {
+    }
+
+    /** Called when a user is removed from the device. */
+    public void onUserRemovedLocked(int userId) {
+    }
+
+    /**
+     * Called when JobSchedulerService has determined that the job is not ready to be run. The
+     * Controller can evaluate if it can or should do something to promote this job's readiness.
+     */
+    public void evaluateStateLocked(JobStatus jobStatus) {
+    }
+
+    /**
+     * Called when something with the UID has changed. The controller should re-evaluate any
+     * internal state tracking dependent on this UID.
+     */
+    public void reevaluateStateLocked(int uid) {
+    }
+
+    protected boolean wouldBeReadyWithConstraintLocked(JobStatus jobStatus, int constraint) {
+        // This is very cheap to check (just a few conditions on data in JobStatus).
+        final boolean jobWouldBeReady = jobStatus.wouldBeReadyWithConstraint(constraint);
+        if (DEBUG) {
+            Slog.v(TAG, "wouldBeReadyWithConstraintLocked: " + jobStatus.toShortString()
+                    + " constraint=" + constraint
+                    + " readyWithConstraint=" + jobWouldBeReady);
+        }
+        if (!jobWouldBeReady) {
+            // If the job wouldn't be ready, nothing to do here.
+            return false;
+        }
+
+        // This is potentially more expensive since JSS may have to query component
+        // presence.
+        return mService.areComponentsInPlaceLocked(jobStatus);
+    }
+
+    public abstract void dumpControllerStateLocked(IndentingPrintWriter pw,
+            Predicate<JobStatus> predicate);
+    public abstract void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
+            Predicate<JobStatus> predicate);
+
+    /** Dump any internal constants the Controller may have. */
+    public void dumpConstants(IndentingPrintWriter pw) {
+    }
+
+    /** Dump any internal constants the Controller may have. */
+    public void dumpConstants(ProtoOutputStream proto) {
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java
new file mode 100644
index 0000000..51187df
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers;
+
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.UserHandle;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateControllerProto;
+import com.android.server.storage.DeviceStorageMonitorService;
+
+import java.util.function.Predicate;
+
+/**
+ * Simple controller that tracks the status of the device's storage.
+ */
+public final class StorageController extends StateController {
+    private static final String TAG = "JobScheduler.Storage";
+    private static final boolean DEBUG = JobSchedulerService.DEBUG
+            || Log.isLoggable(TAG, Log.DEBUG);
+
+    private final ArraySet<JobStatus> mTrackedTasks = new ArraySet<JobStatus>();
+    private final StorageTracker mStorageTracker;
+
+    @VisibleForTesting
+    public StorageTracker getTracker() {
+        return mStorageTracker;
+    }
+
+    public StorageController(JobSchedulerService service) {
+        super(service);
+        mStorageTracker = new StorageTracker();
+        mStorageTracker.startTracking();
+    }
+
+    @Override
+    public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
+        if (taskStatus.hasStorageNotLowConstraint()) {
+            mTrackedTasks.add(taskStatus);
+            taskStatus.setTrackingController(JobStatus.TRACKING_STORAGE);
+            taskStatus.setStorageNotLowConstraintSatisfied(mStorageTracker.isStorageNotLow());
+        }
+    }
+
+    @Override
+    public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob,
+            boolean forUpdate) {
+        if (taskStatus.clearTrackingController(JobStatus.TRACKING_STORAGE)) {
+            mTrackedTasks.remove(taskStatus);
+        }
+    }
+
+    private void maybeReportNewStorageState() {
+        final boolean storageNotLow = mStorageTracker.isStorageNotLow();
+        boolean reportChange = false;
+        synchronized (mLock) {
+            for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
+                final JobStatus ts = mTrackedTasks.valueAt(i);
+                reportChange |= ts.setStorageNotLowConstraintSatisfied(storageNotLow);
+            }
+        }
+        if (storageNotLow) {
+            // Tell the scheduler that any ready jobs should be flushed.
+            mStateChangedListener.onRunJobNow(null);
+        } else if (reportChange) {
+            // Let the scheduler know that state has changed. This may or may not result in an
+            // execution.
+            mStateChangedListener.onControllerStateChanged();
+        }
+    }
+
+    public final class StorageTracker extends BroadcastReceiver {
+        /**
+         * Track whether storage is low.
+         */
+        private boolean mStorageLow;
+        /** Sequence number of last broadcast. */
+        private int mLastStorageSeq = -1;
+
+        public StorageTracker() {
+        }
+
+        public void startTracking() {
+            IntentFilter filter = new IntentFilter();
+
+            // Storage status.  Just need to register, since STORAGE_LOW is a sticky
+            // broadcast we will receive that if it is currently active.
+            filter.addAction(Intent.ACTION_DEVICE_STORAGE_LOW);
+            filter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
+            mContext.registerReceiver(this, filter);
+        }
+
+        public boolean isStorageNotLow() {
+            return !mStorageLow;
+        }
+
+        public int getSeq() {
+            return mLastStorageSeq;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            onReceiveInternal(intent);
+        }
+
+        @VisibleForTesting
+        public void onReceiveInternal(Intent intent) {
+            final String action = intent.getAction();
+            mLastStorageSeq = intent.getIntExtra(DeviceStorageMonitorService.EXTRA_SEQUENCE,
+                    mLastStorageSeq);
+            if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(action)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Available storage too low to do work. @ "
+                            + sElapsedRealtimeClock.millis());
+                }
+                mStorageLow = true;
+                maybeReportNewStorageState();
+            } else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Available storage high enough to do work. @ "
+                            + sElapsedRealtimeClock.millis());
+                }
+                mStorageLow = false;
+                maybeReportNewStorageState();
+            }
+        }
+    }
+
+    @Override
+    public void dumpControllerStateLocked(IndentingPrintWriter pw,
+            Predicate<JobStatus> predicate) {
+        pw.println("Not low: " + mStorageTracker.isStorageNotLow());
+        pw.println("Sequence: " + mStorageTracker.getSeq());
+        pw.println();
+
+        for (int i = 0; i < mTrackedTasks.size(); i++) {
+            final JobStatus js = mTrackedTasks.valueAt(i);
+            if (!predicate.test(js)) {
+                continue;
+            }
+            pw.print("#");
+            js.printUniqueId(pw);
+            pw.print(" from ");
+            UserHandle.formatUid(pw, js.getSourceUid());
+            pw.println();
+        }
+    }
+
+    @Override
+    public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
+            Predicate<JobStatus> predicate) {
+        final long token = proto.start(fieldId);
+        final long mToken = proto.start(StateControllerProto.STORAGE);
+
+        proto.write(StateControllerProto.StorageController.IS_STORAGE_NOT_LOW,
+                mStorageTracker.isStorageNotLow());
+        proto.write(StateControllerProto.StorageController.LAST_BROADCAST_SEQUENCE_NUMBER,
+                mStorageTracker.getSeq());
+
+        for (int i = 0; i < mTrackedTasks.size(); i++) {
+            final JobStatus js = mTrackedTasks.valueAt(i);
+            if (!predicate.test(js)) {
+                continue;
+            }
+            final long jsToken = proto.start(StateControllerProto.StorageController.TRACKED_JOBS);
+            js.writeToShortProto(proto, StateControllerProto.StorageController.TrackedJob.INFO);
+            proto.write(StateControllerProto.StorageController.TrackedJob.SOURCE_UID,
+                    js.getSourceUid());
+            proto.end(jsToken);
+        }
+
+        proto.end(mToken);
+        proto.end(token);
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
new file mode 100644
index 0000000..4c11947
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
@@ -0,0 +1,504 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers;
+
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
+import android.annotation.Nullable;
+import android.app.AlarmManager;
+import android.app.AlarmManager.OnAlarmListener;
+import android.content.Context;
+import android.os.Process;
+import android.os.UserHandle;
+import android.os.WorkSource;
+import android.util.Log;
+import android.util.Slog;
+import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateControllerProto;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.function.Predicate;
+
+/**
+ * This class sets an alarm for the next expiring job, and determines whether a job's minimum
+ * delay has been satisfied.
+ */
+public final class TimeController extends StateController {
+    private static final String TAG = "JobScheduler.Time";
+    private static final boolean DEBUG = JobSchedulerService.DEBUG
+            || Log.isLoggable(TAG, Log.DEBUG);
+
+    /** Deadline alarm tag for logging purposes */
+    private final String DEADLINE_TAG = "*job.deadline*";
+    /** Delay alarm tag for logging purposes */
+    private final String DELAY_TAG = "*job.delay*";
+
+    private long mNextJobExpiredElapsedMillis;
+    private long mNextDelayExpiredElapsedMillis;
+
+    private final boolean mChainedAttributionEnabled;
+
+    private AlarmManager mAlarmService = null;
+    /** List of tracked jobs, sorted asc. by deadline */
+    private final List<JobStatus> mTrackedJobs = new LinkedList<>();
+
+    public TimeController(JobSchedulerService service) {
+        super(service);
+
+        mNextJobExpiredElapsedMillis = Long.MAX_VALUE;
+        mNextDelayExpiredElapsedMillis = Long.MAX_VALUE;
+        mChainedAttributionEnabled = mService.isChainedAttributionEnabled();
+    }
+
+    /**
+     * Check if the job has a timing constraint, and if so determine where to insert it in our
+     * list.
+     */
+    @Override
+    public void maybeStartTrackingJobLocked(JobStatus job, JobStatus lastJob) {
+        if (job.hasTimingDelayConstraint() || job.hasDeadlineConstraint()) {
+            maybeStopTrackingJobLocked(job, null, false);
+
+            // First: check the constraints now, because if they are already satisfied
+            // then there is no need to track it.  This gives us a fast path for a common
+            // pattern of having a job with a 0 deadline constraint ("run immediately").
+            // Unlike most controllers, once one of our constraints has been satisfied, it
+            // will never be unsatisfied (our time base can not go backwards).
+            final long nowElapsedMillis = sElapsedRealtimeClock.millis();
+            if (job.hasDeadlineConstraint() && evaluateDeadlineConstraint(job, nowElapsedMillis)) {
+                return;
+            } else if (job.hasTimingDelayConstraint() && evaluateTimingDelayConstraint(job,
+                    nowElapsedMillis)) {
+                if (!job.hasDeadlineConstraint()) {
+                    // If it doesn't have a deadline, we'll never have to touch it again.
+                    return;
+                }
+            }
+
+            boolean isInsert = false;
+            ListIterator<JobStatus> it = mTrackedJobs.listIterator(mTrackedJobs.size());
+            while (it.hasPrevious()) {
+                JobStatus ts = it.previous();
+                if (ts.getLatestRunTimeElapsed() < job.getLatestRunTimeElapsed()) {
+                    // Insert
+                    isInsert = true;
+                    break;
+                }
+            }
+            if (isInsert) {
+                it.next();
+            }
+            it.add(job);
+
+            job.setTrackingController(JobStatus.TRACKING_TIME);
+            WorkSource ws = deriveWorkSource(job.getSourceUid(), job.getSourcePackageName());
+
+            // Only update alarms if the job would be ready with the relevant timing constraint
+            // satisfied.
+            if (job.hasTimingDelayConstraint()
+                    && wouldBeReadyWithConstraintLocked(job, JobStatus.CONSTRAINT_TIMING_DELAY)) {
+                maybeUpdateDelayAlarmLocked(job.getEarliestRunTime(), ws);
+            }
+            if (job.hasDeadlineConstraint()
+                    && wouldBeReadyWithConstraintLocked(job, JobStatus.CONSTRAINT_DEADLINE)) {
+                maybeUpdateDeadlineAlarmLocked(job.getLatestRunTimeElapsed(), ws);
+            }
+        }
+    }
+
+    /**
+     * When we stop tracking a job, we only need to update our alarms if the job we're no longer
+     * tracking was the one our alarms were based off of.
+     */
+    @Override
+    public void maybeStopTrackingJobLocked(JobStatus job, JobStatus incomingJob,
+            boolean forUpdate) {
+        if (job.clearTrackingController(JobStatus.TRACKING_TIME)) {
+            if (mTrackedJobs.remove(job)) {
+                checkExpiredDelaysAndResetAlarm();
+                checkExpiredDeadlinesAndResetAlarm();
+            }
+        }
+    }
+
+    @Override
+    public void evaluateStateLocked(JobStatus job) {
+        final long nowElapsedMillis = sElapsedRealtimeClock.millis();
+
+        // Check deadline constraint first because if it's satisfied, we avoid a little bit of
+        // unnecessary processing of the timing delay.
+        if (job.hasDeadlineConstraint()
+                && !job.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE)
+                && job.getLatestRunTimeElapsed() <= mNextJobExpiredElapsedMillis) {
+            if (evaluateDeadlineConstraint(job, nowElapsedMillis)) {
+                checkExpiredDeadlinesAndResetAlarm();
+                checkExpiredDelaysAndResetAlarm();
+            } else {
+                final boolean isAlarmForJob =
+                        job.getLatestRunTimeElapsed() == mNextJobExpiredElapsedMillis;
+                final boolean wouldBeReady = wouldBeReadyWithConstraintLocked(
+                        job, JobStatus.CONSTRAINT_DEADLINE);
+                if ((isAlarmForJob && !wouldBeReady) || (!isAlarmForJob && wouldBeReady)) {
+                    checkExpiredDeadlinesAndResetAlarm();
+                }
+            }
+        }
+        if (job.hasTimingDelayConstraint()
+                && !job.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY)
+                && job.getEarliestRunTime() <= mNextDelayExpiredElapsedMillis) {
+            if (evaluateTimingDelayConstraint(job, nowElapsedMillis)) {
+                checkExpiredDelaysAndResetAlarm();
+            } else {
+                final boolean isAlarmForJob =
+                        job.getEarliestRunTime() == mNextDelayExpiredElapsedMillis;
+                final boolean wouldBeReady = wouldBeReadyWithConstraintLocked(
+                        job, JobStatus.CONSTRAINT_TIMING_DELAY);
+                if ((isAlarmForJob && !wouldBeReady) || (!isAlarmForJob && wouldBeReady)) {
+                    checkExpiredDelaysAndResetAlarm();
+                }
+            }
+        }
+    }
+
+    @Override
+    public void reevaluateStateLocked(int uid) {
+        checkExpiredDeadlinesAndResetAlarm();
+        checkExpiredDelaysAndResetAlarm();
+    }
+
+    /**
+     * Determines whether this controller can stop tracking the given job.
+     * The controller is no longer interested in a job once its time constraint is satisfied, and
+     * the job's deadline is fulfilled - unlike other controllers a time constraint can't toggle
+     * back and forth.
+     */
+    private boolean canStopTrackingJobLocked(JobStatus job) {
+        return (!job.hasTimingDelayConstraint()
+                        || job.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY))
+                && (!job.hasDeadlineConstraint()
+                        || job.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE));
+    }
+
+    private void ensureAlarmServiceLocked() {
+        if (mAlarmService == null) {
+            mAlarmService = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+        }
+    }
+
+    /**
+     * Checks list of jobs for ones that have an expired deadline, sending them to the JobScheduler
+     * if so, removing them from this list, and updating the alarm for the next expiry time.
+     */
+    @VisibleForTesting
+    void checkExpiredDeadlinesAndResetAlarm() {
+        synchronized (mLock) {
+            long nextExpiryTime = Long.MAX_VALUE;
+            int nextExpiryUid = 0;
+            String nextExpiryPackageName = null;
+            final long nowElapsedMillis = sElapsedRealtimeClock.millis();
+
+            ListIterator<JobStatus> it = mTrackedJobs.listIterator();
+            while (it.hasNext()) {
+                JobStatus job = it.next();
+                if (!job.hasDeadlineConstraint()) {
+                    continue;
+                }
+
+                if (evaluateDeadlineConstraint(job, nowElapsedMillis)) {
+                    if (job.isReady()) {
+                        // If the job still isn't ready, there's no point trying to rush the
+                        // Scheduler.
+                        mStateChangedListener.onRunJobNow(job);
+                    }
+                    it.remove();
+                } else {  // Sorted by expiry time, so take the next one and stop.
+                    if (!wouldBeReadyWithConstraintLocked(job, JobStatus.CONSTRAINT_DEADLINE)) {
+                        if (DEBUG) {
+                            Slog.i(TAG,
+                                    "Skipping " + job + " because deadline won't make it ready.");
+                        }
+                        continue;
+                    }
+                    nextExpiryTime = job.getLatestRunTimeElapsed();
+                    nextExpiryUid = job.getSourceUid();
+                    nextExpiryPackageName = job.getSourcePackageName();
+                    break;
+                }
+            }
+            setDeadlineExpiredAlarmLocked(nextExpiryTime,
+                    deriveWorkSource(nextExpiryUid, nextExpiryPackageName));
+        }
+    }
+
+    /** @return true if the job's deadline constraint is satisfied */
+    private boolean evaluateDeadlineConstraint(JobStatus job, long nowElapsedMillis) {
+        final long jobDeadline = job.getLatestRunTimeElapsed();
+
+        if (jobDeadline <= nowElapsedMillis) {
+            if (job.hasTimingDelayConstraint()) {
+                job.setTimingDelayConstraintSatisfied(true);
+            }
+            job.setDeadlineConstraintSatisfied(true);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Handles alarm that notifies us that a job's delay has expired. Iterates through the list of
+     * tracked jobs and marks them as ready as appropriate.
+     */
+    @VisibleForTesting
+    void checkExpiredDelaysAndResetAlarm() {
+        synchronized (mLock) {
+            final long nowElapsedMillis = sElapsedRealtimeClock.millis();
+            long nextDelayTime = Long.MAX_VALUE;
+            int nextDelayUid = 0;
+            String nextDelayPackageName = null;
+            boolean ready = false;
+            Iterator<JobStatus> it = mTrackedJobs.iterator();
+            while (it.hasNext()) {
+                final JobStatus job = it.next();
+                if (!job.hasTimingDelayConstraint()) {
+                    continue;
+                }
+                if (evaluateTimingDelayConstraint(job, nowElapsedMillis)) {
+                    if (canStopTrackingJobLocked(job)) {
+                        it.remove();
+                    }
+                    if (job.isReady()) {
+                        ready = true;
+                    }
+                } else {
+                    if (!wouldBeReadyWithConstraintLocked(job, JobStatus.CONSTRAINT_TIMING_DELAY)) {
+                        if (DEBUG) {
+                            Slog.i(TAG,
+                                    "Skipping " + job + " because delay won't make it ready.");
+                        }
+                        continue;
+                    }
+                    // If this job still doesn't have its delay constraint satisfied,
+                    // then see if it is the next upcoming delay time for the alarm.
+                    final long jobDelayTime = job.getEarliestRunTime();
+                    if (nextDelayTime > jobDelayTime) {
+                        nextDelayTime = jobDelayTime;
+                        nextDelayUid = job.getSourceUid();
+                        nextDelayPackageName = job.getSourcePackageName();
+                    }
+                }
+            }
+            if (ready) {
+                mStateChangedListener.onControllerStateChanged();
+            }
+            setDelayExpiredAlarmLocked(nextDelayTime,
+                    deriveWorkSource(nextDelayUid, nextDelayPackageName));
+        }
+    }
+
+    private WorkSource deriveWorkSource(int uid, @Nullable String packageName) {
+        if (mChainedAttributionEnabled) {
+            WorkSource ws = new WorkSource();
+            ws.createWorkChain()
+                    .addNode(uid, packageName)
+                    .addNode(Process.SYSTEM_UID, "JobScheduler");
+            return ws;
+        } else {
+            return packageName == null ? new WorkSource(uid) : new WorkSource(uid, packageName);
+        }
+    }
+
+    /** @return true if the job's delay constraint is satisfied */
+    private boolean evaluateTimingDelayConstraint(JobStatus job, long nowElapsedMillis) {
+        final long jobDelayTime = job.getEarliestRunTime();
+        if (jobDelayTime <= nowElapsedMillis) {
+            job.setTimingDelayConstraintSatisfied(true);
+            return true;
+        }
+        return false;
+    }
+
+    private void maybeUpdateDelayAlarmLocked(long delayExpiredElapsed, WorkSource ws) {
+        if (delayExpiredElapsed < mNextDelayExpiredElapsedMillis) {
+            setDelayExpiredAlarmLocked(delayExpiredElapsed, ws);
+        }
+    }
+
+    private void maybeUpdateDeadlineAlarmLocked(long deadlineExpiredElapsed, WorkSource ws) {
+        if (deadlineExpiredElapsed < mNextJobExpiredElapsedMillis) {
+            setDeadlineExpiredAlarmLocked(deadlineExpiredElapsed, ws);
+        }
+    }
+
+    /**
+     * Set an alarm with the {@link android.app.AlarmManager} for the next time at which a job's
+     * delay will expire.
+     * This alarm <b>will</b> wake up the phone.
+     */
+    private void setDelayExpiredAlarmLocked(long alarmTimeElapsedMillis, WorkSource ws) {
+        alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
+        if (mNextDelayExpiredElapsedMillis == alarmTimeElapsedMillis) {
+            return;
+        }
+        mNextDelayExpiredElapsedMillis = alarmTimeElapsedMillis;
+        updateAlarmWithListenerLocked(DELAY_TAG, mNextDelayExpiredListener,
+                mNextDelayExpiredElapsedMillis, ws);
+    }
+
+    /**
+     * Set an alarm with the {@link android.app.AlarmManager} for the next time at which a job's
+     * deadline will expire.
+     * This alarm <b>will</b> wake up the phone.
+     */
+    private void setDeadlineExpiredAlarmLocked(long alarmTimeElapsedMillis, WorkSource ws) {
+        alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
+        if (mNextJobExpiredElapsedMillis == alarmTimeElapsedMillis) {
+            return;
+        }
+        mNextJobExpiredElapsedMillis = alarmTimeElapsedMillis;
+        updateAlarmWithListenerLocked(DEADLINE_TAG, mDeadlineExpiredListener,
+                mNextJobExpiredElapsedMillis, ws);
+    }
+
+    private long maybeAdjustAlarmTime(long proposedAlarmTimeElapsedMillis) {
+        return Math.max(proposedAlarmTimeElapsedMillis, sElapsedRealtimeClock.millis());
+    }
+
+    private void updateAlarmWithListenerLocked(String tag, OnAlarmListener listener,
+            long alarmTimeElapsed, WorkSource ws) {
+        ensureAlarmServiceLocked();
+        if (alarmTimeElapsed == Long.MAX_VALUE) {
+            mAlarmService.cancel(listener);
+        } else {
+            if (DEBUG) {
+                Slog.d(TAG, "Setting " + tag + " for: " + alarmTimeElapsed);
+            }
+            mAlarmService.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTimeElapsed,
+                    AlarmManager.WINDOW_HEURISTIC, 0, tag, listener, null, ws);
+        }
+    }
+
+    // Job/delay expiration alarm handling
+
+    private final OnAlarmListener mDeadlineExpiredListener = new OnAlarmListener() {
+        @Override
+        public void onAlarm() {
+            if (DEBUG) {
+                Slog.d(TAG, "Deadline-expired alarm fired");
+            }
+            checkExpiredDeadlinesAndResetAlarm();
+        }
+    };
+
+    private final OnAlarmListener mNextDelayExpiredListener = new OnAlarmListener() {
+        @Override
+        public void onAlarm() {
+            if (DEBUG) {
+                Slog.d(TAG, "Delay-expired alarm fired");
+            }
+            checkExpiredDelaysAndResetAlarm();
+        }
+    };
+
+    @VisibleForTesting
+    void recheckAlarmsLocked() {
+        checkExpiredDeadlinesAndResetAlarm();
+        checkExpiredDelaysAndResetAlarm();
+    }
+
+    @Override
+    public void dumpControllerStateLocked(IndentingPrintWriter pw,
+            Predicate<JobStatus> predicate) {
+        final long nowElapsed = sElapsedRealtimeClock.millis();
+        pw.println("Elapsed clock: " + nowElapsed);
+
+        pw.print("Next delay alarm in ");
+        TimeUtils.formatDuration(mNextDelayExpiredElapsedMillis, nowElapsed, pw);
+        pw.println();
+        pw.print("Next deadline alarm in ");
+        TimeUtils.formatDuration(mNextJobExpiredElapsedMillis, nowElapsed, pw);
+        pw.println();
+        pw.println();
+
+        for (JobStatus ts : mTrackedJobs) {
+            if (!predicate.test(ts)) {
+                continue;
+            }
+            pw.print("#");
+            ts.printUniqueId(pw);
+            pw.print(" from ");
+            UserHandle.formatUid(pw, ts.getSourceUid());
+            pw.print(": Delay=");
+            if (ts.hasTimingDelayConstraint()) {
+                TimeUtils.formatDuration(ts.getEarliestRunTime(), nowElapsed, pw);
+            } else {
+                pw.print("N/A");
+            }
+            pw.print(", Deadline=");
+            if (ts.hasDeadlineConstraint()) {
+                TimeUtils.formatDuration(ts.getLatestRunTimeElapsed(), nowElapsed, pw);
+            } else {
+                pw.print("N/A");
+            }
+            pw.println();
+        }
+    }
+
+    @Override
+    public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
+            Predicate<JobStatus> predicate) {
+        final long token = proto.start(fieldId);
+        final long mToken = proto.start(StateControllerProto.TIME);
+
+        final long nowElapsed = sElapsedRealtimeClock.millis();
+        proto.write(StateControllerProto.TimeController.NOW_ELAPSED_REALTIME, nowElapsed);
+        proto.write(StateControllerProto.TimeController.TIME_UNTIL_NEXT_DELAY_ALARM_MS,
+                mNextDelayExpiredElapsedMillis - nowElapsed);
+        proto.write(StateControllerProto.TimeController.TIME_UNTIL_NEXT_DEADLINE_ALARM_MS,
+                mNextJobExpiredElapsedMillis - nowElapsed);
+
+        for (JobStatus ts : mTrackedJobs) {
+            if (!predicate.test(ts)) {
+                continue;
+            }
+            final long tsToken = proto.start(StateControllerProto.TimeController.TRACKED_JOBS);
+            ts.writeToShortProto(proto, StateControllerProto.TimeController.TrackedJob.INFO);
+
+            proto.write(StateControllerProto.TimeController.TrackedJob.HAS_TIMING_DELAY_CONSTRAINT,
+                    ts.hasTimingDelayConstraint());
+            proto.write(StateControllerProto.TimeController.TrackedJob.DELAY_TIME_REMAINING_MS,
+                    ts.getEarliestRunTime() - nowElapsed);
+
+            proto.write(StateControllerProto.TimeController.TrackedJob.HAS_DEADLINE_CONSTRAINT,
+                    ts.hasDeadlineConstraint());
+            proto.write(StateControllerProto.TimeController.TrackedJob.TIME_REMAINING_UNTIL_DEADLINE_MS,
+                    ts.getLatestRunTimeElapsed() - nowElapsed);
+
+            proto.end(tsToken);
+        }
+
+        proto.end(mToken);
+        proto.end(token);
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
new file mode 100644
index 0000000..82c33f5
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers.idle;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.server.am.ActivityManagerService;
+import com.android.server.job.JobSchedulerService;
+
+import java.io.PrintWriter;
+
+public final class CarIdlenessTracker extends BroadcastReceiver implements IdlenessTracker {
+    private static final String TAG = "JobScheduler.CarIdlenessTracker";
+    private static final boolean DEBUG = JobSchedulerService.DEBUG
+            || Log.isLoggable(TAG, Log.DEBUG);
+
+    public static final String ACTION_GARAGE_MODE_ON =
+            "com.android.server.jobscheduler.GARAGE_MODE_ON";
+    public static final String ACTION_GARAGE_MODE_OFF =
+            "com.android.server.jobscheduler.GARAGE_MODE_OFF";
+
+    public static final String ACTION_FORCE_IDLE = "com.android.server.jobscheduler.FORCE_IDLE";
+    public static final String ACTION_UNFORCE_IDLE = "com.android.server.jobscheduler.UNFORCE_IDLE";
+
+    // After construction, mutations of idle/screen-on state will only happen
+    // on the main looper thread, either in onReceive() or in an alarm callback.
+    private boolean mIdle;
+    private boolean mGarageModeOn;
+    private boolean mForced;
+    private IdlenessListener mIdleListener;
+
+    public CarIdlenessTracker() {
+        // At boot we presume that the user has just "interacted" with the
+        // device in some meaningful way.
+        mIdle = false;
+        mGarageModeOn = false;
+        mForced = false;
+    }
+
+    @Override
+    public boolean isIdle() {
+        return mIdle;
+    }
+
+    @Override
+    public void startTracking(Context context, IdlenessListener listener) {
+        mIdleListener = listener;
+
+        IntentFilter filter = new IntentFilter();
+
+        // Screen state
+        filter.addAction(Intent.ACTION_SCREEN_ON);
+
+        // State of GarageMode
+        filter.addAction(ACTION_GARAGE_MODE_ON);
+        filter.addAction(ACTION_GARAGE_MODE_OFF);
+
+        // Debugging/instrumentation
+        filter.addAction(ACTION_FORCE_IDLE);
+        filter.addAction(ACTION_UNFORCE_IDLE);
+        filter.addAction(ActivityManagerService.ACTION_TRIGGER_IDLE);
+
+        context.registerReceiver(this, filter);
+    }
+
+    @Override
+    public void dump(PrintWriter pw) {
+        pw.print("  mIdle: "); pw.println(mIdle);
+        pw.print("  mGarageModeOn: "); pw.println(mGarageModeOn);
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final String action = intent.getAction();
+        logIfDebug("Received action: " + action);
+
+        // Check for forced actions
+        if (action.equals(ACTION_FORCE_IDLE)) {
+            logIfDebug("Forcing idle...");
+            setForceIdleState(true);
+        } else if (action.equals(ACTION_UNFORCE_IDLE)) {
+            logIfDebug("Unforcing idle...");
+            setForceIdleState(false);
+        } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
+            logIfDebug("Screen is on...");
+            handleScreenOn();
+        } else if (action.equals(ACTION_GARAGE_MODE_ON)) {
+            logIfDebug("GarageMode is on...");
+            mGarageModeOn = true;
+            updateIdlenessState();
+        } else if (action.equals(ACTION_GARAGE_MODE_OFF)) {
+            logIfDebug("GarageMode is off...");
+            mGarageModeOn = false;
+            updateIdlenessState();
+        } else if (action.equals(ActivityManagerService.ACTION_TRIGGER_IDLE)) {
+            if (!mGarageModeOn) {
+                logIfDebug("Idle trigger fired...");
+                triggerIdlenessOnce();
+            } else {
+                logIfDebug("TRIGGER_IDLE received but not changing state; idle="
+                        + mIdle + " screen=" + mGarageModeOn);
+            }
+        }
+    }
+
+    private void setForceIdleState(boolean forced) {
+        mForced = forced;
+        updateIdlenessState();
+    }
+
+    private void updateIdlenessState() {
+        final boolean newState = (mForced || mGarageModeOn);
+        if (mIdle != newState) {
+            // State of idleness changed. Notifying idleness controller
+            logIfDebug("Device idleness changed. New idle=" + newState);
+            mIdle = newState;
+            mIdleListener.reportNewIdleState(mIdle);
+        } else {
+            // Nothing changed, device idleness is in the same state as new state
+            logIfDebug("Device idleness is the same. Current idle=" + newState);
+        }
+    }
+
+    private void triggerIdlenessOnce() {
+        // This is simply triggering idleness once until some constraint will switch it back off
+        if (mIdle) {
+            // Already in idle state. Nothing to do
+            logIfDebug("Device is already idle");
+        } else {
+            // Going idle once
+            logIfDebug("Device is going idle once");
+            mIdle = true;
+            mIdleListener.reportNewIdleState(mIdle);
+        }
+    }
+
+    private void handleScreenOn() {
+        if (mForced || mGarageModeOn) {
+            // Even though screen is on, the device remains idle
+            logIfDebug("Screen is on, but device cannot exit idle");
+        } else if (mIdle) {
+            // Exiting idle
+            logIfDebug("Device is exiting idle");
+            mIdle = false;
+        } else {
+            // Already in non-idle state. Nothing to do
+            logIfDebug("Device is already non-idle");
+        }
+    }
+
+    private static void logIfDebug(String msg) {
+        if (DEBUG) {
+            Slog.v(TAG, msg);
+        }
+    }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
new file mode 100644
index 0000000..a85bd40
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers.idle;
+
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
+import android.app.AlarmManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+import android.util.Log;
+import android.util.Slog;
+import com.android.server.am.ActivityManagerService;
+import com.android.server.job.JobSchedulerService;
+
+import java.io.PrintWriter;
+
+public final class DeviceIdlenessTracker extends BroadcastReceiver implements IdlenessTracker {
+    private static final String TAG = "JobScheduler.DeviceIdlenessTracker";
+    private static final boolean DEBUG = JobSchedulerService.DEBUG
+            || Log.isLoggable(TAG, Log.DEBUG);
+
+    private AlarmManager mAlarm;
+
+    // After construction, mutations of idle/screen-on state will only happen
+    // on the main looper thread, either in onReceive() or in an alarm callback.
+    private long mInactivityIdleThreshold;
+    private long mIdleWindowSlop;
+    private boolean mIdle;
+    private boolean mScreenOn;
+    private boolean mDockIdle;
+    private IdlenessListener mIdleListener;
+
+    private AlarmManager.OnAlarmListener mIdleAlarmListener = () -> {
+        handleIdleTrigger();
+    };
+
+    public DeviceIdlenessTracker() {
+        // At boot we presume that the user has just "interacted" with the
+        // device in some meaningful way.
+        mIdle = false;
+        mScreenOn = true;
+        mDockIdle = false;
+    }
+
+    @Override
+    public boolean isIdle() {
+        return mIdle;
+    }
+
+    @Override
+    public void startTracking(Context context, IdlenessListener listener) {
+        mIdleListener = listener;
+        mInactivityIdleThreshold = context.getResources().getInteger(
+                com.android.internal.R.integer.config_jobSchedulerInactivityIdleThreshold);
+        mIdleWindowSlop = context.getResources().getInteger(
+                com.android.internal.R.integer.config_jobSchedulerIdleWindowSlop);
+        mAlarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+
+        IntentFilter filter = new IntentFilter();
+
+        // Screen state
+        filter.addAction(Intent.ACTION_SCREEN_ON);
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
+
+        // Dreaming state
+        filter.addAction(Intent.ACTION_DREAMING_STARTED);
+        filter.addAction(Intent.ACTION_DREAMING_STOPPED);
+
+        // Debugging/instrumentation
+        filter.addAction(ActivityManagerService.ACTION_TRIGGER_IDLE);
+
+        // Wireless charging dock state
+        filter.addAction(Intent.ACTION_DOCK_IDLE);
+        filter.addAction(Intent.ACTION_DOCK_ACTIVE);
+
+        context.registerReceiver(this, filter);
+    }
+
+    @Override
+    public void dump(PrintWriter pw) {
+        pw.print("  mIdle: "); pw.println(mIdle);
+        pw.print("  mScreenOn: "); pw.println(mScreenOn);
+        pw.print("  mDockIdle: "); pw.println(mDockIdle);
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final String action = intent.getAction();
+        if (action.equals(Intent.ACTION_SCREEN_ON)
+                || action.equals(Intent.ACTION_DREAMING_STOPPED)
+                || action.equals(Intent.ACTION_DOCK_ACTIVE)) {
+            if (action.equals(Intent.ACTION_DOCK_ACTIVE)) {
+                if (!mScreenOn) {
+                    // Ignore this intent during screen off
+                    return;
+                } else {
+                    mDockIdle = false;
+                }
+            } else {
+                mScreenOn = true;
+                mDockIdle = false;
+            }
+            if (DEBUG) {
+                Slog.v(TAG,"exiting idle : " + action);
+            }
+            //cancel the alarm
+            mAlarm.cancel(mIdleAlarmListener);
+            if (mIdle) {
+            // possible transition to not-idle
+                mIdle = false;
+                mIdleListener.reportNewIdleState(mIdle);
+            }
+        } else if (action.equals(Intent.ACTION_SCREEN_OFF)
+                || action.equals(Intent.ACTION_DREAMING_STARTED)
+                || action.equals(Intent.ACTION_DOCK_IDLE)) {
+            // when the screen goes off or dreaming starts or wireless charging dock in idle,
+            // we schedule the alarm that will tell us when we have decided the device is
+            // truly idle.
+            if (action.equals(Intent.ACTION_DOCK_IDLE)) {
+                if (!mScreenOn) {
+                    // Ignore this intent during screen off
+                    return;
+                } else {
+                    mDockIdle = true;
+                }
+            } else {
+                mScreenOn = false;
+                mDockIdle = false;
+            }
+            final long nowElapsed = sElapsedRealtimeClock.millis();
+            final long when = nowElapsed + mInactivityIdleThreshold;
+            if (DEBUG) {
+                Slog.v(TAG, "Scheduling idle : " + action + " now:" + nowElapsed + " when="
+                        + when);
+            }
+            mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                    when, mIdleWindowSlop, "JS idleness", mIdleAlarmListener, null);
+        } else if (action.equals(ActivityManagerService.ACTION_TRIGGER_IDLE)) {
+            handleIdleTrigger();
+        }
+    }
+
+    private void handleIdleTrigger() {
+        // idle time starts now. Do not set mIdle if screen is on.
+        if (!mIdle && (!mScreenOn || mDockIdle)) {
+            if (DEBUG) {
+                Slog.v(TAG, "Idle trigger fired @ " + sElapsedRealtimeClock.millis());
+            }
+            mIdle = true;
+            mIdleListener.reportNewIdleState(mIdle);
+        } else {
+            if (DEBUG) {
+                Slog.v(TAG, "TRIGGER_IDLE received but not changing state; idle="
+                        + mIdle + " screen=" + mScreenOn);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessListener.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessListener.java
new file mode 100644
index 0000000..7ffd7cd
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessListener.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers.idle;
+
+/**
+ * Interface through which an IdlenessTracker informs the job scheduler of
+ * changes in the device's inactivity state.
+ */
+public interface IdlenessListener {
+    /**
+     * Tell the job scheduler that the device's idle state has changed.
+     *
+     * @param deviceIsIdle {@code true} to indicate that the device is now considered
+     * to be idle; {@code false} to indicate that the device is now being interacted with,
+     * so jobs with idle constraints should not be run.
+     */
+    void reportNewIdleState(boolean deviceIsIdle);
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessTracker.java
new file mode 100644
index 0000000..09f01c2
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessTracker.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job.controllers.idle;
+
+import android.content.Context;
+
+import java.io.PrintWriter;
+
+public interface IdlenessTracker {
+    /**
+     * One-time initialization:  this method is called once, after construction of
+     * the IdlenessTracker instance.  This is when the tracker should actually begin
+     * monitoring whatever signals it consumes in deciding when the device is in a
+     * non-interacting state.  When the idle state changes thereafter, the given
+     * listener must be called to report the new state.
+     */
+    void startTracking(Context context, IdlenessListener listener);
+
+    /**
+     * Report whether the device is currently considered "idle" for purposes of
+     * running scheduled jobs with idleness constraints.
+     *
+     * @return {@code true} if the job scheduler should consider idleness
+     * constraints to be currently satisfied; {@code false} otherwise.
+     */
+    boolean isIdle();
+
+    /**
+     * Dump useful information about tracked idleness-related state in plaintext.
+     */
+    void dump(PrintWriter pw);
+}
