Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8a9de1d authored by Kweku Adams's avatar Kweku Adams Committed by Android (Google) Code Review
Browse files

Merge "Account for the power allowlist."

parents e295eaab 2a25c418
Loading
Loading
Loading
Loading
+64 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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);
+17 −5
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;

@@ -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
@@ -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));
@@ -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();

+6 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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);
    }
+102 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;
@@ -213,6 +225,9 @@ public class InternalResourceService extends SystemService {
                    onUserRemoved(userId);
                }
                break;
                case PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED:
                    onExemptionListChanged();
                    break;
            }
        }
    };
@@ -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;
                }
            }
        }
    }

@@ -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;
@@ -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;
@@ -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();
@@ -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();
@@ -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);
@@ -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()));

@@ -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);

+18 −5
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;

@@ -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
@@ -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,
@@ -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();