Merge "Exempt exact alarms from the stock limit."
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user