Loading apex/jobscheduler/service/java/com/android/server/tare/Agent.java +16 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -85,11 +90,12 @@ 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 Loading @@ -97,11 +103,12 @@ class Agent { > 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) + 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; Loading Loading @@ -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))); } } Loading Loading @@ -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)))); } } Loading @@ -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)))); } Loading Loading @@ -223,6 +230,6 @@ class Agent { @GuardedBy("mLock") void dumpLocked(IndentingPrintWriter pw) { pw.print("Current GDP: "); pw.println(mCurrentNarcsInCirculation); pw.println(narcToString(mCurrentNarcsInCirculation)); } } apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java +25 −20 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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); Loading Loading @@ -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() { Loading apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java +15 −15 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; } Loading apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java +176 −20 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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, Loading @@ -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. */ Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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 "); Loading apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java +6 −6 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); /** Loading @@ -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); } Loading
apex/jobscheduler/service/java/com/android/server/tare/Agent.java +16 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -85,11 +90,12 @@ 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 Loading @@ -97,11 +103,12 @@ class Agent { > 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) + 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; Loading Loading @@ -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))); } } Loading Loading @@ -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)))); } } Loading @@ -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)))); } Loading Loading @@ -223,6 +230,6 @@ class Agent { @GuardedBy("mLock") void dumpLocked(IndentingPrintWriter pw) { pw.print("Current GDP: "); pw.println(mCurrentNarcsInCirculation); pw.println(narcToString(mCurrentNarcsInCirculation)); } }
apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java +25 −20 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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); Loading Loading @@ -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() { Loading
apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java +15 −15 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; } Loading
apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java +176 −20 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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, Loading @@ -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. */ Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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 "); Loading
apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java +6 −6 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); /** Loading @@ -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); }