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