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

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

Merge "Handle Background Restricted apps."

parents 0fe33ba7 3c4e2194
Loading
Loading
Loading
Loading
+48 −4
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ 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_BG_RESTRICTED;
import static com.android.server.tare.EconomicPolicy.REGULATION_BG_UNRESTRICTED;
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;
@@ -510,12 +512,12 @@ class Agent {
        }
        final CompleteEconomicPolicy economicPolicy = mIrs.getCompleteEconomicPolicyLocked();
        final long originalBalance = ledger.getCurrentBalance();
        final long maxBalance = economicPolicy.getMaxSatiatedBalance(userId, pkgName);
        if (transaction.delta > 0
                && originalBalance + transaction.delta > economicPolicy.getMaxSatiatedBalance()) {
                && originalBalance + transaction.delta > maxBalance) {
            // Set lower bound at 0 so we don't accidentally take away credits when we were trying
            // to _give_ the app credits.
            final long newDelta =
                    Math.max(0, economicPolicy.getMaxSatiatedBalance() - originalBalance);
            final long newDelta = Math.max(0, maxBalance - originalBalance);
            Slog.i(TAG, "Would result in becoming too rich. Decreasing transaction "
                    + eventToString(transaction.eventId)
                    + (transaction.tag == null ? "" : ":" + transaction.tag)
@@ -660,6 +662,47 @@ class Agent {
        }
    }

    /**
     * Reclaim all ARCs from an app that was just restricted.
     */
    @GuardedBy("mLock")
    void onAppRestrictedLocked(final int userId, @NonNull final String pkgName) {
        final long curBalance = getBalanceLocked(userId, pkgName);
        final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName);
        if (curBalance <= minBalance) {
            return;
        }
        if (DEBUG) {
            Slog.i(TAG, "App restricted! Taking " + curBalance
                    + " 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_BG_RESTRICTED, null, -curBalance, 0),
                true);
    }

    /**
     * Give an app that was just unrestricted some ARCs.
     */
    @GuardedBy("mLock")
    void onAppUnrestrictedLocked(final int userId, @NonNull final String pkgName) {
        final Ledger ledger = mScribe.getLedgerLocked(userId, pkgName);
        if (ledger.getCurrentBalance() > 0) {
            Slog.wtf(TAG, "App " + pkgName + " had credits while it was restricted");
            // App already got credits somehow. Move along.
            return;
        }

        final long now = getCurrentTimeMillis();

        recordTransactionLocked(userId, pkgName, ledger,
                new Ledger.Transaction(now, now, REGULATION_BG_UNRESTRICTED, null,
                        mIrs.getMinBalanceLocked(userId, pkgName), 0), true);
    }

    /** Returns true if an app should be given credits in the general distributions. */
    private boolean shouldGiveCredits(@NonNull InstalledPackageInfo packageInfo) {
        // Skip apps that wouldn't be doing any work. Giving them ARCs would be wasteful.
@@ -668,7 +711,8 @@ class Agent {
        }
        final int userId = UserHandle.getUserId(packageInfo.uid);
        // No point allocating ARCs to the system. It can do whatever it wants.
        return !mIrs.isSystem(userId, packageInfo.packageName);
        return !mIrs.isSystem(userId, packageInfo.packageName)
                && !mIrs.isPackageRestricted(userId, packageInfo.packageName);
    }

    void onCreditSupplyChanged() {
+7 −1
Original line number Diff line number Diff line
@@ -170,6 +170,9 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {

    @Override
    long getMinSatiatedBalance(final int userId, @NonNull final String pkgName) {
        if (mIrs.isPackageRestricted(userId, pkgName)) {
            return 0;
        }
        if (mIrs.isPackageExempted(userId, pkgName)) {
            return mMinSatiatedBalanceExempted;
        }
@@ -178,7 +181,10 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
    }

    @Override
    long getMaxSatiatedBalance() {
    long getMaxSatiatedBalance(int userId, @NonNull String pkgName) {
        if (mIrs.isPackageRestricted(userId, pkgName)) {
            return 0;
        }
        // TODO(230501287): adjust balance based on whether the app has the SCHEDULE_EXACT_ALARM
        // permission granted. Apps without the permission granted shouldn't need a high balance
        // since they won't be able to use exact alarms. Apps with the permission granted could
+6 −6
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
    /** Lazily populated set of rewards covered by this policy. */
    private final SparseArray<Reward> mRewards = new SparseArray<>();
    private final int[] mCostModifiers;
    private long mMaxSatiatedBalance;
    private long mInitialConsumptionLimit;
    private long mHardConsumptionLimit;

@@ -80,16 +79,13 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
    }

    private void updateLimits() {
        long maxSatiatedBalance = 0;
        long initialConsumptionLimit = 0;
        long hardConsumptionLimit = 0;
        for (int i = 0; i < mEnabledEconomicPolicies.size(); ++i) {
            final EconomicPolicy economicPolicy = mEnabledEconomicPolicies.valueAt(i);
            maxSatiatedBalance += economicPolicy.getMaxSatiatedBalance();
            initialConsumptionLimit += economicPolicy.getInitialSatiatedConsumptionLimit();
            hardConsumptionLimit += economicPolicy.getHardSatiatedConsumptionLimit();
        }
        mMaxSatiatedBalance = maxSatiatedBalance;
        mInitialConsumptionLimit = initialConsumptionLimit;
        mHardConsumptionLimit = hardConsumptionLimit;
    }
@@ -104,8 +100,12 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
    }

    @Override
    long getMaxSatiatedBalance() {
        return mMaxSatiatedBalance;
    long getMaxSatiatedBalance(int userId, @NonNull String pkgName) {
        long max = 0;
        for (int i = 0; i < mEnabledEconomicPolicies.size(); ++i) {
            max += mEnabledEconomicPolicies.valueAt(i).getMaxSatiatedBalance(userId, pkgName);
        }
        return max;
    }

    @Override
+4 −1
Original line number Diff line number Diff line
@@ -67,6 +67,9 @@ public abstract class EconomicPolicy {
    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;
    /** App is fully restricted from running in the background. */
    static final int REGULATION_BG_RESTRICTED = TYPE_REGULATION | 5;
    static final int REGULATION_BG_UNRESTRICTED = TYPE_REGULATION | 6;

    static final int REWARD_NOTIFICATION_SEEN = TYPE_REWARD | 0;
    static final int REWARD_NOTIFICATION_INTERACTION = TYPE_REWARD | 1;
@@ -210,7 +213,7 @@ public abstract class EconomicPolicy {
     * exists to ensure that no single app accumulate all available resources and increases fairness
     * for all apps.
     */
    abstract long getMaxSatiatedBalance();
    abstract long getMaxSatiatedBalance(int userId, @NonNull String pkgName);

    /**
     * Returns the maximum number of cakes that should be consumed during a full 100% discharge
+55 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.tare.IEconomyManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
@@ -64,6 +65,8 @@ import android.util.SparseArrayMap;
import android.util.SparseSetArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
@@ -119,6 +122,7 @@ public class InternalResourceService extends SystemService {
    private final PackageManager mPackageManager;
    private final PackageManagerInternal mPackageManagerInternal;

    private IAppOpsService mAppOpsService;
    private IDeviceIdleController mDeviceIdleController;

    private final Agent mAgent;
@@ -145,6 +149,12 @@ public class InternalResourceService extends SystemService {
    private final CopyOnWriteArraySet<TareStateChangeListener> mStateChangeListeners =
            new CopyOnWriteArraySet<>();

    /**
     * List of packages that are fully restricted and shouldn't be allowed to run in the background.
     */
    @GuardedBy("mLock")
    private final SparseSetArray<String> mRestrictedApps = new SparseSetArray<>();

    /** List of packages that are "exempted" from battery restrictions. */
    // TODO(144864180): include userID
    @GuardedBy("mLock")
@@ -160,6 +170,30 @@ public class InternalResourceService extends SystemService {
    @GuardedBy("mLock")
    private int mCurrentBatteryLevel;

    private final IAppOpsCallback mApbListener = new IAppOpsCallback.Stub() {
        @Override
        public void opChanged(int op, int uid, String packageName) {
            boolean restricted = false;
            try {
                restricted = mAppOpsService.checkOperation(
                        AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, packageName)
                        != AppOpsManager.MODE_ALLOWED;
            } catch (RemoteException e) {
                // Shouldn't happen
            }
            final int userId = UserHandle.getUserId(uid);
            synchronized (mLock) {
                if (restricted) {
                    if (mRestrictedApps.add(userId, packageName)) {
                        mAgent.onAppRestrictedLocked(userId, packageName);
                    }
                } else if (mRestrictedApps.remove(UserHandle.getUserId(uid), packageName)) {
                    mAgent.onAppUnrestrictedLocked(userId, packageName);
                }
            }
        }
    };

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Nullable
        private String getPackageName(Intent intent) {
@@ -280,9 +314,11 @@ public class InternalResourceService extends SystemService {

        switch (phase) {
            case PHASE_SYSTEM_SERVICES_READY:
                mConfigObserver.start();
                mAppOpsService = IAppOpsService.Stub.asInterface(
                        ServiceManager.getService(Context.APP_OPS_SERVICE));
                mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
                        ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
                mConfigObserver.start();
                onBootPhaseSystemServicesReady();
                break;
            case PHASE_THIRD_PARTY_APPS_CAN_START:
@@ -365,6 +401,12 @@ public class InternalResourceService extends SystemService {
        }
    }

    boolean isPackageRestricted(final int userId, @NonNull String pkgName) {
        synchronized (mLock) {
            return mRestrictedApps.contains(userId, pkgName);
        }
    }

    boolean isSystem(final int userId, @NonNull String pkgName) {
        if ("android".equals(pkgName)) {
            return true;
@@ -711,6 +753,13 @@ public class InternalResourceService extends SystemService {

        UsageStatsManagerInternal usmi = LocalServices.getService(UsageStatsManagerInternal.class);
        usmi.registerListener(mSurveillanceAgent);

        try {
            mAppOpsService
                    .startWatchingMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, null, mApbListener);
        } catch (RemoteException e) {
            // shouldn't happen.
        }
    }

    /** Perform long-running and/or heavy setup work. This should be called off the main thread. */
@@ -815,6 +864,11 @@ public class InternalResourceService extends SystemService {
            UsageStatsManagerInternal usmi =
                    LocalServices.getService(UsageStatsManagerInternal.class);
            usmi.unregisterListener(mSurveillanceAgent);
            try {
                mAppOpsService.stopWatchingMode(mApbListener);
            } catch (RemoteException e) {
                // shouldn't happen.
            }
        }
        synchronized (mPackageToUidCache) {
            mPackageToUidCache.clear();
Loading