13ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla/*
23ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla * Copyright (C) 2017 The Android Open Source Project
33ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla *
43ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla * Licensed under the Apache License, Version 2.0 (the "License");
53ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla * you may not use this file except in compliance with the License.
63ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla * You may obtain a copy of the License at
73ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla *
83ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla *      http://www.apache.org/licenses/LICENSE-2.0
93ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla *
103ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla * Unless required by applicable law or agreed to in writing, software
113ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla * distributed under the License is distributed on an "AS IS" BASIS,
123ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla * See the License for the specific language governing permissions and
143ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla * limitations under the License
153ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla */
163ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
173ac1daac4044c70ad4ee673214074306de499a18Suprabh Shuklapackage com.android.server.job.controllers;
183ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
199be0140c1474dfd23d46121c51e636040a8080dfMakoto Onukiimport android.os.SystemClock;
203ac1daac4044c70ad4ee673214074306de499a18Suprabh Shuklaimport android.os.UserHandle;
2101bb530242eea8ff32fa3e0db70cbb40951fce24Jeff Sharkeyimport android.util.Log;
223ac1daac4044c70ad4ee673214074306de499a18Suprabh Shuklaimport android.util.Slog;
2385f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adamsimport android.util.proto.ProtoOutputStream;
243ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
25fee8c7b42aeebf3a11b978ee657803da0dfa8147Jeff Sharkeyimport com.android.internal.util.IndentingPrintWriter;
26e491821c5f28440a664bf880682953d8284ad4eeMakoto Onukiimport com.android.internal.util.Preconditions;
27e491821c5f28440a664bf880682953d8284ad4eeMakoto Onukiimport com.android.server.AppStateTracker;
28e491821c5f28440a664bf880682953d8284ad4eeMakoto Onukiimport com.android.server.AppStateTracker.Listener;
29e491821c5f28440a664bf880682953d8284ad4eeMakoto Onukiimport com.android.server.LocalServices;
303ac1daac4044c70ad4ee673214074306de499a18Suprabh Shuklaimport com.android.server.job.JobSchedulerService;
3120afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tateimport com.android.server.job.JobStore;
3285f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adamsimport com.android.server.job.StateControllerProto;
3385f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adamsimport com.android.server.job.StateControllerProto.BackgroundJobsController.TrackedJob;
343ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
35fee8c7b42aeebf3a11b978ee657803da0dfa8147Jeff Sharkeyimport java.util.function.Consumer;
36fee8c7b42aeebf3a11b978ee657803da0dfa8147Jeff Sharkeyimport java.util.function.Predicate;
373ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
3820afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate/**
3920afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate * Tracks the following pieces of JobStatus state:
4020afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate *
4120afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate * - the CONSTRAINT_BACKGROUND_NOT_RESTRICTED general constraint bit, which
4220afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate *    is used to selectively permit battery-saver exempted jobs to run; and
4320afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate *
4420afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate * - the uid-active boolean state expressed by the AppStateTracker.  Jobs in 'active'
4520afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate *    uids are inherently eligible to run jobs regardless of the uid's standby bucket.
4620afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate */
473ac1daac4044c70ad4ee673214074306de499a18Suprabh Shuklapublic final class BackgroundJobsController extends StateController {
4801bb530242eea8ff32fa3e0db70cbb40951fce24Jeff Sharkey    private static final String TAG = "JobScheduler.Background";
4901bb530242eea8ff32fa3e0db70cbb40951fce24Jeff Sharkey    private static final boolean DEBUG = JobSchedulerService.DEBUG
5001bb530242eea8ff32fa3e0db70cbb40951fce24Jeff Sharkey            || Log.isLoggable(TAG, Log.DEBUG);
513ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
5220afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate    // Tri-state about possible "is this uid 'active'?" knowledge
5320afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate    static final int UNKNOWN = 0;
5420afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate    static final int KNOWN_ACTIVE = 1;
5520afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate    static final int KNOWN_INACTIVE = 2;
5620afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate
57e491821c5f28440a664bf880682953d8284ad4eeMakoto Onuki    private final AppStateTracker mAppStateTracker;
583ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
59ac2e8efa4395d30ebeda5885dcb7cb679f793d4cJeff Sharkey    public BackgroundJobsController(JobSchedulerService service) {
60ac2e8efa4395d30ebeda5885dcb7cb679f793d4cJeff Sharkey        super(service);
613ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
62e491821c5f28440a664bf880682953d8284ad4eeMakoto Onuki        mAppStateTracker = Preconditions.checkNotNull(
63e491821c5f28440a664bf880682953d8284ad4eeMakoto Onuki                LocalServices.getService(AppStateTracker.class));
64e491821c5f28440a664bf880682953d8284ad4eeMakoto Onuki        mAppStateTracker.addListener(mForceAppStandbyListener);
653ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla    }
663ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
673ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla    @Override
683ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla    public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
6920afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        updateSingleJobRestrictionLocked(jobStatus, UNKNOWN);
703ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla    }
713ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
723ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla    @Override
733ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla    public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
743ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla            boolean forUpdate) {
753ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla    }
763ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
773ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla    @Override
78fee8c7b42aeebf3a11b978ee657803da0dfa8147Jeff Sharkey    public void dumpControllerStateLocked(final IndentingPrintWriter pw,
79fee8c7b42aeebf3a11b978ee657803da0dfa8147Jeff Sharkey            final Predicate<JobStatus> predicate) {
80fee8c7b42aeebf3a11b978ee657803da0dfa8147Jeff Sharkey        mAppStateTracker.dump(pw);
81fee8c7b42aeebf3a11b978ee657803da0dfa8147Jeff Sharkey        pw.println();
829be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki
83ac2e8efa4395d30ebeda5885dcb7cb679f793d4cJeff Sharkey        mService.getJobStore().forEachJob(predicate, (jobStatus) -> {
849be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki            final int uid = jobStatus.getSourceUid();
8585f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams            final String sourcePkg = jobStatus.getSourcePackageName();
86fee8c7b42aeebf3a11b978ee657803da0dfa8147Jeff Sharkey            pw.print("#");
879be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki            jobStatus.printUniqueId(pw);
889be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki            pw.print(" from ");
899be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki            UserHandle.formatUid(pw, uid);
90e491821c5f28440a664bf880682953d8284ad4eeMakoto Onuki            pw.print(mAppStateTracker.isUidActive(uid) ? " active" : " idle");
91e491821c5f28440a664bf880682953d8284ad4eeMakoto Onuki            if (mAppStateTracker.isUidPowerSaveWhitelisted(uid) ||
92e491821c5f28440a664bf880682953d8284ad4eeMakoto Onuki                    mAppStateTracker.isUidTempPowerSaveWhitelisted(uid)) {
939be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki                pw.print(", whitelisted");
949be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki            }
959be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki            pw.print(": ");
9685f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams            pw.print(sourcePkg);
979be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki
982206af39a28e8ef9d242015f791dc8abb6c3b3ccMakoto Onuki            pw.print(" [RUN_ANY_IN_BACKGROUND ");
99e491821c5f28440a664bf880682953d8284ad4eeMakoto Onuki            pw.print(mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(uid, sourcePkg)
1002206af39a28e8ef9d242015f791dc8abb6c3b3ccMakoto Onuki                    ? "allowed]" : "disallowed]");
1019be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki
1029be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki            if ((jobStatus.satisfiedConstraints
1039be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki                    & JobStatus.CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0) {
1049be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki                pw.println(" RUNNABLE");
1059be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki            } else {
1069be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki                pw.println(" WAITING");
1073ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla            }
1083ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla        });
1093ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla    }
1103ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
11185f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams    @Override
112fee8c7b42aeebf3a11b978ee657803da0dfa8147Jeff Sharkey    public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
113fee8c7b42aeebf3a11b978ee657803da0dfa8147Jeff Sharkey            Predicate<JobStatus> predicate) {
11485f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams        final long token = proto.start(fieldId);
11585f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams        final long mToken = proto.start(StateControllerProto.BACKGROUND);
11685f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams
117e491821c5f28440a664bf880682953d8284ad4eeMakoto Onuki        mAppStateTracker.dumpProto(proto,
11885f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams                StateControllerProto.BackgroundJobsController.FORCE_APP_STANDBY_TRACKER);
11985f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams
120ac2e8efa4395d30ebeda5885dcb7cb679f793d4cJeff Sharkey        mService.getJobStore().forEachJob(predicate, (jobStatus) -> {
12185f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams            final long jsToken =
12285f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams                    proto.start(StateControllerProto.BackgroundJobsController.TRACKED_JOBS);
12385f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams
12485f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams            jobStatus.writeToShortProto(proto,
12585f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams                    TrackedJob.INFO);
12685f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams            final int sourceUid = jobStatus.getSourceUid();
12785f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams            proto.write(TrackedJob.SOURCE_UID, sourceUid);
12885f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams            final String sourcePkg = jobStatus.getSourcePackageName();
12985f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams            proto.write(TrackedJob.SOURCE_PACKAGE_NAME, sourcePkg);
13085f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams
13185f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams            proto.write(TrackedJob.IS_IN_FOREGROUND,
132e491821c5f28440a664bf880682953d8284ad4eeMakoto Onuki                    mAppStateTracker.isUidActive(sourceUid));
13385f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams            proto.write(TrackedJob.IS_WHITELISTED,
134e491821c5f28440a664bf880682953d8284ad4eeMakoto Onuki                    mAppStateTracker.isUidPowerSaveWhitelisted(sourceUid) ||
135e491821c5f28440a664bf880682953d8284ad4eeMakoto Onuki                    mAppStateTracker.isUidTempPowerSaveWhitelisted(sourceUid));
13685f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams
13785f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams            proto.write(
13885f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams                    TrackedJob.CAN_RUN_ANY_IN_BACKGROUND,
139e491821c5f28440a664bf880682953d8284ad4eeMakoto Onuki                    mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(
14085f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams                            sourceUid, sourcePkg));
14185f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams
14285f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams            proto.write(
14385f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams                    TrackedJob.ARE_CONSTRAINTS_SATISFIED,
14485f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams                    (jobStatus.satisfiedConstraints &
14585f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams                            JobStatus.CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0);
14685f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams
14785f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams            proto.end(jsToken);
14885f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams        });
14985f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams
15085f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams        proto.end(mToken);
15185f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams        proto.end(token);
15285f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams    }
15385f2fbcb1fc3277ea825ec3dc52f636b47302425Kweku Adams
1549be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki    private void updateAllJobRestrictionsLocked() {
15520afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        updateJobRestrictionsLocked(/*filterUid=*/ -1, UNKNOWN);
1563ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla    }
1573ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
15820afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate    private void updateJobRestrictionsForUidLocked(int uid, boolean isActive) {
15920afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        updateJobRestrictionsLocked(uid, (isActive) ? KNOWN_ACTIVE : KNOWN_INACTIVE);
1603ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla    }
1613ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
16220afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate    private void updateJobRestrictionsLocked(int filterUid, int newActiveState) {
16320afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        final UpdateJobFunctor updateTrackedJobs = new UpdateJobFunctor(newActiveState);
1649be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki
1659be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki        final long start = DEBUG ? SystemClock.elapsedRealtimeNanos() : 0;
1669be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki
16720afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        final JobStore store = mService.getJobStore();
16820afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        if (filterUid > 0) {
16920afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate            store.forEachJobForSourceUid(filterUid, updateTrackedJobs);
17020afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        } else {
17120afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate            store.forEachJob(updateTrackedJobs);
17220afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        }
1739be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki
1749be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki        final long time = DEBUG ? (SystemClock.elapsedRealtimeNanos() - start) : 0;
1759be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki        if (DEBUG) {
17601bb530242eea8ff32fa3e0db70cbb40951fce24Jeff Sharkey            Slog.d(TAG, String.format(
1779be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki                    "Job status updated: %d/%d checked/total jobs, %d us",
1789be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki                    updateTrackedJobs.mCheckedCount,
1799be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki                    updateTrackedJobs.mTotalCount,
1809be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki                    (time / 1000)
1819be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki                    ));
1823ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla        }
1833ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
1849be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki        if (updateTrackedJobs.mChanged) {
1859be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki            mStateChangedListener.onControllerStateChanged();
1863ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla        }
1873ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla    }
1883ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
18920afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate    boolean updateSingleJobRestrictionLocked(JobStatus jobStatus, int activeState) {
1903ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
1919be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki        final int uid = jobStatus.getSourceUid();
1929be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki        final String packageName = jobStatus.getSourcePackageName();
1939be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki
194e491821c5f28440a664bf880682953d8284ad4eeMakoto Onuki        final boolean canRun = !mAppStateTracker.areJobsRestricted(uid, packageName,
19515407846682b269e6b7fd0c24b84f709257fab5dMakoto Onuki                (jobStatus.getInternalFlags() & JobStatus.INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION)
19615407846682b269e6b7fd0c24b84f709257fab5dMakoto Onuki                        != 0);
1979be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki
19820afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        final boolean isActive;
19920afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        if (activeState == UNKNOWN) {
20020afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate            isActive = mAppStateTracker.isUidActive(uid);
20120afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        } else {
20220afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate            isActive = (activeState == KNOWN_ACTIVE);
20320afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        }
20420afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        boolean didChange = jobStatus.setBackgroundNotRestrictedConstraintSatisfied(canRun);
20520afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        didChange |= jobStatus.setUidActive(isActive);
20620afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        return didChange;
2073ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla    }
2083ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
209fee8c7b42aeebf3a11b978ee657803da0dfa8147Jeff Sharkey    private final class UpdateJobFunctor implements Consumer<JobStatus> {
21020afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        final int activeState;
2119be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki        boolean mChanged = false;
2129be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki        int mTotalCount = 0;
2139be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki        int mCheckedCount = 0;
2149be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki
21520afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        public UpdateJobFunctor(int newActiveState) {
21620afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate            activeState = newActiveState;
2173ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla        }
2183ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla
2193ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla        @Override
220fee8c7b42aeebf3a11b978ee657803da0dfa8147Jeff Sharkey        public void accept(JobStatus jobStatus) {
2219be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki            mTotalCount++;
2229be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki            mCheckedCount++;
22320afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate            if (updateSingleJobRestrictionLocked(jobStatus, activeState)) {
2249be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki                mChanged = true;
2253ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla            }
2263ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla        }
2273ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla    }
2289be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki
2299be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki    private final Listener mForceAppStandbyListener = new Listener() {
2309be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki        @Override
2312206af39a28e8ef9d242015f791dc8abb6c3b3ccMakoto Onuki        public void updateAllJobs() {
232998fb4e80e2edad9baf5c07432442b6418e2674cChristopher Tate            synchronized (mLock) {
233998fb4e80e2edad9baf5c07432442b6418e2674cChristopher Tate                updateAllJobRestrictionsLocked();
234998fb4e80e2edad9baf5c07432442b6418e2674cChristopher Tate            }
2352206af39a28e8ef9d242015f791dc8abb6c3b3ccMakoto Onuki        }
2362206af39a28e8ef9d242015f791dc8abb6c3b3ccMakoto Onuki
2372206af39a28e8ef9d242015f791dc8abb6c3b3ccMakoto Onuki        @Override
23820afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        public void updateJobsForUid(int uid, boolean isActive) {
239998fb4e80e2edad9baf5c07432442b6418e2674cChristopher Tate            synchronized (mLock) {
24020afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate                updateJobRestrictionsForUidLocked(uid, isActive);
241998fb4e80e2edad9baf5c07432442b6418e2674cChristopher Tate            }
2429be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki        }
2439be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki
2449be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki        @Override
24520afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate        public void updateJobsForUidPackage(int uid, String packageName, boolean isActive) {
246998fb4e80e2edad9baf5c07432442b6418e2674cChristopher Tate            synchronized (mLock) {
24720afddd2ed37c2c9c0214b382cc3edd6d4ee81a8Christopher Tate                updateJobRestrictionsForUidLocked(uid, isActive);
248998fb4e80e2edad9baf5c07432442b6418e2674cChristopher Tate            }
2499be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki        }
2509be0140c1474dfd23d46121c51e636040a8080dfMakoto Onuki    };
2513ac1daac4044c70ad4ee673214074306de499a18Suprabh Shukla}
252