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 d7c3a86d1d602..2ecc0ed798d2e 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java @@ -28,7 +28,6 @@ import static com.android.server.tare.EconomicPolicy.eventToString; import static com.android.server.tare.EconomicPolicy.getEventType; import static com.android.server.tare.TareUtils.appToString; import static com.android.server.tare.TareUtils.getCurrentTimeMillis; -import static com.android.server.tare.TareUtils.narcToString; import android.annotation.NonNull; import android.annotation.Nullable; @@ -81,6 +80,8 @@ class Agent { * to use older transactions or provide older transactions to apps. */ private static final long MAX_TRANSACTION_AGE_MS = 24 * HOUR_IN_MILLIS; + /** The maximum number of transactions to dump per ledger. */ + private static final int MAX_NUM_TRANSACTION_DUMP = 25; private static final String ALARM_TAG_AFFORDABILITY_CHECK = "*tare.affordability_check*"; private static final String ALARM_TAG_LEDGER_CLEANUP = "*tare.ledger_cleanup*"; @@ -193,6 +194,12 @@ class Agent { return balance; } + /** Returns the total amount of narcs currently allocated to apps. */ + @GuardedBy("mLock") + long getCurrentCirculationLocked() { + return mCurrentNarcsInCirculation; + } + @GuardedBy("mLock") void noteInstantaneousEventLocked(final int userId, @NonNull final String pkgName, final int eventId, @Nullable String tag) { @@ -1287,8 +1294,19 @@ class Agent { @GuardedBy("mLock") void dumpLocked(IndentingPrintWriter pw) { - pw.print("Current GDP: "); - pw.println(narcToString(mCurrentNarcsInCirculation)); + pw.println("Ledgers:"); + pw.increaseIndent(); + mLedgers.forEach((userId, pkgName, ledger) -> { + pw.print(appToString(userId, pkgName)); + if (mIrs.isSystem(userId, pkgName)) { + pw.print(" (system)"); + } + pw.println(); + pw.increaseIndent(); + ledger.dump(pw, MAX_NUM_TRANSACTION_DUMP); + pw.decreaseIndent(); + }); + pw.decreaseIndent(); pw.println(); mBalanceThresholdAlarmListener.dumpLocked(pw); 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 6ef945684f76c..fc057f7d187f3 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java @@ -103,6 +103,7 @@ import android.os.Handler; import android.os.UserHandle; import android.provider.Settings; import android.util.KeyValueListParser; +import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.SparseArray; @@ -361,4 +362,22 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy { TARE_ALARM_MANAGER_CONSTANTS)); } } + + @Override + void dump(IndentingPrintWriter pw) { + pw.println("Actions:"); + pw.increaseIndent(); + for (int i = 0; i < mActions.size(); ++i) { + dumpAction(pw, mActions.valueAt(i)); + } + pw.decreaseIndent(); + + pw.println(); + pw.println("Rewards:"); + pw.increaseIndent(); + for (int i = 0; i < mRewards.size(); ++i) { + dumpReward(pw, mRewards.valueAt(i)); + } + pw.decreaseIndent(); + } } 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 f05e5c9afd1d0..dbc7bd6b1f732 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java @@ -148,5 +148,35 @@ public class CompleteEconomicPolicy extends EconomicPolicy { @Override void dump(IndentingPrintWriter pw) { dumpActiveModifiers(pw); + + pw.println(); + pw.println(getClass().getSimpleName() + ":"); + pw.increaseIndent(); + + pw.println("Cached actions:"); + pw.increaseIndent(); + for (int i = 0; i < mActions.size(); ++i) { + dumpAction(pw, mActions.valueAt(i)); + } + pw.decreaseIndent(); + + pw.println(); + pw.println("Cached rewards:"); + pw.increaseIndent(); + for (int i = 0; i < mRewards.size(); ++i) { + dumpReward(pw, mRewards.valueAt(i)); + } + pw.decreaseIndent(); + + for (int i = 0; i < mEnabledEconomicPolicies.size(); i++) { + final EconomicPolicy economicPolicy = mEnabledEconomicPolicies.valueAt(i); + pw.println(); + pw.print("(Includes) "); + pw.println(economicPolicy.getClass().getSimpleName() + ":"); + pw.increaseIndent(); + economicPolicy.dump(pw); + pw.decreaseIndent(); + } + pw.decreaseIndent(); } } 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 fa14d107bd552..d16e378bce9e5 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java @@ -21,6 +21,7 @@ import static com.android.server.tare.Modifier.COST_MODIFIER_DEVICE_IDLE; import static com.android.server.tare.Modifier.COST_MODIFIER_POWER_SAVE_MODE; import static com.android.server.tare.Modifier.COST_MODIFIER_PROCESS_STATE; import static com.android.server.tare.Modifier.NUM_COST_MODIFIERS; +import static com.android.server.tare.TareUtils.narcToString; import android.annotation.CallSuper; import android.annotation.IntDef; @@ -399,4 +400,26 @@ public abstract class EconomicPolicy { pw.decreaseIndent(); } } + + protected static void dumpAction(IndentingPrintWriter pw, @NonNull Action action) { + pw.print(actionToString(action.id)); + pw.print(": "); + pw.print("ctp="); + pw.print(narcToString(action.costToProduce)); + pw.print(", basePrice="); + pw.print(narcToString(action.basePrice)); + pw.println(); + } + + protected static void dumpReward(IndentingPrintWriter pw, @NonNull Reward reward) { + pw.print(rewardToString(reward.id)); + pw.print(": "); + pw.print("instant="); + pw.print(narcToString(reward.instantReward)); + pw.print(", ongoing/sec="); + pw.print(narcToString(reward.ongoingRewardPerSecond)); + pw.print(", maxDaily="); + pw.print(narcToString(reward.maxDailyReward)); + pw.println(); + } } 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 b435c9e1a66de..6538229430951 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java @@ -21,6 +21,7 @@ import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static com.android.server.tare.TareUtils.appToString; import static com.android.server.tare.TareUtils.getCurrentTimeMillis; +import static com.android.server.tare.TareUtils.narcToString; import android.annotation.NonNull; import android.annotation.Nullable; @@ -601,6 +602,10 @@ public class InternalResourceService extends SystemService { if ("-h".equals(arg) || "--help".equals(arg)) { dumpHelp(pw); return; + } else if ("-a".equals(arg)) { + // -a is passed when dumping a bug report so we have to acknowledge the + // argument. However, we currently don't do anything differently for bug + // reports. } else if (arg.length() > 0 && arg.charAt(0) == '-') { pw.println("Unknown option: " + arg); return; @@ -787,9 +792,23 @@ public class InternalResourceService extends SystemService { pw.print("Current battery level: "); pw.println(mCurrentBatteryLevel); - mCompleteEconomicPolicy.dump(pw); - pw.println(); + final long maxCircluation = getMaxCirculationLocked(); + pw.print("Max circulation (current/satiated): "); + pw.print(narcToString(maxCircluation)); + pw.print("/"); + pw.println(narcToString(mCompleteEconomicPolicy.getMaxSatiatedCirculation())); + final long currentCirculation = mAgent.getCurrentCirculationLocked(); + pw.print("Current GDP: "); + pw.print(narcToString(currentCirculation)); + pw.print(" ("); + pw.print(String.format("%.2f", 100f * currentCirculation / maxCircluation)); + pw.println("% of current max)"); + + pw.println(); + mCompleteEconomicPolicy.dump(pw); + + pw.println(); mAgent.dumpLocked(pw); } } 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 e339650fabe18..c332f2f53b086 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java @@ -112,6 +112,7 @@ import android.os.Handler; import android.os.UserHandle; import android.provider.Settings; import android.util.KeyValueListParser; +import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.SparseArray; @@ -335,4 +336,22 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy { TARE_JOB_SCHEDULER_CONSTANTS)); } } + + @Override + void dump(IndentingPrintWriter pw) { + pw.println("Actions:"); + pw.increaseIndent(); + for (int i = 0; i < mActions.size(); ++i) { + dumpAction(pw, mActions.valueAt(i)); + } + pw.decreaseIndent(); + + pw.println(); + pw.println("Rewards:"); + pw.increaseIndent(); + for (int i = 0; i < mRewards.size(); ++i) { + dumpReward(pw, mRewards.valueAt(i)); + } + pw.decreaseIndent(); + } } 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 76543d74f15e0..f2b78c0cd3e5c 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java @@ -116,9 +116,13 @@ class Ledger { } } - void dump(IndentingPrintWriter pw) { + void dump(IndentingPrintWriter pw, int numRecentTransactions) { pw.print("Current balance", narcToString(getCurrentBalance())).println(); - mTransactions.forEach((transaction) -> { + + final int size = mTransactions.size(); + for (int i = Math.max(0, size - numRecentTransactions); i < size; ++i) { + final Transaction transaction = mTransactions.get(i); + dumpTime(pw, transaction.startTimeMs); pw.print("--"); dumpTime(pw, transaction.endTimeMs); @@ -126,6 +130,6 @@ class Ledger { 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 1e047aa60cf8b..78508d4129efb 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java @@ -59,14 +59,19 @@ class TareUtils { final long sub = Math.abs(narcs) % NARC_IN_ARC; final long arcs = narcToArc(narcs); if (arcs == 0) { - return sub + " narcs"; + return sub == 1 + ? sub + " narc" + : sub + " narcs"; } StringBuilder sb = new StringBuilder(); sb.append(arcs); if (sub > 0) { sb.append(".").append(sub / (NARC_IN_ARC / 1000)); } - sb.append(" ARCs"); + sb.append(" ARC"); + if (arcs != 1 || sub > 0) { + sb.append("s"); + } return sb.toString(); }