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