1 /*
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 package com.android.server;
17 
18 import android.annotation.NonNull;
19 import android.app.ActivityManager;
20 import android.app.ActivityManagerInternal;
21 import android.app.AppOpsManager;
22 import android.app.AppOpsManager.PackageOps;
23 import android.app.IActivityManager;
24 import android.app.IUidObserver;
25 import android.app.usage.UsageStatsManager;
26 import android.app.usage.UsageStatsManagerInternal;
27 import android.content.BroadcastReceiver;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.IntentFilter;
31 import android.database.ContentObserver;
32 import android.net.Uri;
33 import android.os.BatteryManager;
34 import android.os.Handler;
35 import android.os.Looper;
36 import android.os.Message;
37 import android.os.PowerManager.ServiceType;
38 import android.os.PowerManagerInternal;
39 import android.os.RemoteException;
40 import android.os.ServiceManager;
41 import android.os.UserHandle;
42 import android.provider.Settings;
43 import android.util.ArraySet;
44 import android.util.Pair;
45 import android.util.Slog;
46 import android.util.SparseBooleanArray;
47 import android.util.SparseSetArray;
48 import android.util.proto.ProtoOutputStream;
49 
50 import com.android.internal.annotations.GuardedBy;
51 import com.android.internal.annotations.VisibleForTesting;
52 import com.android.internal.app.IAppOpsCallback;
53 import com.android.internal.app.IAppOpsService;
54 import com.android.internal.util.ArrayUtils;
55 import com.android.internal.util.IndentingPrintWriter;
56 import com.android.internal.util.Preconditions;
57 import com.android.internal.util.StatLogger;
58 import com.android.server.AppStateTrackerProto.ExemptedPackage;
59 import com.android.server.AppStateTrackerProto.RunAnyInBackgroundRestrictedPackages;
60 import com.android.server.usage.AppStandbyInternal;
61 import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
62 
63 import java.io.PrintWriter;
64 import java.util.Arrays;
65 import java.util.List;
66 import java.util.Objects;
67 
68 /**
69  * Class to keep track of the information related to "force app standby", which includes:
70  * - OP_RUN_ANY_IN_BACKGROUND for each package
71  * - UID foreground/active state
72  * - User+system power save whitelist
73  * - Temporary power save whitelist
74  * - Global "force all apps standby" mode enforced by battery saver.
75  *
76  * Test: atest com.android.server.AppStateTrackerTest
77  */
78 public class AppStateTracker {
79     private static final String TAG = "AppStateTracker";
80     private static final boolean DEBUG = false;
81 
82     private final Object mLock = new Object();
83     private final Context mContext;
84 
85     @VisibleForTesting
86     static final int TARGET_OP = AppOpsManager.OP_RUN_ANY_IN_BACKGROUND;
87 
88     IActivityManager mIActivityManager;
89     ActivityManagerInternal mActivityManagerInternal;
90     AppOpsManager mAppOpsManager;
91     IAppOpsService mAppOpsService;
92     PowerManagerInternal mPowerManagerInternal;
93     StandbyTracker mStandbyTracker;
94     AppStandbyInternal mAppStandbyInternal;
95 
96     private final MyHandler mHandler;
97 
98     @VisibleForTesting
99     FeatureFlagsObserver mFlagsObserver;
100 
101     /**
102      * Pair of (uid (not user-id), packageName) with OP_RUN_ANY_IN_BACKGROUND *not* allowed.
103      */
104     @GuardedBy("mLock")
105     final ArraySet<Pair<Integer, String>> mRunAnyRestrictedPackages = new ArraySet<>();
106 
107     /** UIDs that are active. */
108     @GuardedBy("mLock")
109     final SparseBooleanArray mActiveUids = new SparseBooleanArray();
110 
111     /** UIDs that are in the foreground. */
112     @GuardedBy("mLock")
113     final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
114 
115     /**
116      * System except-idle + user whitelist in the device idle controller.
117      */
118     @GuardedBy("mLock")
119     private int[] mPowerWhitelistedAllAppIds = new int[0];
120 
121     /**
122      * User whitelisted apps in the device idle controller.
123      */
124     @GuardedBy("mLock")
125     private int[] mPowerWhitelistedUserAppIds = new int[0];
126 
127     @GuardedBy("mLock")
128     private int[] mTempWhitelistedAppIds = mPowerWhitelistedAllAppIds;
129 
130     /**
131      * Per-user packages that are in the EXEMPT bucket.
132      */
133     @GuardedBy("mLock")
134     private final SparseSetArray<String> mExemptedPackages = new SparseSetArray<>();
135 
136     @GuardedBy("mLock")
137     final ArraySet<Listener> mListeners = new ArraySet<>();
138 
139     @GuardedBy("mLock")
140     boolean mStarted;
141 
142     /**
143      * Only used for small battery use-case.
144      */
145     @GuardedBy("mLock")
146     boolean mIsPluggedIn;
147 
148     @GuardedBy("mLock")
149     boolean mBatterySaverEnabled;
150 
151     /**
152      * True if the forced app standby is currently enabled
153      */
154     @GuardedBy("mLock")
155     boolean mForceAllAppsStandby;
156 
157     /**
158      * True if the forced app standby for small battery devices feature is enabled in settings
159      */
160     @GuardedBy("mLock")
161     boolean mForceAllAppStandbyForSmallBattery;
162 
163     /**
164      * True if the forced app standby feature is enabled in settings
165      */
166     @GuardedBy("mLock")
167     boolean mForcedAppStandbyEnabled;
168 
169     interface Stats {
170         int UID_FG_STATE_CHANGED = 0;
171         int UID_ACTIVE_STATE_CHANGED = 1;
172         int RUN_ANY_CHANGED = 2;
173         int ALL_UNWHITELISTED = 3;
174         int ALL_WHITELIST_CHANGED = 4;
175         int TEMP_WHITELIST_CHANGED = 5;
176         int EXEMPT_CHANGED = 6;
177         int FORCE_ALL_CHANGED = 7;
178         int FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8;
179 
180         int IS_UID_ACTIVE_CACHED = 9;
181         int IS_UID_ACTIVE_RAW = 10;
182     }
183 
184     private final StatLogger mStatLogger = new StatLogger(new String[] {
185             "UID_FG_STATE_CHANGED",
186             "UID_ACTIVE_STATE_CHANGED",
187             "RUN_ANY_CHANGED",
188             "ALL_UNWHITELISTED",
189             "ALL_WHITELIST_CHANGED",
190             "TEMP_WHITELIST_CHANGED",
191             "EXEMPT_CHANGED",
192             "FORCE_ALL_CHANGED",
193             "FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED",
194 
195             "IS_UID_ACTIVE_CACHED",
196             "IS_UID_ACTIVE_RAW",
197     });
198 
199     @VisibleForTesting
200     class FeatureFlagsObserver extends ContentObserver {
FeatureFlagsObserver()201         FeatureFlagsObserver() {
202             super(null);
203         }
204 
register()205         void register() {
206             mContext.getContentResolver().registerContentObserver(
207                     Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED),
208                     false, this);
209 
210             mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
211                     Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED), false, this);
212         }
213 
isForcedAppStandbyEnabled()214         boolean isForcedAppStandbyEnabled() {
215             return injectGetGlobalSettingInt(Settings.Global.FORCED_APP_STANDBY_ENABLED, 1) == 1;
216         }
217 
isForcedAppStandbyForSmallBatteryEnabled()218         boolean isForcedAppStandbyForSmallBatteryEnabled() {
219             return injectGetGlobalSettingInt(
220                     Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED, 0) == 1;
221         }
222 
223         @Override
onChange(boolean selfChange, Uri uri)224         public void onChange(boolean selfChange, Uri uri) {
225             if (Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED).equals(uri)) {
226                 final boolean enabled = isForcedAppStandbyEnabled();
227                 synchronized (mLock) {
228                     if (mForcedAppStandbyEnabled == enabled) {
229                         return;
230                     }
231                     mForcedAppStandbyEnabled = enabled;
232                     if (DEBUG) {
233                         Slog.d(TAG,"Forced app standby feature flag changed: "
234                                 + mForcedAppStandbyEnabled);
235                     }
236                 }
237                 mHandler.notifyForcedAppStandbyFeatureFlagChanged();
238             } else if (Settings.Global.getUriFor(
239                     Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED).equals(uri)) {
240                 final boolean enabled = isForcedAppStandbyForSmallBatteryEnabled();
241                 synchronized (mLock) {
242                     if (mForceAllAppStandbyForSmallBattery == enabled) {
243                         return;
244                     }
245                     mForceAllAppStandbyForSmallBattery = enabled;
246                     if (DEBUG) {
247                         Slog.d(TAG, "Forced app standby for small battery feature flag changed: "
248                                 + mForceAllAppStandbyForSmallBattery);
249                     }
250                     updateForceAllAppStandbyState();
251                 }
252             } else {
253                 Slog.w(TAG, "Unexpected feature flag uri encountered: " + uri);
254             }
255         }
256     }
257 
258     public static abstract class Listener {
259         /**
260          * This is called when the OP_RUN_ANY_IN_BACKGROUND appops changed for a package.
261          */
onRunAnyAppOpsChanged(AppStateTracker sender, int uid, @NonNull String packageName)262         private void onRunAnyAppOpsChanged(AppStateTracker sender,
263                 int uid, @NonNull String packageName) {
264             updateJobsForUidPackage(uid, packageName, sender.isUidActive(uid));
265 
266             if (!sender.areAlarmsRestricted(uid, packageName, /*allowWhileIdle=*/ false)) {
267                 unblockAlarmsForUidPackage(uid, packageName);
268             } else if (!sender.areAlarmsRestricted(uid, packageName, /*allowWhileIdle=*/ true)){
269                 // we need to deliver the allow-while-idle alarms for this uid, package
270                 unblockAllUnrestrictedAlarms();
271             }
272 
273             if (!sender.isRunAnyInBackgroundAppOpsAllowed(uid, packageName)) {
274                 Slog.v(TAG, "Package " + packageName + "/" + uid
275                         + " toggled into fg service restriction");
276                 stopForegroundServicesForUidPackage(uid, packageName);
277             }
278         }
279 
280         /**
281          * This is called when the foreground state changed for a UID.
282          */
onUidForegroundStateChanged(AppStateTracker sender, int uid)283         private void onUidForegroundStateChanged(AppStateTracker sender, int uid) {
284             onUidForeground(uid, sender.isUidInForeground(uid));
285         }
286 
287         /**
288          * This is called when the active/idle state changed for a UID.
289          */
onUidActiveStateChanged(AppStateTracker sender, int uid)290         private void onUidActiveStateChanged(AppStateTracker sender, int uid) {
291             final boolean isActive = sender.isUidActive(uid);
292 
293             updateJobsForUid(uid, isActive);
294 
295             if (isActive) {
296                 unblockAlarmsForUid(uid);
297             }
298         }
299 
300         /**
301          * This is called when an app-id(s) is removed from the power save whitelist.
302          */
onPowerSaveUnwhitelisted(AppStateTracker sender)303         private void onPowerSaveUnwhitelisted(AppStateTracker sender) {
304             updateAllJobs();
305             unblockAllUnrestrictedAlarms();
306         }
307 
308         /**
309          * This is called when the power save whitelist changes, excluding the
310          * {@link #onPowerSaveUnwhitelisted} case.
311          */
onPowerSaveWhitelistedChanged(AppStateTracker sender)312         private void onPowerSaveWhitelistedChanged(AppStateTracker sender) {
313             updateAllJobs();
314         }
315 
316         /**
317          * This is called when the temp whitelist changes.
318          */
onTempPowerSaveWhitelistChanged(AppStateTracker sender)319         private void onTempPowerSaveWhitelistChanged(AppStateTracker sender) {
320 
321             // TODO This case happens rather frequently; consider optimizing and update jobs
322             // only for affected app-ids.
323 
324             updateAllJobs();
325 
326             // Note when an app is just put in the temp whitelist, we do *not* drain pending alarms.
327         }
328 
329         /**
330          * This is called when the EXEMPT bucket is updated.
331          */
onExemptChanged(AppStateTracker sender)332         private void onExemptChanged(AppStateTracker sender) {
333             // This doesn't happen very often, so just re-evaluate all jobs / alarms.
334             updateAllJobs();
335             unblockAllUnrestrictedAlarms();
336         }
337 
338         /**
339          * This is called when the global "force all apps standby" flag changes.
340          */
onForceAllAppsStandbyChanged(AppStateTracker sender)341         private void onForceAllAppsStandbyChanged(AppStateTracker sender) {
342             updateAllJobs();
343 
344             if (!sender.isForceAllAppsStandbyEnabled()) {
345                 unblockAllUnrestrictedAlarms();
346             }
347         }
348 
349         /**
350          * Called when the job restrictions for multiple UIDs might have changed, so the job
351          * scheduler should re-evaluate all restrictions for all jobs.
352          */
updateAllJobs()353         public void updateAllJobs() {
354         }
355 
356         /**
357          * Called when the job restrictions for a UID might have changed, so the job
358          * scheduler should re-evaluate all restrictions for all jobs.
359          */
updateJobsForUid(int uid, boolean isNowActive)360         public void updateJobsForUid(int uid, boolean isNowActive) {
361         }
362 
363         /**
364          * Called when the job restrictions for a UID - package might have changed, so the job
365          * scheduler should re-evaluate all restrictions for all jobs.
366          */
updateJobsForUidPackage(int uid, String packageName, boolean isNowActive)367         public void updateJobsForUidPackage(int uid, String packageName, boolean isNowActive) {
368         }
369 
370         /**
371          * Called when an app goes into forced app standby and its foreground
372          * services need to be removed from that state.
373          */
stopForegroundServicesForUidPackage(int uid, String packageName)374         public void stopForegroundServicesForUidPackage(int uid, String packageName) {
375         }
376 
377         /**
378          * Called when the job restrictions for multiple UIDs might have changed, so the alarm
379          * manager should re-evaluate all restrictions for all blocked jobs.
380          */
unblockAllUnrestrictedAlarms()381         public void unblockAllUnrestrictedAlarms() {
382         }
383 
384         /**
385          * Called when all jobs for a specific UID are unblocked.
386          */
unblockAlarmsForUid(int uid)387         public void unblockAlarmsForUid(int uid) {
388         }
389 
390         /**
391          * Called when all alarms for a specific UID - package are unblocked.
392          */
unblockAlarmsForUidPackage(int uid, String packageName)393         public void unblockAlarmsForUidPackage(int uid, String packageName) {
394         }
395 
396         /**
397          * Called when a UID comes into the foreground or the background.
398          *
399          * @see #isUidInForeground(int)
400          */
onUidForeground(int uid, boolean foreground)401         public void onUidForeground(int uid, boolean foreground) {
402         }
403     }
404 
AppStateTracker(Context context, Looper looper)405     public AppStateTracker(Context context, Looper looper) {
406         mContext = context;
407         mHandler = new MyHandler(looper);
408     }
409 
410     /**
411      * Call it when the system is ready.
412      */
onSystemServicesReady()413     public void onSystemServicesReady() {
414         synchronized (mLock) {
415             if (mStarted) {
416                 return;
417             }
418             mStarted = true;
419 
420             mIActivityManager = Objects.requireNonNull(injectIActivityManager());
421             mActivityManagerInternal = Objects.requireNonNull(injectActivityManagerInternal());
422             mAppOpsManager = Objects.requireNonNull(injectAppOpsManager());
423             mAppOpsService = Objects.requireNonNull(injectIAppOpsService());
424             mPowerManagerInternal = Objects.requireNonNull(injectPowerManagerInternal());
425             mAppStandbyInternal = Objects.requireNonNull(injectAppStandbyInternal());
426 
427             mFlagsObserver = new FeatureFlagsObserver();
428             mFlagsObserver.register();
429             mForcedAppStandbyEnabled = mFlagsObserver.isForcedAppStandbyEnabled();
430             mForceAllAppStandbyForSmallBattery =
431                     mFlagsObserver.isForcedAppStandbyForSmallBatteryEnabled();
432             mStandbyTracker = new StandbyTracker();
433             mAppStandbyInternal.addListener(mStandbyTracker);
434 
435             try {
436                 mIActivityManager.registerUidObserver(new UidObserver(),
437                         ActivityManager.UID_OBSERVER_GONE
438                                 | ActivityManager.UID_OBSERVER_IDLE
439                                 | ActivityManager.UID_OBSERVER_ACTIVE
440                                 | ActivityManager.UID_OBSERVER_PROCSTATE,
441                         ActivityManager.PROCESS_STATE_UNKNOWN, null);
442                 mAppOpsService.startWatchingMode(TARGET_OP, null,
443                         new AppOpsWatcher());
444             } catch (RemoteException e) {
445                 // shouldn't happen.
446             }
447 
448             IntentFilter filter = new IntentFilter();
449             filter.addAction(Intent.ACTION_USER_REMOVED);
450             filter.addAction(Intent.ACTION_BATTERY_CHANGED);
451             filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
452             mContext.registerReceiver(new MyReceiver(), filter);
453 
454             refreshForcedAppStandbyUidPackagesLocked();
455 
456             mPowerManagerInternal.registerLowPowerModeObserver(
457                     ServiceType.FORCE_ALL_APPS_STANDBY,
458                     (state) -> {
459                         synchronized (mLock) {
460                             mBatterySaverEnabled = state.batterySaverEnabled;
461                             updateForceAllAppStandbyState();
462                         }
463                     });
464 
465             mBatterySaverEnabled = mPowerManagerInternal.getLowPowerState(
466                     ServiceType.FORCE_ALL_APPS_STANDBY).batterySaverEnabled;
467 
468             updateForceAllAppStandbyState();
469         }
470     }
471 
472     @VisibleForTesting
injectAppOpsManager()473     AppOpsManager injectAppOpsManager() {
474         return mContext.getSystemService(AppOpsManager.class);
475     }
476 
477     @VisibleForTesting
injectIAppOpsService()478     IAppOpsService injectIAppOpsService() {
479         return IAppOpsService.Stub.asInterface(
480                 ServiceManager.getService(Context.APP_OPS_SERVICE));
481     }
482 
483     @VisibleForTesting
injectIActivityManager()484     IActivityManager injectIActivityManager() {
485         return ActivityManager.getService();
486     }
487 
488     @VisibleForTesting
injectActivityManagerInternal()489     ActivityManagerInternal injectActivityManagerInternal() {
490         return LocalServices.getService(ActivityManagerInternal.class);
491     }
492 
493     @VisibleForTesting
injectPowerManagerInternal()494     PowerManagerInternal injectPowerManagerInternal() {
495         return LocalServices.getService(PowerManagerInternal.class);
496     }
497 
498     @VisibleForTesting
injectAppStandbyInternal()499     AppStandbyInternal injectAppStandbyInternal() {
500         return LocalServices.getService(AppStandbyInternal.class);
501     }
502 
503     @VisibleForTesting
isSmallBatteryDevice()504     boolean isSmallBatteryDevice() {
505         return ActivityManager.isSmallBatteryDevice();
506     }
507 
508     @VisibleForTesting
injectGetGlobalSettingInt(String key, int def)509     int injectGetGlobalSettingInt(String key, int def) {
510         return Settings.Global.getInt(mContext.getContentResolver(), key, def);
511     }
512 
513     /**
514      * Update {@link #mRunAnyRestrictedPackages} with the current app ops state.
515      */
516     @GuardedBy("mLock")
refreshForcedAppStandbyUidPackagesLocked()517     private void refreshForcedAppStandbyUidPackagesLocked() {
518         mRunAnyRestrictedPackages.clear();
519         final List<PackageOps> ops = mAppOpsManager.getPackagesForOps(
520                 new int[] {TARGET_OP});
521 
522         if (ops == null) {
523             return;
524         }
525         final int size = ops.size();
526         for (int i = 0; i < size; i++) {
527             final AppOpsManager.PackageOps pkg = ops.get(i);
528             final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps();
529 
530             for (int j = 0; j < entries.size(); j++) {
531                 AppOpsManager.OpEntry ent = entries.get(j);
532                 if (ent.getOp() != TARGET_OP) {
533                     continue;
534                 }
535                 if (ent.getMode() != AppOpsManager.MODE_ALLOWED) {
536                     mRunAnyRestrictedPackages.add(Pair.create(
537                             pkg.getUid(), pkg.getPackageName()));
538                 }
539             }
540         }
541     }
542 
updateForceAllAppStandbyState()543     private void updateForceAllAppStandbyState() {
544         synchronized (mLock) {
545             if (mForceAllAppStandbyForSmallBattery && isSmallBatteryDevice()) {
546                 toggleForceAllAppsStandbyLocked(!mIsPluggedIn);
547             } else {
548                 toggleForceAllAppsStandbyLocked(mBatterySaverEnabled);
549             }
550         }
551     }
552 
553     /**
554      * Update {@link #mForceAllAppsStandby} and notifies the listeners.
555      */
556     @GuardedBy("mLock")
toggleForceAllAppsStandbyLocked(boolean enable)557     private void toggleForceAllAppsStandbyLocked(boolean enable) {
558         if (enable == mForceAllAppsStandby) {
559             return;
560         }
561         mForceAllAppsStandby = enable;
562 
563         mHandler.notifyForceAllAppsStandbyChanged();
564     }
565 
566     @GuardedBy("mLock")
findForcedAppStandbyUidPackageIndexLocked(int uid, @NonNull String packageName)567     private int findForcedAppStandbyUidPackageIndexLocked(int uid, @NonNull String packageName) {
568         final int size = mRunAnyRestrictedPackages.size();
569         if (size > 8) {
570             return mRunAnyRestrictedPackages.indexOf(Pair.create(uid, packageName));
571         }
572         for (int i = 0; i < size; i++) {
573             final Pair<Integer, String> pair = mRunAnyRestrictedPackages.valueAt(i);
574 
575             if ((pair.first == uid) && packageName.equals(pair.second)) {
576                 return i;
577             }
578         }
579         return -1;
580     }
581 
582     /**
583      * @return whether a uid package-name pair is in mRunAnyRestrictedPackages.
584      */
585     @GuardedBy("mLock")
isRunAnyRestrictedLocked(int uid, @NonNull String packageName)586     boolean isRunAnyRestrictedLocked(int uid, @NonNull String packageName) {
587         return findForcedAppStandbyUidPackageIndexLocked(uid, packageName) >= 0;
588     }
589 
590     /**
591      * Add to / remove from {@link #mRunAnyRestrictedPackages}.
592      */
593     @GuardedBy("mLock")
updateForcedAppStandbyUidPackageLocked(int uid, @NonNull String packageName, boolean restricted)594     boolean updateForcedAppStandbyUidPackageLocked(int uid, @NonNull String packageName,
595             boolean restricted) {
596         final int index = findForcedAppStandbyUidPackageIndexLocked(uid, packageName);
597         final boolean wasRestricted = index >= 0;
598         if (wasRestricted == restricted) {
599             return false;
600         }
601         if (restricted) {
602             mRunAnyRestrictedPackages.add(Pair.create(uid, packageName));
603         } else {
604             mRunAnyRestrictedPackages.removeAt(index);
605         }
606         return true;
607     }
608 
addUidToArray(SparseBooleanArray array, int uid)609     private static boolean addUidToArray(SparseBooleanArray array, int uid) {
610         if (UserHandle.isCore(uid)) {
611             return false;
612         }
613         if (array.get(uid)) {
614             return false;
615         }
616         array.put(uid, true);
617         return true;
618     }
619 
removeUidFromArray(SparseBooleanArray array, int uid, boolean remove)620     private static boolean removeUidFromArray(SparseBooleanArray array, int uid, boolean remove) {
621         if (UserHandle.isCore(uid)) {
622             return false;
623         }
624         if (!array.get(uid)) {
625             return false;
626         }
627         if (remove) {
628             array.delete(uid);
629         } else {
630             array.put(uid, false);
631         }
632         return true;
633     }
634 
635     private final class UidObserver extends IUidObserver.Stub {
636         @Override
onUidStateChanged(int uid, int procState, long procStateSeq, int capability)637         public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) {
638             mHandler.onUidStateChanged(uid, procState);
639         }
640 
641         @Override
onUidActive(int uid)642         public void onUidActive(int uid) {
643             mHandler.onUidActive(uid);
644         }
645 
646         @Override
onUidGone(int uid, boolean disabled)647         public void onUidGone(int uid, boolean disabled) {
648             mHandler.onUidGone(uid, disabled);
649         }
650 
651         @Override
onUidIdle(int uid, boolean disabled)652         public void onUidIdle(int uid, boolean disabled) {
653             mHandler.onUidIdle(uid, disabled);
654         }
655 
656         @Override
onUidCachedChanged(int uid, boolean cached)657         public void onUidCachedChanged(int uid, boolean cached) {
658         }
659     }
660 
661     private final class AppOpsWatcher extends IAppOpsCallback.Stub {
662         @Override
opChanged(int op, int uid, String packageName)663         public void opChanged(int op, int uid, String packageName) throws RemoteException {
664             boolean restricted = false;
665             try {
666                 restricted = mAppOpsService.checkOperation(TARGET_OP,
667                         uid, packageName) != AppOpsManager.MODE_ALLOWED;
668             } catch (RemoteException e) {
669                 // Shouldn't happen
670             }
671             synchronized (mLock) {
672                 if (updateForcedAppStandbyUidPackageLocked(uid, packageName, restricted)) {
673                     mHandler.notifyRunAnyAppOpsChanged(uid, packageName);
674                 }
675             }
676         }
677     }
678 
679     private final class MyReceiver extends BroadcastReceiver {
680         @Override
onReceive(Context context, Intent intent)681         public void onReceive(Context context, Intent intent) {
682             if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
683                 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
684                 if (userId > 0) {
685                     mHandler.doUserRemoved(userId);
686                 }
687             } else if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
688                 synchronized (mLock) {
689                     mIsPluggedIn = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
690                 }
691                 updateForceAllAppStandbyState();
692             } else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
693                     && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
694                 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
695                 final String pkgName = intent.getData().getSchemeSpecificPart();
696                 if (mExemptedPackages.remove(userId, pkgName)) {
697                     mHandler.notifyExemptChanged();
698                 }
699             }
700         }
701     }
702 
703     final class StandbyTracker extends AppIdleStateChangeListener {
704         @Override
onAppIdleStateChanged(String packageName, int userId, boolean idle, int bucket, int reason)705         public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
706                 int bucket, int reason) {
707             if (DEBUG) {
708                 Slog.d(TAG,"onAppIdleStateChanged: " + packageName + " u" + userId
709                         + (idle ? " idle" : " active") + " " + bucket);
710             }
711             synchronized (mLock) {
712                 final boolean changed;
713                 if (bucket == UsageStatsManager.STANDBY_BUCKET_EXEMPTED) {
714                     changed = mExemptedPackages.add(userId, packageName);
715                 } else {
716                     changed = mExemptedPackages.remove(userId, packageName);
717                 }
718                 if (changed) {
719                     mHandler.notifyExemptChanged();
720                 }
721             }
722         }
723     }
724 
cloneListeners()725     private Listener[] cloneListeners() {
726         synchronized (mLock) {
727             return mListeners.toArray(new Listener[mListeners.size()]);
728         }
729     }
730 
731     private class MyHandler extends Handler {
732         private static final int MSG_UID_ACTIVE_STATE_CHANGED = 0;
733         private static final int MSG_UID_FG_STATE_CHANGED = 1;
734         private static final int MSG_RUN_ANY_CHANGED = 3;
735         private static final int MSG_ALL_UNWHITELISTED = 4;
736         private static final int MSG_ALL_WHITELIST_CHANGED = 5;
737         private static final int MSG_TEMP_WHITELIST_CHANGED = 6;
738         private static final int MSG_FORCE_ALL_CHANGED = 7;
739         private static final int MSG_USER_REMOVED = 8;
740         private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 9;
741         private static final int MSG_EXEMPT_CHANGED = 10;
742 
743         private static final int MSG_ON_UID_STATE_CHANGED = 11;
744         private static final int MSG_ON_UID_ACTIVE = 12;
745         private static final int MSG_ON_UID_GONE = 13;
746         private static final int MSG_ON_UID_IDLE = 14;
747 
MyHandler(Looper looper)748         public MyHandler(Looper looper) {
749             super(looper);
750         }
751 
notifyUidActiveStateChanged(int uid)752         public void notifyUidActiveStateChanged(int uid) {
753             obtainMessage(MSG_UID_ACTIVE_STATE_CHANGED, uid, 0).sendToTarget();
754         }
755 
notifyUidForegroundStateChanged(int uid)756         public void notifyUidForegroundStateChanged(int uid) {
757             obtainMessage(MSG_UID_FG_STATE_CHANGED, uid, 0).sendToTarget();
758         }
759 
notifyRunAnyAppOpsChanged(int uid, @NonNull String packageName)760         public void notifyRunAnyAppOpsChanged(int uid, @NonNull String packageName) {
761             obtainMessage(MSG_RUN_ANY_CHANGED, uid, 0, packageName).sendToTarget();
762         }
763 
notifyAllUnwhitelisted()764         public void notifyAllUnwhitelisted() {
765             removeMessages(MSG_ALL_UNWHITELISTED);
766             obtainMessage(MSG_ALL_UNWHITELISTED).sendToTarget();
767         }
768 
notifyAllWhitelistChanged()769         public void notifyAllWhitelistChanged() {
770             removeMessages(MSG_ALL_WHITELIST_CHANGED);
771             obtainMessage(MSG_ALL_WHITELIST_CHANGED).sendToTarget();
772         }
773 
notifyTempWhitelistChanged()774         public void notifyTempWhitelistChanged() {
775             removeMessages(MSG_TEMP_WHITELIST_CHANGED);
776             obtainMessage(MSG_TEMP_WHITELIST_CHANGED).sendToTarget();
777         }
778 
notifyForceAllAppsStandbyChanged()779         public void notifyForceAllAppsStandbyChanged() {
780             removeMessages(MSG_FORCE_ALL_CHANGED);
781             obtainMessage(MSG_FORCE_ALL_CHANGED).sendToTarget();
782         }
783 
notifyForcedAppStandbyFeatureFlagChanged()784         public void notifyForcedAppStandbyFeatureFlagChanged() {
785             removeMessages(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED);
786             obtainMessage(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED).sendToTarget();
787         }
788 
notifyExemptChanged()789         public void notifyExemptChanged() {
790             removeMessages(MSG_EXEMPT_CHANGED);
791             obtainMessage(MSG_EXEMPT_CHANGED).sendToTarget();
792         }
793 
doUserRemoved(int userId)794         public void doUserRemoved(int userId) {
795             obtainMessage(MSG_USER_REMOVED, userId, 0).sendToTarget();
796         }
797 
onUidStateChanged(int uid, int procState)798         public void onUidStateChanged(int uid, int procState) {
799             obtainMessage(MSG_ON_UID_STATE_CHANGED, uid, procState).sendToTarget();
800         }
801 
onUidActive(int uid)802         public void onUidActive(int uid) {
803             obtainMessage(MSG_ON_UID_ACTIVE, uid, 0).sendToTarget();
804         }
805 
onUidGone(int uid, boolean disabled)806         public void onUidGone(int uid, boolean disabled) {
807             obtainMessage(MSG_ON_UID_GONE, uid, disabled ? 1 : 0).sendToTarget();
808         }
809 
onUidIdle(int uid, boolean disabled)810         public void onUidIdle(int uid, boolean disabled) {
811             obtainMessage(MSG_ON_UID_IDLE, uid, disabled ? 1 : 0).sendToTarget();
812         }
813 
814         @Override
handleMessage(Message msg)815         public void handleMessage(Message msg) {
816             switch (msg.what) {
817                 case MSG_USER_REMOVED:
818                     handleUserRemoved(msg.arg1);
819                     return;
820             }
821 
822             // Only notify the listeners when started.
823             synchronized (mLock) {
824                 if (!mStarted) {
825                     return;
826                 }
827             }
828             final AppStateTracker sender = AppStateTracker.this;
829 
830             long start = mStatLogger.getTime();
831             switch (msg.what) {
832                 case MSG_UID_ACTIVE_STATE_CHANGED:
833                     for (Listener l : cloneListeners()) {
834                         l.onUidActiveStateChanged(sender, msg.arg1);
835                     }
836                     mStatLogger.logDurationStat(Stats.UID_ACTIVE_STATE_CHANGED, start);
837                     return;
838 
839                 case MSG_UID_FG_STATE_CHANGED:
840                     for (Listener l : cloneListeners()) {
841                         l.onUidForegroundStateChanged(sender, msg.arg1);
842                     }
843                     mStatLogger.logDurationStat(Stats.UID_FG_STATE_CHANGED, start);
844                     return;
845 
846                 case MSG_RUN_ANY_CHANGED:
847                     for (Listener l : cloneListeners()) {
848                         l.onRunAnyAppOpsChanged(sender, msg.arg1, (String) msg.obj);
849                     }
850                     mStatLogger.logDurationStat(Stats.RUN_ANY_CHANGED, start);
851                     return;
852 
853                 case MSG_ALL_UNWHITELISTED:
854                     for (Listener l : cloneListeners()) {
855                         l.onPowerSaveUnwhitelisted(sender);
856                     }
857                     mStatLogger.logDurationStat(Stats.ALL_UNWHITELISTED, start);
858                     return;
859 
860                 case MSG_ALL_WHITELIST_CHANGED:
861                     for (Listener l : cloneListeners()) {
862                         l.onPowerSaveWhitelistedChanged(sender);
863                     }
864                     mStatLogger.logDurationStat(Stats.ALL_WHITELIST_CHANGED, start);
865                     return;
866 
867                 case MSG_TEMP_WHITELIST_CHANGED:
868                     for (Listener l : cloneListeners()) {
869                         l.onTempPowerSaveWhitelistChanged(sender);
870                     }
871                     mStatLogger.logDurationStat(Stats.TEMP_WHITELIST_CHANGED, start);
872                     return;
873 
874                 case MSG_EXEMPT_CHANGED:
875                     for (Listener l : cloneListeners()) {
876                         l.onExemptChanged(sender);
877                     }
878                     mStatLogger.logDurationStat(Stats.EXEMPT_CHANGED, start);
879                     return;
880 
881                 case MSG_FORCE_ALL_CHANGED:
882                     for (Listener l : cloneListeners()) {
883                         l.onForceAllAppsStandbyChanged(sender);
884                     }
885                     mStatLogger.logDurationStat(Stats.FORCE_ALL_CHANGED, start);
886                     return;
887 
888                 case MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED:
889                     // Feature flag for forced app standby changed.
890                     final boolean unblockAlarms;
891                     synchronized (mLock) {
892                         unblockAlarms = !mForcedAppStandbyEnabled && !mForceAllAppsStandby;
893                     }
894                     for (Listener l : cloneListeners()) {
895                         l.updateAllJobs();
896                         if (unblockAlarms) {
897                             l.unblockAllUnrestrictedAlarms();
898                         }
899                     }
900                     mStatLogger.logDurationStat(
901                             Stats.FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED, start);
902                     return;
903 
904                 case MSG_USER_REMOVED:
905                     handleUserRemoved(msg.arg1);
906                     return;
907 
908                 case MSG_ON_UID_STATE_CHANGED:
909                     handleUidStateChanged(msg.arg1, msg.arg2);
910                     return;
911                 case MSG_ON_UID_ACTIVE:
912                     handleUidActive(msg.arg1);
913                     return;
914                 case MSG_ON_UID_GONE:
915                     handleUidGone(msg.arg1, msg.arg1 != 0);
916                     return;
917                 case MSG_ON_UID_IDLE:
918                     handleUidIdle(msg.arg1, msg.arg1 != 0);
919                     return;
920             }
921         }
922 
handleUidStateChanged(int uid, int procState)923         public void handleUidStateChanged(int uid, int procState) {
924             synchronized (mLock) {
925                 if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
926                     if (removeUidFromArray(mForegroundUids, uid, false)) {
927                         mHandler.notifyUidForegroundStateChanged(uid);
928                     }
929                 } else {
930                     if (addUidToArray(mForegroundUids, uid)) {
931                         mHandler.notifyUidForegroundStateChanged(uid);
932                     }
933                 }
934             }
935         }
936 
handleUidActive(int uid)937         public void handleUidActive(int uid) {
938             synchronized (mLock) {
939                 if (addUidToArray(mActiveUids, uid)) {
940                     mHandler.notifyUidActiveStateChanged(uid);
941                 }
942             }
943         }
944 
handleUidGone(int uid, boolean disabled)945         public void handleUidGone(int uid, boolean disabled) {
946             removeUid(uid, true);
947         }
948 
handleUidIdle(int uid, boolean disabled)949         public void handleUidIdle(int uid, boolean disabled) {
950             // Just to avoid excessive memcpy, don't remove from the array in this case.
951             removeUid(uid, false);
952         }
953 
removeUid(int uid, boolean remove)954         private void removeUid(int uid, boolean remove) {
955             synchronized (mLock) {
956                 if (removeUidFromArray(mActiveUids, uid, remove)) {
957                     mHandler.notifyUidActiveStateChanged(uid);
958                 }
959                 if (removeUidFromArray(mForegroundUids, uid, remove)) {
960                     mHandler.notifyUidForegroundStateChanged(uid);
961                 }
962             }
963         }
964     }
965 
handleUserRemoved(int removedUserId)966     void handleUserRemoved(int removedUserId) {
967         synchronized (mLock) {
968             for (int i = mRunAnyRestrictedPackages.size() - 1; i >= 0; i--) {
969                 final Pair<Integer, String> pair = mRunAnyRestrictedPackages.valueAt(i);
970                 final int uid = pair.first;
971                 final int userId = UserHandle.getUserId(uid);
972 
973                 if (userId == removedUserId) {
974                     mRunAnyRestrictedPackages.removeAt(i);
975                 }
976             }
977             cleanUpArrayForUser(mActiveUids, removedUserId);
978             cleanUpArrayForUser(mForegroundUids, removedUserId);
979             mExemptedPackages.remove(removedUserId);
980         }
981     }
982 
cleanUpArrayForUser(SparseBooleanArray array, int removedUserId)983     private void cleanUpArrayForUser(SparseBooleanArray array, int removedUserId) {
984         for (int i = array.size() - 1; i >= 0; i--) {
985             final int uid = array.keyAt(i);
986             final int userId = UserHandle.getUserId(uid);
987 
988             if (userId == removedUserId) {
989                 array.removeAt(i);
990             }
991         }
992     }
993 
994     /**
995      * Called by device idle controller to update the power save whitelists.
996      */
setPowerSaveWhitelistAppIds( int[] powerSaveWhitelistExceptIdleAppIdArray, int[] powerSaveWhitelistUserAppIdArray, int[] tempWhitelistAppIdArray)997     public void setPowerSaveWhitelistAppIds(
998             int[] powerSaveWhitelistExceptIdleAppIdArray,
999             int[] powerSaveWhitelistUserAppIdArray,
1000             int[] tempWhitelistAppIdArray) {
1001         synchronized (mLock) {
1002             final int[] previousWhitelist = mPowerWhitelistedAllAppIds;
1003             final int[] previousTempWhitelist = mTempWhitelistedAppIds;
1004 
1005             mPowerWhitelistedAllAppIds = powerSaveWhitelistExceptIdleAppIdArray;
1006             mTempWhitelistedAppIds = tempWhitelistAppIdArray;
1007             mPowerWhitelistedUserAppIds = powerSaveWhitelistUserAppIdArray;
1008 
1009             if (isAnyAppIdUnwhitelisted(previousWhitelist, mPowerWhitelistedAllAppIds)) {
1010                 mHandler.notifyAllUnwhitelisted();
1011             } else if (!Arrays.equals(previousWhitelist, mPowerWhitelistedAllAppIds)) {
1012                 mHandler.notifyAllWhitelistChanged();
1013             }
1014 
1015             if (!Arrays.equals(previousTempWhitelist, mTempWhitelistedAppIds)) {
1016                 mHandler.notifyTempWhitelistChanged();
1017             }
1018 
1019         }
1020     }
1021 
1022     /**
1023      * @retunr true if a sorted app-id array {@code prevArray} has at least one element
1024      * that's not in a sorted app-id array {@code newArray}.
1025      */
1026     @VisibleForTesting
isAnyAppIdUnwhitelisted(int[] prevArray, int[] newArray)1027     static boolean isAnyAppIdUnwhitelisted(int[] prevArray, int[] newArray) {
1028         int i1 = 0;
1029         int i2 = 0;
1030         boolean prevFinished;
1031         boolean newFinished;
1032 
1033         for (;;) {
1034             prevFinished = i1 >= prevArray.length;
1035             newFinished = i2 >= newArray.length;
1036             if (prevFinished || newFinished) {
1037                 break;
1038             }
1039             int a1 = prevArray[i1];
1040             int a2 = newArray[i2];
1041 
1042             if (a1 == a2) {
1043                 i1++;
1044                 i2++;
1045                 continue;
1046             }
1047             if (a1 < a2) {
1048                 // prevArray has an element that's not in a2.
1049                 return true;
1050             }
1051             i2++;
1052         }
1053         if (prevFinished) {
1054             return false;
1055         }
1056         return newFinished;
1057     }
1058 
1059     // Public interface.
1060 
1061     /**
1062      * Register a new listener.
1063      */
addListener(@onNull Listener listener)1064     public void addListener(@NonNull Listener listener) {
1065         synchronized (mLock) {
1066             mListeners.add(listener);
1067         }
1068     }
1069 
1070     /**
1071      * @return whether alarms should be restricted for a UID package-name.
1072      */
areAlarmsRestricted(int uid, @NonNull String packageName, boolean isExemptOnBatterySaver)1073     public boolean areAlarmsRestricted(int uid, @NonNull String packageName,
1074             boolean isExemptOnBatterySaver) {
1075         return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ false,
1076                 isExemptOnBatterySaver);
1077     }
1078 
1079     /**
1080      * @return whether jobs should be restricted for a UID package-name.
1081      */
areJobsRestricted(int uid, @NonNull String packageName, boolean hasForegroundExemption)1082     public boolean areJobsRestricted(int uid, @NonNull String packageName,
1083             boolean hasForegroundExemption) {
1084         return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ true,
1085                 hasForegroundExemption);
1086     }
1087 
1088     /**
1089      * @return whether foreground services should be suppressed in the background
1090      * due to forced app standby for the given app
1091      */
areForegroundServicesRestricted(int uid, @NonNull String packageName)1092     public boolean areForegroundServicesRestricted(int uid, @NonNull String packageName) {
1093         synchronized (mLock) {
1094             return isRunAnyRestrictedLocked(uid, packageName);
1095         }
1096     }
1097 
1098     /**
1099      * @return whether force-app-standby is effective for a UID package-name.
1100      */
isRestricted(int uid, @NonNull String packageName, boolean useTempWhitelistToo, boolean exemptOnBatterySaver)1101     private boolean isRestricted(int uid, @NonNull String packageName,
1102             boolean useTempWhitelistToo, boolean exemptOnBatterySaver) {
1103         if (isUidActive(uid)) {
1104             return false;
1105         }
1106         synchronized (mLock) {
1107             // Whitelisted?
1108             final int appId = UserHandle.getAppId(uid);
1109             if (ArrayUtils.contains(mPowerWhitelistedAllAppIds, appId)) {
1110                 return false;
1111             }
1112             if (useTempWhitelistToo &&
1113                     ArrayUtils.contains(mTempWhitelistedAppIds, appId)) {
1114                 return false;
1115             }
1116             if (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName)) {
1117                 return true;
1118             }
1119             if (exemptOnBatterySaver) {
1120                 return false;
1121             }
1122             final int userId = UserHandle.getUserId(uid);
1123             if (mAppStandbyInternal.isAppIdleEnabled() && !mAppStandbyInternal.isInParole()
1124                     && mExemptedPackages.contains(userId, packageName)) {
1125                 return false;
1126             }
1127             return mForceAllAppsStandby;
1128         }
1129     }
1130 
1131     /**
1132      * @return whether a UID is in active or not *based on cached information.*
1133      *
1134      * Note this information is based on the UID proc state callback, meaning it's updated
1135      * asynchronously and may subtly be stale. If the fresh data is needed, use
1136      * {@link #isUidActiveSynced} instead.
1137      */
isUidActive(int uid)1138     public boolean isUidActive(int uid) {
1139         if (UserHandle.isCore(uid)) {
1140             return true;
1141         }
1142         synchronized (mLock) {
1143             return mActiveUids.get(uid);
1144         }
1145     }
1146 
1147     /**
1148      * @return whether a UID is in active or not *right now.*
1149      *
1150      * This gives the fresh information, but may access the activity manager so is slower.
1151      */
isUidActiveSynced(int uid)1152     public boolean isUidActiveSynced(int uid) {
1153         if (isUidActive(uid)) { // Use the cached one first.
1154             return true;
1155         }
1156         final long start = mStatLogger.getTime();
1157 
1158         final boolean ret = mActivityManagerInternal.isUidActive(uid);
1159         mStatLogger.logDurationStat(Stats.IS_UID_ACTIVE_RAW, start);
1160 
1161         return ret;
1162     }
1163 
1164     /**
1165      * @return whether a UID is in the foreground or not.
1166      *
1167      * Note this information is based on the UID proc state callback, meaning it's updated
1168      * asynchronously and may subtly be stale. If the fresh data is needed, use
1169      * {@link ActivityManagerInternal#getUidProcessState} instead.
1170      */
isUidInForeground(int uid)1171     public boolean isUidInForeground(int uid) {
1172         if (UserHandle.isCore(uid)) {
1173             return true;
1174         }
1175         synchronized (mLock) {
1176             return mForegroundUids.get(uid);
1177         }
1178     }
1179 
1180     /**
1181      * @return whether force all apps standby is enabled or not.
1182      *
1183      */
isForceAllAppsStandbyEnabled()1184     boolean isForceAllAppsStandbyEnabled() {
1185         synchronized (mLock) {
1186             return mForceAllAppsStandby;
1187         }
1188     }
1189 
1190     /**
1191      * @return whether a UID/package has {@code OP_RUN_ANY_IN_BACKGROUND} allowed or not.
1192      *
1193      * Note clients normally shouldn't need to access it. It's only for dumpsys.
1194      */
isRunAnyInBackgroundAppOpsAllowed(int uid, @NonNull String packageName)1195     public boolean isRunAnyInBackgroundAppOpsAllowed(int uid, @NonNull String packageName) {
1196         synchronized (mLock) {
1197             return !isRunAnyRestrictedLocked(uid, packageName);
1198         }
1199     }
1200 
1201     /**
1202      * @return whether a UID is in the user / system defined power-save whitelist or not.
1203      *
1204      * Note clients normally shouldn't need to access it. It's only for dumpsys.
1205      */
isUidPowerSaveWhitelisted(int uid)1206     public boolean isUidPowerSaveWhitelisted(int uid) {
1207         synchronized (mLock) {
1208             return ArrayUtils.contains(mPowerWhitelistedAllAppIds, UserHandle.getAppId(uid));
1209         }
1210     }
1211 
1212     /**
1213      * @param uid the uid to check for
1214      * @return whether a UID is in the user defined power-save whitelist or not.
1215      */
isUidPowerSaveUserWhitelisted(int uid)1216     public boolean isUidPowerSaveUserWhitelisted(int uid) {
1217         synchronized (mLock) {
1218             return ArrayUtils.contains(mPowerWhitelistedUserAppIds, UserHandle.getAppId(uid));
1219         }
1220     }
1221 
1222     /**
1223      * @return whether a UID is in the temp power-save whitelist or not.
1224      *
1225      * Note clients normally shouldn't need to access it. It's only for dumpsys.
1226      */
isUidTempPowerSaveWhitelisted(int uid)1227     public boolean isUidTempPowerSaveWhitelisted(int uid) {
1228         synchronized (mLock) {
1229             return ArrayUtils.contains(mTempWhitelistedAppIds, UserHandle.getAppId(uid));
1230         }
1231     }
1232 
1233     @Deprecated
dump(PrintWriter pw, String prefix)1234     public void dump(PrintWriter pw, String prefix) {
1235         dump(new IndentingPrintWriter(pw, "  ").setIndent(prefix));
1236     }
1237 
dump(IndentingPrintWriter pw)1238     public void dump(IndentingPrintWriter pw) {
1239         synchronized (mLock) {
1240             pw.println("Forced App Standby Feature enabled: " + mForcedAppStandbyEnabled);
1241 
1242             pw.print("Force all apps standby: ");
1243             pw.println(isForceAllAppsStandbyEnabled());
1244 
1245             pw.print("Small Battery Device: ");
1246             pw.println(isSmallBatteryDevice());
1247 
1248             pw.print("Force all apps standby for small battery device: ");
1249             pw.println(mForceAllAppStandbyForSmallBattery);
1250 
1251             pw.print("Plugged In: ");
1252             pw.println(mIsPluggedIn);
1253 
1254             pw.print("Active uids: ");
1255             dumpUids(pw, mActiveUids);
1256 
1257             pw.print("Foreground uids: ");
1258             dumpUids(pw, mForegroundUids);
1259 
1260             pw.print("Except-idle + user whitelist appids: ");
1261             pw.println(Arrays.toString(mPowerWhitelistedAllAppIds));
1262 
1263             pw.print("User whitelist appids: ");
1264             pw.println(Arrays.toString(mPowerWhitelistedUserAppIds));
1265 
1266             pw.print("Temp whitelist appids: ");
1267             pw.println(Arrays.toString(mTempWhitelistedAppIds));
1268 
1269             pw.println("Exempted packages:");
1270             pw.increaseIndent();
1271             for (int i = 0; i < mExemptedPackages.size(); i++) {
1272                 pw.print("User ");
1273                 pw.print(mExemptedPackages.keyAt(i));
1274                 pw.println();
1275 
1276                 pw.increaseIndent();
1277                 for (int j = 0; j < mExemptedPackages.sizeAt(i); j++) {
1278                     pw.print(mExemptedPackages.valueAt(i, j));
1279                     pw.println();
1280                 }
1281                 pw.decreaseIndent();
1282             }
1283             pw.decreaseIndent();
1284             pw.println();
1285 
1286             pw.println("Restricted packages:");
1287             pw.increaseIndent();
1288             for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
1289                 pw.print(UserHandle.formatUid(uidAndPackage.first));
1290                 pw.print(" ");
1291                 pw.print(uidAndPackage.second);
1292                 pw.println();
1293             }
1294             pw.decreaseIndent();
1295 
1296             mStatLogger.dump(pw);
1297         }
1298     }
1299 
dumpUids(PrintWriter pw, SparseBooleanArray array)1300     private void dumpUids(PrintWriter pw, SparseBooleanArray array) {
1301         pw.print("[");
1302 
1303         String sep = "";
1304         for (int i = 0; i < array.size(); i++) {
1305             if (array.valueAt(i)) {
1306                 pw.print(sep);
1307                 pw.print(UserHandle.formatUid(array.keyAt(i)));
1308                 sep = " ";
1309             }
1310         }
1311         pw.println("]");
1312     }
1313 
dumpProto(ProtoOutputStream proto, long fieldId)1314     public void dumpProto(ProtoOutputStream proto, long fieldId) {
1315         synchronized (mLock) {
1316             final long token = proto.start(fieldId);
1317 
1318             proto.write(AppStateTrackerProto.FORCED_APP_STANDBY_FEATURE_ENABLED,
1319                     mForcedAppStandbyEnabled);
1320             proto.write(AppStateTrackerProto.FORCE_ALL_APPS_STANDBY,
1321                     isForceAllAppsStandbyEnabled());
1322             proto.write(AppStateTrackerProto.IS_SMALL_BATTERY_DEVICE, isSmallBatteryDevice());
1323             proto.write(AppStateTrackerProto.FORCE_ALL_APPS_STANDBY_FOR_SMALL_BATTERY,
1324                     mForceAllAppStandbyForSmallBattery);
1325             proto.write(AppStateTrackerProto.IS_PLUGGED_IN, mIsPluggedIn);
1326 
1327             for (int i = 0; i < mActiveUids.size(); i++) {
1328                 if (mActiveUids.valueAt(i)) {
1329                     proto.write(AppStateTrackerProto.ACTIVE_UIDS, mActiveUids.keyAt(i));
1330                 }
1331             }
1332 
1333             for (int i = 0; i < mForegroundUids.size(); i++) {
1334                 if (mForegroundUids.valueAt(i)) {
1335                     proto.write(AppStateTrackerProto.FOREGROUND_UIDS, mForegroundUids.keyAt(i));
1336                 }
1337             }
1338 
1339             for (int appId : mPowerWhitelistedAllAppIds) {
1340                 proto.write(AppStateTrackerProto.POWER_SAVE_WHITELIST_APP_IDS, appId);
1341             }
1342 
1343             for (int appId : mPowerWhitelistedUserAppIds) {
1344                 proto.write(AppStateTrackerProto.POWER_SAVE_USER_WHITELIST_APP_IDS, appId);
1345             }
1346 
1347             for (int appId : mTempWhitelistedAppIds) {
1348                 proto.write(AppStateTrackerProto.TEMP_POWER_SAVE_WHITELIST_APP_IDS, appId);
1349             }
1350 
1351             for (int i = 0; i < mExemptedPackages.size(); i++) {
1352                 for (int j = 0; j < mExemptedPackages.sizeAt(i); j++) {
1353                     final long token2 = proto.start(AppStateTrackerProto.EXEMPTED_PACKAGES);
1354 
1355                     proto.write(ExemptedPackage.USER_ID, mExemptedPackages.keyAt(i));
1356                     proto.write(ExemptedPackage.PACKAGE_NAME, mExemptedPackages.valueAt(i, j));
1357 
1358                     proto.end(token2);
1359                 }
1360             }
1361 
1362             for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
1363                 final long token2 = proto.start(
1364                         AppStateTrackerProto.RUN_ANY_IN_BACKGROUND_RESTRICTED_PACKAGES);
1365                 proto.write(RunAnyInBackgroundRestrictedPackages.UID, uidAndPackage.first);
1366                 proto.write(RunAnyInBackgroundRestrictedPackages.PACKAGE_NAME,
1367                         uidAndPackage.second);
1368                 proto.end(token2);
1369             }
1370 
1371             mStatLogger.dumpProto(proto, AppStateTrackerProto.STATS);
1372 
1373             proto.end(token);
1374         }
1375     }
1376 }
1377