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