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 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 448 switch (intent.getAction()) { 449 case Intent.ACTION_USER_REMOVED: 450 if (userId > 0) { 451 mHandler.doUserRemoved(userId); 452 } 453 break; 454 case Intent.ACTION_BATTERY_CHANGED: 455 synchronized (mLock) { 456 mIsPluggedIn = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0); 457 } 458 updateForceAllAppStandbyState(); 459 break; 460 case Intent.ACTION_PACKAGE_REMOVED: 461 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 462 final String pkgName = intent.getData().getSchemeSpecificPart(); 463 final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 464 // No need to notify for state change as all the alarms and jobs should be 465 // removed too. 466 synchronized (mLock) { 467 mExemptedBucketPackages.remove(userId, pkgName); 468 mRunAnyRestrictedPackages.remove(Pair.create(uid, pkgName)); 469 updateBackgroundRestrictedUidPackagesLocked(); 470 mActiveUids.delete(uid); 471 } 472 } 473 break; 474 } 475 } 476 }; 477 478 /** 479 * Call it when the system is ready. 480 */ onSystemServicesReady()481 public void onSystemServicesReady() { 482 synchronized (mLock) { 483 if (mStarted) { 484 return; 485 } 486 mStarted = true; 487 488 mIActivityManager = Objects.requireNonNull(injectIActivityManager()); 489 mActivityManagerInternal = Objects.requireNonNull(injectActivityManagerInternal()); 490 mAppOpsManager = Objects.requireNonNull(injectAppOpsManager()); 491 mAppOpsService = Objects.requireNonNull(injectIAppOpsService()); 492 mPowerManagerInternal = Objects.requireNonNull(injectPowerManagerInternal()); 493 mAppStandbyInternal = Objects.requireNonNull(injectAppStandbyInternal()); 494 495 mFlagsObserver = new FeatureFlagsObserver(); 496 mFlagsObserver.register(); 497 mForceAllAppStandbyForSmallBattery = 498 mFlagsObserver.isForcedAppStandbyForSmallBatteryEnabled(); 499 mStandbyTracker = new StandbyTracker(); 500 mAppStandbyInternal.addListener(mStandbyTracker); 501 mActivityManagerInternal.addAppBackgroundRestrictionListener( 502 mAppBackgroundRestrictionListener); 503 504 try { 505 mIActivityManager.registerUidObserver(new UidObserver(), 506 ActivityManager.UID_OBSERVER_GONE 507 | ActivityManager.UID_OBSERVER_IDLE 508 | ActivityManager.UID_OBSERVER_ACTIVE 509 | ActivityManager.UID_OBSERVER_CACHED, 510 ActivityManager.PROCESS_STATE_UNKNOWN, null); 511 mAppOpsService.startWatchingMode(TARGET_OP, null, 512 new AppOpsWatcher()); 513 } catch (RemoteException e) { 514 // shouldn't happen. 515 } 516 517 IntentFilter filter = new IntentFilter(); 518 filter.addAction(Intent.ACTION_USER_REMOVED); 519 filter.addAction(Intent.ACTION_BATTERY_CHANGED); 520 mContext.registerReceiver(mReceiver, filter); 521 522 filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED); 523 filter.addDataScheme(IntentFilter.SCHEME_PACKAGE); 524 mContext.registerReceiver(mReceiver, filter); 525 526 refreshForcedAppStandbyUidPackagesLocked(); 527 528 mPowerManagerInternal.registerLowPowerModeObserver( 529 ServiceType.FORCE_ALL_APPS_STANDBY, 530 (state) -> { 531 synchronized (mLock) { 532 mBatterySaverEnabled = state.batterySaverEnabled; 533 updateForceAllAppStandbyState(); 534 } 535 }); 536 537 mBatterySaverEnabled = mPowerManagerInternal.getLowPowerState( 538 ServiceType.FORCE_ALL_APPS_STANDBY).batterySaverEnabled; 539 540 updateForceAllAppStandbyState(); 541 } 542 } 543 544 @VisibleForTesting injectAppOpsManager()545 AppOpsManager injectAppOpsManager() { 546 return mContext.getSystemService(AppOpsManager.class); 547 } 548 549 @VisibleForTesting injectIAppOpsService()550 IAppOpsService injectIAppOpsService() { 551 return IAppOpsService.Stub.asInterface( 552 ServiceManager.getService(Context.APP_OPS_SERVICE)); 553 } 554 555 @VisibleForTesting injectIActivityManager()556 IActivityManager injectIActivityManager() { 557 return ActivityManager.getService(); 558 } 559 560 @VisibleForTesting injectActivityManagerInternal()561 ActivityManagerInternal injectActivityManagerInternal() { 562 return LocalServices.getService(ActivityManagerInternal.class); 563 } 564 565 @VisibleForTesting injectPowerManagerInternal()566 PowerManagerInternal injectPowerManagerInternal() { 567 return LocalServices.getService(PowerManagerInternal.class); 568 } 569 570 @VisibleForTesting injectAppStandbyInternal()571 AppStandbyInternal injectAppStandbyInternal() { 572 return LocalServices.getService(AppStandbyInternal.class); 573 } 574 575 @VisibleForTesting isSmallBatteryDevice()576 boolean isSmallBatteryDevice() { 577 return ActivityManager.isSmallBatteryDevice(); 578 } 579 580 @VisibleForTesting injectGetGlobalSettingInt(String key, int def)581 int injectGetGlobalSettingInt(String key, int def) { 582 return Settings.Global.getInt(mContext.getContentResolver(), key, def); 583 } 584 585 /** 586 * Update {@link #mRunAnyRestrictedPackages} with the current app ops state. 587 */ 588 @GuardedBy("mLock") refreshForcedAppStandbyUidPackagesLocked()589 private void refreshForcedAppStandbyUidPackagesLocked() { 590 mRunAnyRestrictedPackages.clear(); 591 final List<PackageOps> ops = mAppOpsManager.getPackagesForOps( 592 new int[] {TARGET_OP}); 593 594 if (ops == null) { 595 return; 596 } 597 final int size = ops.size(); 598 for (int i = 0; i < size; i++) { 599 final AppOpsManager.PackageOps pkg = ops.get(i); 600 final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps(); 601 602 for (int j = 0; j < entries.size(); j++) { 603 AppOpsManager.OpEntry ent = entries.get(j); 604 if (ent.getOp() != TARGET_OP) { 605 continue; 606 } 607 if (ent.getMode() != AppOpsManager.MODE_ALLOWED) { 608 mRunAnyRestrictedPackages.add(Pair.create( 609 pkg.getUid(), pkg.getPackageName())); 610 } 611 } 612 } 613 updateBackgroundRestrictedUidPackagesLocked(); 614 } 615 616 /** 617 * Update the {@link #mBackgroundRestrictedUidPackages} upon mutations on 618 * {@link #mRunAnyRestrictedPackages}. 619 */ 620 @GuardedBy("mLock") updateBackgroundRestrictedUidPackagesLocked()621 private void updateBackgroundRestrictedUidPackagesLocked() { 622 Set<Pair<Integer, String>> fasUidPkgs = new ArraySet<>(); 623 for (int i = 0, size = mRunAnyRestrictedPackages.size(); i < size; i++) { 624 fasUidPkgs.add(mRunAnyRestrictedPackages.valueAt(i)); 625 } 626 mBackgroundRestrictedUidPackages = Collections.unmodifiableSet(fasUidPkgs); 627 } 628 updateForceAllAppStandbyState()629 private void updateForceAllAppStandbyState() { 630 synchronized (mLock) { 631 if (mForceAllAppStandbyForSmallBattery && isSmallBatteryDevice()) { 632 toggleForceAllAppsStandbyLocked(!mIsPluggedIn); 633 } else { 634 toggleForceAllAppsStandbyLocked(mBatterySaverEnabled); 635 } 636 } 637 } 638 639 /** 640 * Update {@link #mForceAllAppsStandby} and notifies the listeners. 641 */ 642 @GuardedBy("mLock") toggleForceAllAppsStandbyLocked(boolean enable)643 private void toggleForceAllAppsStandbyLocked(boolean enable) { 644 if (enable == mForceAllAppsStandby) { 645 return; 646 } 647 mForceAllAppsStandby = enable; 648 649 mHandler.notifyForceAllAppsStandbyChanged(); 650 } 651 652 @GuardedBy("mLock") findForcedAppStandbyUidPackageIndexLocked(int uid, @NonNull String packageName)653 private int findForcedAppStandbyUidPackageIndexLocked(int uid, @NonNull String packageName) { 654 final int size = mRunAnyRestrictedPackages.size(); 655 if (size > 8) { 656 return mRunAnyRestrictedPackages.indexOf(Pair.create(uid, packageName)); 657 } 658 for (int i = 0; i < size; i++) { 659 final Pair<Integer, String> pair = mRunAnyRestrictedPackages.valueAt(i); 660 661 if ((pair.first == uid) && packageName.equals(pair.second)) { 662 return i; 663 } 664 } 665 return -1; 666 } 667 668 /** 669 * @return whether a uid package-name pair is in mRunAnyRestrictedPackages. 670 */ 671 @GuardedBy("mLock") isRunAnyRestrictedLocked(int uid, @NonNull String packageName)672 boolean isRunAnyRestrictedLocked(int uid, @NonNull String packageName) { 673 return findForcedAppStandbyUidPackageIndexLocked(uid, packageName) >= 0; 674 } 675 676 /** 677 * Add to / remove from {@link #mRunAnyRestrictedPackages}. 678 */ 679 @GuardedBy("mLock") updateForcedAppStandbyUidPackageLocked(int uid, @NonNull String packageName, boolean restricted)680 boolean updateForcedAppStandbyUidPackageLocked(int uid, @NonNull String packageName, 681 boolean restricted) { 682 final int index = findForcedAppStandbyUidPackageIndexLocked(uid, packageName); 683 final boolean wasRestricted = index >= 0; 684 if (wasRestricted == restricted) { 685 return false; 686 } 687 if (restricted) { 688 mRunAnyRestrictedPackages.add(Pair.create(uid, packageName)); 689 } else { 690 mRunAnyRestrictedPackages.removeAt(index); 691 } 692 updateBackgroundRestrictedUidPackagesLocked(); 693 return true; 694 } 695 addUidToArray(SparseBooleanArray array, int uid)696 private static boolean addUidToArray(SparseBooleanArray array, int uid) { 697 if (UserHandle.isCore(uid)) { 698 return false; 699 } 700 if (array.get(uid)) { 701 return false; 702 } 703 array.put(uid, true); 704 return true; 705 } 706 removeUidFromArray(SparseBooleanArray array, int uid, boolean remove)707 private static boolean removeUidFromArray(SparseBooleanArray array, int uid, boolean remove) { 708 if (UserHandle.isCore(uid)) { 709 return false; 710 } 711 if (!array.get(uid)) { 712 return false; 713 } 714 if (remove) { 715 array.delete(uid); 716 } else { 717 array.put(uid, false); 718 } 719 return true; 720 } 721 722 private final class UidObserver extends android.app.UidObserver { 723 @Override onUidActive(int uid)724 public void onUidActive(int uid) { 725 mHandler.onUidActive(uid); 726 } 727 728 @Override onUidGone(int uid, boolean disabled)729 public void onUidGone(int uid, boolean disabled) { 730 mHandler.onUidGone(uid, disabled); 731 } 732 733 @Override onUidIdle(int uid, boolean disabled)734 public void onUidIdle(int uid, boolean disabled) { 735 mHandler.onUidIdle(uid, disabled); 736 } 737 738 @Override onUidCachedChanged(int uid, boolean cached)739 public void onUidCachedChanged(int uid, boolean cached) { 740 mHandler.onUidCachedChanged(uid, cached); 741 } 742 } 743 744 private final class AppOpsWatcher extends IAppOpsCallback.Stub { 745 @Override opChanged(int op, int uid, String packageName)746 public void opChanged(int op, int uid, String packageName) throws RemoteException { 747 boolean restricted = false; 748 try { 749 restricted = mAppOpsService.checkOperation(TARGET_OP, 750 uid, packageName) != AppOpsManager.MODE_ALLOWED; 751 } catch (RemoteException e) { 752 // Shouldn't happen 753 } 754 if (restricted) { 755 Counter.logIncrementWithUid(APP_RESTRICTION_COUNTER_METRIC_ID, uid); 756 } 757 synchronized (mLock) { 758 if (updateForcedAppStandbyUidPackageLocked(uid, packageName, restricted)) { 759 mHandler.notifyRunAnyAppOpsChanged(uid, packageName); 760 } 761 } 762 } 763 } 764 765 final class StandbyTracker extends AppIdleStateChangeListener { 766 @Override onAppIdleStateChanged(String packageName, int userId, boolean idle, int bucket, int reason)767 public void onAppIdleStateChanged(String packageName, int userId, boolean idle, 768 int bucket, int reason) { 769 if (DEBUG) { 770 Slog.d(TAG, "onAppIdleStateChanged: " + packageName + " u" + userId 771 + (idle ? " idle" : " active") + " " + bucket); 772 } 773 synchronized (mLock) { 774 final boolean changed; 775 if (bucket == UsageStatsManager.STANDBY_BUCKET_EXEMPTED) { 776 changed = mExemptedBucketPackages.add(userId, packageName); 777 } else { 778 changed = mExemptedBucketPackages.remove(userId, packageName); 779 } 780 if (changed) { 781 mHandler.notifyExemptedBucketChanged(); 782 } 783 } 784 } 785 } 786 cloneListeners()787 private Listener[] cloneListeners() { 788 synchronized (mLock) { 789 return mListeners.toArray(new Listener[mListeners.size()]); 790 } 791 } 792 793 private class MyHandler extends Handler { 794 private static final int MSG_UID_ACTIVE_STATE_CHANGED = 0; 795 // Unused ids 1, 2. 796 private static final int MSG_RUN_ANY_CHANGED = 3; 797 private static final int MSG_ALL_UNEXEMPTED = 4; 798 private static final int MSG_ALL_EXEMPTION_LIST_CHANGED = 5; 799 private static final int MSG_TEMP_EXEMPTION_LIST_CHANGED = 6; 800 private static final int MSG_FORCE_ALL_CHANGED = 7; 801 private static final int MSG_USER_REMOVED = 8; 802 // Unused id 9. 803 private static final int MSG_EXEMPTED_BUCKET_CHANGED = 10; 804 private static final int MSG_AUTO_RESTRICTED_BUCKET_FEATURE_FLAG_CHANGED = 11; 805 806 private static final int MSG_ON_UID_ACTIVE = 12; 807 private static final int MSG_ON_UID_GONE = 13; 808 private static final int MSG_ON_UID_IDLE = 14; 809 private static final int MSG_ON_UID_CACHED = 15; 810 MyHandler(Looper looper)811 MyHandler(Looper looper) { 812 super(looper); 813 } 814 notifyUidActiveStateChanged(int uid)815 public void notifyUidActiveStateChanged(int uid) { 816 obtainMessage(MSG_UID_ACTIVE_STATE_CHANGED, uid, 0).sendToTarget(); 817 } 818 notifyRunAnyAppOpsChanged(int uid, @NonNull String packageName)819 public void notifyRunAnyAppOpsChanged(int uid, @NonNull String packageName) { 820 obtainMessage(MSG_RUN_ANY_CHANGED, uid, 0, packageName).sendToTarget(); 821 } 822 notifyAllUnexempted()823 public void notifyAllUnexempted() { 824 removeMessages(MSG_ALL_UNEXEMPTED); 825 obtainMessage(MSG_ALL_UNEXEMPTED).sendToTarget(); 826 } 827 notifyAllExemptionListChanged()828 public void notifyAllExemptionListChanged() { 829 removeMessages(MSG_ALL_EXEMPTION_LIST_CHANGED); 830 obtainMessage(MSG_ALL_EXEMPTION_LIST_CHANGED).sendToTarget(); 831 } 832 notifyTempExemptionListChanged()833 public void notifyTempExemptionListChanged() { 834 removeMessages(MSG_TEMP_EXEMPTION_LIST_CHANGED); 835 obtainMessage(MSG_TEMP_EXEMPTION_LIST_CHANGED).sendToTarget(); 836 } 837 notifyForceAllAppsStandbyChanged()838 public void notifyForceAllAppsStandbyChanged() { 839 removeMessages(MSG_FORCE_ALL_CHANGED); 840 obtainMessage(MSG_FORCE_ALL_CHANGED).sendToTarget(); 841 } 842 notifyExemptedBucketChanged()843 public void notifyExemptedBucketChanged() { 844 removeMessages(MSG_EXEMPTED_BUCKET_CHANGED); 845 obtainMessage(MSG_EXEMPTED_BUCKET_CHANGED).sendToTarget(); 846 } 847 notifyAutoRestrictedBucketFeatureFlagChanged(boolean autoRestrictedBucket)848 public void notifyAutoRestrictedBucketFeatureFlagChanged(boolean autoRestrictedBucket) { 849 removeMessages(MSG_AUTO_RESTRICTED_BUCKET_FEATURE_FLAG_CHANGED); 850 obtainMessage(MSG_AUTO_RESTRICTED_BUCKET_FEATURE_FLAG_CHANGED, 851 autoRestrictedBucket ? 1 : 0, 0).sendToTarget(); 852 } 853 doUserRemoved(int userId)854 public void doUserRemoved(int userId) { 855 obtainMessage(MSG_USER_REMOVED, userId, 0).sendToTarget(); 856 } 857 onUidActive(int uid)858 public void onUidActive(int uid) { 859 obtainMessage(MSG_ON_UID_ACTIVE, uid, 0).sendToTarget(); 860 } 861 onUidGone(int uid, boolean disabled)862 public void onUidGone(int uid, boolean disabled) { 863 obtainMessage(MSG_ON_UID_GONE, uid, disabled ? 1 : 0).sendToTarget(); 864 } 865 onUidIdle(int uid, boolean disabled)866 public void onUidIdle(int uid, boolean disabled) { 867 obtainMessage(MSG_ON_UID_IDLE, uid, disabled ? 1 : 0).sendToTarget(); 868 } 869 onUidCachedChanged(int uid, boolean cached)870 public void onUidCachedChanged(int uid, boolean cached) { 871 obtainMessage(MSG_ON_UID_CACHED, uid, cached ? 1 : 0).sendToTarget(); 872 } 873 874 @Override handleMessage(Message msg)875 public void handleMessage(Message msg) { 876 switch (msg.what) { 877 case MSG_USER_REMOVED: 878 handleUserRemoved(msg.arg1); 879 return; 880 } 881 882 // Only notify the listeners when started. 883 synchronized (mLock) { 884 if (!mStarted) { 885 return; 886 } 887 } 888 final AppStateTrackerImpl sender = AppStateTrackerImpl.this; 889 890 long start = mStatLogger.getTime(); 891 switch (msg.what) { 892 case MSG_UID_ACTIVE_STATE_CHANGED: 893 for (Listener l : cloneListeners()) { 894 l.onUidActiveStateChanged(sender, msg.arg1); 895 } 896 mStatLogger.logDurationStat(Stats.UID_ACTIVE_STATE_CHANGED, start); 897 return; 898 899 case MSG_RUN_ANY_CHANGED: 900 for (Listener l : cloneListeners()) { 901 l.onRunAnyAppOpsChanged(sender, msg.arg1, (String) msg.obj); 902 } 903 mStatLogger.logDurationStat(Stats.RUN_ANY_CHANGED, start); 904 return; 905 906 case MSG_ALL_UNEXEMPTED: 907 for (Listener l : cloneListeners()) { 908 l.onPowerSaveUnexempted(sender); 909 } 910 mStatLogger.logDurationStat(Stats.ALL_UNEXEMPTED, start); 911 return; 912 913 case MSG_ALL_EXEMPTION_LIST_CHANGED: 914 for (Listener l : cloneListeners()) { 915 l.onPowerSaveExemptionListChanged(sender); 916 } 917 mStatLogger.logDurationStat(Stats.ALL_EXEMPTION_LIST_CHANGED, start); 918 return; 919 920 case MSG_TEMP_EXEMPTION_LIST_CHANGED: 921 for (Listener l : cloneListeners()) { 922 l.onTempPowerSaveExemptionListChanged(sender); 923 } 924 mStatLogger.logDurationStat(Stats.TEMP_EXEMPTION_LIST_CHANGED, start); 925 return; 926 927 case MSG_EXEMPTED_BUCKET_CHANGED: 928 for (Listener l : cloneListeners()) { 929 l.onExemptedBucketChanged(sender); 930 } 931 mStatLogger.logDurationStat(Stats.EXEMPTED_BUCKET_CHANGED, start); 932 return; 933 934 case MSG_FORCE_ALL_CHANGED: 935 for (Listener l : cloneListeners()) { 936 l.onForceAllAppsStandbyChanged(sender); 937 } 938 mStatLogger.logDurationStat(Stats.FORCE_ALL_CHANGED, start); 939 return; 940 941 case MSG_USER_REMOVED: 942 handleUserRemoved(msg.arg1); 943 return; 944 945 case MSG_AUTO_RESTRICTED_BUCKET_FEATURE_FLAG_CHANGED: 946 final boolean autoRestrictedBucket = msg.arg1 == 1; 947 for (Listener l : cloneListeners()) { 948 l.onAutoRestrictedBucketFeatureFlagChanged(sender, autoRestrictedBucket); 949 } 950 return; 951 952 case MSG_ON_UID_ACTIVE: 953 handleUidActive(msg.arg1); 954 return; 955 case MSG_ON_UID_GONE: 956 handleUidGone(msg.arg1); 957 if (msg.arg2 != 0) { 958 handleUidDisabled(msg.arg1); 959 } 960 return; 961 case MSG_ON_UID_IDLE: 962 handleUidIdle(msg.arg1); 963 if (msg.arg2 != 0) { 964 handleUidDisabled(msg.arg1); 965 } 966 return; 967 case MSG_ON_UID_CACHED: 968 handleUidCached(msg.arg1, (msg.arg2 != 0)); 969 return; 970 } 971 } 972 handleUidCached(int uid, boolean cached)973 private void handleUidCached(int uid, boolean cached) { 974 for (Listener l : cloneListeners()) { 975 l.handleUidCachedChanged(uid, cached); 976 } 977 } 978 handleUidDisabled(int uid)979 private void handleUidDisabled(int uid) { 980 for (Listener l : cloneListeners()) { 981 l.removeAlarmsForUid(uid); 982 } 983 } 984 handleUidActive(int uid)985 public void handleUidActive(int uid) { 986 synchronized (mLock) { 987 if (addUidToArray(mActiveUids, uid)) { 988 mHandler.notifyUidActiveStateChanged(uid); 989 } 990 } 991 } 992 handleUidGone(int uid)993 public void handleUidGone(int uid) { 994 removeUid(uid, true); 995 } 996 handleUidIdle(int uid)997 public void handleUidIdle(int uid) { 998 // Just to avoid excessive memcpy, don't remove from the array in this case. 999 removeUid(uid, false); 1000 } 1001 removeUid(int uid, boolean remove)1002 private void removeUid(int uid, boolean remove) { 1003 synchronized (mLock) { 1004 if (removeUidFromArray(mActiveUids, uid, remove)) { 1005 mHandler.notifyUidActiveStateChanged(uid); 1006 } 1007 } 1008 } 1009 } 1010 handleUserRemoved(int removedUserId)1011 void handleUserRemoved(int removedUserId) { 1012 synchronized (mLock) { 1013 for (int i = mRunAnyRestrictedPackages.size() - 1; i >= 0; i--) { 1014 final Pair<Integer, String> pair = mRunAnyRestrictedPackages.valueAt(i); 1015 final int uid = pair.first; 1016 final int userId = UserHandle.getUserId(uid); 1017 1018 if (userId == removedUserId) { 1019 mRunAnyRestrictedPackages.removeAt(i); 1020 } 1021 } 1022 updateBackgroundRestrictedUidPackagesLocked(); 1023 cleanUpArrayForUser(mActiveUids, removedUserId); 1024 mExemptedBucketPackages.remove(removedUserId); 1025 } 1026 } 1027 cleanUpArrayForUser(SparseBooleanArray array, int removedUserId)1028 private void cleanUpArrayForUser(SparseBooleanArray array, int removedUserId) { 1029 for (int i = array.size() - 1; i >= 0; i--) { 1030 final int uid = array.keyAt(i); 1031 final int userId = UserHandle.getUserId(uid); 1032 1033 if (userId == removedUserId) { 1034 array.removeAt(i); 1035 } 1036 } 1037 } 1038 1039 /** 1040 * Called by device idle controller to update the power save exemption lists. 1041 */ setPowerSaveExemptionListAppIds( int[] powerSaveExemptionListExceptIdleAppIdArray, int[] powerSaveExemptionListUserAppIdArray, int[] tempExemptionListAppIdArray)1042 public void setPowerSaveExemptionListAppIds( 1043 int[] powerSaveExemptionListExceptIdleAppIdArray, 1044 int[] powerSaveExemptionListUserAppIdArray, 1045 int[] tempExemptionListAppIdArray) { 1046 synchronized (mLock) { 1047 final int[] previousExemptionList = mPowerExemptAllAppIds; 1048 final int[] previousTempExemptionList = mTempExemptAppIds; 1049 1050 mPowerExemptAllAppIds = powerSaveExemptionListExceptIdleAppIdArray; 1051 mTempExemptAppIds = tempExemptionListAppIdArray; 1052 mPowerExemptUserAppIds = powerSaveExemptionListUserAppIdArray; 1053 1054 if (isAnyAppIdUnexempt(previousExemptionList, mPowerExemptAllAppIds)) { 1055 mHandler.notifyAllUnexempted(); 1056 } else if (!Arrays.equals(previousExemptionList, mPowerExemptAllAppIds)) { 1057 mHandler.notifyAllExemptionListChanged(); 1058 } 1059 1060 if (!Arrays.equals(previousTempExemptionList, mTempExemptAppIds)) { 1061 mHandler.notifyTempExemptionListChanged(); 1062 } 1063 1064 } 1065 } 1066 1067 /** 1068 * @return true if a sorted app-id array {@code prevArray} has at least one element 1069 * that's not in a sorted app-id array {@code newArray}. 1070 */ 1071 @VisibleForTesting isAnyAppIdUnexempt(int[] prevArray, int[] newArray)1072 static boolean isAnyAppIdUnexempt(int[] prevArray, int[] newArray) { 1073 int i1 = 0; 1074 int i2 = 0; 1075 boolean prevFinished; 1076 boolean newFinished; 1077 1078 for (;;) { 1079 prevFinished = i1 >= prevArray.length; 1080 newFinished = i2 >= newArray.length; 1081 if (prevFinished || newFinished) { 1082 break; 1083 } 1084 int a1 = prevArray[i1]; 1085 int a2 = newArray[i2]; 1086 1087 if (a1 == a2) { 1088 i1++; 1089 i2++; 1090 continue; 1091 } 1092 if (a1 < a2) { 1093 // prevArray has an element that's not in a2. 1094 return true; 1095 } 1096 i2++; 1097 } 1098 if (prevFinished) { 1099 return false; 1100 } 1101 return newFinished; 1102 } 1103 1104 // Public interface. 1105 1106 /** 1107 * Register a listener to get callbacks when any state changes. 1108 */ addListener(@onNull Listener listener)1109 public void addListener(@NonNull Listener listener) { 1110 synchronized (mLock) { 1111 mListeners.add(listener); 1112 } 1113 } 1114 1115 /** 1116 * @return whether alarms should be restricted for a UID package-name, due to explicit 1117 * user-forced app standby. Use {{@link #areAlarmsRestrictedByBatterySaver} to check for 1118 * restrictions induced by battery saver. 1119 */ areAlarmsRestricted(int uid, @NonNull String packageName)1120 public boolean areAlarmsRestricted(int uid, @NonNull String packageName) { 1121 if (isUidActive(uid)) { 1122 return false; 1123 } 1124 synchronized (mLock) { 1125 final int appId = UserHandle.getAppId(uid); 1126 if (ArrayUtils.contains(mPowerExemptAllAppIds, appId)) { 1127 return false; 1128 } 1129 // If apps will be put into restricted standby bucket automatically on user-forced 1130 // app standby, instead of blocking alarms completely, let the restricted standby bucket 1131 // policy take care of it. 1132 return (!mActivityManagerInternal.isBgAutoRestrictedBucketFeatureFlagEnabled() 1133 && isRunAnyRestrictedLocked(uid, packageName)); 1134 } 1135 } 1136 1137 /** 1138 * @return whether alarms should be restricted when due to battery saver. 1139 */ areAlarmsRestrictedByBatterySaver(int uid, @NonNull String packageName)1140 public boolean areAlarmsRestrictedByBatterySaver(int uid, @NonNull String packageName) { 1141 if (isUidActive(uid)) { 1142 return false; 1143 } 1144 synchronized (mLock) { 1145 final int appId = UserHandle.getAppId(uid); 1146 if (ArrayUtils.contains(mPowerExemptAllAppIds, appId)) { 1147 return false; 1148 } 1149 final int userId = UserHandle.getUserId(uid); 1150 if (mAppStandbyInternal.isAppIdleEnabled() && !mAppStandbyInternal.isInParole() 1151 && mExemptedBucketPackages.contains(userId, packageName)) { 1152 return false; 1153 } 1154 return mForceAllAppsStandby; 1155 } 1156 } 1157 1158 1159 /** 1160 * @return whether jobs should be restricted for a UID package-name. This could be due to 1161 * battery saver or user-forced app standby 1162 */ areJobsRestricted(int uid, @NonNull String packageName, boolean hasForegroundExemption)1163 public boolean areJobsRestricted(int uid, @NonNull String packageName, 1164 boolean hasForegroundExemption) { 1165 if (isUidActive(uid)) { 1166 return false; 1167 } 1168 synchronized (mLock) { 1169 final int appId = UserHandle.getAppId(uid); 1170 if (ArrayUtils.contains(mPowerExemptAllAppIds, appId) 1171 || ArrayUtils.contains(mTempExemptAppIds, appId)) { 1172 return false; 1173 } 1174 // If apps will be put into restricted standby bucket automatically on user-forced 1175 // app standby, instead of blocking jobs completely, let the restricted standby bucket 1176 // policy take care of it. 1177 if (!mActivityManagerInternal.isBgAutoRestrictedBucketFeatureFlagEnabled() 1178 && isRunAnyRestrictedLocked(uid, packageName)) { 1179 return true; 1180 } 1181 if (hasForegroundExemption) { 1182 return false; 1183 } 1184 final int userId = UserHandle.getUserId(uid); 1185 if (mAppStandbyInternal.isAppIdleEnabled() && !mAppStandbyInternal.isInParole() 1186 && mExemptedBucketPackages.contains(userId, packageName)) { 1187 return false; 1188 } 1189 return mForceAllAppsStandby; 1190 } 1191 } 1192 1193 /** 1194 * @return whether a UID is in active or not *based on cached information.* 1195 * 1196 * Note this information is based on the UID proc state callback, meaning it's updated 1197 * asynchronously and may subtly be stale. If the fresh data is needed, use 1198 * {@link #isUidActiveSynced} instead. 1199 */ isUidActive(int uid)1200 public boolean isUidActive(int uid) { 1201 if (UserHandle.isCore(uid)) { 1202 return true; 1203 } 1204 synchronized (mLock) { 1205 return mActiveUids.get(uid); 1206 } 1207 } 1208 1209 /** 1210 * @return whether a UID is in active or not *right now.* 1211 * 1212 * This gives the fresh information, but may access the activity manager so is slower. 1213 */ isUidActiveSynced(int uid)1214 public boolean isUidActiveSynced(int uid) { 1215 if (isUidActive(uid)) { // Use the cached one first. 1216 return true; 1217 } 1218 final long start = mStatLogger.getTime(); 1219 1220 final boolean ret = mActivityManagerInternal.isUidActive(uid); 1221 mStatLogger.logDurationStat(Stats.IS_UID_ACTIVE_RAW, start); 1222 1223 return ret; 1224 } 1225 1226 /** 1227 * @return whether force all apps standby is enabled or not. 1228 */ isForceAllAppsStandbyEnabled()1229 public boolean isForceAllAppsStandbyEnabled() { 1230 synchronized (mLock) { 1231 return mForceAllAppsStandby; 1232 } 1233 } 1234 1235 /** 1236 * @return whether a UID/package has {@code OP_RUN_ANY_IN_BACKGROUND} allowed or not. 1237 * 1238 * Note clients normally shouldn't need to access it. It's only for dumpsys. 1239 */ isRunAnyInBackgroundAppOpsAllowed(int uid, @NonNull String packageName)1240 public boolean isRunAnyInBackgroundAppOpsAllowed(int uid, @NonNull String packageName) { 1241 synchronized (mLock) { 1242 return !isRunAnyRestrictedLocked(uid, packageName); 1243 } 1244 } 1245 1246 /** 1247 * @return whether a UID is in the user / system defined power-save exemption list or not. 1248 * 1249 * Note clients normally shouldn't need to access it. It's only for dumpsys. 1250 */ isUidPowerSaveExempt(int uid)1251 public boolean isUidPowerSaveExempt(int uid) { 1252 synchronized (mLock) { 1253 return ArrayUtils.contains(mPowerExemptAllAppIds, UserHandle.getAppId(uid)); 1254 } 1255 } 1256 1257 /** 1258 * @param uid the uid to check for 1259 * @return whether a UID is in the user defined power-save exemption list or not. 1260 */ isUidPowerSaveUserExempt(int uid)1261 public boolean isUidPowerSaveUserExempt(int uid) { 1262 synchronized (mLock) { 1263 return ArrayUtils.contains(mPowerExemptUserAppIds, UserHandle.getAppId(uid)); 1264 } 1265 } 1266 1267 /** 1268 * @return whether a UID is in the temp power-save exemption list or not. 1269 * 1270 * Note clients normally shouldn't need to access it. It's only for dumpsys. 1271 */ isUidTempPowerSaveExempt(int uid)1272 public boolean isUidTempPowerSaveExempt(int uid) { 1273 synchronized (mLock) { 1274 return ArrayUtils.contains(mTempExemptAppIds, UserHandle.getAppId(uid)); 1275 } 1276 } 1277 1278 /** 1279 * Dump the internal state to the given PrintWriter. Can be included in the dump 1280 * of a binder service to be output on the shell command "dumpsys". 1281 */ dump(IndentingPrintWriter pw)1282 public void dump(IndentingPrintWriter pw) { 1283 synchronized (mLock) { 1284 pw.println("Current AppStateTracker State:"); 1285 1286 pw.increaseIndent(); 1287 pw.print("Force all apps standby: "); 1288 pw.println(isForceAllAppsStandbyEnabled()); 1289 1290 pw.print("Small Battery Device: "); 1291 pw.println(isSmallBatteryDevice()); 1292 1293 pw.print("Force all apps standby for small battery device: "); 1294 pw.println(mForceAllAppStandbyForSmallBattery); 1295 1296 pw.print("Plugged In: "); 1297 pw.println(mIsPluggedIn); 1298 1299 pw.print("Active uids: "); 1300 dumpUids(pw, mActiveUids); 1301 1302 pw.print("Except-idle + user exemption list appids: "); 1303 pw.println(Arrays.toString(mPowerExemptAllAppIds)); 1304 1305 pw.print("User exemption list appids: "); 1306 pw.println(Arrays.toString(mPowerExemptUserAppIds)); 1307 1308 pw.print("Temp exemption list appids: "); 1309 pw.println(Arrays.toString(mTempExemptAppIds)); 1310 1311 pw.println("Exempted bucket packages:"); 1312 pw.increaseIndent(); 1313 for (int i = 0; i < mExemptedBucketPackages.size(); i++) { 1314 pw.print("User "); 1315 pw.print(mExemptedBucketPackages.keyAt(i)); 1316 pw.println(); 1317 1318 pw.increaseIndent(); 1319 for (int j = 0; j < mExemptedBucketPackages.sizeAt(i); j++) { 1320 pw.print(mExemptedBucketPackages.valueAt(i, j)); 1321 pw.println(); 1322 } 1323 pw.decreaseIndent(); 1324 } 1325 pw.decreaseIndent(); 1326 pw.println(); 1327 1328 pw.println("Restricted packages:"); 1329 pw.increaseIndent(); 1330 for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) { 1331 pw.print(UserHandle.formatUid(uidAndPackage.first)); 1332 pw.print(" "); 1333 pw.print(uidAndPackage.second); 1334 pw.println(); 1335 } 1336 pw.decreaseIndent(); 1337 1338 mStatLogger.dump(pw); 1339 pw.decreaseIndent(); 1340 } 1341 } 1342 dumpUids(PrintWriter pw, SparseBooleanArray array)1343 private void dumpUids(PrintWriter pw, SparseBooleanArray array) { 1344 pw.print("["); 1345 1346 String sep = ""; 1347 for (int i = 0; i < array.size(); i++) { 1348 if (array.valueAt(i)) { 1349 pw.print(sep); 1350 pw.print(UserHandle.formatUid(array.keyAt(i))); 1351 sep = " "; 1352 } 1353 } 1354 pw.println("]"); 1355 } 1356 1357 /** 1358 * Proto version of {@link #dump(IndentingPrintWriter)} 1359 */ dumpProto(ProtoOutputStream proto, long fieldId)1360 public void dumpProto(ProtoOutputStream proto, long fieldId) { 1361 synchronized (mLock) { 1362 final long token = proto.start(fieldId); 1363 1364 proto.write(AppStateTrackerProto.FORCE_ALL_APPS_STANDBY, 1365 isForceAllAppsStandbyEnabled()); 1366 proto.write(AppStateTrackerProto.IS_SMALL_BATTERY_DEVICE, isSmallBatteryDevice()); 1367 proto.write(AppStateTrackerProto.FORCE_ALL_APPS_STANDBY_FOR_SMALL_BATTERY, 1368 mForceAllAppStandbyForSmallBattery); 1369 proto.write(AppStateTrackerProto.IS_PLUGGED_IN, mIsPluggedIn); 1370 1371 for (int i = 0; i < mActiveUids.size(); i++) { 1372 if (mActiveUids.valueAt(i)) { 1373 proto.write(AppStateTrackerProto.ACTIVE_UIDS, mActiveUids.keyAt(i)); 1374 } 1375 } 1376 1377 for (int appId : mPowerExemptAllAppIds) { 1378 proto.write(AppStateTrackerProto.POWER_SAVE_EXEMPT_APP_IDS, appId); 1379 } 1380 1381 for (int appId : mPowerExemptUserAppIds) { 1382 proto.write(AppStateTrackerProto.POWER_SAVE_USER_EXEMPT_APP_IDS, appId); 1383 } 1384 1385 for (int appId : mTempExemptAppIds) { 1386 proto.write(AppStateTrackerProto.TEMP_POWER_SAVE_EXEMPT_APP_IDS, appId); 1387 } 1388 1389 for (int i = 0; i < mExemptedBucketPackages.size(); i++) { 1390 for (int j = 0; j < mExemptedBucketPackages.sizeAt(i); j++) { 1391 final long token2 = proto.start(AppStateTrackerProto.EXEMPTED_BUCKET_PACKAGES); 1392 1393 proto.write(ExemptedPackage.USER_ID, mExemptedBucketPackages.keyAt(i)); 1394 proto.write(ExemptedPackage.PACKAGE_NAME, 1395 mExemptedBucketPackages.valueAt(i, j)); 1396 1397 proto.end(token2); 1398 } 1399 } 1400 1401 for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) { 1402 final long token2 = proto.start( 1403 AppStateTrackerProto.RUN_ANY_IN_BACKGROUND_RESTRICTED_PACKAGES); 1404 proto.write(RunAnyInBackgroundRestrictedPackages.UID, uidAndPackage.first); 1405 proto.write(RunAnyInBackgroundRestrictedPackages.PACKAGE_NAME, 1406 uidAndPackage.second); 1407 proto.end(token2); 1408 } 1409 1410 mStatLogger.dumpProto(proto, AppStateTrackerProto.STATS); 1411 1412 proto.end(token); 1413 } 1414 } 1415 } 1416