1 /* 2 * Copyright (C) 2021 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 17 package com.android.server.tare; 18 19 import static android.app.tare.EconomyManager.ENABLED_MODE_OFF; 20 import static android.app.tare.EconomyManager.ENABLED_MODE_ON; 21 import static android.app.tare.EconomyManager.ENABLED_MODE_SHADOW; 22 import static android.app.tare.EconomyManager.enabledModeToString; 23 import static android.provider.Settings.Global.TARE_ALARM_MANAGER_CONSTANTS; 24 import static android.provider.Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS; 25 import static android.text.format.DateUtils.DAY_IN_MILLIS; 26 import static android.text.format.DateUtils.HOUR_IN_MILLIS; 27 import static android.text.format.DateUtils.MINUTE_IN_MILLIS; 28 29 import static com.android.server.tare.TareUtils.appToString; 30 import static com.android.server.tare.TareUtils.cakeToString; 31 import static com.android.server.tare.TareUtils.getCurrentTimeMillis; 32 33 import android.annotation.NonNull; 34 import android.annotation.Nullable; 35 import android.app.AlarmManager; 36 import android.app.AppOpsManager; 37 import android.app.tare.EconomyManager; 38 import android.app.tare.IEconomyManager; 39 import android.app.usage.UsageEvents; 40 import android.app.usage.UsageStatsManagerInternal; 41 import android.content.BroadcastReceiver; 42 import android.content.ContentResolver; 43 import android.content.Context; 44 import android.content.Intent; 45 import android.content.IntentFilter; 46 import android.content.pm.PackageInfo; 47 import android.content.pm.PackageManager; 48 import android.content.pm.PackageManagerInternal; 49 import android.database.ContentObserver; 50 import android.net.Uri; 51 import android.os.BatteryManager; 52 import android.os.BatteryManagerInternal; 53 import android.os.Binder; 54 import android.os.Handler; 55 import android.os.IDeviceIdleController; 56 import android.os.Looper; 57 import android.os.Message; 58 import android.os.ParcelFileDescriptor; 59 import android.os.PowerManager; 60 import android.os.RemoteException; 61 import android.os.ServiceManager; 62 import android.os.SystemClock; 63 import android.os.UserHandle; 64 import android.provider.DeviceConfig; 65 import android.provider.Settings; 66 import android.util.ArraySet; 67 import android.util.IndentingPrintWriter; 68 import android.util.Log; 69 import android.util.Slog; 70 import android.util.SparseArrayMap; 71 import android.util.SparseLongArray; 72 import android.util.SparseSetArray; 73 74 import com.android.internal.annotations.GuardedBy; 75 import com.android.internal.app.IAppOpsCallback; 76 import com.android.internal.app.IAppOpsService; 77 import com.android.internal.os.SomeArgs; 78 import com.android.internal.util.ArrayUtils; 79 import com.android.internal.util.DumpUtils; 80 import com.android.server.LocalServices; 81 import com.android.server.SystemService; 82 import com.android.server.pm.UserManagerInternal; 83 import com.android.server.tare.EconomicPolicy.Cost; 84 import com.android.server.tare.EconomyManagerInternal.TareStateChangeListener; 85 86 import java.io.FileDescriptor; 87 import java.io.PrintWriter; 88 import java.util.ArrayList; 89 import java.util.List; 90 import java.util.Objects; 91 92 /** 93 * Responsible for handling app's ARC count based on events, ensuring ARCs are credited when 94 * appropriate, and reclaiming ARCs at the right times. The IRS deals with the high level details 95 * while the {@link Agent} deals with the nitty-gritty details. 96 * 97 * Note on locking: Any function with the suffix 'Locked' needs to lock on {@link #mLock}. 98 * 99 * @hide 100 */ 101 public class InternalResourceService extends SystemService { 102 public static final String TAG = "TARE-IRS"; 103 public static final boolean DEBUG = Log.isLoggable("TARE", Log.DEBUG); 104 105 static final long UNUSED_RECLAMATION_PERIOD_MS = 24 * HOUR_IN_MILLIS; 106 /** How much of an app's unused wealth should be reclaimed periodically. */ 107 private static final float DEFAULT_UNUSED_RECLAMATION_PERCENTAGE = .1f; 108 /** 109 * The minimum amount of time an app must not have been used by the user before we start 110 * periodically reclaiming ARCs from it. 111 */ 112 private static final long MIN_UNUSED_TIME_MS = 3 * DAY_IN_MILLIS; 113 /** The amount of time to delay reclamation by after boot. */ 114 private static final long RECLAMATION_STARTUP_DELAY_MS = 30_000L; 115 /** 116 * The amount of time after TARE has first been set up that a system installer will be allowed 117 * expanded credit privileges. 118 */ 119 static final long INSTALLER_FIRST_SETUP_GRACE_PERIOD_MS = 7 * DAY_IN_MILLIS; 120 /** 121 * The amount of time to wait after TARE has first been set up before considering adjusting the 122 * stock/consumption limit. 123 */ 124 private static final long STOCK_ADJUSTMENT_FIRST_SETUP_GRACE_PERIOD_MS = 5 * DAY_IN_MILLIS; 125 /** 126 * The battery level above which we may consider quantitative easing (increasing the consumption 127 * limit). 128 */ 129 private static final int QUANTITATIVE_EASING_BATTERY_THRESHOLD = 50; 130 /** 131 * The battery level above which we may consider adjusting the desired stock level. 132 */ 133 private static final int STOCK_RECALCULATION_BATTERY_THRESHOLD = 80; 134 /** 135 * The amount of time to wait before considering recalculating the desired stock level. 136 */ 137 private static final long STOCK_RECALCULATION_DELAY_MS = 16 * HOUR_IN_MILLIS; 138 /** 139 * The minimum amount of time we must have background drain for before considering 140 * recalculating the desired stock level. 141 */ 142 private static final long STOCK_RECALCULATION_MIN_DATA_DURATION_MS = 8 * HOUR_IN_MILLIS; 143 private static final int PACKAGE_QUERY_FLAGS = 144 PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE 145 | PackageManager.MATCH_APEX | PackageManager.GET_PERMISSIONS; 146 147 /** Global lock for all resource economy state. */ 148 private final Object mLock = new Object(); 149 150 private final Handler mHandler; 151 private final BatteryManagerInternal mBatteryManagerInternal; 152 private final PackageManager mPackageManager; 153 private final PackageManagerInternal mPackageManagerInternal; 154 155 private IAppOpsService mAppOpsService; 156 private IDeviceIdleController mDeviceIdleController; 157 158 private final Agent mAgent; 159 private final Analyst mAnalyst; 160 private final ConfigObserver mConfigObserver; 161 private final EconomyManagerStub mEconomyManagerStub; 162 private final Scribe mScribe; 163 164 @GuardedBy("mLock") 165 private CompleteEconomicPolicy mCompleteEconomicPolicy; 166 167 @NonNull 168 @GuardedBy("mLock") 169 private final SparseArrayMap<String, InstalledPackageInfo> mPkgCache = new SparseArrayMap<>(); 170 171 /** Cached mapping of UIDs (for all users) to a list of packages in the UID. */ 172 @GuardedBy("mLock") 173 private final SparseSetArray<String> mUidToPackageCache = new SparseSetArray<>(); 174 175 /** Cached mapping of userId+package to their UIDs (for all users) */ 176 @GuardedBy("mPackageToUidCache") 177 private final SparseArrayMap<String, Integer> mPackageToUidCache = new SparseArrayMap<>(); 178 179 @GuardedBy("mStateChangeListeners") 180 private final SparseSetArray<TareStateChangeListener> mStateChangeListeners = 181 new SparseSetArray<>(); 182 183 /** 184 * List of packages that are fully restricted and shouldn't be allowed to run in the background. 185 */ 186 @GuardedBy("mLock") 187 private final SparseSetArray<String> mRestrictedApps = new SparseSetArray<>(); 188 189 /** List of packages that are "exempted" from battery restrictions. */ 190 // TODO(144864180): include userID 191 @GuardedBy("mLock") 192 private ArraySet<String> mExemptedApps = new ArraySet<>(); 193 194 @GuardedBy("mLock") 195 private final SparseArrayMap<String, Boolean> mVipOverrides = new SparseArrayMap<>(); 196 197 /** 198 * Set of temporary Very Important Packages and when their VIP status ends, in the elapsed 199 * realtime ({@link android.annotation.ElapsedRealtimeLong}) timebase. 200 */ 201 @GuardedBy("mLock") 202 private final SparseArrayMap<String, Long> mTemporaryVips = new SparseArrayMap<>(); 203 204 /** Set of apps each installer is responsible for installing. */ 205 @GuardedBy("mLock") 206 private final SparseArrayMap<String, ArraySet<String>> mInstallers = new SparseArrayMap<>(); 207 208 /** The package name of the wellbeing app. */ 209 @GuardedBy("mLock") 210 @Nullable 211 private String mWellbeingPackage; 212 213 private volatile boolean mHasBattery = true; 214 @EconomyManager.EnabledMode 215 private volatile int mEnabledMode; 216 private volatile int mBootPhase; 217 private volatile boolean mExemptListLoaded; 218 // In the range [0,100] to represent 0% to 100% battery. 219 @GuardedBy("mLock") 220 private int mCurrentBatteryLevel; 221 222 // TODO(250007395): make configurable per device (via config.xml) 223 private final int mDefaultTargetBackgroundBatteryLifeHours; 224 @GuardedBy("mLock") 225 private int mTargetBackgroundBatteryLifeHours; 226 227 private final IAppOpsCallback mApbListener = new IAppOpsCallback.Stub() { 228 @Override 229 public void opChanged(int op, int uid, String packageName) { 230 boolean restricted = false; 231 try { 232 restricted = mAppOpsService.checkOperation( 233 AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, packageName) 234 != AppOpsManager.MODE_ALLOWED; 235 } catch (RemoteException e) { 236 // Shouldn't happen 237 } 238 final int userId = UserHandle.getUserId(uid); 239 synchronized (mLock) { 240 if (restricted) { 241 if (mRestrictedApps.add(userId, packageName)) { 242 mAgent.onAppRestrictedLocked(userId, packageName); 243 } 244 } else if (mRestrictedApps.remove(UserHandle.getUserId(uid), packageName)) { 245 mAgent.onAppUnrestrictedLocked(userId, packageName); 246 } 247 } 248 } 249 }; 250 251 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 252 @Nullable 253 private String getPackageName(Intent intent) { 254 Uri uri = intent.getData(); 255 return uri != null ? uri.getSchemeSpecificPart() : null; 256 } 257 258 @Override 259 public void onReceive(Context context, Intent intent) { 260 switch (intent.getAction()) { 261 case Intent.ACTION_BATTERY_CHANGED: { 262 final boolean hasBattery = 263 intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, mHasBattery); 264 if (mHasBattery != hasBattery) { 265 mHasBattery = hasBattery; 266 mConfigObserver.updateEnabledStatus(); 267 } 268 } 269 break; 270 case Intent.ACTION_BATTERY_LEVEL_CHANGED: 271 onBatteryLevelChanged(); 272 break; 273 case Intent.ACTION_PACKAGE_FULLY_REMOVED: { 274 final String pkgName = getPackageName(intent); 275 final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1); 276 onPackageRemoved(pkgUid, pkgName); 277 } 278 break; 279 case Intent.ACTION_PACKAGE_ADDED: { 280 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 281 final String pkgName = getPackageName(intent); 282 final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1); 283 onPackageAdded(pkgUid, pkgName); 284 } 285 } 286 break; 287 case Intent.ACTION_PACKAGE_RESTARTED: { 288 final String pkgName = getPackageName(intent); 289 final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1); 290 final int userId = UserHandle.getUserId(pkgUid); 291 onPackageForceStopped(userId, pkgName); 292 } 293 break; 294 case Intent.ACTION_USER_ADDED: { 295 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 296 onUserAdded(userId); 297 } 298 break; 299 case Intent.ACTION_USER_REMOVED: { 300 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 301 onUserRemoved(userId); 302 } 303 break; 304 case PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED: 305 onExemptionListChanged(); 306 break; 307 } 308 } 309 }; 310 311 private final UsageStatsManagerInternal.UsageEventListener mSurveillanceAgent = 312 new UsageStatsManagerInternal.UsageEventListener() { 313 /** 314 * Callback to inform listeners of a new event. 315 */ 316 @Override 317 public void onUsageEvent(int userId, @NonNull UsageEvents.Event event) { 318 mHandler.obtainMessage(MSG_PROCESS_USAGE_EVENT, userId, 0, event) 319 .sendToTarget(); 320 } 321 }; 322 323 private final AlarmManager.OnAlarmListener mUnusedWealthReclamationListener = 324 new AlarmManager.OnAlarmListener() { 325 @Override 326 public void onAlarm() { 327 synchronized (mLock) { 328 mAgent.reclaimUnusedAssetsLocked( 329 DEFAULT_UNUSED_RECLAMATION_PERCENTAGE, MIN_UNUSED_TIME_MS, false); 330 mScribe.setLastReclamationTimeLocked(getCurrentTimeMillis()); 331 scheduleUnusedWealthReclamationLocked(); 332 } 333 } 334 }; 335 336 private static final int MSG_NOTIFY_AFFORDABILITY_CHANGE_LISTENER = 0; 337 private static final int MSG_SCHEDULE_UNUSED_WEALTH_RECLAMATION_EVENT = 1; 338 private static final int MSG_PROCESS_USAGE_EVENT = 2; 339 private static final int MSG_NOTIFY_STATE_CHANGE_LISTENERS = 3; 340 private static final int MSG_NOTIFY_STATE_CHANGE_LISTENER = 4; 341 private static final int MSG_CLEAN_UP_TEMP_VIP_LIST = 5; 342 private static final String ALARM_TAG_WEALTH_RECLAMATION = "*tare.reclamation*"; 343 344 /** 345 * Initializes the system service. 346 * <p> 347 * Subclasses must define a single argument constructor that accepts the context 348 * and passes it to super. 349 * </p> 350 * 351 * @param context The system server context. 352 */ InternalResourceService(Context context)353 public InternalResourceService(Context context) { 354 super(context); 355 356 mHandler = new IrsHandler(TareHandlerThread.get().getLooper()); 357 mBatteryManagerInternal = LocalServices.getService(BatteryManagerInternal.class); 358 mPackageManager = context.getPackageManager(); 359 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); 360 mEconomyManagerStub = new EconomyManagerStub(); 361 mAnalyst = new Analyst(); 362 mScribe = new Scribe(this, mAnalyst); 363 mCompleteEconomicPolicy = new CompleteEconomicPolicy(this); 364 mAgent = new Agent(this, mScribe, mAnalyst); 365 366 mConfigObserver = new ConfigObserver(mHandler, context); 367 368 mDefaultTargetBackgroundBatteryLifeHours = 369 mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH) 370 ? 100 // ~ 1.0%/hr 371 : 40; // ~ 2.5%/hr 372 mTargetBackgroundBatteryLifeHours = mDefaultTargetBackgroundBatteryLifeHours; 373 374 publishLocalService(EconomyManagerInternal.class, new LocalService()); 375 } 376 377 @Override onStart()378 public void onStart() { 379 publishBinderService(Context.RESOURCE_ECONOMY_SERVICE, mEconomyManagerStub); 380 } 381 382 @Override onBootPhase(int phase)383 public void onBootPhase(int phase) { 384 mBootPhase = phase; 385 386 switch (phase) { 387 case PHASE_SYSTEM_SERVICES_READY: 388 mAppOpsService = IAppOpsService.Stub.asInterface( 389 ServiceManager.getService(Context.APP_OPS_SERVICE)); 390 mDeviceIdleController = IDeviceIdleController.Stub.asInterface( 391 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 392 mConfigObserver.start(); 393 onBootPhaseSystemServicesReady(); 394 break; 395 case PHASE_THIRD_PARTY_APPS_CAN_START: 396 onBootPhaseThirdPartyAppsCanStart(); 397 break; 398 case PHASE_BOOT_COMPLETED: 399 onBootPhaseBootCompleted(); 400 break; 401 } 402 } 403 404 @NonNull getLock()405 Object getLock() { 406 return mLock; 407 } 408 409 /** Returns the installed packages for all users. */ 410 @NonNull 411 @GuardedBy("mLock") getCompleteEconomicPolicyLocked()412 CompleteEconomicPolicy getCompleteEconomicPolicyLocked() { 413 return mCompleteEconomicPolicy; 414 } 415 416 /** Returns the number of apps that this app is expected to update at some point. */ getAppUpdateResponsibilityCount(final int userId, @NonNull final String pkgName)417 int getAppUpdateResponsibilityCount(final int userId, @NonNull final String pkgName) { 418 synchronized (mLock) { 419 // TODO(248274798): return 0 if the app has lost the install permission 420 return ArrayUtils.size(mInstallers.get(userId, pkgName)); 421 } 422 } 423 424 @NonNull getInstalledPackages()425 SparseArrayMap<String, InstalledPackageInfo> getInstalledPackages() { 426 synchronized (mLock) { 427 return mPkgCache; 428 } 429 } 430 431 /** Returns the installed packages for the specified user. */ 432 @NonNull getInstalledPackages(final int userId)433 List<InstalledPackageInfo> getInstalledPackages(final int userId) { 434 final List<InstalledPackageInfo> userPkgs = new ArrayList<>(); 435 synchronized (mLock) { 436 final int uIdx = mPkgCache.indexOfKey(userId); 437 if (uIdx < 0) { 438 return userPkgs; 439 } 440 for (int p = mPkgCache.numElementsForKeyAt(uIdx) - 1; p >= 0; --p) { 441 final InstalledPackageInfo packageInfo = mPkgCache.valueAt(uIdx, p); 442 userPkgs.add(packageInfo); 443 } 444 } 445 return userPkgs; 446 } 447 448 @Nullable getInstalledPackageInfo(final int userId, @NonNull final String pkgName)449 InstalledPackageInfo getInstalledPackageInfo(final int userId, @NonNull final String pkgName) { 450 synchronized (mLock) { 451 return mPkgCache.get(userId, pkgName); 452 } 453 } 454 455 @GuardedBy("mLock") getConsumptionLimitLocked()456 long getConsumptionLimitLocked() { 457 return mCurrentBatteryLevel * mScribe.getSatiatedConsumptionLimitLocked() / 100; 458 } 459 460 @GuardedBy("mLock") getMinBalanceLocked(final int userId, @NonNull final String pkgName)461 long getMinBalanceLocked(final int userId, @NonNull final String pkgName) { 462 return mCurrentBatteryLevel * mCompleteEconomicPolicy.getMinSatiatedBalance(userId, pkgName) 463 / 100; 464 } 465 466 @GuardedBy("mLock") getInitialSatiatedConsumptionLimitLocked()467 long getInitialSatiatedConsumptionLimitLocked() { 468 return mCompleteEconomicPolicy.getInitialSatiatedConsumptionLimit(); 469 } 470 471 getRealtimeSinceFirstSetupMs()472 long getRealtimeSinceFirstSetupMs() { 473 return mScribe.getRealtimeSinceFirstSetupMs(SystemClock.elapsedRealtime()); 474 } 475 getUid(final int userId, @NonNull final String pkgName)476 int getUid(final int userId, @NonNull final String pkgName) { 477 synchronized (mPackageToUidCache) { 478 Integer uid = mPackageToUidCache.get(userId, pkgName); 479 if (uid == null) { 480 uid = mPackageManagerInternal.getPackageUid(pkgName, 0, userId); 481 mPackageToUidCache.add(userId, pkgName, uid); 482 } 483 return uid; 484 } 485 } 486 487 @EconomyManager.EnabledMode getEnabledMode()488 int getEnabledMode() { 489 return mEnabledMode; 490 } 491 492 @EconomyManager.EnabledMode getEnabledMode(int policyId)493 int getEnabledMode(int policyId) { 494 synchronized (mLock) { 495 // For now, treat enabled policies as using the same enabled mode as full TARE. 496 // TODO: have enabled mode by policy 497 if (mCompleteEconomicPolicy.isPolicyEnabled(policyId)) { 498 return mEnabledMode; 499 } 500 return ENABLED_MODE_OFF; 501 } 502 } 503 isHeadlessSystemApp(final int userId, @NonNull String pkgName)504 boolean isHeadlessSystemApp(final int userId, @NonNull String pkgName) { 505 if (pkgName == null) { 506 Slog.wtfStack(TAG, "isHeadlessSystemApp called with null package"); 507 return false; 508 } 509 synchronized (mLock) { 510 final InstalledPackageInfo ipo = getInstalledPackageInfo(userId, pkgName); 511 if (ipo != null && ipo.isHeadlessSystemApp) { 512 return true; 513 } 514 // The wellbeing app is pre-set on the device, not expected to be interacted with 515 // much by the user, but can be expected to do work in the background on behalf of 516 // the user. As such, it's a pseudo-headless system app, so treat it as a headless 517 // system app. 518 return pkgName.equals(mWellbeingPackage); 519 } 520 } 521 isPackageExempted(final int userId, @NonNull String pkgName)522 boolean isPackageExempted(final int userId, @NonNull String pkgName) { 523 synchronized (mLock) { 524 return mExemptedApps.contains(pkgName); 525 } 526 } 527 isPackageRestricted(final int userId, @NonNull String pkgName)528 boolean isPackageRestricted(final int userId, @NonNull String pkgName) { 529 synchronized (mLock) { 530 return mRestrictedApps.contains(userId, pkgName); 531 } 532 } 533 isSystem(final int userId, @NonNull String pkgName)534 boolean isSystem(final int userId, @NonNull String pkgName) { 535 if ("android".equals(pkgName)) { 536 return true; 537 } 538 return UserHandle.isCore(getUid(userId, pkgName)); 539 } 540 isVip(final int userId, @NonNull String pkgName)541 boolean isVip(final int userId, @NonNull String pkgName) { 542 return isVip(userId, pkgName, SystemClock.elapsedRealtime()); 543 } 544 isVip(final int userId, @NonNull String pkgName, final long nowElapsed)545 boolean isVip(final int userId, @NonNull String pkgName, final long nowElapsed) { 546 synchronized (mLock) { 547 final Boolean override = mVipOverrides.get(userId, pkgName); 548 if (override != null) { 549 return override; 550 } 551 } 552 if (isSystem(userId, pkgName)) { 553 // The government, I mean the system, can create ARCs as it needs to in order to 554 // operate. 555 return true; 556 } 557 synchronized (mLock) { 558 final Long expirationTimeElapsed = mTemporaryVips.get(userId, pkgName); 559 if (expirationTimeElapsed != null) { 560 return nowElapsed <= expirationTimeElapsed; 561 } 562 } 563 return false; 564 } 565 onBatteryLevelChanged()566 void onBatteryLevelChanged() { 567 synchronized (mLock) { 568 final int newBatteryLevel = getCurrentBatteryLevel(); 569 mAnalyst.noteBatteryLevelChange(newBatteryLevel); 570 final boolean increased = newBatteryLevel > mCurrentBatteryLevel; 571 if (increased) { 572 if (newBatteryLevel >= STOCK_RECALCULATION_BATTERY_THRESHOLD) { 573 maybeAdjustDesiredStockLevelLocked(); 574 } 575 mAgent.distributeBasicIncomeLocked(newBatteryLevel); 576 } else if (newBatteryLevel == mCurrentBatteryLevel) { 577 // The broadcast is also sent when the plug type changes... 578 return; 579 } 580 mCurrentBatteryLevel = newBatteryLevel; 581 adjustCreditSupplyLocked(increased); 582 } 583 } 584 onDeviceStateChanged()585 void onDeviceStateChanged() { 586 synchronized (mLock) { 587 mAgent.onDeviceStateChangedLocked(); 588 } 589 } 590 onExemptionListChanged()591 void onExemptionListChanged() { 592 final int[] userIds = LocalServices.getService(UserManagerInternal.class).getUserIds(); 593 synchronized (mLock) { 594 final ArraySet<String> removed = mExemptedApps; 595 final ArraySet<String> added = new ArraySet<>(); 596 try { 597 mExemptedApps = new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist()); 598 mExemptListLoaded = true; 599 } catch (RemoteException e) { 600 // Shouldn't happen. 601 } 602 603 for (int i = mExemptedApps.size() - 1; i >= 0; --i) { 604 final String pkg = mExemptedApps.valueAt(i); 605 if (!removed.contains(pkg)) { 606 added.add(pkg); 607 } 608 removed.remove(pkg); 609 } 610 for (int a = added.size() - 1; a >= 0; --a) { 611 final String pkgName = added.valueAt(a); 612 for (int userId : userIds) { 613 // Since the exemption list doesn't specify user ID and we track by user ID, 614 // we need to see if the app exists on the user before talking to the agent. 615 // Otherwise, we may end up with invalid ledgers. 616 final boolean appExists = getUid(userId, pkgName) >= 0; 617 if (appExists) { 618 mAgent.onAppExemptedLocked(userId, pkgName); 619 } 620 } 621 } 622 for (int r = removed.size() - 1; r >= 0; --r) { 623 final String pkgName = removed.valueAt(r); 624 for (int userId : userIds) { 625 // Since the exemption list doesn't specify user ID and we track by user ID, 626 // we need to see if the app exists on the user before talking to the agent. 627 // Otherwise, we may end up with invalid ledgers. 628 final boolean appExists = getUid(userId, pkgName) >= 0; 629 if (appExists) { 630 mAgent.onAppUnexemptedLocked(userId, pkgName); 631 } 632 } 633 } 634 } 635 } 636 onPackageAdded(final int uid, @NonNull final String pkgName)637 void onPackageAdded(final int uid, @NonNull final String pkgName) { 638 final int userId = UserHandle.getUserId(uid); 639 final PackageInfo packageInfo; 640 try { 641 packageInfo = 642 mPackageManager.getPackageInfoAsUser(pkgName, PACKAGE_QUERY_FLAGS, userId); 643 } catch (PackageManager.NameNotFoundException e) { 644 Slog.wtf(TAG, "PM couldn't find newly added package: " + pkgName, e); 645 return; 646 } 647 synchronized (mPackageToUidCache) { 648 mPackageToUidCache.add(userId, pkgName, uid); 649 } 650 synchronized (mLock) { 651 final InstalledPackageInfo ipo = new InstalledPackageInfo(getContext(), userId, 652 packageInfo); 653 final InstalledPackageInfo oldIpo = mPkgCache.add(userId, pkgName, ipo); 654 maybeUpdateInstallerStatusLocked(oldIpo, ipo); 655 mUidToPackageCache.add(uid, pkgName); 656 // TODO: only do this when the user first launches the app (app leaves stopped state) 657 mAgent.grantBirthrightLocked(userId, pkgName); 658 if (ipo.installerPackageName != null) { 659 mAgent.noteInstantaneousEventLocked(userId, ipo.installerPackageName, 660 JobSchedulerEconomicPolicy.REWARD_APP_INSTALL, null); 661 } 662 } 663 } 664 onPackageForceStopped(final int userId, @NonNull final String pkgName)665 void onPackageForceStopped(final int userId, @NonNull final String pkgName) { 666 synchronized (mLock) { 667 // Remove all credits if the user force stops the app. It will slowly regain them 668 // in response to different events. 669 mAgent.reclaimAllAssetsLocked(userId, pkgName, EconomicPolicy.REGULATION_FORCE_STOP); 670 } 671 } 672 onPackageRemoved(final int uid, @NonNull final String pkgName)673 void onPackageRemoved(final int uid, @NonNull final String pkgName) { 674 final int userId = UserHandle.getUserId(uid); 675 synchronized (mPackageToUidCache) { 676 mPackageToUidCache.delete(userId, pkgName); 677 } 678 synchronized (mLock) { 679 mUidToPackageCache.remove(uid, pkgName); 680 mVipOverrides.delete(userId, pkgName); 681 final InstalledPackageInfo ipo = mPkgCache.delete(userId, pkgName); 682 mInstallers.delete(userId, pkgName); 683 if (ipo != null && ipo.installerPackageName != null) { 684 final ArraySet<String> list = mInstallers.get(userId, ipo.installerPackageName); 685 if (list != null) { 686 list.remove(pkgName); 687 } 688 } 689 mAgent.onPackageRemovedLocked(userId, pkgName); 690 } 691 } 692 onUidStateChanged(final int uid)693 void onUidStateChanged(final int uid) { 694 synchronized (mLock) { 695 final ArraySet<String> pkgNames = getPackagesForUidLocked(uid); 696 if (pkgNames == null) { 697 Slog.e(TAG, "Don't have packages for uid " + uid); 698 } else { 699 mAgent.onAppStatesChangedLocked(UserHandle.getUserId(uid), pkgNames); 700 } 701 } 702 } 703 onUserAdded(final int userId)704 void onUserAdded(final int userId) { 705 synchronized (mLock) { 706 final List<PackageInfo> pkgs = 707 mPackageManager.getInstalledPackagesAsUser(PACKAGE_QUERY_FLAGS, userId); 708 for (int i = pkgs.size() - 1; i >= 0; --i) { 709 final InstalledPackageInfo ipo = 710 new InstalledPackageInfo(getContext(), userId, pkgs.get(i)); 711 final InstalledPackageInfo oldIpo = mPkgCache.add(userId, ipo.packageName, ipo); 712 maybeUpdateInstallerStatusLocked(oldIpo, ipo); 713 } 714 mAgent.grantBirthrightsLocked(userId); 715 final long nowElapsed = SystemClock.elapsedRealtime(); 716 mScribe.setUserAddedTimeLocked(userId, nowElapsed); 717 grantInstallersTemporaryVipStatusLocked(userId, 718 nowElapsed, INSTALLER_FIRST_SETUP_GRACE_PERIOD_MS); 719 } 720 } 721 onUserRemoved(final int userId)722 void onUserRemoved(final int userId) { 723 synchronized (mLock) { 724 mVipOverrides.delete(userId); 725 final int uIdx = mPkgCache.indexOfKey(userId); 726 if (uIdx >= 0) { 727 for (int p = mPkgCache.numElementsForKeyAt(uIdx) - 1; p >= 0; --p) { 728 final InstalledPackageInfo pkgInfo = mPkgCache.valueAt(uIdx, p); 729 mUidToPackageCache.remove(pkgInfo.uid); 730 } 731 } 732 mInstallers.delete(userId); 733 mPkgCache.delete(userId); 734 mAgent.onUserRemovedLocked(userId); 735 mScribe.onUserRemovedLocked(userId); 736 } 737 } 738 739 /** 740 * Try to increase the consumption limit if apps are reaching the current limit too quickly. 741 */ 742 @GuardedBy("mLock") maybePerformQuantitativeEasingLocked()743 void maybePerformQuantitativeEasingLocked() { 744 if (mConfigObserver.ENABLE_TIP3) { 745 maybeAdjustDesiredStockLevelLocked(); 746 return; 747 } 748 if (getRealtimeSinceFirstSetupMs() < STOCK_ADJUSTMENT_FIRST_SETUP_GRACE_PERIOD_MS) { 749 // Things can be very tumultuous soon after first setup. 750 return; 751 } 752 // We don't need to increase the limit if the device runs out of consumable credits 753 // when the battery is low. 754 final long remainingConsumableCakes = mScribe.getRemainingConsumableCakesLocked(); 755 if (mCurrentBatteryLevel <= QUANTITATIVE_EASING_BATTERY_THRESHOLD 756 || remainingConsumableCakes > 0) { 757 return; 758 } 759 final long currentConsumptionLimit = mScribe.getSatiatedConsumptionLimitLocked(); 760 final long shortfall = (mCurrentBatteryLevel - QUANTITATIVE_EASING_BATTERY_THRESHOLD) 761 * currentConsumptionLimit / 100; 762 final long newConsumptionLimit = Math.min(currentConsumptionLimit + shortfall, 763 mCompleteEconomicPolicy.getMaxSatiatedConsumptionLimit()); 764 if (newConsumptionLimit != currentConsumptionLimit) { 765 Slog.i(TAG, "Increasing consumption limit from " + cakeToString(currentConsumptionLimit) 766 + " to " + cakeToString(newConsumptionLimit)); 767 mScribe.setConsumptionLimitLocked(newConsumptionLimit); 768 adjustCreditSupplyLocked(/* allowIncrease */ true); 769 } 770 } 771 772 /** 773 * Adjust the consumption limit based on historical data and the target battery drain. 774 */ 775 @GuardedBy("mLock") maybeAdjustDesiredStockLevelLocked()776 void maybeAdjustDesiredStockLevelLocked() { 777 if (!mConfigObserver.ENABLE_TIP3) { 778 return; 779 } 780 if (getRealtimeSinceFirstSetupMs() < STOCK_ADJUSTMENT_FIRST_SETUP_GRACE_PERIOD_MS) { 781 // Things can be very tumultuous soon after first setup. 782 return; 783 } 784 // Don't adjust the limit too often or while the battery is low. 785 final long now = getCurrentTimeMillis(); 786 if ((now - mScribe.getLastStockRecalculationTimeLocked()) < STOCK_RECALCULATION_DELAY_MS 787 || mCurrentBatteryLevel <= STOCK_RECALCULATION_BATTERY_THRESHOLD) { 788 return; 789 } 790 791 // For now, use screen off battery drain as a proxy for background battery drain. 792 // TODO: get more accurate background battery drain numbers 793 final long totalScreenOffDurationMs = mAnalyst.getBatteryScreenOffDurationMs(); 794 if (totalScreenOffDurationMs < STOCK_RECALCULATION_MIN_DATA_DURATION_MS) { 795 return; 796 } 797 final long totalDischargeMah = mAnalyst.getBatteryScreenOffDischargeMah(); 798 if (totalDischargeMah == 0) { 799 Slog.i(TAG, "Total discharge was 0"); 800 return; 801 } 802 final long batteryCapacityMah = mBatteryManagerInternal.getBatteryFullCharge() / 1000; 803 final long estimatedLifeHours = batteryCapacityMah * totalScreenOffDurationMs 804 / totalDischargeMah / HOUR_IN_MILLIS; 805 final long percentageOfTarget = 806 100 * estimatedLifeHours / mTargetBackgroundBatteryLifeHours; 807 if (DEBUG) { 808 Slog.d(TAG, "maybeAdjustDesiredStockLevelLocked:" 809 + " screenOffMs=" + totalScreenOffDurationMs 810 + " dischargeMah=" + totalDischargeMah 811 + " capacityMah=" + batteryCapacityMah 812 + " estimatedLifeHours=" + estimatedLifeHours 813 + " %ofTarget=" + percentageOfTarget); 814 } 815 final long currentConsumptionLimit = mScribe.getSatiatedConsumptionLimitLocked(); 816 final long newConsumptionLimit; 817 if (percentageOfTarget > 105) { 818 // The stock is too low. We're doing pretty well. We can increase the stock slightly 819 // to let apps do more work in the background. 820 newConsumptionLimit = Math.min((long) (currentConsumptionLimit * 1.01), 821 mCompleteEconomicPolicy.getMaxSatiatedConsumptionLimit()); 822 } else if (percentageOfTarget < 100) { 823 // The stock is too high IMO. We're below the target. Decrease the stock to reduce 824 // background work. 825 newConsumptionLimit = Math.max((long) (currentConsumptionLimit * .98), 826 mCompleteEconomicPolicy.getMinSatiatedConsumptionLimit()); 827 } else { 828 // The stock is just right. 829 return; 830 } 831 // TODO(250007191): calculate and log implied service level 832 if (newConsumptionLimit != currentConsumptionLimit) { 833 Slog.i(TAG, "Adjusting consumption limit from " + cakeToString(currentConsumptionLimit) 834 + " to " + cakeToString(newConsumptionLimit) 835 + " because drain was " + percentageOfTarget + "% of target"); 836 mScribe.setConsumptionLimitLocked(newConsumptionLimit); 837 adjustCreditSupplyLocked(/* allowIncrease */ true); 838 mScribe.setLastStockRecalculationTimeLocked(now); 839 } 840 } 841 postAffordabilityChanged(final int userId, @NonNull final String pkgName, @NonNull Agent.ActionAffordabilityNote affordabilityNote)842 void postAffordabilityChanged(final int userId, @NonNull final String pkgName, 843 @NonNull Agent.ActionAffordabilityNote affordabilityNote) { 844 if (DEBUG) { 845 Slog.d(TAG, userId + ":" + pkgName + " affordability changed to " 846 + affordabilityNote.isCurrentlyAffordable()); 847 } 848 final SomeArgs args = SomeArgs.obtain(); 849 args.argi1 = userId; 850 args.arg1 = pkgName; 851 args.arg2 = affordabilityNote; 852 mHandler.obtainMessage(MSG_NOTIFY_AFFORDABILITY_CHANGE_LISTENER, args).sendToTarget(); 853 } 854 855 @GuardedBy("mLock") adjustCreditSupplyLocked(boolean allowIncrease)856 private void adjustCreditSupplyLocked(boolean allowIncrease) { 857 final long newLimit = getConsumptionLimitLocked(); 858 final long remainingConsumableCakes = mScribe.getRemainingConsumableCakesLocked(); 859 if (remainingConsumableCakes == newLimit) { 860 return; 861 } 862 if (remainingConsumableCakes > newLimit) { 863 mScribe.adjustRemainingConsumableCakesLocked(newLimit - remainingConsumableCakes); 864 } else if (allowIncrease) { 865 final double perc = mCurrentBatteryLevel / 100d; 866 final long shortfall = newLimit - remainingConsumableCakes; 867 mScribe.adjustRemainingConsumableCakesLocked((long) (perc * shortfall)); 868 } 869 mAgent.onCreditSupplyChanged(); 870 } 871 872 @GuardedBy("mLock") grantInstallersTemporaryVipStatusLocked(int userId, long nowElapsed, long grantDurationMs)873 private void grantInstallersTemporaryVipStatusLocked(int userId, long nowElapsed, 874 long grantDurationMs) { 875 final long grantEndTimeElapsed = nowElapsed + grantDurationMs; 876 final int uIdx = mPkgCache.indexOfKey(userId); 877 if (uIdx < 0) { 878 return; 879 } 880 for (int pIdx = mPkgCache.numElementsForKey(uIdx) - 1; pIdx >= 0; --pIdx) { 881 final InstalledPackageInfo ipo = mPkgCache.valueAt(uIdx, pIdx); 882 883 if (ipo.isSystemInstaller) { 884 final Long currentGrantEndTimeElapsed = mTemporaryVips.get(userId, ipo.packageName); 885 if (currentGrantEndTimeElapsed == null 886 || currentGrantEndTimeElapsed < grantEndTimeElapsed) { 887 mTemporaryVips.add(userId, ipo.packageName, grantEndTimeElapsed); 888 } 889 } 890 } 891 mHandler.sendEmptyMessageDelayed(MSG_CLEAN_UP_TEMP_VIP_LIST, grantDurationMs); 892 } 893 894 @GuardedBy("mLock") processUsageEventLocked(final int userId, @NonNull UsageEvents.Event event)895 private void processUsageEventLocked(final int userId, @NonNull UsageEvents.Event event) { 896 if (mEnabledMode == ENABLED_MODE_OFF) { 897 return; 898 } 899 final String pkgName = event.getPackageName(); 900 if (DEBUG) { 901 Slog.d(TAG, "Processing event " + event.getEventType() 902 + " (" + event.mInstanceId + ")" 903 + " for " + appToString(userId, pkgName)); 904 } 905 final long nowElapsed = SystemClock.elapsedRealtime(); 906 switch (event.getEventType()) { 907 case UsageEvents.Event.ACTIVITY_RESUMED: 908 mAgent.noteOngoingEventLocked(userId, pkgName, 909 EconomicPolicy.REWARD_TOP_ACTIVITY, String.valueOf(event.mInstanceId), 910 nowElapsed); 911 break; 912 case UsageEvents.Event.ACTIVITY_PAUSED: 913 case UsageEvents.Event.ACTIVITY_STOPPED: 914 case UsageEvents.Event.ACTIVITY_DESTROYED: 915 final long now = getCurrentTimeMillis(); 916 mAgent.stopOngoingActionLocked(userId, pkgName, 917 EconomicPolicy.REWARD_TOP_ACTIVITY, String.valueOf(event.mInstanceId), 918 nowElapsed, now); 919 break; 920 case UsageEvents.Event.USER_INTERACTION: 921 case UsageEvents.Event.CHOOSER_ACTION: 922 mAgent.noteInstantaneousEventLocked(userId, pkgName, 923 EconomicPolicy.REWARD_OTHER_USER_INTERACTION, null); 924 break; 925 case UsageEvents.Event.NOTIFICATION_INTERRUPTION: 926 case UsageEvents.Event.NOTIFICATION_SEEN: 927 mAgent.noteInstantaneousEventLocked(userId, pkgName, 928 EconomicPolicy.REWARD_NOTIFICATION_SEEN, null); 929 break; 930 } 931 } 932 933 @GuardedBy("mLock") scheduleUnusedWealthReclamationLocked()934 private void scheduleUnusedWealthReclamationLocked() { 935 final long now = getCurrentTimeMillis(); 936 final long nextReclamationTime = Math.max(now + RECLAMATION_STARTUP_DELAY_MS, 937 mScribe.getLastReclamationTimeLocked() + UNUSED_RECLAMATION_PERIOD_MS); 938 mHandler.post(() -> { 939 // Never call out to AlarmManager with the lock held. This sits below AM. 940 AlarmManager alarmManager = getContext().getSystemService(AlarmManager.class); 941 if (alarmManager != null) { 942 alarmManager.setWindow(AlarmManager.ELAPSED_REALTIME, 943 SystemClock.elapsedRealtime() + (nextReclamationTime - now), 944 30 * MINUTE_IN_MILLIS, 945 ALARM_TAG_WEALTH_RECLAMATION, mUnusedWealthReclamationListener, mHandler); 946 } else { 947 mHandler.sendEmptyMessageDelayed( 948 MSG_SCHEDULE_UNUSED_WEALTH_RECLAMATION_EVENT, RECLAMATION_STARTUP_DELAY_MS); 949 } 950 }); 951 } 952 getCurrentBatteryLevel()953 private int getCurrentBatteryLevel() { 954 return mBatteryManagerInternal.getBatteryLevel(); 955 } 956 957 @Nullable 958 @GuardedBy("mLock") getPackagesForUidLocked(final int uid)959 private ArraySet<String> getPackagesForUidLocked(final int uid) { 960 ArraySet<String> packages = mUidToPackageCache.get(uid); 961 if (packages == null) { 962 final String[] pkgs = mPackageManager.getPackagesForUid(uid); 963 if (pkgs != null) { 964 for (String pkg : pkgs) { 965 mUidToPackageCache.add(uid, pkg); 966 } 967 packages = mUidToPackageCache.get(uid); 968 } 969 } 970 return packages; 971 } 972 isTareSupported()973 private boolean isTareSupported() { 974 // TARE is presently designed for devices with batteries. Don't enable it on 975 // battery-less devices for now. 976 return mHasBattery; 977 } 978 979 @GuardedBy("mLock") loadInstalledPackageListLocked()980 private void loadInstalledPackageListLocked() { 981 mPkgCache.clear(); 982 final UserManagerInternal userManagerInternal = 983 LocalServices.getService(UserManagerInternal.class); 984 final int[] userIds = userManagerInternal.getUserIds(); 985 for (int userId : userIds) { 986 final List<PackageInfo> pkgs = 987 mPackageManager.getInstalledPackagesAsUser(PACKAGE_QUERY_FLAGS, userId); 988 for (int i = pkgs.size() - 1; i >= 0; --i) { 989 final InstalledPackageInfo ipo = 990 new InstalledPackageInfo(getContext(), userId, pkgs.get(i)); 991 final InstalledPackageInfo oldIpo = mPkgCache.add(userId, ipo.packageName, ipo); 992 maybeUpdateInstallerStatusLocked(oldIpo, ipo); 993 } 994 } 995 } 996 997 /** 998 * Used to update the set of installed apps for each installer. This only has an effect if the 999 * installer package name is different between {@code oldIpo} and {@code newIpo}. 1000 */ 1001 @GuardedBy("mLock") maybeUpdateInstallerStatusLocked(@ullable InstalledPackageInfo oldIpo, @NonNull InstalledPackageInfo newIpo)1002 private void maybeUpdateInstallerStatusLocked(@Nullable InstalledPackageInfo oldIpo, 1003 @NonNull InstalledPackageInfo newIpo) { 1004 final boolean changed; 1005 if (oldIpo == null) { 1006 changed = newIpo.installerPackageName != null; 1007 } else { 1008 changed = !Objects.equals(oldIpo.installerPackageName, newIpo.installerPackageName); 1009 } 1010 if (!changed) { 1011 return; 1012 } 1013 // InstallSourceInfo doesn't track userId, so for now, assume the installer on the package's 1014 // user profile did the installation. 1015 // TODO(246640162): use the actual installer's user ID 1016 final int userId = UserHandle.getUserId(newIpo.uid); 1017 final String pkgName = newIpo.packageName; 1018 if (oldIpo != null) { 1019 final ArraySet<String> oldList = mInstallers.get(userId, oldIpo.installerPackageName); 1020 if (oldList != null) { 1021 oldList.remove(pkgName); 1022 } 1023 } 1024 if (newIpo.installerPackageName != null) { 1025 ArraySet<String> newList = mInstallers.get(userId, newIpo.installerPackageName); 1026 if (newList == null) { 1027 newList = new ArraySet<>(); 1028 mInstallers.add(userId, newIpo.installerPackageName, newList); 1029 } 1030 newList.add(pkgName); 1031 } 1032 } 1033 registerListeners()1034 private void registerListeners() { 1035 final IntentFilter filter = new IntentFilter(); 1036 filter.addAction(Intent.ACTION_BATTERY_CHANGED); 1037 filter.addAction(Intent.ACTION_BATTERY_LEVEL_CHANGED); 1038 filter.addAction(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); 1039 getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); 1040 1041 final IntentFilter pkgFilter = new IntentFilter(); 1042 pkgFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED); 1043 pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 1044 pkgFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED); 1045 pkgFilter.addDataScheme("package"); 1046 getContext() 1047 .registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, pkgFilter, null, null); 1048 1049 final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED); 1050 userFilter.addAction(Intent.ACTION_USER_ADDED); 1051 getContext() 1052 .registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, userFilter, null, null); 1053 1054 UsageStatsManagerInternal usmi = LocalServices.getService(UsageStatsManagerInternal.class); 1055 usmi.registerListener(mSurveillanceAgent); 1056 1057 try { 1058 mAppOpsService 1059 .startWatchingMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, null, mApbListener); 1060 } catch (RemoteException e) { 1061 // shouldn't happen. 1062 } 1063 } 1064 1065 /** Perform long-running and/or heavy setup work. This should be called off the main thread. */ setupHeavyWork()1066 private void setupHeavyWork() { 1067 if (mBootPhase < PHASE_THIRD_PARTY_APPS_CAN_START || mEnabledMode == ENABLED_MODE_OFF) { 1068 return; 1069 } 1070 synchronized (mLock) { 1071 mCompleteEconomicPolicy.setup(mConfigObserver.getAllDeviceConfigProperties()); 1072 loadInstalledPackageListLocked(); 1073 final SparseLongArray timeSinceUsersAdded; 1074 final boolean isFirstSetup = !mScribe.recordExists(); 1075 final long nowElapsed = SystemClock.elapsedRealtime(); 1076 if (isFirstSetup) { 1077 mAgent.grantBirthrightsLocked(); 1078 mScribe.setConsumptionLimitLocked( 1079 mCompleteEconomicPolicy.getInitialSatiatedConsumptionLimit()); 1080 // Set the last reclamation time to now so we don't start reclaiming assets 1081 // too early. 1082 mScribe.setLastReclamationTimeLocked(getCurrentTimeMillis()); 1083 timeSinceUsersAdded = new SparseLongArray(); 1084 } else { 1085 mScribe.loadFromDiskLocked(); 1086 if (mScribe.getSatiatedConsumptionLimitLocked() 1087 < mCompleteEconomicPolicy.getMinSatiatedConsumptionLimit() 1088 || mScribe.getSatiatedConsumptionLimitLocked() 1089 > mCompleteEconomicPolicy.getMaxSatiatedConsumptionLimit()) { 1090 // Reset the consumption limit since several factors may have changed. 1091 mScribe.setConsumptionLimitLocked( 1092 mCompleteEconomicPolicy.getInitialSatiatedConsumptionLimit()); 1093 } else { 1094 // Adjust the supply in case battery level changed while the device was off. 1095 adjustCreditSupplyLocked(true); 1096 } 1097 timeSinceUsersAdded = mScribe.getRealtimeSinceUsersAddedLocked(nowElapsed); 1098 } 1099 1100 final int[] userIds = LocalServices.getService(UserManagerInternal.class).getUserIds(); 1101 for (int userId : userIds) { 1102 final long timeSinceUserAddedMs = timeSinceUsersAdded.get(userId, 0); 1103 // Temporarily mark installers as VIPs so they aren't subject to credit 1104 // limits and policies on first boot. 1105 if (timeSinceUserAddedMs < INSTALLER_FIRST_SETUP_GRACE_PERIOD_MS) { 1106 final long remainingGraceDurationMs = 1107 INSTALLER_FIRST_SETUP_GRACE_PERIOD_MS - timeSinceUserAddedMs; 1108 1109 grantInstallersTemporaryVipStatusLocked(userId, nowElapsed, 1110 remainingGraceDurationMs); 1111 } 1112 } 1113 scheduleUnusedWealthReclamationLocked(); 1114 } 1115 } 1116 onBootPhaseSystemServicesReady()1117 private void onBootPhaseSystemServicesReady() { 1118 if (mBootPhase < PHASE_SYSTEM_SERVICES_READY || mEnabledMode == ENABLED_MODE_OFF) { 1119 return; 1120 } 1121 synchronized (mLock) { 1122 registerListeners(); 1123 // As of Android UDC, users can't change the wellbeing package, so load it once 1124 // as soon as possible and don't bother trying to update it afterwards. 1125 mWellbeingPackage = mPackageManager.getWellbeingPackageName(); 1126 mCurrentBatteryLevel = getCurrentBatteryLevel(); 1127 // Get the current battery presence, if available. This would succeed if TARE is 1128 // toggled long after boot. 1129 final Intent batteryStatus = getContext().registerReceiver(null, 1130 new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); 1131 if (batteryStatus != null) { 1132 final boolean hasBattery = 1133 batteryStatus.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true); 1134 if (mHasBattery != hasBattery) { 1135 mHasBattery = hasBattery; 1136 mConfigObserver.updateEnabledStatus(); 1137 } 1138 } 1139 } 1140 } 1141 onBootPhaseThirdPartyAppsCanStart()1142 private void onBootPhaseThirdPartyAppsCanStart() { 1143 if (mBootPhase < PHASE_THIRD_PARTY_APPS_CAN_START || mEnabledMode == ENABLED_MODE_OFF) { 1144 return; 1145 } 1146 mHandler.post(this::setupHeavyWork); 1147 } 1148 onBootPhaseBootCompleted()1149 private void onBootPhaseBootCompleted() { 1150 if (mBootPhase < PHASE_BOOT_COMPLETED || mEnabledMode == ENABLED_MODE_OFF) { 1151 return; 1152 } 1153 synchronized (mLock) { 1154 if (!mExemptListLoaded) { 1155 try { 1156 mExemptedApps = new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist()); 1157 mExemptListLoaded = true; 1158 } catch (RemoteException e) { 1159 // Shouldn't happen. 1160 } 1161 } 1162 } 1163 } 1164 setupEverything()1165 private void setupEverything() { 1166 if (mEnabledMode == ENABLED_MODE_OFF) { 1167 return; 1168 } 1169 if (mBootPhase >= PHASE_SYSTEM_SERVICES_READY) { 1170 onBootPhaseSystemServicesReady(); 1171 } 1172 if (mBootPhase >= PHASE_THIRD_PARTY_APPS_CAN_START) { 1173 onBootPhaseThirdPartyAppsCanStart(); 1174 } 1175 if (mBootPhase >= PHASE_BOOT_COMPLETED) { 1176 onBootPhaseBootCompleted(); 1177 } 1178 } 1179 tearDownEverything()1180 private void tearDownEverything() { 1181 if (mEnabledMode != ENABLED_MODE_OFF) { 1182 return; 1183 } 1184 synchronized (mLock) { 1185 mAgent.tearDownLocked(); 1186 mAnalyst.tearDown(); 1187 mCompleteEconomicPolicy.tearDown(); 1188 mExemptedApps.clear(); 1189 mExemptListLoaded = false; 1190 mHandler.post(() -> { 1191 // Never call out to AlarmManager with the lock held. This sits below AM. 1192 AlarmManager alarmManager = getContext().getSystemService(AlarmManager.class); 1193 if (alarmManager != null) { 1194 alarmManager.cancel(mUnusedWealthReclamationListener); 1195 } 1196 }); 1197 mPkgCache.clear(); 1198 mScribe.tearDownLocked(); 1199 mUidToPackageCache.clear(); 1200 getContext().unregisterReceiver(mBroadcastReceiver); 1201 UsageStatsManagerInternal usmi = 1202 LocalServices.getService(UsageStatsManagerInternal.class); 1203 usmi.unregisterListener(mSurveillanceAgent); 1204 try { 1205 mAppOpsService.stopWatchingMode(mApbListener); 1206 } catch (RemoteException e) { 1207 // shouldn't happen. 1208 } 1209 } 1210 synchronized (mPackageToUidCache) { 1211 mPackageToUidCache.clear(); 1212 } 1213 } 1214 1215 private final class IrsHandler extends Handler { IrsHandler(Looper looper)1216 IrsHandler(Looper looper) { 1217 super(looper); 1218 } 1219 1220 @Override handleMessage(Message msg)1221 public void handleMessage(Message msg) { 1222 switch (msg.what) { 1223 case MSG_CLEAN_UP_TEMP_VIP_LIST: { 1224 removeMessages(MSG_CLEAN_UP_TEMP_VIP_LIST); 1225 1226 synchronized (mLock) { 1227 final long nowElapsed = SystemClock.elapsedRealtime(); 1228 1229 long earliestExpiration = Long.MAX_VALUE; 1230 for (int u = 0; u < mTemporaryVips.numMaps(); ++u) { 1231 final int userId = mTemporaryVips.keyAt(u); 1232 1233 for (int p = mTemporaryVips.numElementsForKeyAt(u) - 1; p >= 0; --p) { 1234 final String pkgName = mTemporaryVips.keyAt(u, p); 1235 final Long expiration = mTemporaryVips.valueAt(u, p); 1236 1237 if (expiration == null || expiration < nowElapsed) { 1238 mTemporaryVips.delete(userId, pkgName); 1239 } else { 1240 earliestExpiration = Math.min(earliestExpiration, expiration); 1241 } 1242 } 1243 } 1244 1245 if (earliestExpiration < Long.MAX_VALUE) { 1246 sendEmptyMessageDelayed(MSG_CLEAN_UP_TEMP_VIP_LIST, 1247 earliestExpiration - nowElapsed); 1248 } 1249 } 1250 } 1251 break; 1252 1253 case MSG_NOTIFY_AFFORDABILITY_CHANGE_LISTENER: { 1254 final SomeArgs args = (SomeArgs) msg.obj; 1255 final int userId = args.argi1; 1256 final String pkgName = (String) args.arg1; 1257 final Agent.ActionAffordabilityNote affordabilityNote = 1258 (Agent.ActionAffordabilityNote) args.arg2; 1259 1260 final EconomyManagerInternal.AffordabilityChangeListener listener = 1261 affordabilityNote.getListener(); 1262 listener.onAffordabilityChanged(userId, pkgName, 1263 affordabilityNote.getActionBill(), 1264 affordabilityNote.isCurrentlyAffordable()); 1265 1266 args.recycle(); 1267 } 1268 break; 1269 1270 case MSG_NOTIFY_STATE_CHANGE_LISTENER: { 1271 final int policy = msg.arg1; 1272 final TareStateChangeListener listener = (TareStateChangeListener) msg.obj; 1273 listener.onTareEnabledModeChanged(getEnabledMode(policy)); 1274 } 1275 break; 1276 1277 case MSG_NOTIFY_STATE_CHANGE_LISTENERS: { 1278 final int changedPolicies = msg.arg1; 1279 synchronized (mStateChangeListeners) { 1280 final int size = mStateChangeListeners.size(); 1281 for (int l = 0; l < size; ++l) { 1282 final int policy = mStateChangeListeners.keyAt(l); 1283 if ((policy & changedPolicies) == 0) { 1284 continue; 1285 } 1286 final ArraySet<TareStateChangeListener> listeners = 1287 mStateChangeListeners.get(policy); 1288 final int enabledMode = getEnabledMode(policy); 1289 for (int p = listeners.size() - 1; p >= 0; --p) { 1290 final TareStateChangeListener listener = listeners.valueAt(p); 1291 listener.onTareEnabledModeChanged(enabledMode); 1292 } 1293 } 1294 } 1295 } 1296 break; 1297 1298 case MSG_PROCESS_USAGE_EVENT: { 1299 final int userId = msg.arg1; 1300 final UsageEvents.Event event = (UsageEvents.Event) msg.obj; 1301 synchronized (mLock) { 1302 processUsageEventLocked(userId, event); 1303 } 1304 } 1305 break; 1306 1307 case MSG_SCHEDULE_UNUSED_WEALTH_RECLAMATION_EVENT: { 1308 removeMessages(MSG_SCHEDULE_UNUSED_WEALTH_RECLAMATION_EVENT); 1309 synchronized (mLock) { 1310 scheduleUnusedWealthReclamationLocked(); 1311 } 1312 } 1313 break; 1314 } 1315 } 1316 } 1317 1318 /** 1319 * Binder stub trampoline implementation 1320 */ 1321 final class EconomyManagerStub extends IEconomyManager.Stub { 1322 /** 1323 * "dumpsys" infrastructure 1324 */ 1325 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1326 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1327 if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return; 1328 1329 boolean dumpAll = true; 1330 if (!ArrayUtils.isEmpty(args)) { 1331 String arg = args[0]; 1332 if ("-h".equals(arg) || "--help".equals(arg)) { 1333 dumpHelp(pw); 1334 return; 1335 } else if ("-a".equals(arg)) { 1336 // -a is passed when dumping a bug report. Bug reports have a time limit for 1337 // each service dump, so we can't dump everything. 1338 dumpAll = false; 1339 } else if (arg.length() > 0 && arg.charAt(0) == '-') { 1340 pw.println("Unknown option: " + arg); 1341 return; 1342 } 1343 } 1344 1345 final long identityToken = Binder.clearCallingIdentity(); 1346 try { 1347 dumpInternal(new IndentingPrintWriter(pw, " "), dumpAll); 1348 } finally { 1349 Binder.restoreCallingIdentity(identityToken); 1350 } 1351 } 1352 1353 @Override 1354 @EconomyManager.EnabledMode getEnabledMode()1355 public int getEnabledMode() { 1356 return InternalResourceService.this.getEnabledMode(); 1357 } 1358 1359 @Override handleShellCommand(@onNull ParcelFileDescriptor in, @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, @NonNull String[] args)1360 public int handleShellCommand(@NonNull ParcelFileDescriptor in, 1361 @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, 1362 @NonNull String[] args) { 1363 return (new TareShellCommand(InternalResourceService.this)).exec( 1364 this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), 1365 args); 1366 } 1367 } 1368 1369 private final class LocalService implements EconomyManagerInternal { 1370 /** 1371 * Use an extremely large value to indicate that an app can pay for a bill indefinitely. 1372 * The value set here should be large/long enough that there's no reasonable expectation 1373 * of a device operating uninterrupted (or in the exact same state) for that period of time. 1374 * We intentionally don't use Long.MAX_VALUE to avoid potential overflow if a client 1375 * doesn't check the value and just immediately adds it to the current time. 1376 */ 1377 private static final long FOREVER_MS = 27 * 365 * 24 * HOUR_IN_MILLIS; 1378 1379 @Override registerAffordabilityChangeListener(int userId, @NonNull String pkgName, @NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill)1380 public void registerAffordabilityChangeListener(int userId, @NonNull String pkgName, 1381 @NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill) { 1382 if (!isTareSupported() || isSystem(userId, pkgName)) { 1383 // The system's affordability never changes. 1384 return; 1385 } 1386 synchronized (mLock) { 1387 mAgent.registerAffordabilityChangeListenerLocked(userId, pkgName, listener, bill); 1388 } 1389 } 1390 1391 @Override unregisterAffordabilityChangeListener(int userId, @NonNull String pkgName, @NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill)1392 public void unregisterAffordabilityChangeListener(int userId, @NonNull String pkgName, 1393 @NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill) { 1394 if (isSystem(userId, pkgName)) { 1395 // The system's affordability never changes. 1396 return; 1397 } 1398 synchronized (mLock) { 1399 mAgent.unregisterAffordabilityChangeListenerLocked(userId, pkgName, listener, bill); 1400 } 1401 } 1402 1403 @Override registerTareStateChangeListener(@onNull TareStateChangeListener listener, int policyId)1404 public void registerTareStateChangeListener(@NonNull TareStateChangeListener listener, 1405 int policyId) { 1406 if (!isTareSupported()) { 1407 return; 1408 } 1409 synchronized (mStateChangeListeners) { 1410 if (mStateChangeListeners.add(policyId, listener)) { 1411 mHandler.obtainMessage(MSG_NOTIFY_STATE_CHANGE_LISTENER, policyId, 0, listener) 1412 .sendToTarget(); 1413 } 1414 } 1415 } 1416 1417 @Override unregisterTareStateChangeListener(@onNull TareStateChangeListener listener)1418 public void unregisterTareStateChangeListener(@NonNull TareStateChangeListener listener) { 1419 synchronized (mStateChangeListeners) { 1420 for (int i = mStateChangeListeners.size() - 1; i >= 0; --i) { 1421 final ArraySet<TareStateChangeListener> listeners = 1422 mStateChangeListeners.get(mStateChangeListeners.keyAt(i)); 1423 listeners.remove(listener); 1424 } 1425 } 1426 } 1427 1428 @Override canPayFor(int userId, @NonNull String pkgName, @NonNull ActionBill bill)1429 public boolean canPayFor(int userId, @NonNull String pkgName, @NonNull ActionBill bill) { 1430 if (mEnabledMode == ENABLED_MODE_OFF) { 1431 return true; 1432 } 1433 if (isVip(userId, pkgName)) { 1434 // The government, I mean the system, can create ARCs as it needs to in order to 1435 // allow VIPs to operate. 1436 return true; 1437 } 1438 // TODO: take temp-allowlist into consideration 1439 long requiredBalance = 0; 1440 final List<EconomyManagerInternal.AnticipatedAction> projectedActions = 1441 bill.getAnticipatedActions(); 1442 synchronized (mLock) { 1443 for (int i = 0; i < projectedActions.size(); ++i) { 1444 AnticipatedAction action = projectedActions.get(i); 1445 final Cost cost = mCompleteEconomicPolicy.getCostOfAction( 1446 action.actionId, userId, pkgName); 1447 requiredBalance += cost.price * action.numInstantaneousCalls 1448 + cost.price * (action.ongoingDurationMs / 1000); 1449 } 1450 return mAgent.getBalanceLocked(userId, pkgName) >= requiredBalance 1451 && mScribe.getRemainingConsumableCakesLocked() >= requiredBalance; 1452 } 1453 } 1454 1455 @Override getMaxDurationMs(int userId, @NonNull String pkgName, @NonNull ActionBill bill)1456 public long getMaxDurationMs(int userId, @NonNull String pkgName, 1457 @NonNull ActionBill bill) { 1458 if (mEnabledMode == ENABLED_MODE_OFF) { 1459 return FOREVER_MS; 1460 } 1461 if (isVip(userId, pkgName)) { 1462 return FOREVER_MS; 1463 } 1464 long totalCostPerSecond = 0; 1465 final List<EconomyManagerInternal.AnticipatedAction> projectedActions = 1466 bill.getAnticipatedActions(); 1467 synchronized (mLock) { 1468 for (int i = 0; i < projectedActions.size(); ++i) { 1469 AnticipatedAction action = projectedActions.get(i); 1470 final Cost cost = mCompleteEconomicPolicy.getCostOfAction( 1471 action.actionId, userId, pkgName); 1472 totalCostPerSecond += cost.price; 1473 } 1474 if (totalCostPerSecond == 0) { 1475 return FOREVER_MS; 1476 } 1477 final long minBalance = Math.min( 1478 mAgent.getBalanceLocked(userId, pkgName), 1479 mScribe.getRemainingConsumableCakesLocked()); 1480 return minBalance * 1000 / totalCostPerSecond; 1481 } 1482 } 1483 1484 @Override getEnabledMode()1485 public int getEnabledMode() { 1486 return mEnabledMode; 1487 } 1488 1489 @Override getEnabledMode(int policyId)1490 public int getEnabledMode(int policyId) { 1491 return InternalResourceService.this.getEnabledMode(policyId); 1492 } 1493 1494 @Override noteInstantaneousEvent(int userId, @NonNull String pkgName, int eventId, @Nullable String tag)1495 public void noteInstantaneousEvent(int userId, @NonNull String pkgName, int eventId, 1496 @Nullable String tag) { 1497 if (mEnabledMode == ENABLED_MODE_OFF) { 1498 return; 1499 } 1500 synchronized (mLock) { 1501 mAgent.noteInstantaneousEventLocked(userId, pkgName, eventId, tag); 1502 } 1503 } 1504 1505 @Override noteOngoingEventStarted(int userId, @NonNull String pkgName, int eventId, @Nullable String tag)1506 public void noteOngoingEventStarted(int userId, @NonNull String pkgName, int eventId, 1507 @Nullable String tag) { 1508 if (mEnabledMode == ENABLED_MODE_OFF) { 1509 return; 1510 } 1511 synchronized (mLock) { 1512 final long nowElapsed = SystemClock.elapsedRealtime(); 1513 mAgent.noteOngoingEventLocked(userId, pkgName, eventId, tag, nowElapsed); 1514 } 1515 } 1516 1517 @Override noteOngoingEventStopped(int userId, @NonNull String pkgName, int eventId, @Nullable String tag)1518 public void noteOngoingEventStopped(int userId, @NonNull String pkgName, int eventId, 1519 @Nullable String tag) { 1520 if (mEnabledMode == ENABLED_MODE_OFF) { 1521 return; 1522 } 1523 final long nowElapsed = SystemClock.elapsedRealtime(); 1524 final long now = getCurrentTimeMillis(); 1525 synchronized (mLock) { 1526 mAgent.stopOngoingActionLocked(userId, pkgName, eventId, tag, nowElapsed, now); 1527 } 1528 } 1529 } 1530 1531 private class ConfigObserver extends ContentObserver 1532 implements DeviceConfig.OnPropertiesChangedListener { 1533 private static final String KEY_ENABLE_TIP3 = "enable_tip3"; 1534 private static final String KEY_TARGET_BACKGROUND_BATTERY_LIFE_HOURS = 1535 "target_bg_battery_life_hrs"; 1536 1537 private static final boolean DEFAULT_ENABLE_TIP3 = true; 1538 1539 /** Use a target background battery drain rate to determine consumption limits. */ 1540 public boolean ENABLE_TIP3 = DEFAULT_ENABLE_TIP3; 1541 1542 private final ContentResolver mContentResolver; 1543 ConfigObserver(Handler handler, Context context)1544 ConfigObserver(Handler handler, Context context) { 1545 super(handler); 1546 mContentResolver = context.getContentResolver(); 1547 } 1548 start()1549 public void start() { 1550 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_TARE, 1551 TareHandlerThread.getExecutor(), this); 1552 mContentResolver.registerContentObserver( 1553 Settings.Global.getUriFor(Settings.Global.ENABLE_TARE), false, this); 1554 mContentResolver.registerContentObserver( 1555 Settings.Global.getUriFor(TARE_ALARM_MANAGER_CONSTANTS), false, this); 1556 mContentResolver.registerContentObserver( 1557 Settings.Global.getUriFor(TARE_JOB_SCHEDULER_CONSTANTS), false, this); 1558 onPropertiesChanged(getAllDeviceConfigProperties()); 1559 updateEnabledStatus(); 1560 } 1561 1562 @NonNull getAllDeviceConfigProperties()1563 DeviceConfig.Properties getAllDeviceConfigProperties() { 1564 // Don't want to cache the Properties object locally in case it ends up being large, 1565 // especially since it'll only be used once/infrequently (during setup or on a change). 1566 return DeviceConfig.getProperties(DeviceConfig.NAMESPACE_TARE); 1567 } 1568 1569 @Override onChange(boolean selfChange, Uri uri)1570 public void onChange(boolean selfChange, Uri uri) { 1571 if (uri.equals(Settings.Global.getUriFor(Settings.Global.ENABLE_TARE))) { 1572 updateEnabledStatus(); 1573 } else if (uri.equals(Settings.Global.getUriFor(TARE_ALARM_MANAGER_CONSTANTS)) 1574 || uri.equals(Settings.Global.getUriFor(TARE_JOB_SCHEDULER_CONSTANTS))) { 1575 updateEconomicPolicy(); 1576 } 1577 } 1578 1579 @Override onPropertiesChanged(DeviceConfig.Properties properties)1580 public void onPropertiesChanged(DeviceConfig.Properties properties) { 1581 boolean economicPolicyUpdated = false; 1582 synchronized (mLock) { 1583 for (String name : properties.getKeyset()) { 1584 if (name == null) { 1585 continue; 1586 } 1587 switch (name) { 1588 case EconomyManager.KEY_ENABLE_TARE_MODE: 1589 updateEnabledStatus(); 1590 break; 1591 case KEY_ENABLE_TIP3: 1592 ENABLE_TIP3 = properties.getBoolean(name, DEFAULT_ENABLE_TIP3); 1593 break; 1594 case KEY_TARGET_BACKGROUND_BATTERY_LIFE_HOURS: 1595 synchronized (mLock) { 1596 mTargetBackgroundBatteryLifeHours = properties.getInt(name, 1597 mDefaultTargetBackgroundBatteryLifeHours); 1598 maybeAdjustDesiredStockLevelLocked(); 1599 } 1600 break; 1601 default: 1602 if (!economicPolicyUpdated 1603 && (name.startsWith("am") || name.startsWith("js") 1604 || name.startsWith("enable_policy"))) { 1605 updateEconomicPolicy(); 1606 economicPolicyUpdated = true; 1607 } 1608 } 1609 } 1610 } 1611 } 1612 updateEnabledStatus()1613 private void updateEnabledStatus() { 1614 // User setting should override DeviceConfig setting. 1615 final int tareEnabledModeDC = DeviceConfig.getInt(DeviceConfig.NAMESPACE_TARE, 1616 EconomyManager.KEY_ENABLE_TARE_MODE, EconomyManager.DEFAULT_ENABLE_TARE_MODE); 1617 final int tareEnabledModeConfig = isTareSupported() 1618 ? Settings.Global.getInt(mContentResolver, 1619 Settings.Global.ENABLE_TARE, tareEnabledModeDC) 1620 : ENABLED_MODE_OFF; 1621 final int enabledMode; 1622 if (tareEnabledModeConfig == ENABLED_MODE_OFF 1623 || tareEnabledModeConfig == ENABLED_MODE_ON 1624 || tareEnabledModeConfig == ENABLED_MODE_SHADOW) { 1625 // Config has a valid enabled mode. 1626 enabledMode = tareEnabledModeConfig; 1627 } else { 1628 enabledMode = EconomyManager.DEFAULT_ENABLE_TARE_MODE; 1629 } 1630 if (mEnabledMode != enabledMode) { 1631 // A full change where we've gone from OFF to {SHADOW or ON}, or vie versa. 1632 // With this transition, we'll have to set up or tear down. 1633 final boolean fullEnableChange = 1634 mEnabledMode == ENABLED_MODE_OFF || enabledMode == ENABLED_MODE_OFF; 1635 mEnabledMode = enabledMode; 1636 if (fullEnableChange) { 1637 if (mEnabledMode != ENABLED_MODE_OFF) { 1638 setupEverything(); 1639 } else { 1640 tearDownEverything(); 1641 } 1642 } 1643 mHandler.obtainMessage( 1644 MSG_NOTIFY_STATE_CHANGE_LISTENERS, EconomicPolicy.ALL_POLICIES, 0) 1645 .sendToTarget(); 1646 } 1647 } 1648 updateEconomicPolicy()1649 private void updateEconomicPolicy() { 1650 synchronized (mLock) { 1651 final long minLimit = mCompleteEconomicPolicy.getMinSatiatedConsumptionLimit(); 1652 final long maxLimit = mCompleteEconomicPolicy.getMaxSatiatedConsumptionLimit(); 1653 final int oldEnabledPolicies = mCompleteEconomicPolicy.getEnabledPolicyIds(); 1654 mCompleteEconomicPolicy.tearDown(); 1655 mCompleteEconomicPolicy = new CompleteEconomicPolicy(InternalResourceService.this); 1656 if (mEnabledMode != ENABLED_MODE_OFF 1657 && mBootPhase >= PHASE_THIRD_PARTY_APPS_CAN_START) { 1658 mCompleteEconomicPolicy.setup(getAllDeviceConfigProperties()); 1659 if (minLimit != mCompleteEconomicPolicy.getMinSatiatedConsumptionLimit() 1660 || maxLimit 1661 != mCompleteEconomicPolicy.getMaxSatiatedConsumptionLimit()) { 1662 // Reset the consumption limit since several factors may have changed. 1663 mScribe.setConsumptionLimitLocked( 1664 mCompleteEconomicPolicy.getInitialSatiatedConsumptionLimit()); 1665 } 1666 mAgent.onPricingChangedLocked(); 1667 final int newEnabledPolicies = mCompleteEconomicPolicy.getEnabledPolicyIds(); 1668 if (oldEnabledPolicies != newEnabledPolicies) { 1669 final int changedPolicies = oldEnabledPolicies ^ newEnabledPolicies; 1670 mHandler.obtainMessage( 1671 MSG_NOTIFY_STATE_CHANGE_LISTENERS, changedPolicies, 0) 1672 .sendToTarget(); 1673 } 1674 } 1675 } 1676 } 1677 } 1678 1679 // Shell command infrastructure executeClearVip(@onNull PrintWriter pw)1680 int executeClearVip(@NonNull PrintWriter pw) { 1681 synchronized (mLock) { 1682 final SparseSetArray<String> changedPkgs = new SparseSetArray<>(); 1683 for (int u = mVipOverrides.numMaps() - 1; u >= 0; --u) { 1684 final int userId = mVipOverrides.keyAt(u); 1685 1686 for (int p = mVipOverrides.numElementsForKeyAt(u) - 1; p >= 0; --p) { 1687 changedPkgs.add(userId, mVipOverrides.keyAt(u, p)); 1688 } 1689 } 1690 mVipOverrides.clear(); 1691 if (mEnabledMode != ENABLED_MODE_OFF) { 1692 mAgent.onVipStatusChangedLocked(changedPkgs); 1693 } 1694 } 1695 pw.println("Cleared all VIP statuses"); 1696 return TareShellCommand.COMMAND_SUCCESS; 1697 } 1698 executeSetVip(@onNull PrintWriter pw, int userId, @NonNull String pkgName, @Nullable Boolean newVipState)1699 int executeSetVip(@NonNull PrintWriter pw, 1700 int userId, @NonNull String pkgName, @Nullable Boolean newVipState) { 1701 final boolean changed; 1702 synchronized (mLock) { 1703 final boolean wasVip = isVip(userId, pkgName); 1704 if (newVipState == null) { 1705 mVipOverrides.delete(userId, pkgName); 1706 } else { 1707 mVipOverrides.add(userId, pkgName, newVipState); 1708 } 1709 changed = isVip(userId, pkgName) != wasVip; 1710 if (mEnabledMode != ENABLED_MODE_OFF && changed) { 1711 mAgent.onVipStatusChangedLocked(userId, pkgName); 1712 } 1713 } 1714 pw.println(appToString(userId, pkgName) + " VIP status set to " + newVipState + "." 1715 + " Final VIP state changed? " + changed); 1716 return TareShellCommand.COMMAND_SUCCESS; 1717 } 1718 1719 // Dump infrastructure dumpHelp(PrintWriter pw)1720 private static void dumpHelp(PrintWriter pw) { 1721 pw.println("Resource Economy (economy) dump options:"); 1722 pw.println(" [-h|--help] [package] ..."); 1723 pw.println(" -h | --help: print this help"); 1724 pw.println(" [package] is an optional package name to limit the output to."); 1725 } 1726 dumpInternal(final IndentingPrintWriter pw, final boolean dumpAll)1727 private void dumpInternal(final IndentingPrintWriter pw, final boolean dumpAll) { 1728 if (!isTareSupported()) { 1729 pw.print("Unsupported by device"); 1730 return; 1731 } 1732 synchronized (mLock) { 1733 pw.print("Enabled mode: "); 1734 pw.println(enabledModeToString(mEnabledMode)); 1735 1736 pw.print("Current battery level: "); 1737 pw.println(mCurrentBatteryLevel); 1738 1739 final long consumptionLimit = getConsumptionLimitLocked(); 1740 pw.print("Consumption limit (current/initial-satiated/current-satiated): "); 1741 pw.print(cakeToString(consumptionLimit)); 1742 pw.print("/"); 1743 pw.print(cakeToString(mCompleteEconomicPolicy.getInitialSatiatedConsumptionLimit())); 1744 pw.print("/"); 1745 pw.println(cakeToString(mScribe.getSatiatedConsumptionLimitLocked())); 1746 1747 pw.print("Target bg battery life (hours): "); 1748 pw.print(mTargetBackgroundBatteryLifeHours); 1749 pw.print(" ("); 1750 pw.print(String.format("%.2f", 100f / mTargetBackgroundBatteryLifeHours)); 1751 pw.println("%/hr)"); 1752 1753 final long remainingConsumable = mScribe.getRemainingConsumableCakesLocked(); 1754 pw.print("Goods remaining: "); 1755 pw.print(cakeToString(remainingConsumable)); 1756 pw.print(" ("); 1757 pw.print(String.format("%.2f", 100f * remainingConsumable / consumptionLimit)); 1758 pw.println("% of current limit)"); 1759 1760 pw.print("Device wealth: "); 1761 pw.println(cakeToString(mScribe.getCakesInCirculationForLoggingLocked())); 1762 1763 pw.println(); 1764 pw.print("Exempted apps", mExemptedApps); 1765 pw.println(); 1766 1767 pw.println(); 1768 pw.print("Wellbeing app="); 1769 pw.println(mWellbeingPackage == null ? "None" : mWellbeingPackage); 1770 1771 boolean printedVips = false; 1772 pw.println(); 1773 pw.print("VIPs:"); 1774 pw.increaseIndent(); 1775 for (int u = 0; u < mVipOverrides.numMaps(); ++u) { 1776 final int userId = mVipOverrides.keyAt(u); 1777 1778 for (int p = 0; p < mVipOverrides.numElementsForKeyAt(u); ++p) { 1779 final String pkgName = mVipOverrides.keyAt(u, p); 1780 1781 printedVips = true; 1782 pw.println(); 1783 pw.print(appToString(userId, pkgName)); 1784 pw.print("="); 1785 pw.print(mVipOverrides.valueAt(u, p)); 1786 } 1787 } 1788 if (printedVips) { 1789 pw.println(); 1790 } else { 1791 pw.print(" None"); 1792 } 1793 pw.decreaseIndent(); 1794 pw.println(); 1795 1796 boolean printedTempVips = false; 1797 pw.println(); 1798 pw.print("Temp VIPs:"); 1799 pw.increaseIndent(); 1800 for (int u = 0; u < mTemporaryVips.numMaps(); ++u) { 1801 final int userId = mTemporaryVips.keyAt(u); 1802 1803 for (int p = 0; p < mTemporaryVips.numElementsForKeyAt(u); ++p) { 1804 final String pkgName = mTemporaryVips.keyAt(u, p); 1805 1806 printedTempVips = true; 1807 pw.println(); 1808 pw.print(appToString(userId, pkgName)); 1809 pw.print("="); 1810 pw.print(mTemporaryVips.valueAt(u, p)); 1811 } 1812 } 1813 if (printedTempVips) { 1814 pw.println(); 1815 } else { 1816 pw.print(" None"); 1817 } 1818 pw.decreaseIndent(); 1819 pw.println(); 1820 1821 pw.println(); 1822 pw.println("Installers:"); 1823 pw.increaseIndent(); 1824 for (int u = 0; u < mInstallers.numMaps(); ++u) { 1825 final int userId = mInstallers.keyAt(u); 1826 1827 for (int p = 0; p < mInstallers.numElementsForKeyAt(u); ++p) { 1828 final String pkgName = mInstallers.keyAt(u, p); 1829 1830 pw.print(appToString(userId, pkgName)); 1831 pw.print(": "); 1832 pw.print(mInstallers.valueAt(u, p).size()); 1833 pw.println(" apps"); 1834 } 1835 } 1836 pw.decreaseIndent(); 1837 1838 pw.println(); 1839 mCompleteEconomicPolicy.dump(pw); 1840 1841 pw.println(); 1842 mScribe.dumpLocked(pw, dumpAll); 1843 1844 pw.println(); 1845 mAgent.dumpLocked(pw); 1846 1847 pw.println(); 1848 mAnalyst.dump(pw); 1849 1850 // Put this at the end since this may be a lot and we want to have the earlier 1851 // information easily accessible. 1852 boolean printedInterestingIpos = false; 1853 pw.println(); 1854 pw.print("Interesting apps:"); 1855 pw.increaseIndent(); 1856 for (int u = 0; u < mPkgCache.numMaps(); ++u) { 1857 for (int p = 0; p < mPkgCache.numElementsForKeyAt(u); ++p) { 1858 final InstalledPackageInfo ipo = mPkgCache.valueAt(u, p); 1859 1860 // Printing out every single app will be too much. Only print apps that 1861 // have some interesting characteristic. 1862 final boolean isInteresting = ipo.hasCode 1863 && ipo.isHeadlessSystemApp 1864 && !UserHandle.isCore(ipo.uid); 1865 if (!isInteresting) { 1866 continue; 1867 } 1868 1869 printedInterestingIpos = true; 1870 pw.println(); 1871 pw.print(ipo); 1872 } 1873 } 1874 if (printedInterestingIpos) { 1875 pw.println(); 1876 } else { 1877 pw.print(" None"); 1878 } 1879 pw.decreaseIndent(); 1880 } 1881 } 1882 } 1883