blob: 8776f3a9f6c81324e38af9561294c1fc900d8e89 [file] [log] [blame]
Makoto Onuki9be01402017-11-10 13:22:26 -08001/*
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 */
16package com.android.server;
17
18import android.annotation.NonNull;
Makoto Onuki9be01402017-11-10 13:22:26 -080019import android.app.ActivityManager;
20import android.app.AppOpsManager;
21import android.app.AppOpsManager.PackageOps;
Makoto Onuki2206af32017-11-21 16:25:35 -080022import android.app.IActivityManager;
Makoto Onuki9be01402017-11-10 13:22:26 -080023import android.app.IUidObserver;
Makoto Onuki2206af32017-11-21 16:25:35 -080024import android.content.BroadcastReceiver;
Makoto Onuki9be01402017-11-10 13:22:26 -080025import android.content.Context;
Makoto Onuki2206af32017-11-21 16:25:35 -080026import android.content.Intent;
27import android.content.IntentFilter;
Suprabh Shukla4deb8522018-01-08 16:27:10 -080028import android.database.ContentObserver;
Makoto Onuki9be01402017-11-10 13:22:26 -080029import android.os.Handler;
Makoto Onuki2206af32017-11-21 16:25:35 -080030import android.os.Looper;
31import android.os.Message;
Makoto Onuki9be01402017-11-10 13:22:26 -080032import android.os.PowerManager.ServiceType;
33import android.os.PowerManagerInternal;
34import android.os.RemoteException;
35import android.os.ServiceManager;
36import android.os.UserHandle;
Suprabh Shukla4deb8522018-01-08 16:27:10 -080037import android.provider.Settings;
Makoto Onuki9be01402017-11-10 13:22:26 -080038import android.util.ArraySet;
39import android.util.Pair;
Suprabh Shukla4deb8522018-01-08 16:27:10 -080040import android.util.Slog;
Makoto Onuki9be01402017-11-10 13:22:26 -080041import android.util.SparseBooleanArray;
Makoto Onuki2206af32017-11-21 16:25:35 -080042import android.util.proto.ProtoOutputStream;
Makoto Onuki9be01402017-11-10 13:22:26 -080043
44import com.android.internal.annotations.GuardedBy;
Makoto Onuki2206af32017-11-21 16:25:35 -080045import com.android.internal.annotations.VisibleForTesting;
Makoto Onuki9be01402017-11-10 13:22:26 -080046import com.android.internal.app.IAppOpsCallback;
47import com.android.internal.app.IAppOpsService;
Makoto Onuki2206af32017-11-21 16:25:35 -080048import com.android.internal.util.ArrayUtils;
Makoto Onuki9be01402017-11-10 13:22:26 -080049import com.android.internal.util.Preconditions;
Makoto Onuki2206af32017-11-21 16:25:35 -080050import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrictedPackages;
Makoto Onuki9be01402017-11-10 13:22:26 -080051
Makoto Onuki2206af32017-11-21 16:25:35 -080052import java.io.PrintWriter;
53import java.util.Arrays;
Makoto Onuki9be01402017-11-10 13:22:26 -080054import java.util.List;
55
56/**
Makoto Onuki2206af32017-11-21 16:25:35 -080057 * Class to keep track of the information related to "force app standby", which includes:
58 * - OP_RUN_ANY_IN_BACKGROUND for each package
59 * - UID foreground state
60 * - User+system power save whitelist
61 * - Temporary power save whitelist
62 * - Global "force all apps standby" mode enforced by battery saver.
Makoto Onuki9be01402017-11-10 13:22:26 -080063 *
Makoto Onuki2206af32017-11-21 16:25:35 -080064 * TODO: In general, we can reduce the number of callbacks by checking all signals before sending
Suprabh Shukla4deb8522018-01-08 16:27:10 -080065 * each callback. For example, even when an UID comes into the foreground, if it wasn't
66 * originally restricted, then there's no need to send an event.
67 * Doing this would be error-prone, so we punt it for now, but we should revisit it later.
Makoto Onuki2206af32017-11-21 16:25:35 -080068 *
69 * Test:
Suprabh Shukla4deb8522018-01-08 16:27:10 -080070 * atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
Makoto Onuki9be01402017-11-10 13:22:26 -080071 */
72public class ForceAppStandbyTracker {
73 private static final String TAG = "ForceAppStandbyTracker";
Suprabh Shukla4deb8522018-01-08 16:27:10 -080074 private static final boolean DEBUG = false;
Makoto Onuki9be01402017-11-10 13:22:26 -080075
76 @GuardedBy("ForceAppStandbyTracker.class")
77 private static ForceAppStandbyTracker sInstance;
78
79 private final Object mLock = new Object();
80 private final Context mContext;
81
Makoto Onuki2206af32017-11-21 16:25:35 -080082 @VisibleForTesting
83 static final int TARGET_OP = AppOpsManager.OP_RUN_ANY_IN_BACKGROUND;
84
85 IActivityManager mIActivityManager;
Makoto Onuki9be01402017-11-10 13:22:26 -080086 AppOpsManager mAppOpsManager;
87 IAppOpsService mAppOpsService;
88 PowerManagerInternal mPowerManagerInternal;
89
Makoto Onuki2206af32017-11-21 16:25:35 -080090 private final MyHandler mHandler;
Makoto Onuki9be01402017-11-10 13:22:26 -080091
92 /**
93 * Pair of (uid (not user-id), packageName) with OP_RUN_ANY_IN_BACKGROUND *not* allowed.
94 */
95 @GuardedBy("mLock")
Makoto Onuki2206af32017-11-21 16:25:35 -080096 final ArraySet<Pair<Integer, String>> mRunAnyRestrictedPackages = new ArraySet<>();
Makoto Onuki9be01402017-11-10 13:22:26 -080097
98 @GuardedBy("mLock")
99 final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
100
101 @GuardedBy("mLock")
Makoto Onuki2206af32017-11-21 16:25:35 -0800102 private int[] mPowerWhitelistedAllAppIds = new int[0];
103
104 @GuardedBy("mLock")
105 private int[] mTempWhitelistedAppIds = mPowerWhitelistedAllAppIds;
106
107 @GuardedBy("mLock")
Makoto Onuki9be01402017-11-10 13:22:26 -0800108 final ArraySet<Listener> mListeners = new ArraySet<>();
109
110 @GuardedBy("mLock")
111 boolean mStarted;
112
113 @GuardedBy("mLock")
Makoto Onuki12391f22018-01-18 21:44:28 +0000114 boolean mForceAllAppsStandby; // True if device is in extreme battery saver mode
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800115
116 @GuardedBy("mLock")
Makoto Onuki12391f22018-01-18 21:44:28 +0000117 boolean mForcedAppStandbyEnabled; // True if the forced app standby feature is enabled
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800118
Makoto Onuki12391f22018-01-18 21:44:28 +0000119 private class FeatureFlagObserver extends ContentObserver {
120 FeatureFlagObserver() {
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800121 super(null);
122 }
123
124 void register() {
125 mContext.getContentResolver().registerContentObserver(
126 Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED),
127 false, this);
128 }
129
130 boolean isForcedAppStandbyEnabled() {
131 return Settings.Global.getInt(mContext.getContentResolver(),
132 Settings.Global.FORCED_APP_STANDBY_ENABLED, 1) == 1;
133 }
134
135 @Override
Makoto Onuki12391f22018-01-18 21:44:28 +0000136 public void onChange(boolean selfChange) {
137 final boolean enabled = isForcedAppStandbyEnabled();
138 synchronized (mLock) {
139 if (mForcedAppStandbyEnabled == enabled) {
140 return;
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800141 }
Makoto Onuki12391f22018-01-18 21:44:28 +0000142 mForcedAppStandbyEnabled = enabled;
143 if (DEBUG) {
144 Slog.d(TAG,
145 "Forced app standby feature flag changed: " + mForcedAppStandbyEnabled);
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800146 }
147 }
Makoto Onuki12391f22018-01-18 21:44:28 +0000148 mHandler.notifyFeatureFlagChanged();
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800149 }
150 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800151
152 public static abstract class Listener {
Makoto Onuki2206af32017-11-21 16:25:35 -0800153 /**
154 * This is called when the OP_RUN_ANY_IN_BACKGROUND appops changed for a package.
155 */
156 private void onRunAnyAppOpsChanged(ForceAppStandbyTracker sender,
157 int uid, @NonNull String packageName) {
158 updateJobsForUidPackage(uid, packageName);
159
160 if (!sender.areAlarmsRestricted(uid, packageName)) {
161 unblockAlarmsForUidPackage(uid, packageName);
162 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800163 }
164
Makoto Onuki2206af32017-11-21 16:25:35 -0800165 /**
166 * This is called when the foreground state changed for a UID.
167 */
168 private void onUidForegroundStateChanged(ForceAppStandbyTracker sender, int uid) {
169 updateJobsForUid(uid);
170
171 if (sender.isInForeground(uid)) {
172 unblockAlarmsForUid(uid);
173 }
174 }
175
176 /**
177 * This is called when an app-id(s) is removed from the power save whitelist.
178 */
179 private void onPowerSaveUnwhitelisted(ForceAppStandbyTracker sender) {
180 updateAllJobs();
181 unblockAllUnrestrictedAlarms();
182 }
183
184 /**
185 * This is called when the power save whitelist changes, excluding the
186 * {@link #onPowerSaveUnwhitelisted} case.
187 */
188 private void onPowerSaveWhitelistedChanged(ForceAppStandbyTracker sender) {
189 updateAllJobs();
190 }
191
192 /**
193 * This is called when the temp whitelist changes.
194 */
195 private void onTempPowerSaveWhitelistChanged(ForceAppStandbyTracker sender) {
196
197 // TODO This case happens rather frequently; consider optimizing and update jobs
198 // only for affected app-ids.
199
200 updateAllJobs();
201 }
202
203 /**
204 * This is called when the global "force all apps standby" flag changes.
205 */
206 private void onForceAllAppsStandbyChanged(ForceAppStandbyTracker sender) {
207 updateAllJobs();
208
209 if (!sender.isForceAllAppsStandbyEnabled()) {
210 unblockAllUnrestrictedAlarms();
211 }
212 }
213
214 /**
215 * Called when the job restrictions for multiple UIDs might have changed, so the job
216 * scheduler should re-evaluate all restrictions for all jobs.
217 */
218 public void updateAllJobs() {
219 }
220
221 /**
222 * Called when the job restrictions for a UID might have changed, so the job
223 * scheduler should re-evaluate all restrictions for all jobs.
224 */
225 public void updateJobsForUid(int uid) {
226 }
227
228 /**
229 * Called when the job restrictions for a UID - package might have changed, so the job
230 * scheduler should re-evaluate all restrictions for all jobs.
231 */
232 public void updateJobsForUidPackage(int uid, String packageName) {
233 }
234
235 /**
236 * Called when the job restrictions for multiple UIDs might have changed, so the alarm
237 * manager should re-evaluate all restrictions for all blocked jobs.
238 */
239 public void unblockAllUnrestrictedAlarms() {
240 }
241
242 /**
243 * Called when all jobs for a specific UID are unblocked.
244 */
245 public void unblockAlarmsForUid(int uid) {
246 }
247
248 /**
249 * Called when all alarms for a specific UID - package are unblocked.
250 */
251 public void unblockAlarmsForUidPackage(int uid, String packageName) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800252 }
253 }
254
Makoto Onuki2206af32017-11-21 16:25:35 -0800255 @VisibleForTesting
256 ForceAppStandbyTracker(Context context, Looper looper) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800257 mContext = context;
Makoto Onuki2206af32017-11-21 16:25:35 -0800258 mHandler = new MyHandler(looper);
259 }
260
261 private ForceAppStandbyTracker(Context context) {
262 this(context, FgThread.get().getLooper());
Makoto Onuki9be01402017-11-10 13:22:26 -0800263 }
264
265 /**
266 * Get the singleton instance.
267 */
268 public static synchronized ForceAppStandbyTracker getInstance(Context context) {
269 if (sInstance == null) {
270 sInstance = new ForceAppStandbyTracker(context);
271 }
272 return sInstance;
273 }
274
275 /**
276 * Call it when the system is ready.
277 */
278 public void start() {
279 synchronized (mLock) {
280 if (mStarted) {
281 return;
282 }
283 mStarted = true;
284
Makoto Onuki2206af32017-11-21 16:25:35 -0800285 mIActivityManager = Preconditions.checkNotNull(injectIActivityManager());
286 mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
287 mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
288 mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
Makoto Onuki12391f22018-01-18 21:44:28 +0000289 final FeatureFlagObserver flagObserver = new FeatureFlagObserver();
290 flagObserver.register();
291 mForcedAppStandbyEnabled = flagObserver.isForcedAppStandbyEnabled();
Makoto Onuki9be01402017-11-10 13:22:26 -0800292
293 try {
Makoto Onuki2206af32017-11-21 16:25:35 -0800294 mIActivityManager.registerUidObserver(new UidObserver(),
Makoto Onuki9be01402017-11-10 13:22:26 -0800295 ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
296 | ActivityManager.UID_OBSERVER_ACTIVE,
297 ActivityManager.PROCESS_STATE_UNKNOWN, null);
Makoto Onuki2206af32017-11-21 16:25:35 -0800298 mAppOpsService.startWatchingMode(TARGET_OP, null,
Makoto Onuki9be01402017-11-10 13:22:26 -0800299 new AppOpsWatcher());
300 } catch (RemoteException e) {
301 // shouldn't happen.
302 }
303
Makoto Onuki2206af32017-11-21 16:25:35 -0800304 IntentFilter filter = new IntentFilter();
305 filter.addAction(Intent.ACTION_USER_REMOVED);
306 mContext.registerReceiver(new MyReceiver(), filter);
Makoto Onuki9be01402017-11-10 13:22:26 -0800307
308 refreshForcedAppStandbyUidPackagesLocked();
Makoto Onuki2206af32017-11-21 16:25:35 -0800309
310 mPowerManagerInternal.registerLowPowerModeObserver(
311 ServiceType.FORCE_ALL_APPS_STANDBY,
Makoto Onuki12391f22018-01-18 21:44:28 +0000312 (state) -> updateForceAllAppsStandby(state.batterySaverEnabled));
Makoto Onuki2206af32017-11-21 16:25:35 -0800313
Makoto Onuki12391f22018-01-18 21:44:28 +0000314 updateForceAllAppsStandby(mPowerManagerInternal.getLowPowerState(
315 ServiceType.FORCE_ALL_APPS_STANDBY).batterySaverEnabled);
Makoto Onuki9be01402017-11-10 13:22:26 -0800316 }
317 }
318
Makoto Onuki2206af32017-11-21 16:25:35 -0800319 @VisibleForTesting
320 AppOpsManager injectAppOpsManager() {
321 return mContext.getSystemService(AppOpsManager.class);
322 }
323
324 @VisibleForTesting
325 IAppOpsService injectIAppOpsService() {
326 return IAppOpsService.Stub.asInterface(
327 ServiceManager.getService(Context.APP_OPS_SERVICE));
328 }
329
330 @VisibleForTesting
331 IActivityManager injectIActivityManager() {
332 return ActivityManager.getService();
333 }
334
335 @VisibleForTesting
336 PowerManagerInternal injectPowerManagerInternal() {
337 return LocalServices.getService(PowerManagerInternal.class);
338 }
339
Makoto Onuki9be01402017-11-10 13:22:26 -0800340 /**
Makoto Onuki2206af32017-11-21 16:25:35 -0800341 * Update {@link #mRunAnyRestrictedPackages} with the current app ops state.
Makoto Onuki9be01402017-11-10 13:22:26 -0800342 */
343 private void refreshForcedAppStandbyUidPackagesLocked() {
Makoto Onuki2206af32017-11-21 16:25:35 -0800344 mRunAnyRestrictedPackages.clear();
345 final List<PackageOps> ops = mAppOpsManager.getPackagesForOps(
346 new int[] {TARGET_OP});
Makoto Onuki9be01402017-11-10 13:22:26 -0800347
348 if (ops == null) {
349 return;
350 }
351 final int size = ops.size();
352 for (int i = 0; i < size; i++) {
353 final AppOpsManager.PackageOps pkg = ops.get(i);
354 final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps();
355
356 for (int j = 0; j < entries.size(); j++) {
357 AppOpsManager.OpEntry ent = entries.get(j);
Makoto Onuki2206af32017-11-21 16:25:35 -0800358 if (ent.getOp() != TARGET_OP) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800359 continue;
360 }
361 if (ent.getMode() != AppOpsManager.MODE_ALLOWED) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800362 mRunAnyRestrictedPackages.add(Pair.create(
Makoto Onuki9be01402017-11-10 13:22:26 -0800363 pkg.getUid(), pkg.getPackageName()));
364 }
365 }
366 }
367 }
368
Makoto Onuki2206af32017-11-21 16:25:35 -0800369 /**
370 * Update {@link #mForceAllAppsStandby} and notifies the listeners.
371 */
Makoto Onuki12391f22018-01-18 21:44:28 +0000372 void updateForceAllAppsStandby(boolean enable) {
373 synchronized (mLock) {
374 if (enable == mForceAllAppsStandby) {
375 return;
376 }
377 mForceAllAppsStandby = enable;
Nancy Zheng9a603822018-01-12 11:45:37 -0800378
Makoto Onuki12391f22018-01-18 21:44:28 +0000379 mHandler.notifyForceAllAppsStandbyChanged();
380 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800381 }
382
383 private int findForcedAppStandbyUidPackageIndexLocked(int uid, @NonNull String packageName) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800384 final int size = mRunAnyRestrictedPackages.size();
385 if (size > 8) {
386 return mRunAnyRestrictedPackages.indexOf(Pair.create(uid, packageName));
387 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800388 for (int i = 0; i < size; i++) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800389 final Pair<Integer, String> pair = mRunAnyRestrictedPackages.valueAt(i);
Makoto Onuki9be01402017-11-10 13:22:26 -0800390
391 if ((pair.first == uid) && packageName.equals(pair.second)) {
392 return i;
393 }
394 }
395 return -1;
396 }
397
398 /**
Makoto Onuki2206af32017-11-21 16:25:35 -0800399 * @return whether a uid package-name pair is in mRunAnyRestrictedPackages.
Makoto Onuki9be01402017-11-10 13:22:26 -0800400 */
Makoto Onuki2206af32017-11-21 16:25:35 -0800401 boolean isRunAnyRestrictedLocked(int uid, @NonNull String packageName) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800402 return findForcedAppStandbyUidPackageIndexLocked(uid, packageName) >= 0;
403 }
404
Makoto Onuki2206af32017-11-21 16:25:35 -0800405 /**
406 * Add to / remove from {@link #mRunAnyRestrictedPackages}.
407 */
408 boolean updateForcedAppStandbyUidPackageLocked(int uid, @NonNull String packageName,
Makoto Onuki9be01402017-11-10 13:22:26 -0800409 boolean restricted) {
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800410 final int index = findForcedAppStandbyUidPackageIndexLocked(uid, packageName);
Makoto Onuki9be01402017-11-10 13:22:26 -0800411 final boolean wasRestricted = index >= 0;
412 if (wasRestricted == restricted) {
413 return false;
414 }
415 if (restricted) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800416 mRunAnyRestrictedPackages.add(Pair.create(uid, packageName));
Makoto Onuki9be01402017-11-10 13:22:26 -0800417 } else {
Makoto Onuki2206af32017-11-21 16:25:35 -0800418 mRunAnyRestrictedPackages.removeAt(index);
Makoto Onuki9be01402017-11-10 13:22:26 -0800419 }
420 return true;
421 }
422
Makoto Onuki2206af32017-11-21 16:25:35 -0800423 /**
424 * Puts a UID to {@link #mForegroundUids}.
425 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800426 void uidToForeground(int uid) {
427 synchronized (mLock) {
428 if (!UserHandle.isApp(uid)) {
429 return;
430 }
431 // TODO This can be optimized by calling indexOfKey and sharing the index for get and
432 // put.
433 if (mForegroundUids.get(uid)) {
434 return;
435 }
436 mForegroundUids.put(uid, true);
Makoto Onuki2206af32017-11-21 16:25:35 -0800437 mHandler.notifyUidForegroundStateChanged(uid);
Makoto Onuki9be01402017-11-10 13:22:26 -0800438 }
439 }
440
Makoto Onuki2206af32017-11-21 16:25:35 -0800441 /**
442 * Sets false for a UID {@link #mForegroundUids}, or remove it when {@code remove} is true.
443 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800444 void uidToBackground(int uid, boolean remove) {
445 synchronized (mLock) {
446 if (!UserHandle.isApp(uid)) {
447 return;
448 }
449 // TODO This can be optimized by calling indexOfKey and sharing the index for get and
450 // put.
451 if (!mForegroundUids.get(uid)) {
452 return;
453 }
454 if (remove) {
455 mForegroundUids.delete(uid);
456 } else {
457 mForegroundUids.put(uid, false);
458 }
Makoto Onuki2206af32017-11-21 16:25:35 -0800459 mHandler.notifyUidForegroundStateChanged(uid);
Makoto Onuki9be01402017-11-10 13:22:26 -0800460 }
461 }
462
Makoto Onuki2206af32017-11-21 16:25:35 -0800463 private final class UidObserver extends IUidObserver.Stub {
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800464 @Override
465 public void onUidStateChanged(int uid, int procState, long procStateSeq) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800466 }
467
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800468 @Override
469 public void onUidGone(int uid, boolean disabled) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800470 uidToBackground(uid, /*remove=*/ true);
471 }
472
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800473 @Override
474 public void onUidActive(int uid) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800475 uidToForeground(uid);
476 }
477
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800478 @Override
479 public void onUidIdle(int uid, boolean disabled) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800480 // Just to avoid excessive memcpy, don't remove from the array in this case.
481 uidToBackground(uid, /*remove=*/ false);
482 }
483
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800484 @Override
485 public void onUidCachedChanged(int uid, boolean cached) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800486 }
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800487 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800488
489 private final class AppOpsWatcher extends IAppOpsCallback.Stub {
490 @Override
491 public void opChanged(int op, int uid, String packageName) throws RemoteException {
Makoto Onuki2206af32017-11-21 16:25:35 -0800492 boolean restricted = false;
493 try {
494 restricted = mAppOpsService.checkOperation(TARGET_OP,
495 uid, packageName) != AppOpsManager.MODE_ALLOWED;
496 } catch (RemoteException e) {
497 // Shouldn't happen
498 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800499 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800500 if (updateForcedAppStandbyUidPackageLocked(uid, packageName, restricted)) {
501 mHandler.notifyRunAnyAppOpsChanged(uid, packageName);
502 }
503 }
504 }
505 }
Makoto Onuki9be01402017-11-10 13:22:26 -0800506
Makoto Onuki2206af32017-11-21 16:25:35 -0800507 private final class MyReceiver extends BroadcastReceiver {
508 @Override
509 public void onReceive(Context context, Intent intent) {
510 if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
511 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
512 if (userId > 0) {
513 mHandler.doUserRemoved(userId);
Makoto Onuki9be01402017-11-10 13:22:26 -0800514 }
515 }
516 }
517 }
518
519 private Listener[] cloneListeners() {
520 synchronized (mLock) {
521 return mListeners.toArray(new Listener[mListeners.size()]);
522 }
523 }
524
Makoto Onuki2206af32017-11-21 16:25:35 -0800525 private class MyHandler extends Handler {
526 private static final int MSG_UID_STATE_CHANGED = 1;
527 private static final int MSG_RUN_ANY_CHANGED = 2;
528 private static final int MSG_ALL_UNWHITELISTED = 3;
529 private static final int MSG_ALL_WHITELIST_CHANGED = 4;
530 private static final int MSG_TEMP_WHITELIST_CHANGED = 5;
531 private static final int MSG_FORCE_ALL_CHANGED = 6;
Makoto Onuki2206af32017-11-21 16:25:35 -0800532 private static final int MSG_USER_REMOVED = 7;
Makoto Onuki12391f22018-01-18 21:44:28 +0000533 private static final int MSG_FEATURE_FLAG_CHANGED = 8;
Makoto Onuki9be01402017-11-10 13:22:26 -0800534
Makoto Onuki2206af32017-11-21 16:25:35 -0800535 public MyHandler(Looper looper) {
536 super(looper);
Makoto Onuki9be01402017-11-10 13:22:26 -0800537 }
Makoto Onuki2206af32017-11-21 16:25:35 -0800538
539 public void notifyUidForegroundStateChanged(int uid) {
540 obtainMessage(MSG_UID_STATE_CHANGED, uid, 0).sendToTarget();
541 }
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800542
Makoto Onuki2206af32017-11-21 16:25:35 -0800543 public void notifyRunAnyAppOpsChanged(int uid, @NonNull String packageName) {
544 obtainMessage(MSG_RUN_ANY_CHANGED, uid, 0, packageName).sendToTarget();
545 }
546
547 public void notifyAllUnwhitelisted() {
548 obtainMessage(MSG_ALL_UNWHITELISTED).sendToTarget();
549 }
550
551 public void notifyAllWhitelistChanged() {
552 obtainMessage(MSG_ALL_WHITELIST_CHANGED).sendToTarget();
553 }
554
555 public void notifyTempWhitelistChanged() {
556 obtainMessage(MSG_TEMP_WHITELIST_CHANGED).sendToTarget();
557 }
558
559 public void notifyForceAllAppsStandbyChanged() {
560 obtainMessage(MSG_FORCE_ALL_CHANGED).sendToTarget();
561 }
562
Makoto Onuki12391f22018-01-18 21:44:28 +0000563 public void notifyFeatureFlagChanged() {
564 obtainMessage(MSG_FEATURE_FLAG_CHANGED).sendToTarget();
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800565 }
566
Makoto Onuki2206af32017-11-21 16:25:35 -0800567 public void doUserRemoved(int userId) {
568 obtainMessage(MSG_USER_REMOVED, userId, 0).sendToTarget();
569 }
570
571 @Override
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800572 public void handleMessage(Message msg) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800573 switch (msg.what) {
574 case MSG_USER_REMOVED:
575 handleUserRemoved(msg.arg1);
576 return;
577 }
578
579 // Only notify the listeners when started.
580 synchronized (mLock) {
581 if (!mStarted) {
582 return;
583 }
584 }
585 final ForceAppStandbyTracker sender = ForceAppStandbyTracker.this;
586
587 switch (msg.what) {
588 case MSG_UID_STATE_CHANGED:
589 for (Listener l : cloneListeners()) {
590 l.onUidForegroundStateChanged(sender, msg.arg1);
591 }
592 return;
593 case MSG_RUN_ANY_CHANGED:
594 for (Listener l : cloneListeners()) {
595 l.onRunAnyAppOpsChanged(sender, msg.arg1, (String) msg.obj);
596 }
597 return;
598 case MSG_ALL_UNWHITELISTED:
599 for (Listener l : cloneListeners()) {
600 l.onPowerSaveUnwhitelisted(sender);
601 }
602 return;
603 case MSG_ALL_WHITELIST_CHANGED:
604 for (Listener l : cloneListeners()) {
605 l.onPowerSaveWhitelistedChanged(sender);
606 }
607 return;
608 case MSG_TEMP_WHITELIST_CHANGED:
609 for (Listener l : cloneListeners()) {
610 l.onTempPowerSaveWhitelistChanged(sender);
611 }
612 return;
613 case MSG_FORCE_ALL_CHANGED:
614 for (Listener l : cloneListeners()) {
615 l.onForceAllAppsStandbyChanged(sender);
616 }
617 return;
Makoto Onuki12391f22018-01-18 21:44:28 +0000618 case MSG_FEATURE_FLAG_CHANGED:
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800619 // Feature flag for forced app standby changed.
620 final boolean unblockAlarms;
621 synchronized (mLock) {
622 unblockAlarms = !mForcedAppStandbyEnabled && !mForceAllAppsStandby;
623 }
624 for (Listener l: cloneListeners()) {
625 l.updateAllJobs();
626 if (unblockAlarms) {
627 l.unblockAllUnrestrictedAlarms();
628 }
629 }
630 return;
Makoto Onuki2206af32017-11-21 16:25:35 -0800631 case MSG_USER_REMOVED:
632 handleUserRemoved(msg.arg1);
633 return;
634 }
635 }
636 }
637
638 void handleUserRemoved(int removedUserId) {
639 synchronized (mLock) {
640 for (int i = mRunAnyRestrictedPackages.size() - 1; i >= 0; i--) {
641 final Pair<Integer, String> pair = mRunAnyRestrictedPackages.valueAt(i);
642 final int uid = pair.first;
643 final int userId = UserHandle.getUserId(uid);
644
645 if (userId == removedUserId) {
646 mRunAnyRestrictedPackages.removeAt(i);
647 }
648 }
649 for (int i = mForegroundUids.size() - 1; i >= 0; i--) {
650 final int uid = mForegroundUids.keyAt(i);
651 final int userId = UserHandle.getUserId(uid);
652
653 if (userId == removedUserId) {
654 mForegroundUids.removeAt(i);
655 }
656 }
657 }
658 }
659
660 /**
661 * Called by device idle controller to update the power save whitelists.
662 */
663 public void setPowerSaveWhitelistAppIds(
664 int[] powerSaveWhitelistAllAppIdArray, int[] tempWhitelistAppIdArray) {
665 synchronized (mLock) {
666 final int[] previousWhitelist = mPowerWhitelistedAllAppIds;
667 final int[] previousTempWhitelist = mTempWhitelistedAppIds;
668
669 mPowerWhitelistedAllAppIds = powerSaveWhitelistAllAppIdArray;
670 mTempWhitelistedAppIds = tempWhitelistAppIdArray;
671
672 if (isAnyAppIdUnwhitelisted(previousWhitelist, mPowerWhitelistedAllAppIds)) {
673 mHandler.notifyAllUnwhitelisted();
674 } else if (!Arrays.equals(previousWhitelist, mPowerWhitelistedAllAppIds)) {
675 mHandler.notifyAllWhitelistChanged();
676 }
677
678 if (!Arrays.equals(previousTempWhitelist, mTempWhitelistedAppIds)) {
679 mHandler.notifyTempWhitelistChanged();
680 }
681
682 }
683 }
684
685 /**
686 * @retunr true if a sorted app-id array {@code prevArray} has at least one element
687 * that's not in a sorted app-id array {@code newArray}.
688 */
689 @VisibleForTesting
690 static boolean isAnyAppIdUnwhitelisted(int[] prevArray, int[] newArray) {
691 int i1 = 0;
692 int i2 = 0;
693 boolean prevFinished;
694 boolean newFinished;
695
696 for (;;) {
697 prevFinished = i1 >= prevArray.length;
698 newFinished = i2 >= newArray.length;
699 if (prevFinished || newFinished) {
700 break;
701 }
702 int a1 = prevArray[i1];
703 int a2 = newArray[i2];
704
705 if (a1 == a2) {
706 i1++;
707 i2++;
708 continue;
709 }
710 if (a1 < a2) {
711 // prevArray has an element that's not in a2.
712 return true;
713 }
714 i2++;
715 }
716 if (prevFinished) {
717 return false;
718 }
719 return newFinished;
Makoto Onuki9be01402017-11-10 13:22:26 -0800720 }
721
722 // Public interface.
723
724 /**
725 * Register a new listener.
726 */
727 public void addListener(@NonNull Listener listener) {
728 synchronized (mLock) {
729 mListeners.add(listener);
730 }
731 }
732
733 /**
Makoto Onuki2206af32017-11-21 16:25:35 -0800734 * @return whether alarms should be restricted for a UID package-name.
Makoto Onuki9be01402017-11-10 13:22:26 -0800735 */
Makoto Onuki2206af32017-11-21 16:25:35 -0800736 public boolean areAlarmsRestricted(int uid, @NonNull String packageName) {
737 return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ false);
738 }
739
740 /**
741 * @return whether jobs should be restricted for a UID package-name.
742 */
743 public boolean areJobsRestricted(int uid, @NonNull String packageName) {
744 return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ true);
745 }
746
747 /**
748 * @return whether force-app-standby is effective for a UID package-name.
749 */
750 private boolean isRestricted(int uid, @NonNull String packageName,
751 boolean useTempWhitelistToo) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800752 if (isInForeground(uid)) {
753 return false;
754 }
755 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800756 // Whitelisted?
757 final int appId = UserHandle.getAppId(uid);
758 if (ArrayUtils.contains(mPowerWhitelistedAllAppIds, appId)) {
759 return false;
760 }
761 if (useTempWhitelistToo &&
762 ArrayUtils.contains(mTempWhitelistedAppIds, appId)) {
763 return false;
764 }
765
Makoto Onuki9be01402017-11-10 13:22:26 -0800766 if (mForceAllAppsStandby) {
767 return true;
768 }
Makoto Onuki2206af32017-11-21 16:25:35 -0800769
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800770 return mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName);
Makoto Onuki9be01402017-11-10 13:22:26 -0800771 }
772 }
773
Makoto Onuki2206af32017-11-21 16:25:35 -0800774 /**
775 * @return whether a UID is in the foreground or not.
776 *
777 * Note clients normally shouldn't need to access it. It's only for dumpsys.
778 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800779 public boolean isInForeground(int uid) {
780 if (!UserHandle.isApp(uid)) {
781 return true;
782 }
783 synchronized (mLock) {
784 return mForegroundUids.get(uid);
785 }
786 }
787
Makoto Onuki2206af32017-11-21 16:25:35 -0800788 /**
789 * @return whether force all apps standby is enabled or not.
790 *
791 * Note clients normally shouldn't need to access it.
792 */
793 boolean isForceAllAppsStandbyEnabled() {
Makoto Onuki9be01402017-11-10 13:22:26 -0800794 synchronized (mLock) {
795 return mForceAllAppsStandby;
796 }
797 }
798
Makoto Onuki2206af32017-11-21 16:25:35 -0800799 /**
800 * @return whether a UID/package has {@code OP_RUN_ANY_IN_BACKGROUND} allowed or not.
801 *
802 * Note clients normally shouldn't need to access it. It's only for dumpsys.
803 */
Makoto Onuki9be01402017-11-10 13:22:26 -0800804 public boolean isRunAnyInBackgroundAppOpsAllowed(int uid, @NonNull String packageName) {
805 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800806 return !isRunAnyRestrictedLocked(uid, packageName);
Makoto Onuki9be01402017-11-10 13:22:26 -0800807 }
808 }
809
Makoto Onuki2206af32017-11-21 16:25:35 -0800810 /**
811 * @return whether a UID is in the user / system defined power-save whitelist or not.
812 *
813 * Note clients normally shouldn't need to access it. It's only for dumpsys.
814 */
815 public boolean isUidPowerSaveWhitelisted(int uid) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800816 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800817 return ArrayUtils.contains(mPowerWhitelistedAllAppIds, UserHandle.getAppId(uid));
Makoto Onuki9be01402017-11-10 13:22:26 -0800818 }
819 }
820
Makoto Onuki2206af32017-11-21 16:25:35 -0800821 /**
822 * @return whether a UID is in the temp power-save whitelist or not.
823 *
824 * Note clients normally shouldn't need to access it. It's only for dumpsys.
825 */
826 public boolean isUidTempPowerSaveWhitelisted(int uid) {
Makoto Onuki9be01402017-11-10 13:22:26 -0800827 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -0800828 return ArrayUtils.contains(mTempWhitelistedAppIds, UserHandle.getAppId(uid));
829 }
830 }
831
832 public void dump(PrintWriter pw, String indent) {
833 synchronized (mLock) {
834 pw.print(indent);
Suprabh Shukla4deb8522018-01-08 16:27:10 -0800835 pw.println("Forced App Standby Feature enabled: " + mForcedAppStandbyEnabled);
836
837 pw.print(indent);
Makoto Onuki2206af32017-11-21 16:25:35 -0800838 pw.print("Force all apps standby: ");
839 pw.println(isForceAllAppsStandbyEnabled());
840
841 pw.print(indent);
842 pw.print("Foreground uids: [");
843
844 String sep = "";
845 for (int i = 0; i < mForegroundUids.size(); i++) {
846 if (mForegroundUids.valueAt(i)) {
847 pw.print(sep);
848 pw.print(UserHandle.formatUid(mForegroundUids.keyAt(i)));
849 sep = " ";
850 }
851 }
852 pw.println("]");
853
854 pw.print(indent);
855 pw.print("Whitelist appids: ");
856 pw.println(Arrays.toString(mPowerWhitelistedAllAppIds));
857
858 pw.print(indent);
859 pw.print("Temp whitelist appids: ");
860 pw.println(Arrays.toString(mTempWhitelistedAppIds));
861
862 pw.print(indent);
863 pw.println("Restricted packages:");
864 for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
865 pw.print(indent);
866 pw.print(" ");
867 pw.print(UserHandle.formatUid(uidAndPackage.first));
868 pw.print(" ");
869 pw.print(uidAndPackage.second);
870 pw.println();
871 }
872 }
873 }
874
875 public void dumpProto(ProtoOutputStream proto, long fieldId) {
876 synchronized (mLock) {
877 final long token = proto.start(fieldId);
878
879 proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY, mForceAllAppsStandby);
880
881 for (int i = 0; i < mForegroundUids.size(); i++) {
882 if (mForegroundUids.valueAt(i)) {
883 proto.write(ForceAppStandbyTrackerProto.FOREGROUND_UIDS,
884 mForegroundUids.keyAt(i));
885 }
886 }
887
888 for (int appId : mPowerWhitelistedAllAppIds) {
889 proto.write(ForceAppStandbyTrackerProto.POWER_SAVE_WHITELIST_APP_IDS, appId);
890 }
891
892 for (int appId : mTempWhitelistedAppIds) {
893 proto.write(ForceAppStandbyTrackerProto.TEMP_POWER_SAVE_WHITELIST_APP_IDS, appId);
894 }
895
896 for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
897 final long token2 = proto.start(
898 ForceAppStandbyTrackerProto.RUN_ANY_IN_BACKGROUND_RESTRICTED_PACKAGES);
899 proto.write(RunAnyInBackgroundRestrictedPackages.UID, uidAndPackage.first);
900 proto.write(RunAnyInBackgroundRestrictedPackages.PACKAGE_NAME,
901 uidAndPackage.second);
902 proto.end(token2);
903 }
904 proto.end(token);
Makoto Onuki9be01402017-11-10 13:22:26 -0800905 }
906 }
907}