Merge "Convert event IDs from String to int."
This commit is contained in:
committed by
Android (Google) Code Review
commit
ac3e3dd43c
@@ -16,6 +16,11 @@
|
||||
|
||||
package com.android.server.tare;
|
||||
|
||||
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.eventToString;
|
||||
import static com.android.server.tare.TareUtils.narcToString;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -85,23 +90,25 @@ class Agent {
|
||||
if (transaction.delta > 0 && newArcsInCirculation > maxCirculationAllowed) {
|
||||
final long newDelta = maxCirculationAllowed - mCurrentNarcsInCirculation;
|
||||
Slog.i(TAG, "Would result in too many credits in circulation. Decreasing transaction "
|
||||
+ transaction.reason + (transaction.tag == null ? "" : ":" + transaction.tag)
|
||||
+ eventToString(transaction.eventId)
|
||||
+ (transaction.tag == null ? "" : ":" + transaction.tag)
|
||||
+ " for <" + userId + ">" + pkgName + " by " + (transaction.delta - newDelta));
|
||||
transaction = new Ledger.Transaction(
|
||||
transaction.startTimeMs, transaction.endTimeMs,
|
||||
transaction.reason, transaction.tag, newDelta);
|
||||
transaction.eventId, transaction.tag, newDelta);
|
||||
}
|
||||
final long originalBalance = ledger.getCurrentBalance();
|
||||
if (transaction.delta > 0
|
||||
&& originalBalance + transaction.delta
|
||||
> mCompleteEconomicPolicy.getMaxSatiatedBalance()) {
|
||||
final long newDelta = mCompleteEconomicPolicy.getMaxSatiatedBalance() - originalBalance;
|
||||
Slog.i(TAG, "Would result in becoming too rich. Decreasing transaction "
|
||||
+ transaction.reason + (transaction.tag == null ? "" : ":" + transaction.tag)
|
||||
Slog.i(TAG, "Would result in becoming too rich. Decreasing transaction "
|
||||
+ eventToString(transaction.eventId)
|
||||
+ (transaction.tag == null ? "" : ":" + transaction.tag)
|
||||
+ " for <" + userId + ">" + pkgName + " by " + (transaction.delta - newDelta));
|
||||
transaction = new Ledger.Transaction(
|
||||
transaction.startTimeMs, transaction.endTimeMs,
|
||||
transaction.reason, transaction.tag, newDelta);
|
||||
transaction.eventId, transaction.tag, newDelta);
|
||||
}
|
||||
ledger.recordTransaction(transaction);
|
||||
mCurrentNarcsInCirculation += transaction.delta;
|
||||
@@ -129,7 +136,7 @@ class Agent {
|
||||
if (ledger.getCurrentBalance() < minBalance) {
|
||||
final long shortfall = minBalance - getBalanceLocked(userId, pkgName);
|
||||
recordTransactionLocked(userId, pkgName, ledger,
|
||||
new Ledger.Transaction(now, now, "UNIVERSAL_BASIC_INCOME",
|
||||
new Ledger.Transaction(now, now, REGULATION_BASIC_INCOME,
|
||||
null, (long) (perc * shortfall)));
|
||||
}
|
||||
}
|
||||
@@ -165,7 +172,7 @@ class Agent {
|
||||
}
|
||||
|
||||
recordTransactionLocked(userId, pkgName, ledger,
|
||||
new Ledger.Transaction(now, now, "BIRTHRIGHT", null,
|
||||
new Ledger.Transaction(now, now, REGULATION_BIRTHRIGHT, null,
|
||||
Math.min(maxBirthright, mIrs.getMinBalanceLocked(userId, pkgName))));
|
||||
}
|
||||
}
|
||||
@@ -185,7 +192,7 @@ class Agent {
|
||||
final long now = System.currentTimeMillis();
|
||||
|
||||
recordTransactionLocked(userId, pkgName, ledger,
|
||||
new Ledger.Transaction(now, now, "BIRTHRIGHT", null,
|
||||
new Ledger.Transaction(now, now, REGULATION_BIRTHRIGHT, null,
|
||||
Math.min(maxBirthright, mIrs.getMinBalanceLocked(userId, pkgName))));
|
||||
}
|
||||
|
||||
@@ -223,6 +230,6 @@ class Agent {
|
||||
@GuardedBy("mLock")
|
||||
void dumpLocked(IndentingPrintWriter pw) {
|
||||
pw.print("Current GDP: ");
|
||||
pw.println(mCurrentNarcsInCirculation);
|
||||
pw.println(narcToString(mCurrentNarcsInCirculation));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,26 +24,31 @@ import static com.android.server.tare.TareUtils.arcToNarc;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.SparseArray;
|
||||
|
||||
/**
|
||||
* Policy defining pricing information and daily ARC requirements and suggestions for
|
||||
* AlarmManager.
|
||||
*/
|
||||
public class AlarmManagerEconomicPolicy extends EconomicPolicy {
|
||||
public static final String ACTION_ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE =
|
||||
"ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE";
|
||||
public static final String ACTION_ALARM_WAKEUP_EXACT = "ALARM_WAKEUP_EXACT";
|
||||
public static final String ACTION_ALARM_WAKEUP_INEXACT_ALLOW_WHILE_IDLE =
|
||||
"ALARM_WAKEUP_INEXACT_ALLOW_WHILE_IDLE";
|
||||
public static final String ACTION_ALARM_WAKEUP_INEXACT = "ALARM_WAKEUP_INEXACT";
|
||||
public static final String ACTION_ALARM_NONWAKEUP_EXACT_ALLOW_WHILE_IDLE =
|
||||
"ALARM_NONWAKEUP_EXACT_ALLOW_WHILE_IDLE";
|
||||
public static final String ACTION_ALARM_NONWAKEUP_EXACT = "ALARM_NONWAKEUP_EXACT";
|
||||
public static final String ACTION_ALARM_NONWAKEUP_INEXACT_ALLOW_WHILE_IDLE =
|
||||
"ALARM_NONWAKEUP_INEXACT_ALLOW_WHILE_IDLE";
|
||||
public static final String ACTION_ALARM_NONWAKEUP_INEXACT = "ALARM_NONWAKEUP_INEXACT";
|
||||
public static final String ACTION_ALARM_CLOCK = "ALARM_CLOCK";
|
||||
public static final int ACTION_ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE =
|
||||
TYPE_ACTION | POLICY_AM | 0;
|
||||
public static final int ACTION_ALARM_WAKEUP_EXACT =
|
||||
TYPE_ACTION | POLICY_AM | 1;
|
||||
public static final int ACTION_ALARM_WAKEUP_INEXACT_ALLOW_WHILE_IDLE =
|
||||
TYPE_ACTION | POLICY_AM | 2;
|
||||
public static final int ACTION_ALARM_WAKEUP_INEXACT =
|
||||
TYPE_ACTION | POLICY_AM | 3;
|
||||
public static final int ACTION_ALARM_NONWAKEUP_EXACT_ALLOW_WHILE_IDLE =
|
||||
TYPE_ACTION | POLICY_AM | 4;
|
||||
public static final int ACTION_ALARM_NONWAKEUP_EXACT =
|
||||
TYPE_ACTION | POLICY_AM | 5;
|
||||
public static final int ACTION_ALARM_NONWAKEUP_INEXACT_ALLOW_WHILE_IDLE =
|
||||
TYPE_ACTION | POLICY_AM | 6;
|
||||
public static final int ACTION_ALARM_NONWAKEUP_INEXACT =
|
||||
TYPE_ACTION | POLICY_AM | 7;
|
||||
public static final int ACTION_ALARM_CLOCK =
|
||||
TYPE_ACTION | POLICY_AM | 8;
|
||||
|
||||
private static final int[] COST_MODIFIERS = new int[]{
|
||||
COST_MODIFIER_CHARGING,
|
||||
@@ -52,8 +57,8 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
|
||||
COST_MODIFIER_PROCESS_STATE
|
||||
};
|
||||
|
||||
private final ArrayMap<String, Action> mActions = new ArrayMap<>();
|
||||
private final ArrayMap<String, Reward> mRewards = new ArrayMap<>();
|
||||
private final SparseArray<Action> mActions = new SparseArray<>();
|
||||
private final SparseArray<Reward> mRewards = new SparseArray<>();
|
||||
|
||||
AlarmManagerEconomicPolicy(InternalResourceService irs) {
|
||||
super(irs);
|
||||
@@ -86,14 +91,14 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
Action getAction(@NonNull String actionName) {
|
||||
return mActions.get(actionName);
|
||||
Action getAction(@AppAction int actionId) {
|
||||
return mActions.get(actionId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
Reward getReward(@NonNull String rewardName) {
|
||||
return mRewards.get(rewardName);
|
||||
Reward getReward(@UtilityReward int rewardId) {
|
||||
return mRewards.get(rewardId);
|
||||
}
|
||||
|
||||
private void loadActions() {
|
||||
|
||||
@@ -18,9 +18,9 @@ package com.android.server.tare;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.IndentingPrintWriter;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import libcore.util.EmptyArray;
|
||||
|
||||
@@ -29,9 +29,9 @@ import libcore.util.EmptyArray;
|
||||
public class CompleteEconomicPolicy extends EconomicPolicy {
|
||||
private final ArraySet<EconomicPolicy> mEnabledEconomicPolicies = new ArraySet<>();
|
||||
/** Lazily populated set of actions covered by this policy. */
|
||||
private final ArrayMap<String, Action> mActions = new ArrayMap<>();
|
||||
private final SparseArray<Action> mActions = new SparseArray<>();
|
||||
/** Lazily populated set of rewards covered by this policy. */
|
||||
private final ArrayMap<String, Reward> mRewards = new ArrayMap<>();
|
||||
private final SparseArray<Reward> mRewards = new SparseArray<>();
|
||||
private final int[] mCostModifiers;
|
||||
private final long mMaxSatiatedBalance;
|
||||
private final long mMaxSatiatedCirculation;
|
||||
@@ -93,37 +93,37 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Action getAction(@NonNull String actionName) {
|
||||
if (mActions.containsKey(actionName)) {
|
||||
return mActions.get(actionName);
|
||||
public Action getAction(@AppAction int actionId) {
|
||||
if (mActions.contains(actionId)) {
|
||||
return mActions.get(actionId);
|
||||
}
|
||||
|
||||
long ctp = 0, price = 0;
|
||||
boolean exists = false;
|
||||
for (int i = 0; i < mEnabledEconomicPolicies.size(); ++i) {
|
||||
Action a = mEnabledEconomicPolicies.valueAt(i).getAction(actionName);
|
||||
Action a = mEnabledEconomicPolicies.valueAt(i).getAction(actionId);
|
||||
if (a != null) {
|
||||
exists = true;
|
||||
ctp += a.costToProduce;
|
||||
price += a.basePrice;
|
||||
}
|
||||
}
|
||||
final Action action = exists ? new Action(actionName, ctp, price) : null;
|
||||
mActions.put(actionName, action);
|
||||
final Action action = exists ? new Action(actionId, ctp, price) : null;
|
||||
mActions.put(actionId, action);
|
||||
return action;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Reward getReward(@NonNull String rewardName) {
|
||||
if (mRewards.containsKey(rewardName)) {
|
||||
return mRewards.get(rewardName);
|
||||
public Reward getReward(@UtilityReward int rewardId) {
|
||||
if (mRewards.contains(rewardId)) {
|
||||
return mRewards.get(rewardId);
|
||||
}
|
||||
|
||||
long instantReward = 0, ongoingReward = 0, maxReward = 0;
|
||||
boolean exists = false;
|
||||
for (int i = 0; i < mEnabledEconomicPolicies.size(); ++i) {
|
||||
Reward r = mEnabledEconomicPolicies.valueAt(i).getReward(rewardName);
|
||||
Reward r = mEnabledEconomicPolicies.valueAt(i).getReward(rewardId);
|
||||
if (r != null) {
|
||||
exists = true;
|
||||
instantReward += r.instantReward;
|
||||
@@ -132,8 +132,8 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
|
||||
}
|
||||
}
|
||||
final Reward reward = exists
|
||||
? new Reward(rewardName, instantReward, ongoingReward, maxReward) : null;
|
||||
mRewards.put(rewardName, reward);
|
||||
? new Reward(rewardId, instantReward, ongoingReward, maxReward) : null;
|
||||
mRewards.put(rewardId, reward);
|
||||
return reward;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,9 @@ import static com.android.server.tare.Modifier.COST_MODIFIER_PROCESS_STATE;
|
||||
import static com.android.server.tare.Modifier.NUM_COST_MODIFIERS;
|
||||
|
||||
import android.annotation.CallSuper;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.StringDef;
|
||||
import android.util.IndentingPrintWriter;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -40,14 +40,65 @@ import java.lang.annotation.RetentionPolicy;
|
||||
public abstract class EconomicPolicy {
|
||||
private static final String TAG = "TARE-" + EconomicPolicy.class.getSimpleName();
|
||||
|
||||
// fixme ensure actions and rewards never use the same strings
|
||||
static final String REWARD_TOP_ACTIVITY = "REWARD_TOP_ACTIVITY";
|
||||
static final String REWARD_NOTIFICATION_SEEN = "REWARD_NOTIFICATION_SEEN";
|
||||
static final String REWARD_NOTIFICATION_INTERACTION = "REWARD_NOTIFICATION_INTERACTION";
|
||||
static final String REWARD_WIDGET_INTERACTION = "REWARD_WIDGET_INTERACTION";
|
||||
static final String REWARD_OTHER_USER_INTERACTION = "REWARD_OTHER_USER_INTERACTION";
|
||||
private static final int SHIFT_TYPE = 30;
|
||||
static final int MASK_TYPE = 0b11 << SHIFT_TYPE;
|
||||
static final int TYPE_REGULATION = 0 << SHIFT_TYPE;
|
||||
static final int TYPE_ACTION = 1 << SHIFT_TYPE;
|
||||
static final int TYPE_REWARD = 2 << SHIFT_TYPE;
|
||||
|
||||
@StringDef({
|
||||
private static final int SHIFT_POLICY = 29;
|
||||
static final int MASK_POLICY = 0b1 << SHIFT_POLICY;
|
||||
static final int POLICY_AM = 0 << SHIFT_POLICY;
|
||||
static final int POLICY_JS = 1 << SHIFT_POLICY;
|
||||
|
||||
static final int MASK_EVENT = ~0 - (0b111 << SHIFT_POLICY);
|
||||
|
||||
static final int REGULATION_BASIC_INCOME = TYPE_REGULATION | 0;
|
||||
static final int REGULATION_BIRTHRIGHT = TYPE_REGULATION | 1;
|
||||
static final int REGULATION_TAX = TYPE_REGULATION | 2;
|
||||
|
||||
static final int REWARD_NOTIFICATION_SEEN = TYPE_REWARD | 0;
|
||||
static final int REWARD_NOTIFICATION_INTERACTION = TYPE_REWARD | 1;
|
||||
static final int REWARD_TOP_ACTIVITY = TYPE_REWARD | 2;
|
||||
static final int REWARD_WIDGET_INTERACTION = TYPE_REWARD | 3;
|
||||
static final int REWARD_OTHER_USER_INTERACTION = TYPE_REWARD | 4;
|
||||
|
||||
@IntDef({
|
||||
AlarmManagerEconomicPolicy.ACTION_ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE,
|
||||
AlarmManagerEconomicPolicy.ACTION_ALARM_WAKEUP_EXACT,
|
||||
AlarmManagerEconomicPolicy.ACTION_ALARM_WAKEUP_INEXACT_ALLOW_WHILE_IDLE,
|
||||
AlarmManagerEconomicPolicy.ACTION_ALARM_WAKEUP_INEXACT,
|
||||
AlarmManagerEconomicPolicy.ACTION_ALARM_NONWAKEUP_EXACT_ALLOW_WHILE_IDLE,
|
||||
AlarmManagerEconomicPolicy.ACTION_ALARM_NONWAKEUP_EXACT,
|
||||
AlarmManagerEconomicPolicy.ACTION_ALARM_NONWAKEUP_INEXACT_ALLOW_WHILE_IDLE,
|
||||
AlarmManagerEconomicPolicy.ACTION_ALARM_NONWAKEUP_INEXACT,
|
||||
AlarmManagerEconomicPolicy.ACTION_ALARM_CLOCK,
|
||||
JobSchedulerEconomicPolicy.ACTION_JOB_MAX_START,
|
||||
JobSchedulerEconomicPolicy.ACTION_JOB_MAX_RUNNING,
|
||||
JobSchedulerEconomicPolicy.ACTION_JOB_HIGH_START,
|
||||
JobSchedulerEconomicPolicy.ACTION_JOB_HIGH_RUNNING,
|
||||
JobSchedulerEconomicPolicy.ACTION_JOB_DEFAULT_START,
|
||||
JobSchedulerEconomicPolicy.ACTION_JOB_DEFAULT_RUNNING,
|
||||
JobSchedulerEconomicPolicy.ACTION_JOB_LOW_START,
|
||||
JobSchedulerEconomicPolicy.ACTION_JOB_LOW_RUNNING,
|
||||
JobSchedulerEconomicPolicy.ACTION_JOB_MIN_START,
|
||||
JobSchedulerEconomicPolicy.ACTION_JOB_MIN_RUNNING,
|
||||
JobSchedulerEconomicPolicy.ACTION_JOB_TIMEOUT,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface AppAction {
|
||||
}
|
||||
|
||||
@IntDef({
|
||||
TYPE_ACTION,
|
||||
TYPE_REGULATION,
|
||||
TYPE_REWARD,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface EventType {
|
||||
}
|
||||
|
||||
@IntDef({
|
||||
REWARD_TOP_ACTIVITY,
|
||||
REWARD_NOTIFICATION_SEEN,
|
||||
REWARD_NOTIFICATION_INTERACTION,
|
||||
@@ -59,8 +110,8 @@ public abstract class EconomicPolicy {
|
||||
}
|
||||
|
||||
static class Action {
|
||||
@NonNull
|
||||
public final String name;
|
||||
/** Unique id (including across policies) for this action. */
|
||||
public final int id;
|
||||
/**
|
||||
* How many ARCs the system says it takes to perform this action.
|
||||
*/
|
||||
@@ -72,25 +123,25 @@ public abstract class EconomicPolicy {
|
||||
*/
|
||||
public final long basePrice;
|
||||
|
||||
Action(@NonNull String name, long costToProduce, long basePrice) {
|
||||
this.name = name;
|
||||
Action(int id, long costToProduce, long basePrice) {
|
||||
this.id = id;
|
||||
this.costToProduce = costToProduce;
|
||||
this.basePrice = basePrice;
|
||||
}
|
||||
}
|
||||
|
||||
static class Reward {
|
||||
@NonNull
|
||||
/** Unique id (including across policies) for this reward. */
|
||||
@UtilityReward
|
||||
public final String name;
|
||||
public final int id;
|
||||
public final long instantReward;
|
||||
/** Reward credited per second of ongoing activity. */
|
||||
public final long ongoingRewardPerSecond;
|
||||
/** The maximum amount an app can earn from this reward within a 24 hour period. */
|
||||
public final long maxDailyReward;
|
||||
|
||||
Reward(@NonNull String name, long instantReward, long ongoingReward, long maxDailyReward) {
|
||||
this.name = name;
|
||||
Reward(int id, long instantReward, long ongoingReward, long maxDailyReward) {
|
||||
this.id = id;
|
||||
this.instantReward = instantReward;
|
||||
this.ongoingRewardPerSecond = ongoingReward;
|
||||
this.maxDailyReward = maxDailyReward;
|
||||
@@ -139,16 +190,16 @@ public abstract class EconomicPolicy {
|
||||
abstract int[] getCostModifiers();
|
||||
|
||||
@Nullable
|
||||
abstract Action getAction(@NonNull String actionName);
|
||||
abstract Action getAction(@AppAction int actionId);
|
||||
|
||||
@Nullable
|
||||
abstract Reward getReward(@NonNull String rewardName);
|
||||
abstract Reward getReward(@UtilityReward int rewardId);
|
||||
|
||||
void dump(IndentingPrintWriter pw) {
|
||||
}
|
||||
|
||||
final long getCostOfAction(@NonNull String actionName, int userId, @NonNull String pkgName) {
|
||||
final Action action = getAction(actionName);
|
||||
final long getCostOfAction(int actionId, int userId, @NonNull String pkgName) {
|
||||
final Action action = getAction(actionId);
|
||||
if (action == null) {
|
||||
return 0;
|
||||
}
|
||||
@@ -214,6 +265,111 @@ public abstract class EconomicPolicy {
|
||||
return modifier;
|
||||
}
|
||||
|
||||
@EventType
|
||||
static int getEventType(int eventId) {
|
||||
return eventId & MASK_TYPE;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
static String eventToString(int eventId) {
|
||||
switch (eventId & MASK_TYPE) {
|
||||
case TYPE_ACTION:
|
||||
return actionToString(eventId);
|
||||
|
||||
case TYPE_REGULATION:
|
||||
return regulationToString(eventId);
|
||||
|
||||
case TYPE_REWARD:
|
||||
return rewardToString(eventId);
|
||||
|
||||
default:
|
||||
return "UNKNOWN_EVENT:" + Integer.toHexString(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
static String actionToString(int eventId) {
|
||||
switch (eventId & MASK_POLICY) {
|
||||
case POLICY_AM:
|
||||
switch (eventId) {
|
||||
case AlarmManagerEconomicPolicy.ACTION_ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE:
|
||||
return "ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE";
|
||||
case AlarmManagerEconomicPolicy.ACTION_ALARM_WAKEUP_EXACT:
|
||||
return "ALARM_WAKEUP_EXACT";
|
||||
case AlarmManagerEconomicPolicy.ACTION_ALARM_WAKEUP_INEXACT_ALLOW_WHILE_IDLE:
|
||||
return "ALARM_WAKEUP_INEXACT_ALLOW_WHILE_IDLE";
|
||||
case AlarmManagerEconomicPolicy.ACTION_ALARM_WAKEUP_INEXACT:
|
||||
return "ALARM_WAKEUP_INEXACT";
|
||||
case AlarmManagerEconomicPolicy.ACTION_ALARM_NONWAKEUP_EXACT_ALLOW_WHILE_IDLE:
|
||||
return "ALARM_NONWAKEUP_EXACT_ALLOW_WHILE_IDLE";
|
||||
case AlarmManagerEconomicPolicy.ACTION_ALARM_NONWAKEUP_EXACT:
|
||||
return "ALARM_NONWAKEUP_EXACT";
|
||||
case AlarmManagerEconomicPolicy.ACTION_ALARM_NONWAKEUP_INEXACT_ALLOW_WHILE_IDLE:
|
||||
return "ALARM_NONWAKEUP_INEXACT_ALLOW_WHILE_IDLE";
|
||||
case AlarmManagerEconomicPolicy.ACTION_ALARM_NONWAKEUP_INEXACT:
|
||||
return "ALARM_NONWAKEUP_INEXACT";
|
||||
case AlarmManagerEconomicPolicy.ACTION_ALARM_CLOCK:
|
||||
return "ALARM_CLOCK";
|
||||
}
|
||||
case POLICY_JS:
|
||||
switch (eventId) {
|
||||
case JobSchedulerEconomicPolicy.ACTION_JOB_MAX_START:
|
||||
return "JOB_MAX_START";
|
||||
case JobSchedulerEconomicPolicy.ACTION_JOB_MAX_RUNNING:
|
||||
return "JOB_MAX_RUNNING";
|
||||
case JobSchedulerEconomicPolicy.ACTION_JOB_HIGH_START:
|
||||
return "JOB_HIGH_START";
|
||||
case JobSchedulerEconomicPolicy.ACTION_JOB_HIGH_RUNNING:
|
||||
return "JOB_HIGH_RUNNING";
|
||||
case JobSchedulerEconomicPolicy.ACTION_JOB_DEFAULT_START:
|
||||
return "JOB_DEFAULT_START";
|
||||
case JobSchedulerEconomicPolicy.ACTION_JOB_DEFAULT_RUNNING:
|
||||
return "JOB_DEFAULT_RUNNING";
|
||||
case JobSchedulerEconomicPolicy.ACTION_JOB_LOW_START:
|
||||
return "JOB_LOW_START";
|
||||
case JobSchedulerEconomicPolicy.ACTION_JOB_LOW_RUNNING:
|
||||
return "JOB_LOW_RUNNING";
|
||||
case JobSchedulerEconomicPolicy.ACTION_JOB_MIN_START:
|
||||
return "JOB_MIN_START";
|
||||
case JobSchedulerEconomicPolicy.ACTION_JOB_MIN_RUNNING:
|
||||
return "JOB_MIN_RUNNING";
|
||||
case JobSchedulerEconomicPolicy.ACTION_JOB_TIMEOUT:
|
||||
return "JOB_TIMEOUT";
|
||||
}
|
||||
}
|
||||
return "UNKNOWN_ACTION:" + Integer.toHexString(eventId);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
static String regulationToString(int eventId) {
|
||||
switch (eventId) {
|
||||
case REGULATION_BASIC_INCOME:
|
||||
return "BASIC_INCOME";
|
||||
case REGULATION_BIRTHRIGHT:
|
||||
return "BIRTHRIGHT";
|
||||
case REGULATION_TAX:
|
||||
return "TAX";
|
||||
}
|
||||
return "UNKNOWN_REGULATION:" + Integer.toHexString(eventId);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
static String rewardToString(int eventId) {
|
||||
switch (eventId) {
|
||||
case REWARD_TOP_ACTIVITY:
|
||||
return "REWARD_TOP_ACTIVITY";
|
||||
case REWARD_NOTIFICATION_SEEN:
|
||||
return "REWARD_NOTIFICATION_SEEN";
|
||||
case REWARD_NOTIFICATION_INTERACTION:
|
||||
return "REWARD_NOTIFICATION_INTERACTION";
|
||||
case REWARD_WIDGET_INTERACTION:
|
||||
return "REWARD_WIDGET_INTERACTION";
|
||||
case REWARD_OTHER_USER_INTERACTION:
|
||||
return "REWARD_OTHER_USER_INTERACTION";
|
||||
}
|
||||
return "UNKNOWN_REWARD:" + Integer.toHexString(eventId);
|
||||
}
|
||||
|
||||
protected static void dumpActiveModifiers(IndentingPrintWriter pw) {
|
||||
for (int i = 0; i < NUM_COST_MODIFIERS; ++i) {
|
||||
pw.print("Modifier ");
|
||||
|
||||
@@ -29,8 +29,8 @@ interface EconomyManagerInternal {
|
||||
interface BalanceChangeListener {
|
||||
/**
|
||||
* Called when an app runs out of funds.
|
||||
* {@link #noteOngoingEventStopped(int, String, String, String)} must still be called to formally
|
||||
* end the action.
|
||||
* {@link #noteOngoingEventStopped(int, String, int, String)} must still be called to
|
||||
* formally end the action.
|
||||
*/
|
||||
void onBankruptcy(int userId, @NonNull String pkgName);
|
||||
|
||||
@@ -61,20 +61,20 @@ interface EconomyManagerInternal {
|
||||
*
|
||||
* @param tag An optional tag that can be used to differentiate the same event for the same app.
|
||||
*/
|
||||
void noteInstantaneousEvent(int userId, @NonNull String pkgName, @NonNull String event,
|
||||
void noteInstantaneousEvent(int userId, @NonNull String pkgName, int eventId,
|
||||
@Nullable String tag);
|
||||
|
||||
/**
|
||||
* Note that a long-running event is starting. The event must be specified in one of the
|
||||
* EconomicPolicies. You must always call
|
||||
* {@link #noteOngoingEventStopped(int, String, String, String)} to end the event. Ongoing
|
||||
* {@link #noteOngoingEventStopped(int, String, int, String)} to end the event. Ongoing
|
||||
* events will be separated and grouped by event-tag combinations. There must be an equal
|
||||
* number of start() and stop() calls for the same event-tag combination in order for the
|
||||
* tracking to finally stop (ie. ongoing events are ref-counted).
|
||||
*
|
||||
* @param tag An optional tag that can be used to differentiate the same event for the same app.
|
||||
*/
|
||||
void noteOngoingEventStarted(int userId, @NonNull String pkgName, @NonNull String event,
|
||||
void noteOngoingEventStarted(int userId, @NonNull String pkgName, int eventId,
|
||||
@Nullable String tag);
|
||||
|
||||
/**
|
||||
@@ -85,6 +85,6 @@ interface EconomyManagerInternal {
|
||||
*
|
||||
* @param tag An optional tag that can be used to differentiate the same event for the same app.
|
||||
*/
|
||||
void noteOngoingEventStopped(int userId, @NonNull String pkgName, @NonNull String event,
|
||||
void noteOngoingEventStopped(int userId, @NonNull String pkgName, int eventId,
|
||||
@Nullable String tag);
|
||||
}
|
||||
|
||||
@@ -374,18 +374,18 @@ public class InternalResourceService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noteInstantaneousEvent(int userId, @NonNull String pkgName,
|
||||
@NonNull String event, @Nullable String tag) {
|
||||
public void noteInstantaneousEvent(int userId, @NonNull String pkgName, int eventId,
|
||||
@Nullable String tag) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noteOngoingEventStarted(int userId, @NonNull String pkgName,
|
||||
@NonNull String event, @Nullable String tag) {
|
||||
public void noteOngoingEventStarted(int userId, @NonNull String pkgName, int eventId,
|
||||
@Nullable String tag) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noteOngoingEventStopped(int userId, @NonNull String pkgName,
|
||||
@NonNull String event, @Nullable String tag) {
|
||||
public void noteOngoingEventStopped(int userId, @NonNull String pkgName, int eventId,
|
||||
@Nullable String tag) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,24 +23,24 @@ import static com.android.server.tare.TareUtils.arcToNarc;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.SparseArray;
|
||||
|
||||
/**
|
||||
* Policy defining pricing information and daily ARC requirements and suggestions for
|
||||
* JobScheduler.
|
||||
*/
|
||||
public class JobSchedulerEconomicPolicy extends EconomicPolicy {
|
||||
public static final String ACTION_JOB_MAX_START = "JOB_MAX_START";
|
||||
public static final String ACTION_JOB_MAX_RUNNING = "JOB_MAX_RUNNING";
|
||||
public static final String ACTION_JOB_HIGH_START = "JOB_HIGH_START";
|
||||
public static final String ACTION_JOB_HIGH_RUNNING = "JOB_HIGH_RUNNING";
|
||||
public static final String ACTION_JOB_DEFAULT_START = "JOB_DEFAULT_START";
|
||||
public static final String ACTION_JOB_DEFAULT_RUNNING = "JOB_DEFAULT_RUNNING";
|
||||
public static final String ACTION_JOB_LOW_START = "JOB_LOW_START";
|
||||
public static final String ACTION_JOB_LOW_RUNNING = "JOB_LOW_RUNNING";
|
||||
public static final String ACTION_JOB_MIN_START = "JOB_MIN_START";
|
||||
public static final String ACTION_JOB_MIN_RUNNING = "JOB_MIN_RUNNING";
|
||||
public static final String ACTION_JOB_TIMEOUT = "JOB_TIMEOUT";
|
||||
public static final int ACTION_JOB_MAX_START = TYPE_ACTION | POLICY_JS | 0;
|
||||
public static final int ACTION_JOB_MAX_RUNNING = TYPE_ACTION | POLICY_JS | 1;
|
||||
public static final int ACTION_JOB_HIGH_START = TYPE_ACTION | POLICY_JS | 2;
|
||||
public static final int ACTION_JOB_HIGH_RUNNING = TYPE_ACTION | POLICY_JS | 3;
|
||||
public static final int ACTION_JOB_DEFAULT_START = TYPE_ACTION | POLICY_JS | 4;
|
||||
public static final int ACTION_JOB_DEFAULT_RUNNING = TYPE_ACTION | POLICY_JS | 5;
|
||||
public static final int ACTION_JOB_LOW_START = TYPE_ACTION | POLICY_JS | 6;
|
||||
public static final int ACTION_JOB_LOW_RUNNING = TYPE_ACTION | POLICY_JS | 7;
|
||||
public static final int ACTION_JOB_MIN_START = TYPE_ACTION | POLICY_JS | 8;
|
||||
public static final int ACTION_JOB_MIN_RUNNING = TYPE_ACTION | POLICY_JS | 9;
|
||||
public static final int ACTION_JOB_TIMEOUT = TYPE_ACTION | POLICY_JS | 10;
|
||||
|
||||
private static final int[] COST_MODIFIERS = new int[]{
|
||||
COST_MODIFIER_CHARGING,
|
||||
@@ -48,8 +48,8 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy {
|
||||
COST_MODIFIER_PROCESS_STATE
|
||||
};
|
||||
|
||||
private final ArrayMap<String, Action> mActions = new ArrayMap<>();
|
||||
private final ArrayMap<String, Reward> mRewards = new ArrayMap<>();
|
||||
private final SparseArray<Action> mActions = new SparseArray<>();
|
||||
private final SparseArray<Reward> mRewards = new SparseArray<>();
|
||||
|
||||
JobSchedulerEconomicPolicy(InternalResourceService irs) {
|
||||
super(irs);
|
||||
@@ -81,14 +81,14 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
Action getAction(@NonNull String actionName) {
|
||||
return mActions.get(actionName);
|
||||
Action getAction(@AppAction int actionId) {
|
||||
return mActions.get(actionId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
Reward getReward(@NonNull String rewardName) {
|
||||
return mRewards.get(rewardName);
|
||||
Reward getReward(@UtilityReward int rewardId) {
|
||||
return mRewards.get(rewardId);
|
||||
}
|
||||
|
||||
private void loadActions() {
|
||||
|
||||
@@ -18,12 +18,13 @@ package com.android.server.tare;
|
||||
|
||||
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
|
||||
|
||||
import static com.android.server.tare.TareUtils.narcToArc;
|
||||
import static com.android.server.tare.TareUtils.dumpTime;
|
||||
import static com.android.server.tare.TareUtils.narcToString;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.IndentingPrintWriter;
|
||||
import android.util.SparseLongArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -35,17 +36,16 @@ class Ledger {
|
||||
static class Transaction {
|
||||
public final long startTimeMs;
|
||||
public final long endTimeMs;
|
||||
@NonNull
|
||||
public final String reason;
|
||||
public final int eventId;
|
||||
@Nullable
|
||||
public final String tag;
|
||||
public final long delta;
|
||||
|
||||
Transaction(long startTimeMs, long endTimeMs,
|
||||
@NonNull String reason, @Nullable String tag, long delta) {
|
||||
int eventId, @Nullable String tag, long delta) {
|
||||
this.startTimeMs = startTimeMs;
|
||||
this.endTimeMs = endTimeMs;
|
||||
this.reason = reason;
|
||||
this.eventId = eventId;
|
||||
this.tag = tag;
|
||||
this.delta = delta;
|
||||
}
|
||||
@@ -54,7 +54,7 @@ class Ledger {
|
||||
/** Last saved balance. This doesn't take currently ongoing events into account. */
|
||||
private long mCurrentBalance = 0;
|
||||
private final List<Transaction> mTransactions = new ArrayList<>();
|
||||
private final ArrayMap<String, Long> mCumulativeDeltaPerReason = new ArrayMap<>();
|
||||
private final SparseLongArray mCumulativeDeltaPerReason = new SparseLongArray();
|
||||
private long mEarliestSumTime;
|
||||
|
||||
Ledger() {
|
||||
@@ -68,16 +68,12 @@ class Ledger {
|
||||
mTransactions.add(transaction);
|
||||
mCurrentBalance += transaction.delta;
|
||||
|
||||
Long sum = mCumulativeDeltaPerReason.get(transaction.reason);
|
||||
if (sum == null) {
|
||||
sum = 0L;
|
||||
}
|
||||
sum += transaction.delta;
|
||||
mCumulativeDeltaPerReason.put(transaction.reason, sum);
|
||||
final long sum = mCumulativeDeltaPerReason.get(transaction.eventId);
|
||||
mCumulativeDeltaPerReason.put(transaction.eventId, sum + transaction.delta);
|
||||
mEarliestSumTime = Math.min(mEarliestSumTime, transaction.startTimeMs);
|
||||
}
|
||||
|
||||
long get24HourSum(@NonNull String reason, final long now) {
|
||||
long get24HourSum(int eventId, final long now) {
|
||||
final long windowStartTime = now - 24 * HOUR_IN_MILLIS;
|
||||
if (mEarliestSumTime < windowStartTime) {
|
||||
// Need to redo sums
|
||||
@@ -87,8 +83,7 @@ class Ledger {
|
||||
if (transaction.endTimeMs <= windowStartTime) {
|
||||
break;
|
||||
}
|
||||
final Long sumObj = mCumulativeDeltaPerReason.get(transaction.reason);
|
||||
long sum = sumObj == null ? 0 : sumObj;
|
||||
long sum = mCumulativeDeltaPerReason.get(transaction.eventId);
|
||||
if (transaction.startTimeMs >= windowStartTime) {
|
||||
sum += transaction.delta;
|
||||
} else {
|
||||
@@ -97,24 +92,23 @@ class Ledger {
|
||||
* transaction.delta)
|
||||
/ (transaction.endTimeMs - transaction.startTimeMs);
|
||||
}
|
||||
mCumulativeDeltaPerReason.put(transaction.reason, sum);
|
||||
mCumulativeDeltaPerReason.put(transaction.eventId, sum);
|
||||
}
|
||||
mEarliestSumTime = windowStartTime;
|
||||
}
|
||||
Long sum = mCumulativeDeltaPerReason.get(reason);
|
||||
if (sum == null) {
|
||||
return 0;
|
||||
}
|
||||
return sum;
|
||||
return mCumulativeDeltaPerReason.get(eventId);
|
||||
}
|
||||
|
||||
void dump(IndentingPrintWriter pw) {
|
||||
pw.println("Ledger{");
|
||||
pw.increaseIndent();
|
||||
|
||||
pw.print("cur balance", narcToArc(getCurrentBalance())).println();
|
||||
|
||||
pw.decreaseIndent();
|
||||
pw.println("}");
|
||||
pw.print("Current balance", narcToString(getCurrentBalance())).println();
|
||||
mTransactions.forEach((transaction) -> {
|
||||
dumpTime(pw, transaction.startTimeMs);
|
||||
pw.print("--");
|
||||
dumpTime(pw, transaction.endTimeMs);
|
||||
pw.print(": ");
|
||||
pw.print(EconomicPolicy.eventToString(transaction.eventId));
|
||||
pw.print(" --> ");
|
||||
pw.println(narcToString(transaction.delta));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,47 @@
|
||||
|
||||
package com.android.server.tare;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.util.IndentingPrintWriter;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
class TareUtils {
|
||||
private static final long NARC_IN_ARC = 1_000_000_000L;
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
private static final SimpleDateFormat sDumpDateFormat =
|
||||
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
|
||||
static long arcToNarc(int arcs) {
|
||||
return arcs * 1_000_000_000L;
|
||||
return arcs * NARC_IN_ARC;
|
||||
}
|
||||
|
||||
static void dumpTime(IndentingPrintWriter pw, long time) {
|
||||
pw.print(sDumpDateFormat.format(time));
|
||||
}
|
||||
|
||||
static int narcToArc(long narcs) {
|
||||
return (int) (narcs / 1_000_000_000);
|
||||
return (int) (narcs / NARC_IN_ARC);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
static String narcToString(long narcs) {
|
||||
if (narcs == 0) {
|
||||
return "0 ARCs";
|
||||
}
|
||||
final long sub = Math.abs(narcs) % NARC_IN_ARC;
|
||||
final long arcs = narcToArc(narcs);
|
||||
if (arcs == 0) {
|
||||
return sub + " narcs";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(arcs);
|
||||
if (sub > 0) {
|
||||
sb.append(".").append(sub / (NARC_IN_ARC / 1000));
|
||||
}
|
||||
sb.append(" ARCs");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,40 +36,40 @@ public class LedgerTest {
|
||||
public void testInitialState() {
|
||||
final Ledger ledger = new Ledger();
|
||||
assertEquals(0, ledger.getCurrentBalance());
|
||||
assertEquals(0, ledger.get24HourSum("anything", 0));
|
||||
assertEquals(0, ledger.get24HourSum(0, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleTransactions() {
|
||||
final Ledger ledger = new Ledger();
|
||||
ledger.recordTransaction(new Ledger.Transaction(0, 1000, "test", null, 5));
|
||||
ledger.recordTransaction(new Ledger.Transaction(0, 1000, 1, null, 5));
|
||||
assertEquals(5, ledger.getCurrentBalance());
|
||||
assertEquals(5, ledger.get24HourSum("test", 60_000));
|
||||
ledger.recordTransaction(new Ledger.Transaction(2000, 2000, "test", null, 25));
|
||||
assertEquals(5, ledger.get24HourSum(1, 60_000));
|
||||
ledger.recordTransaction(new Ledger.Transaction(2000, 2000, 1, null, 25));
|
||||
assertEquals(30, ledger.getCurrentBalance());
|
||||
assertEquals(30, ledger.get24HourSum("test", 60_000));
|
||||
ledger.recordTransaction(new Ledger.Transaction(5000, 5500, "test", null, -10));
|
||||
assertEquals(30, ledger.get24HourSum(1, 60_000));
|
||||
ledger.recordTransaction(new Ledger.Transaction(5000, 5500, 1, null, -10));
|
||||
assertEquals(20, ledger.getCurrentBalance());
|
||||
assertEquals(20, ledger.get24HourSum("test", 60_000));
|
||||
assertEquals(20, ledger.get24HourSum(1, 60_000));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test24HourSum() {
|
||||
final Ledger ledger = new Ledger();
|
||||
ledger.recordTransaction(new Ledger.Transaction(0, 1000, "test", null, 500));
|
||||
assertEquals(500, ledger.get24HourSum("test", 24 * HOUR_IN_MILLIS));
|
||||
ledger.recordTransaction(new Ledger.Transaction(0, 1000, 1, null, 500));
|
||||
assertEquals(500, ledger.get24HourSum(1, 24 * HOUR_IN_MILLIS));
|
||||
ledger.recordTransaction(
|
||||
new Ledger.Transaction(2 * HOUR_IN_MILLIS, 3 * HOUR_IN_MILLIS, "test", null, 2500));
|
||||
assertEquals(3000, ledger.get24HourSum("test", 24 * HOUR_IN_MILLIS));
|
||||
new Ledger.Transaction(2 * HOUR_IN_MILLIS, 3 * HOUR_IN_MILLIS, 1, null, 2500));
|
||||
assertEquals(3000, ledger.get24HourSum(1, 24 * HOUR_IN_MILLIS));
|
||||
ledger.recordTransaction(
|
||||
new Ledger.Transaction(4 * HOUR_IN_MILLIS, 4 * HOUR_IN_MILLIS, "test", null, 1));
|
||||
assertEquals(3001, ledger.get24HourSum("test", 24 * HOUR_IN_MILLIS));
|
||||
assertEquals(2501, ledger.get24HourSum("test", 25 * HOUR_IN_MILLIS));
|
||||
assertEquals(2501, ledger.get24HourSum("test", 26 * HOUR_IN_MILLIS));
|
||||
new Ledger.Transaction(4 * HOUR_IN_MILLIS, 4 * HOUR_IN_MILLIS, 1, null, 1));
|
||||
assertEquals(3001, ledger.get24HourSum(1, 24 * HOUR_IN_MILLIS));
|
||||
assertEquals(2501, ledger.get24HourSum(1, 25 * HOUR_IN_MILLIS));
|
||||
assertEquals(2501, ledger.get24HourSum(1, 26 * HOUR_IN_MILLIS));
|
||||
// Pro-rated as the second transaction phases out
|
||||
assertEquals(1251,
|
||||
ledger.get24HourSum("test", 26 * HOUR_IN_MILLIS + 30 * MINUTE_IN_MILLIS));
|
||||
assertEquals(1, ledger.get24HourSum("test", 27 * HOUR_IN_MILLIS));
|
||||
assertEquals(0, ledger.get24HourSum("test", 28 * HOUR_IN_MILLIS));
|
||||
ledger.get24HourSum(1, 26 * HOUR_IN_MILLIS + 30 * MINUTE_IN_MILLIS));
|
||||
assertEquals(1, ledger.get24HourSum(1, 27 * HOUR_IN_MILLIS));
|
||||
assertEquals(0, ledger.get24HourSum(1, 28 * HOUR_IN_MILLIS));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user