blob: fc4015d0fdbe1a606a0e16cbc0e0f71c6045588c [file] [log] [blame]
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.server.job.controllers;
18
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070019import android.content.Context;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070020import android.os.IDeviceIdleController;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070021import android.os.ServiceManager;
Makoto Onuki9be01402017-11-10 13:22:26 -080022import android.os.SystemClock;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070023import android.os.UserHandle;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070024import android.util.Slog;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070025
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070026import com.android.internal.util.ArrayUtils;
Makoto Onuki9be01402017-11-10 13:22:26 -080027import com.android.server.ForceAppStandbyTracker;
28import com.android.server.ForceAppStandbyTracker.Listener;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070029import com.android.server.job.JobSchedulerService;
30import com.android.server.job.JobStore;
31
32import java.io.PrintWriter;
33
34public final class BackgroundJobsController extends StateController {
35
36 private static final String LOG_TAG = "BackgroundJobsController";
37 private static final boolean DEBUG = JobSchedulerService.DEBUG;
38
39 // Singleton factory
40 private static final Object sCreationLock = new Object();
41 private static volatile BackgroundJobsController sController;
42
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070043 private final JobSchedulerService mJobSchedulerService;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070044 private final IDeviceIdleController mDeviceIdleController;
45
Makoto Onuki9be01402017-11-10 13:22:26 -080046 private final ForceAppStandbyTracker mForceAppStandbyTracker;
47
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070048
49 public static BackgroundJobsController get(JobSchedulerService service) {
50 synchronized (sCreationLock) {
51 if (sController == null) {
52 sController = new BackgroundJobsController(service, service.getContext(),
53 service.getLock());
54 }
55 return sController;
56 }
57 }
58
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070059 private BackgroundJobsController(JobSchedulerService service, Context context, Object lock) {
60 super(service, context, lock);
61 mJobSchedulerService = service;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070062 mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
63 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
64
Makoto Onuki9be01402017-11-10 13:22:26 -080065 mForceAppStandbyTracker = ForceAppStandbyTracker.getInstance(context);
66
Makoto Onuki9be01402017-11-10 13:22:26 -080067 mForceAppStandbyTracker.addListener(mForceAppStandbyListener);
68 mForceAppStandbyTracker.start();
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070069 }
70
71 @Override
72 public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
Makoto Onuki9be01402017-11-10 13:22:26 -080073 updateSingleJobRestrictionLocked(jobStatus);
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070074 }
75
76 @Override
77 public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
78 boolean forUpdate) {
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -070079 }
80
81 @Override
82 public void dumpControllerStateLocked(final PrintWriter pw, final int filterUid) {
Suprabh Shuklaa78acfd2017-10-13 19:29:36 -070083 pw.println("BackgroundJobsController");
Makoto Onuki9be01402017-11-10 13:22:26 -080084
Makoto Onuki2206af32017-11-21 16:25:35 -080085 mForceAppStandbyTracker.dump(pw, "");
Makoto Onuki9be01402017-11-10 13:22:26 -080086
87 pw.println("Job state:");
88 mJobSchedulerService.getJobStore().forEachJob((jobStatus) -> {
89 if (!jobStatus.shouldDump(filterUid)) {
90 return;
91 }
92 final int uid = jobStatus.getSourceUid();
93 pw.print(" #");
94 jobStatus.printUniqueId(pw);
95 pw.print(" from ");
96 UserHandle.formatUid(pw, uid);
97 pw.print(mForceAppStandbyTracker.isInForeground(uid) ? " foreground" : " background");
Makoto Onuki2206af32017-11-21 16:25:35 -080098 if (mForceAppStandbyTracker.isUidPowerSaveWhitelisted(uid) ||
99 mForceAppStandbyTracker.isUidTempPowerSaveWhitelisted(uid)) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800100 pw.print(", whitelisted");
101 }
102 pw.print(": ");
103 pw.print(jobStatus.getSourcePackageName());
104
Makoto Onuki2206af32017-11-21 16:25:35 -0800105 pw.print(" [RUN_ANY_IN_BACKGROUND ");
Makoto Onuki9be01402017-11-10 13:22:26 -0800106 pw.print(mForceAppStandbyTracker.isRunAnyInBackgroundAppOpsAllowed(
Makoto Onuki2206af32017-11-21 16:25:35 -0800107 jobStatus.getSourceUid(), jobStatus.getSourcePackageName())
108 ? "allowed]" : "disallowed]");
Makoto Onuki9be01402017-11-10 13:22:26 -0800109
110 if ((jobStatus.satisfiedConstraints
111 & JobStatus.CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0) {
112 pw.println(" RUNNABLE");
113 } else {
114 pw.println(" WAITING");
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -0700115 }
116 });
117 }
118
Makoto Onuki9be01402017-11-10 13:22:26 -0800119 private void updateAllJobRestrictionsLocked() {
120 updateJobRestrictionsLocked(/*filterUid=*/ -1);
121 }
122
123 private void updateJobRestrictionsForUidLocked(int uid) {
124
125 // TODO Use forEachJobForSourceUid() once we have it.
126
127 updateJobRestrictionsLocked(/*filterUid=*/ uid);
128 }
129
130 private void updateJobRestrictionsLocked(int filterUid) {
131 final UpdateJobFunctor updateTrackedJobs =
132 new UpdateJobFunctor(filterUid);
133
134 final long start = DEBUG ? SystemClock.elapsedRealtimeNanos() : 0;
135
136 mJobSchedulerService.getJobStore().forEachJob(updateTrackedJobs);
137
138 final long time = DEBUG ? (SystemClock.elapsedRealtimeNanos() - start) : 0;
139 if (DEBUG) {
140 Slog.d(LOG_TAG, String.format(
141 "Job status updated: %d/%d checked/total jobs, %d us",
142 updateTrackedJobs.mCheckedCount,
143 updateTrackedJobs.mTotalCount,
144 (time / 1000)
145 ));
146 }
147
148 if (updateTrackedJobs.mChanged) {
149 mStateChangedListener.onControllerStateChanged();
150 }
151 }
152
Makoto Onuki9be01402017-11-10 13:22:26 -0800153 boolean updateSingleJobRestrictionLocked(JobStatus jobStatus) {
154
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -0700155 final int uid = jobStatus.getSourceUid();
Makoto Onuki9be01402017-11-10 13:22:26 -0800156 final String packageName = jobStatus.getSourcePackageName();
157
Makoto Onuki2206af32017-11-21 16:25:35 -0800158 final boolean canRun = !mForceAppStandbyTracker.areJobsRestricted(uid, packageName);
Makoto Onuki9be01402017-11-10 13:22:26 -0800159
160 return jobStatus.setBackgroundNotRestrictedConstraintSatisfied(canRun);
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -0700161 }
162
Makoto Onuki9be01402017-11-10 13:22:26 -0800163 private final class UpdateJobFunctor implements JobStore.JobStatusFunctor {
164 private final int mFilterUid;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -0700165
Makoto Onuki9be01402017-11-10 13:22:26 -0800166 boolean mChanged = false;
167 int mTotalCount = 0;
168 int mCheckedCount = 0;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -0700169
Makoto Onuki9be01402017-11-10 13:22:26 -0800170 UpdateJobFunctor(int filterUid) {
171 mFilterUid = filterUid;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -0700172 }
173
174 @Override
175 public void process(JobStatus jobStatus) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800176 mTotalCount++;
177 if ((mFilterUid > 0) && (mFilterUid != jobStatus.getSourceUid())) {
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -0700178 return;
179 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800180 mCheckedCount++;
181 if (updateSingleJobRestrictionLocked(jobStatus)) {
182 mChanged = true;
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -0700183 }
184 }
185 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800186
187 private final Listener mForceAppStandbyListener = new Listener() {
188 @Override
Makoto Onuki2206af32017-11-21 16:25:35 -0800189 public void updateAllJobs() {
190 updateAllJobRestrictionsLocked();
191 }
192
193 @Override
194 public void updateJobsForUid(int uid) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800195 updateJobRestrictionsForUidLocked(uid);
196 }
197
198 @Override
Makoto Onuki2206af32017-11-21 16:25:35 -0800199 public void updateJobsForUidPackage(int uid, String packageName) {
200 updateJobRestrictionsForUidLocked(uid);
Makoto Onuki9be01402017-11-10 13:22:26 -0800201 }
202 };
Suprabh Shukla3ac1daa2017-07-14 12:15:27 -0700203}