Merge "Exempt exact alarms from the stock limit."

This commit is contained in:
Kweku Adams
2023-01-03 22:25:19 +00:00
committed by Android (Google) Code Review
3 changed files with 54 additions and 23 deletions

View File

@@ -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
+ actionCost.costToProduce * (aa.ongoingDurationMs / 1000);
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);

View File

@@ -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,

View File

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