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