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

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

Merge "Exempt exact alarms from the stock limit."

parents de00c5bc 4bedfc19
Loading
Loading
Loading
Loading
+25 −16
Original line number Diff line number Diff line
@@ -164,8 +164,9 @@ class Agent {
    }

    @GuardedBy("mLock")
    private boolean isAffordableLocked(long balance, long price, long ctp) {
        return balance >= price && mScribe.getRemainingConsumableCakesLocked() >= ctp;
    private boolean isAffordableLocked(long balance, long price, long stockLimitHonoringCtp) {
        return balance >= price
                && mScribe.getRemainingConsumableCakesLocked() >= stockLimitHonoringCtp;
    }

    @GuardedBy("mLock")
@@ -303,7 +304,8 @@ class Agent {
                        note.recalculateCosts(economicPolicy, userId, pkgName);
                        final boolean isAffordable = isVip
                                || isAffordableLocked(newBalance,
                                        note.getCachedModifiedPrice(), note.getCtp());
                                        note.getCachedModifiedPrice(),
                                        note.getStockLimitHonoringCtp());
                        if (note.isCurrentlyAffordable() != isAffordable) {
                            note.setNewAffordability(isAffordable);
                            mIrs.postAffordabilityChanged(userId, pkgName, note);
@@ -339,7 +341,7 @@ class Agent {
                note.recalculateCosts(economicPolicy, userId, pkgName);
                final boolean isAffordable = isVip
                        || isAffordableLocked(newBalance,
                        note.getCachedModifiedPrice(), note.getCtp());
                        note.getCachedModifiedPrice(), note.getStockLimitHonoringCtp());
                if (note.isCurrentlyAffordable() != isAffordable) {
                    note.setNewAffordability(isAffordable);
                    mIrs.postAffordabilityChanged(userId, pkgName, note);
@@ -403,7 +405,8 @@ class Agent {
                        note.recalculateCosts(economicPolicy, userId, pkgName);
                        final boolean isAffordable = isVip
                                || isAffordableLocked(newBalance,
                                        note.getCachedModifiedPrice(), note.getCtp());
                                        note.getCachedModifiedPrice(),
                                        note.getStockLimitHonoringCtp());
                        if (note.isCurrentlyAffordable() != isAffordable) {
                            note.setNewAffordability(isAffordable);
                            mIrs.postAffordabilityChanged(userId, pkgName, note);
@@ -541,7 +544,7 @@ class Agent {
                    final ActionAffordabilityNote note = actionAffordabilityNotes.valueAt(i);
                    final boolean isAffordable = isVip
                            || isAffordableLocked(newBalance,
                                    note.getCachedModifiedPrice(), note.getCtp());
                                    note.getCachedModifiedPrice(), note.getStockLimitHonoringCtp());
                    if (note.isCurrentlyAffordable() != isAffordable) {
                        note.setNewAffordability(isAffordable);
                        mIrs.postAffordabilityChanged(userId, pkgName, note);
@@ -882,7 +885,7 @@ class Agent {
                        mUpperThreshold = (mUpperThreshold == Long.MIN_VALUE)
                                ? price : Math.min(mUpperThreshold, price);
                    }
                    final long ctp = note.getCtp();
                    final long ctp = note.getStockLimitHonoringCtp();
                    if (ctp <= mRemainingConsumableCredits) {
                        mCtpThreshold = Math.max(mCtpThreshold, ctp);
                    }
@@ -1119,7 +1122,7 @@ class Agent {
            note.recalculateCosts(economicPolicy, userId, pkgName);
            note.setNewAffordability(isVip
                    || isAffordableLocked(getBalanceLocked(userId, pkgName),
                            note.getCachedModifiedPrice(), note.getCtp()));
                            note.getCachedModifiedPrice(), note.getStockLimitHonoringCtp()));
            mIrs.postAffordabilityChanged(userId, pkgName, note);
            // Update ongoing alarm
            scheduleBalanceCheckLocked(userId, pkgName);
@@ -1146,7 +1149,7 @@ class Agent {
    static final class ActionAffordabilityNote {
        private final EconomyManagerInternal.ActionBill mActionBill;
        private final EconomyManagerInternal.AffordabilityChangeListener mListener;
        private long mCtp;
        private long mStockLimitHonoringCtp;
        private long mModifiedPrice;
        private boolean mIsAffordable;

@@ -1185,29 +1188,34 @@ class Agent {
            return mModifiedPrice;
        }

        private long getCtp() {
            return mCtp;
        /** Returns the cumulative CTP of actions in this note that respect the stock limit. */
        private long getStockLimitHonoringCtp() {
            return mStockLimitHonoringCtp;
        }

        @VisibleForTesting
        void recalculateCosts(@NonNull EconomicPolicy economicPolicy,
                int userId, @NonNull String pkgName) {
            long modifiedPrice = 0;
            long ctp = 0;
            long stockLimitHonoringCtp = 0;
            final List<EconomyManagerInternal.AnticipatedAction> anticipatedActions =
                    mActionBill.getAnticipatedActions();
            for (int i = 0; i < anticipatedActions.size(); ++i) {
                final EconomyManagerInternal.AnticipatedAction aa = anticipatedActions.get(i);
                final EconomicPolicy.Action action = economicPolicy.getAction(aa.actionId);

                final EconomicPolicy.Cost actionCost =
                        economicPolicy.getCostOfAction(aa.actionId, userId, pkgName);
                modifiedPrice += actionCost.price * aa.numInstantaneousCalls
                        + actionCost.price * (aa.ongoingDurationMs / 1000);
                ctp += actionCost.costToProduce * aa.numInstantaneousCalls
                if (action.respectsStockLimit) {
                    stockLimitHonoringCtp +=
                            actionCost.costToProduce * aa.numInstantaneousCalls
                                    + actionCost.costToProduce * (aa.ongoingDurationMs / 1000);
                }
            }
            mModifiedPrice = modifiedPrice;
            mCtp = ctp;
            mStockLimitHonoringCtp = stockLimitHonoringCtp;
        }

        boolean isCurrentlyAffordable() {
@@ -1267,7 +1275,8 @@ class Agent {
                                final ActionAffordabilityNote note =
                                        actionAffordabilityNotes.valueAt(i);
                                final boolean isAffordable = isVip || isAffordableLocked(
                                        newBalance, note.getCachedModifiedPrice(), note.getCtp());
                                        newBalance, note.getCachedModifiedPrice(),
                                        note.getStockLimitHonoringCtp());
                                if (note.isCurrentlyAffordable() != isAffordable) {
                                    note.setNewAffordability(isAffordable);
                                    mIrs.postAffordabilityChanged(userId, pkgName, note);
+18 −7
Original line number Diff line number Diff line
@@ -262,12 +262,17 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
                KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE,
                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE_CAKES);

        // Apps must hold the SCHEDULE_EXACT_ALARM or USE_EXACT_ALARMS permission in order to use
        // exact alarms. Since the user has the option of granting/revoking the permission, we can
        // be a little lenient on the action cost checks and only stop the action if the app has
        // run out of credits, and not when the system has run out of stock.
        mActions.put(ACTION_ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE,
                new Action(ACTION_ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE,
                        getConstantAsCake(mParser, properties,
                                KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP,
                                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP_CAKES),
                        exactAllowWhileIdleWakeupBasePrice));
                        exactAllowWhileIdleWakeupBasePrice,
                        /* respectsStockLimit */ false));
        mActions.put(ACTION_ALARM_WAKEUP_EXACT,
                new Action(ACTION_ALARM_WAKEUP_EXACT,
                        getConstantAsCake(mParser, properties,
@@ -275,7 +280,8 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
                                DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_CTP_CAKES),
                        getConstantAsCake(mParser, properties,
                                KEY_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE,
                                DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES)));
                                DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES),
                        /* respectsStockLimit */ false));

        final long inexactAllowWhileIdleWakeupBasePrice =
                getConstantAsCake(mParser, properties,
@@ -287,7 +293,8 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
                        getConstantAsCake(mParser, properties,
                                KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP,
                                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP_CAKES),
                        inexactAllowWhileIdleWakeupBasePrice));
                        inexactAllowWhileIdleWakeupBasePrice,
                        /* respectsStockLimit */ false));
        mActions.put(ACTION_ALARM_WAKEUP_INEXACT,
                new Action(ACTION_ALARM_WAKEUP_INEXACT,
                        getConstantAsCake(mParser, properties,
@@ -295,7 +302,8 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
                                DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP_CAKES),
                        getConstantAsCake(mParser, properties,
                                KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE,
                                DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE_CAKES)));
                                DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE_CAKES),
                        /* respectsStockLimit */ false));

        final long exactAllowWhileIdleNonWakeupBasePrice = getConstantAsCake(mParser, properties,
                KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_BASE_PRICE,
@@ -305,7 +313,8 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
                        getConstantAsCake(mParser, properties,
                                KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP,
                                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP_CAKES),
                        exactAllowWhileIdleNonWakeupBasePrice));
                        exactAllowWhileIdleNonWakeupBasePrice,
                        /* respectsStockLimit */ false));

        mActions.put(ACTION_ALARM_NONWAKEUP_EXACT,
                new Action(ACTION_ALARM_NONWAKEUP_EXACT,
@@ -314,7 +323,8 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
                                DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP_CAKES),
                        getConstantAsCake(mParser, properties,
                                KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE,
                                DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE_CAKES)));
                                DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE_CAKES),
                        /* respectsStockLimit */ false));

        final long inexactAllowWhileIdleNonWakeupBasePrice = getConstantAsCake(mParser, properties,
                KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE,
@@ -342,7 +352,8 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
                                DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_CTP_CAKES),
                        getConstantAsCake(mParser, properties,
                                KEY_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE,
                                DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE_CAKES)));
                                DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE_CAKES),
                        /* respectsStockLimit */ false));

        mRewards.put(REWARD_TOP_ACTIVITY, new Reward(REWARD_TOP_ACTIVITY,
                getConstantAsCake(mParser, properties,
+11 −0
Original line number Diff line number Diff line
@@ -149,11 +149,22 @@ public abstract class EconomicPolicy {
         * the action unless a modifier lowers the cost to produce.
         */
        public final long basePrice;
        /**
         * Whether the remaining stock limit affects an app's ability to perform this action.
         * If {@code false}, then the action can be performed, even if the cost is higher
         * than the remaining stock. This does not affect checking against an app's balance.
         */
        public final boolean respectsStockLimit;

        Action(int id, long costToProduce, long basePrice) {
            this(id, costToProduce, basePrice, true);
        }

        Action(int id, long costToProduce, long basePrice, boolean respectsStockLimit) {
            this.id = id;
            this.costToProduce = costToProduce;
            this.basePrice = basePrice;
            this.respectsStockLimit = respectsStockLimit;
        }
    }