From fcb8f0732f2c4aeea03761132a9fdf07338614c2 Mon Sep 17 00:00:00 2001 From: Kweku Adams Date: Mon, 14 Jun 2021 15:03:47 -0700 Subject: [PATCH] Convert event IDs from String to int. Convert IDs for rewards, actions, and TARE events from Strings to ints to reduce memory usage, guarantee namespacing, and avoid accidental overlaps. Bug: 158300259 Test: Android builds Change-Id: I2c61c5b61331320dac9dca8f0e29ba2566ed624c --- .../java/com/android/server/tare/Agent.java | 25 ++- .../tare/AlarmManagerEconomicPolicy.java | 45 ++-- .../server/tare/CompleteEconomicPolicy.java | 30 +-- .../android/server/tare/EconomicPolicy.java | 196 ++++++++++++++++-- .../server/tare/EconomyManagerInternal.java | 12 +- .../server/tare/InternalResourceService.java | 12 +- .../tare/JobSchedulerEconomicPolicy.java | 36 ++-- .../java/com/android/server/tare/Ledger.java | 52 ++--- .../com/android/server/tare/TareUtils.java | 39 +++- .../com/android/server/tare/LedgerTest.java | 36 ++-- 10 files changed, 340 insertions(+), 143 deletions(-) diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java index d53fa2035657b..02a9dcf21ac46 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java @@ -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)); } } diff --git a/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java index 744d96194254c..acdf6898b3cc9 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java @@ -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 mActions = new ArrayMap<>(); - private final ArrayMap mRewards = new ArrayMap<>(); + private final SparseArray mActions = new SparseArray<>(); + private final SparseArray 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() { diff --git a/apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java index 376a75ca9e2b8..8c56c61715086 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java @@ -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 mEnabledEconomicPolicies = new ArraySet<>(); /** Lazily populated set of actions covered by this policy. */ - private final ArrayMap mActions = new ArrayMap<>(); + private final SparseArray mActions = new SparseArray<>(); /** Lazily populated set of rewards covered by this policy. */ - private final ArrayMap mRewards = new ArrayMap<>(); + private final SparseArray 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; } diff --git a/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java index f9effa5950ef2..0e54163bea1da 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java @@ -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 "); diff --git a/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java b/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java index 688ad03304c70..5edeeedc3ff68 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java @@ -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); } diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java index 390ef81d74bb2..bb983fbd05c16 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java @@ -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) { } } } diff --git a/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java index 4a2136b9c4b0f..cce75f7eb55bc 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java @@ -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 mActions = new ArrayMap<>(); - private final ArrayMap mRewards = new ArrayMap<>(); + private final SparseArray mActions = new SparseArray<>(); + private final SparseArray 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() { diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java b/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java index e2fd8a464dfd2..0a49a03d832ee 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java @@ -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 mTransactions = new ArrayList<>(); - private final ArrayMap 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)); + }); } } diff --git a/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java b/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java index b3d1a0c7c23fe..2d72f5688688b 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java @@ -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(); } } diff --git a/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java b/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java index f7e1c60384029..65a97596cd732 100644 --- a/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java +++ b/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java @@ -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)); } }