Loading apex/jobscheduler/service/java/com/android/server/tare/Agent.java +64 −0 Original line number Diff line number Diff line Loading @@ -16,8 +16,12 @@ package com.android.server.tare; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static com.android.server.tare.EconomicPolicy.REGULATION_BASIC_INCOME; import static com.android.server.tare.EconomicPolicy.REGULATION_BIRTHRIGHT; import static com.android.server.tare.EconomicPolicy.REGULATION_DEMOTION; import static com.android.server.tare.EconomicPolicy.REGULATION_PROMOTION; import static com.android.server.tare.EconomicPolicy.REGULATION_WEALTH_RECLAMATION; import static com.android.server.tare.EconomicPolicy.TYPE_ACTION; import static com.android.server.tare.EconomicPolicy.TYPE_REWARD; Loading Loading @@ -603,6 +607,51 @@ class Agent { } } /** * Reclaim a percentage of unused ARCs from an app that was just removed from an exemption list. * The amount reclaimed will depend on how recently the app was used. The reclamation will not * reduce an app's balance below its current minimum balance. */ @GuardedBy("mLock") void onAppUnexemptedLocked(final int userId, @NonNull final String pkgName) { final long curBalance = getBalanceLocked(userId, pkgName); final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName); if (curBalance <= minBalance) { return; } // AppStandby only counts elapsed time for things like this // TODO: should we use clock time instead? final long timeSinceLastUsedMs = mAppStandbyInternal.getTimeSinceLastUsedByUser(pkgName, userId); // The app is no longer exempted. We should take away some of credits so it's more in line // with other non-exempt apps. However, don't take away as many credits if the app was used // recently. final double percentageToReclaim; if (timeSinceLastUsedMs < DAY_IN_MILLIS) { percentageToReclaim = .25; } else if (timeSinceLastUsedMs < 2 * DAY_IN_MILLIS) { percentageToReclaim = .5; } else if (timeSinceLastUsedMs < 3 * DAY_IN_MILLIS) { percentageToReclaim = .75; } else { percentageToReclaim = 1; } final long overage = curBalance - minBalance; final long toReclaim = (long) (overage * percentageToReclaim); if (toReclaim > 0) { if (DEBUG) { Slog.i(TAG, "Reclaiming bonus wealth! Taking " + toReclaim + " from " + appToString(userId, pkgName)); } final long now = getCurrentTimeMillis(); final Ledger ledger = mScribe.getLedgerLocked(userId, pkgName); recordTransactionLocked(userId, pkgName, ledger, new Ledger.Transaction(now, now, REGULATION_DEMOTION, null, -toReclaim), true); } } /** Returns true if an app should be given credits in the general distributions. */ private boolean shouldGiveCredits(@NonNull PackageInfo packageInfo) { final ApplicationInfo applicationInfo = packageInfo.applicationInfo; Loading Loading @@ -700,6 +749,21 @@ class Agent { Math.min(maxBirthright, mIrs.getMinBalanceLocked(userId, pkgName))), true); } @GuardedBy("mLock") void onAppExemptedLocked(final int userId, @NonNull final String pkgName) { final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName); final long missing = minBalance - getBalanceLocked(userId, pkgName); if (missing <= 0) { return; } final Ledger ledger = mScribe.getLedgerLocked(userId, pkgName); final long now = getCurrentTimeMillis(); recordTransactionLocked(userId, pkgName, ledger, new Ledger.Transaction(now, now, REGULATION_PROMOTION, null, missing), true); } @GuardedBy("mLock") void onPackageRemovedLocked(final int userId, @NonNull final String pkgName) { reclaimAssetsLocked(userId, pkgName); Loading apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java +17 −5 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_WA import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP; import static android.app.tare.EconomyManager.DEFAULT_AM_MAX_CIRCULATION; import static android.app.tare.EconomyManager.DEFAULT_AM_MAX_SATIATED_BALANCE; import static android.app.tare.EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED; import static android.app.tare.EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP; import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT; import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_MAX; Loading Loading @@ -71,6 +72,7 @@ import static android.app.tare.EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_WAKEUP import static android.app.tare.EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP; import static android.app.tare.EconomyManager.KEY_AM_MAX_CIRCULATION; import static android.app.tare.EconomyManager.KEY_AM_MAX_SATIATED_BALANCE; import static android.app.tare.EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED; import static android.app.tare.EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP; import static android.app.tare.EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT; import static android.app.tare.EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_MAX; Loading Loading @@ -138,7 +140,8 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { COST_MODIFIER_PROCESS_STATE }; private long mMinSatiatedBalance; private long mMinSatiatedBalanceExempted; private long mMinSatiatedBalanceOther; private long mMaxSatiatedBalance; private long mMaxSatiatedCirculation; Loading @@ -163,8 +166,11 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { @Override long getMinSatiatedBalance(final int userId, @NonNull final String pkgName) { // TODO: take exemption into account return mMinSatiatedBalance; if (mInternalResourceService.isPackageExempted(userId, pkgName)) { return mMinSatiatedBalanceExempted; } // TODO: take other exemptions into account return mMinSatiatedBalanceOther; } @Override Loading Loading @@ -205,7 +211,9 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { Slog.e(TAG, "Global setting key incorrect: ", e); } mMinSatiatedBalance = arcToNarc(mParser.getInt(KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP, mMinSatiatedBalanceExempted = arcToNarc(mParser.getInt(KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED, DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED)); mMinSatiatedBalanceOther = arcToNarc(mParser.getInt(KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP, DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP)); mMaxSatiatedBalance = arcToNarc(mParser.getInt(KEY_AM_MAX_SATIATED_BALANCE, DEFAULT_AM_MAX_SATIATED_BALANCE)); Loading Loading @@ -343,7 +351,11 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { @Override void dump(IndentingPrintWriter pw) { pw.print("Min satiated balance", narcToString(mMinSatiatedBalance)).println(); pw.println("Min satiated balances:"); pw.increaseIndent(); pw.print("Exempted", narcToString(mMinSatiatedBalanceExempted)).println(); pw.print("Other", narcToString(mMinSatiatedBalanceOther)).println(); pw.decreaseIndent(); pw.print("Max satiated balance", narcToString(mMaxSatiatedBalance)).println(); pw.print("Min satiated circulation", narcToString(mMaxSatiatedCirculation)).println(); Loading apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java +6 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,8 @@ public abstract class EconomicPolicy { static final int REGULATION_BASIC_INCOME = TYPE_REGULATION | 0; static final int REGULATION_BIRTHRIGHT = TYPE_REGULATION | 1; static final int REGULATION_WEALTH_RECLAMATION = TYPE_REGULATION | 2; static final int REGULATION_PROMOTION = TYPE_REGULATION | 3; static final int REGULATION_DEMOTION = TYPE_REGULATION | 4; static final int REWARD_NOTIFICATION_SEEN = TYPE_REWARD | 0; static final int REWARD_NOTIFICATION_INTERACTION = TYPE_REWARD | 1; Loading Loading @@ -363,6 +365,10 @@ public abstract class EconomicPolicy { return "BIRTHRIGHT"; case REGULATION_WEALTH_RECLAMATION: return "WEALTH_RECLAMATION"; case REGULATION_PROMOTION: return "PROMOTION"; case REGULATION_DEMOTION: return "DEMOTION"; } return "UNKNOWN_REGULATION:" + Integer.toHexString(eventId); } Loading apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java +102 −3 Original line number Diff line number Diff line Loading @@ -45,8 +45,12 @@ import android.net.Uri; import android.os.BatteryManagerInternal; import android.os.Binder; import android.os.Handler; import android.os.IDeviceIdleController; import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; Loading Loading @@ -105,6 +109,8 @@ public class InternalResourceService extends SystemService { private final PackageManager mPackageManager; private final PackageManagerInternal mPackageManagerInternal; private IDeviceIdleController mDeviceIdleController; private final Agent mAgent; private final ConfigObserver mConfigObserver; private final EconomyManagerStub mEconomyManagerStub; Loading Loading @@ -163,8 +169,14 @@ public class InternalResourceService extends SystemService { @GuardedBy("mPackageToUidCache") private final SparseArrayMap<String, Integer> mPackageToUidCache = new SparseArrayMap<>(); /** List of packages that are "exempted" from battery restrictions. */ // TODO(144864180): include userID @GuardedBy("mLock") private ArraySet<String> mExemptedApps = new ArraySet<>(); private volatile boolean mIsEnabled; private volatile int mBootPhase; private volatile boolean mExemptListLoaded; // In the range [0,100] to represent 0% to 100% battery. @GuardedBy("mLock") private int mCurrentBatteryLevel; Loading Loading @@ -213,6 +225,9 @@ public class InternalResourceService extends SystemService { onUserRemoved(userId); } break; case PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED: onExemptionListChanged(); break; } } }; Loading Loading @@ -285,7 +300,22 @@ public class InternalResourceService extends SystemService { if (PHASE_SYSTEM_SERVICES_READY == phase) { mConfigObserver.start(); mDeviceIdleController = IDeviceIdleController.Stub.asInterface( ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); setupEverything(); } else if (PHASE_BOOT_COMPLETED == phase) { if (!mExemptListLoaded) { synchronized (mLock) { try { mExemptedApps = new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist()); } catch (RemoteException e) { // Shouldn't happen. Slog.wtf(TAG, e); } mExemptListLoaded = true; } } } } Loading Loading @@ -350,6 +380,12 @@ public class InternalResourceService extends SystemService { return mIsEnabled; } boolean isPackageExempted(final int userId, @NonNull String pkgName) { synchronized (mLock) { return mExemptedApps.contains(pkgName); } } boolean isSystem(final int userId, @NonNull String pkgName) { if ("android".equals(pkgName)) { return true; Loading @@ -375,6 +411,53 @@ public class InternalResourceService extends SystemService { } } void onExemptionListChanged() { final int[] userIds = LocalServices.getService(UserManagerInternal.class).getUserIds(); synchronized (mLock) { final ArraySet<String> removed = mExemptedApps; final ArraySet<String> added = new ArraySet<>(); try { mExemptedApps = new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist()); } catch (RemoteException e) { // Shouldn't happen. Slog.wtf(TAG, e); return; } for (int i = mExemptedApps.size() - 1; i >= 0; --i) { final String pkg = mExemptedApps.valueAt(i); if (!removed.contains(pkg)) { added.add(pkg); } removed.remove(pkg); } for (int a = added.size() - 1; a >= 0; --a) { final String pkgName = added.valueAt(a); for (int userId : userIds) { // Since the exemption list doesn't specify user ID and we track by user ID, // we need to see if the app exists on the user before talking to the agent. // Otherwise, we may end up with invalid ledgers. final boolean appExists = getUid(userId, pkgName) >= 0; if (appExists) { mAgent.onAppExemptedLocked(userId, pkgName); } } } for (int r = removed.size() - 1; r >= 0; --r) { final String pkgName = removed.valueAt(r); for (int userId : userIds) { // Since the exemption list doesn't specify user ID and we track by user ID, // we need to see if the app exists on the user before talking to the agent. // Otherwise, we may end up with invalid ledgers. final boolean appExists = getUid(userId, pkgName) >= 0; if (appExists) { mAgent.onAppUnexemptedLocked(userId, pkgName); } } } } } void onPackageAdded(final int uid, @NonNull final String pkgName) { final int userId = UserHandle.getUserId(uid); final PackageInfo packageInfo; Loading Loading @@ -602,6 +685,7 @@ public class InternalResourceService extends SystemService { private void registerListeners() { final IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_LEVEL_CHANGED); filter.addAction(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); final IntentFilter pkgFilter = new IntentFilter(); Loading @@ -625,6 +709,15 @@ public class InternalResourceService extends SystemService { private void setupHeavyWork() { synchronized (mLock) { loadInstalledPackageListLocked(); if (mBootPhase >= PHASE_BOOT_COMPLETED && !mExemptListLoaded) { try { mExemptedApps = new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist()); } catch (RemoteException e) { // Shouldn't happen. Slog.wtf(TAG, e); } mExemptListLoaded = true; } final boolean isFirstSetup = !mScribe.recordExists(); if (isFirstSetup) { mAgent.grantBirthrightsLocked(); Loading Loading @@ -654,6 +747,8 @@ public class InternalResourceService extends SystemService { synchronized (mLock) { mAgent.tearDownLocked(); mCompleteEconomicPolicy.tearDown(); mExemptedApps.clear(); mExemptListLoaded = false; mHandler.post(() -> { // Never call out to AlarmManager with the lock held. This sits below AM. AlarmManager alarmManager = getContext().getSystemService(AlarmManager.class); Loading Loading @@ -953,9 +1048,9 @@ public class InternalResourceService extends SystemService { pw.print("Current battery level: "); pw.println(mCurrentBatteryLevel); final long maxCircluation = getMaxCirculationLocked(); final long maxCirculation = getMaxCirculationLocked(); pw.print("Max circulation (current/satiated): "); pw.print(narcToString(maxCircluation)); pw.print(narcToString(maxCirculation)); pw.print("/"); pw.println(narcToString(mCompleteEconomicPolicy.getMaxSatiatedCirculation())); Loading @@ -963,9 +1058,13 @@ public class InternalResourceService extends SystemService { pw.print("Current GDP: "); pw.print(narcToString(currentCirculation)); pw.print(" ("); pw.print(String.format("%.2f", 100f * currentCirculation / maxCircluation)); pw.print(String.format("%.2f", 100f * currentCirculation / maxCirculation)); pw.println("% of current max)"); pw.println(); pw.print("Exempted apps", mExemptedApps); pw.println(); pw.println(); mCompleteEconomicPolicy.dump(pw); Loading apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java +18 −5 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_TIMEOUT_PENA import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP; import static android.app.tare.EconomyManager.DEFAULT_JS_MAX_CIRCULATION; import static android.app.tare.EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE; import static android.app.tare.EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED; import static android.app.tare.EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP; import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT; import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_MAX; Loading Loading @@ -80,6 +81,7 @@ import static android.app.tare.EconomyManager.KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_ import static android.app.tare.EconomyManager.KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP; import static android.app.tare.EconomyManager.KEY_JS_MAX_CIRCULATION; import static android.app.tare.EconomyManager.KEY_JS_MAX_SATIATED_BALANCE; import static android.app.tare.EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED; import static android.app.tare.EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP; import static android.app.tare.EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT; import static android.app.tare.EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_MAX; Loading Loading @@ -140,7 +142,8 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { COST_MODIFIER_PROCESS_STATE }; private long mMinSatiatedBalance; private long mMinSatiatedBalanceExempted; private long mMinSatiatedBalanceOther; private long mMaxSatiatedBalance; private long mMaxSatiatedCirculation; Loading @@ -165,8 +168,11 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { @Override long getMinSatiatedBalance(final int userId, @NonNull final String pkgName) { // TODO: incorporate time since usage return mMinSatiatedBalance; if (mInternalResourceService.isPackageExempted(userId, pkgName)) { return mMinSatiatedBalanceExempted; } // TODO: take other exemptions into account return mMinSatiatedBalanceOther; } @Override Loading Loading @@ -207,7 +213,10 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { Slog.e(TAG, "Global setting key incorrect: ", e); } mMinSatiatedBalance = arcToNarc( mMinSatiatedBalanceExempted = arcToNarc( mParser.getInt(KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED, DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED)); mMinSatiatedBalanceOther = arcToNarc( mParser.getInt(KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP, DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP)); mMaxSatiatedBalance = arcToNarc(mParser.getInt(KEY_JS_MAX_SATIATED_BALANCE, Loading Loading @@ -317,7 +326,11 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { @Override void dump(IndentingPrintWriter pw) { pw.print("Min satiated balance", narcToString(mMinSatiatedBalance)).println(); pw.println("Min satiated balances:"); pw.increaseIndent(); pw.print("Exempted", narcToString(mMinSatiatedBalanceExempted)).println(); pw.print("Other", narcToString(mMinSatiatedBalanceOther)).println(); pw.decreaseIndent(); pw.print("Max satiated balance", narcToString(mMaxSatiatedBalance)).println(); pw.print("Min satiated circulation", narcToString(mMaxSatiatedCirculation)).println(); Loading Loading
apex/jobscheduler/service/java/com/android/server/tare/Agent.java +64 −0 Original line number Diff line number Diff line Loading @@ -16,8 +16,12 @@ package com.android.server.tare; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static com.android.server.tare.EconomicPolicy.REGULATION_BASIC_INCOME; import static com.android.server.tare.EconomicPolicy.REGULATION_BIRTHRIGHT; import static com.android.server.tare.EconomicPolicy.REGULATION_DEMOTION; import static com.android.server.tare.EconomicPolicy.REGULATION_PROMOTION; import static com.android.server.tare.EconomicPolicy.REGULATION_WEALTH_RECLAMATION; import static com.android.server.tare.EconomicPolicy.TYPE_ACTION; import static com.android.server.tare.EconomicPolicy.TYPE_REWARD; Loading Loading @@ -603,6 +607,51 @@ class Agent { } } /** * Reclaim a percentage of unused ARCs from an app that was just removed from an exemption list. * The amount reclaimed will depend on how recently the app was used. The reclamation will not * reduce an app's balance below its current minimum balance. */ @GuardedBy("mLock") void onAppUnexemptedLocked(final int userId, @NonNull final String pkgName) { final long curBalance = getBalanceLocked(userId, pkgName); final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName); if (curBalance <= minBalance) { return; } // AppStandby only counts elapsed time for things like this // TODO: should we use clock time instead? final long timeSinceLastUsedMs = mAppStandbyInternal.getTimeSinceLastUsedByUser(pkgName, userId); // The app is no longer exempted. We should take away some of credits so it's more in line // with other non-exempt apps. However, don't take away as many credits if the app was used // recently. final double percentageToReclaim; if (timeSinceLastUsedMs < DAY_IN_MILLIS) { percentageToReclaim = .25; } else if (timeSinceLastUsedMs < 2 * DAY_IN_MILLIS) { percentageToReclaim = .5; } else if (timeSinceLastUsedMs < 3 * DAY_IN_MILLIS) { percentageToReclaim = .75; } else { percentageToReclaim = 1; } final long overage = curBalance - minBalance; final long toReclaim = (long) (overage * percentageToReclaim); if (toReclaim > 0) { if (DEBUG) { Slog.i(TAG, "Reclaiming bonus wealth! Taking " + toReclaim + " from " + appToString(userId, pkgName)); } final long now = getCurrentTimeMillis(); final Ledger ledger = mScribe.getLedgerLocked(userId, pkgName); recordTransactionLocked(userId, pkgName, ledger, new Ledger.Transaction(now, now, REGULATION_DEMOTION, null, -toReclaim), true); } } /** Returns true if an app should be given credits in the general distributions. */ private boolean shouldGiveCredits(@NonNull PackageInfo packageInfo) { final ApplicationInfo applicationInfo = packageInfo.applicationInfo; Loading Loading @@ -700,6 +749,21 @@ class Agent { Math.min(maxBirthright, mIrs.getMinBalanceLocked(userId, pkgName))), true); } @GuardedBy("mLock") void onAppExemptedLocked(final int userId, @NonNull final String pkgName) { final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName); final long missing = minBalance - getBalanceLocked(userId, pkgName); if (missing <= 0) { return; } final Ledger ledger = mScribe.getLedgerLocked(userId, pkgName); final long now = getCurrentTimeMillis(); recordTransactionLocked(userId, pkgName, ledger, new Ledger.Transaction(now, now, REGULATION_PROMOTION, null, missing), true); } @GuardedBy("mLock") void onPackageRemovedLocked(final int userId, @NonNull final String pkgName) { reclaimAssetsLocked(userId, pkgName); Loading
apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java +17 −5 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_WA import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP; import static android.app.tare.EconomyManager.DEFAULT_AM_MAX_CIRCULATION; import static android.app.tare.EconomyManager.DEFAULT_AM_MAX_SATIATED_BALANCE; import static android.app.tare.EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED; import static android.app.tare.EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP; import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT; import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_MAX; Loading Loading @@ -71,6 +72,7 @@ import static android.app.tare.EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_WAKEUP import static android.app.tare.EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP; import static android.app.tare.EconomyManager.KEY_AM_MAX_CIRCULATION; import static android.app.tare.EconomyManager.KEY_AM_MAX_SATIATED_BALANCE; import static android.app.tare.EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED; import static android.app.tare.EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP; import static android.app.tare.EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT; import static android.app.tare.EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_MAX; Loading Loading @@ -138,7 +140,8 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { COST_MODIFIER_PROCESS_STATE }; private long mMinSatiatedBalance; private long mMinSatiatedBalanceExempted; private long mMinSatiatedBalanceOther; private long mMaxSatiatedBalance; private long mMaxSatiatedCirculation; Loading @@ -163,8 +166,11 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { @Override long getMinSatiatedBalance(final int userId, @NonNull final String pkgName) { // TODO: take exemption into account return mMinSatiatedBalance; if (mInternalResourceService.isPackageExempted(userId, pkgName)) { return mMinSatiatedBalanceExempted; } // TODO: take other exemptions into account return mMinSatiatedBalanceOther; } @Override Loading Loading @@ -205,7 +211,9 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { Slog.e(TAG, "Global setting key incorrect: ", e); } mMinSatiatedBalance = arcToNarc(mParser.getInt(KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP, mMinSatiatedBalanceExempted = arcToNarc(mParser.getInt(KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED, DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED)); mMinSatiatedBalanceOther = arcToNarc(mParser.getInt(KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP, DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP)); mMaxSatiatedBalance = arcToNarc(mParser.getInt(KEY_AM_MAX_SATIATED_BALANCE, DEFAULT_AM_MAX_SATIATED_BALANCE)); Loading Loading @@ -343,7 +351,11 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { @Override void dump(IndentingPrintWriter pw) { pw.print("Min satiated balance", narcToString(mMinSatiatedBalance)).println(); pw.println("Min satiated balances:"); pw.increaseIndent(); pw.print("Exempted", narcToString(mMinSatiatedBalanceExempted)).println(); pw.print("Other", narcToString(mMinSatiatedBalanceOther)).println(); pw.decreaseIndent(); pw.print("Max satiated balance", narcToString(mMaxSatiatedBalance)).println(); pw.print("Min satiated circulation", narcToString(mMaxSatiatedCirculation)).println(); Loading
apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java +6 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,8 @@ public abstract class EconomicPolicy { static final int REGULATION_BASIC_INCOME = TYPE_REGULATION | 0; static final int REGULATION_BIRTHRIGHT = TYPE_REGULATION | 1; static final int REGULATION_WEALTH_RECLAMATION = TYPE_REGULATION | 2; static final int REGULATION_PROMOTION = TYPE_REGULATION | 3; static final int REGULATION_DEMOTION = TYPE_REGULATION | 4; static final int REWARD_NOTIFICATION_SEEN = TYPE_REWARD | 0; static final int REWARD_NOTIFICATION_INTERACTION = TYPE_REWARD | 1; Loading Loading @@ -363,6 +365,10 @@ public abstract class EconomicPolicy { return "BIRTHRIGHT"; case REGULATION_WEALTH_RECLAMATION: return "WEALTH_RECLAMATION"; case REGULATION_PROMOTION: return "PROMOTION"; case REGULATION_DEMOTION: return "DEMOTION"; } return "UNKNOWN_REGULATION:" + Integer.toHexString(eventId); } Loading
apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java +102 −3 Original line number Diff line number Diff line Loading @@ -45,8 +45,12 @@ import android.net.Uri; import android.os.BatteryManagerInternal; import android.os.Binder; import android.os.Handler; import android.os.IDeviceIdleController; import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; Loading Loading @@ -105,6 +109,8 @@ public class InternalResourceService extends SystemService { private final PackageManager mPackageManager; private final PackageManagerInternal mPackageManagerInternal; private IDeviceIdleController mDeviceIdleController; private final Agent mAgent; private final ConfigObserver mConfigObserver; private final EconomyManagerStub mEconomyManagerStub; Loading Loading @@ -163,8 +169,14 @@ public class InternalResourceService extends SystemService { @GuardedBy("mPackageToUidCache") private final SparseArrayMap<String, Integer> mPackageToUidCache = new SparseArrayMap<>(); /** List of packages that are "exempted" from battery restrictions. */ // TODO(144864180): include userID @GuardedBy("mLock") private ArraySet<String> mExemptedApps = new ArraySet<>(); private volatile boolean mIsEnabled; private volatile int mBootPhase; private volatile boolean mExemptListLoaded; // In the range [0,100] to represent 0% to 100% battery. @GuardedBy("mLock") private int mCurrentBatteryLevel; Loading Loading @@ -213,6 +225,9 @@ public class InternalResourceService extends SystemService { onUserRemoved(userId); } break; case PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED: onExemptionListChanged(); break; } } }; Loading Loading @@ -285,7 +300,22 @@ public class InternalResourceService extends SystemService { if (PHASE_SYSTEM_SERVICES_READY == phase) { mConfigObserver.start(); mDeviceIdleController = IDeviceIdleController.Stub.asInterface( ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); setupEverything(); } else if (PHASE_BOOT_COMPLETED == phase) { if (!mExemptListLoaded) { synchronized (mLock) { try { mExemptedApps = new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist()); } catch (RemoteException e) { // Shouldn't happen. Slog.wtf(TAG, e); } mExemptListLoaded = true; } } } } Loading Loading @@ -350,6 +380,12 @@ public class InternalResourceService extends SystemService { return mIsEnabled; } boolean isPackageExempted(final int userId, @NonNull String pkgName) { synchronized (mLock) { return mExemptedApps.contains(pkgName); } } boolean isSystem(final int userId, @NonNull String pkgName) { if ("android".equals(pkgName)) { return true; Loading @@ -375,6 +411,53 @@ public class InternalResourceService extends SystemService { } } void onExemptionListChanged() { final int[] userIds = LocalServices.getService(UserManagerInternal.class).getUserIds(); synchronized (mLock) { final ArraySet<String> removed = mExemptedApps; final ArraySet<String> added = new ArraySet<>(); try { mExemptedApps = new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist()); } catch (RemoteException e) { // Shouldn't happen. Slog.wtf(TAG, e); return; } for (int i = mExemptedApps.size() - 1; i >= 0; --i) { final String pkg = mExemptedApps.valueAt(i); if (!removed.contains(pkg)) { added.add(pkg); } removed.remove(pkg); } for (int a = added.size() - 1; a >= 0; --a) { final String pkgName = added.valueAt(a); for (int userId : userIds) { // Since the exemption list doesn't specify user ID and we track by user ID, // we need to see if the app exists on the user before talking to the agent. // Otherwise, we may end up with invalid ledgers. final boolean appExists = getUid(userId, pkgName) >= 0; if (appExists) { mAgent.onAppExemptedLocked(userId, pkgName); } } } for (int r = removed.size() - 1; r >= 0; --r) { final String pkgName = removed.valueAt(r); for (int userId : userIds) { // Since the exemption list doesn't specify user ID and we track by user ID, // we need to see if the app exists on the user before talking to the agent. // Otherwise, we may end up with invalid ledgers. final boolean appExists = getUid(userId, pkgName) >= 0; if (appExists) { mAgent.onAppUnexemptedLocked(userId, pkgName); } } } } } void onPackageAdded(final int uid, @NonNull final String pkgName) { final int userId = UserHandle.getUserId(uid); final PackageInfo packageInfo; Loading Loading @@ -602,6 +685,7 @@ public class InternalResourceService extends SystemService { private void registerListeners() { final IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_LEVEL_CHANGED); filter.addAction(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); final IntentFilter pkgFilter = new IntentFilter(); Loading @@ -625,6 +709,15 @@ public class InternalResourceService extends SystemService { private void setupHeavyWork() { synchronized (mLock) { loadInstalledPackageListLocked(); if (mBootPhase >= PHASE_BOOT_COMPLETED && !mExemptListLoaded) { try { mExemptedApps = new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist()); } catch (RemoteException e) { // Shouldn't happen. Slog.wtf(TAG, e); } mExemptListLoaded = true; } final boolean isFirstSetup = !mScribe.recordExists(); if (isFirstSetup) { mAgent.grantBirthrightsLocked(); Loading Loading @@ -654,6 +747,8 @@ public class InternalResourceService extends SystemService { synchronized (mLock) { mAgent.tearDownLocked(); mCompleteEconomicPolicy.tearDown(); mExemptedApps.clear(); mExemptListLoaded = false; mHandler.post(() -> { // Never call out to AlarmManager with the lock held. This sits below AM. AlarmManager alarmManager = getContext().getSystemService(AlarmManager.class); Loading Loading @@ -953,9 +1048,9 @@ public class InternalResourceService extends SystemService { pw.print("Current battery level: "); pw.println(mCurrentBatteryLevel); final long maxCircluation = getMaxCirculationLocked(); final long maxCirculation = getMaxCirculationLocked(); pw.print("Max circulation (current/satiated): "); pw.print(narcToString(maxCircluation)); pw.print(narcToString(maxCirculation)); pw.print("/"); pw.println(narcToString(mCompleteEconomicPolicy.getMaxSatiatedCirculation())); Loading @@ -963,9 +1058,13 @@ public class InternalResourceService extends SystemService { pw.print("Current GDP: "); pw.print(narcToString(currentCirculation)); pw.print(" ("); pw.print(String.format("%.2f", 100f * currentCirculation / maxCircluation)); pw.print(String.format("%.2f", 100f * currentCirculation / maxCirculation)); pw.println("% of current max)"); pw.println(); pw.print("Exempted apps", mExemptedApps); pw.println(); pw.println(); mCompleteEconomicPolicy.dump(pw); Loading
apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java +18 −5 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_TIMEOUT_PENA import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP; import static android.app.tare.EconomyManager.DEFAULT_JS_MAX_CIRCULATION; import static android.app.tare.EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE; import static android.app.tare.EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED; import static android.app.tare.EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP; import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT; import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_MAX; Loading Loading @@ -80,6 +81,7 @@ import static android.app.tare.EconomyManager.KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_ import static android.app.tare.EconomyManager.KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP; import static android.app.tare.EconomyManager.KEY_JS_MAX_CIRCULATION; import static android.app.tare.EconomyManager.KEY_JS_MAX_SATIATED_BALANCE; import static android.app.tare.EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED; import static android.app.tare.EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP; import static android.app.tare.EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT; import static android.app.tare.EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_MAX; Loading Loading @@ -140,7 +142,8 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { COST_MODIFIER_PROCESS_STATE }; private long mMinSatiatedBalance; private long mMinSatiatedBalanceExempted; private long mMinSatiatedBalanceOther; private long mMaxSatiatedBalance; private long mMaxSatiatedCirculation; Loading @@ -165,8 +168,11 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { @Override long getMinSatiatedBalance(final int userId, @NonNull final String pkgName) { // TODO: incorporate time since usage return mMinSatiatedBalance; if (mInternalResourceService.isPackageExempted(userId, pkgName)) { return mMinSatiatedBalanceExempted; } // TODO: take other exemptions into account return mMinSatiatedBalanceOther; } @Override Loading Loading @@ -207,7 +213,10 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { Slog.e(TAG, "Global setting key incorrect: ", e); } mMinSatiatedBalance = arcToNarc( mMinSatiatedBalanceExempted = arcToNarc( mParser.getInt(KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED, DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED)); mMinSatiatedBalanceOther = arcToNarc( mParser.getInt(KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP, DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP)); mMaxSatiatedBalance = arcToNarc(mParser.getInt(KEY_JS_MAX_SATIATED_BALANCE, Loading Loading @@ -317,7 +326,11 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { @Override void dump(IndentingPrintWriter pw) { pw.print("Min satiated balance", narcToString(mMinSatiatedBalance)).println(); pw.println("Min satiated balances:"); pw.increaseIndent(); pw.print("Exempted", narcToString(mMinSatiatedBalanceExempted)).println(); pw.print("Other", narcToString(mMinSatiatedBalanceOther)).println(); pw.decreaseIndent(); pw.print("Max satiated balance", narcToString(mMaxSatiatedBalance)).println(); pw.print("Min satiated circulation", narcToString(mMaxSatiatedCirculation)).println(); Loading