Merge "Update state when the config changes."

This commit is contained in:
Kweku Adams
2021-09-23 16:23:05 +00:00
committed by Android (Google) Code Review
6 changed files with 94 additions and 103 deletions

View File

@@ -89,7 +89,6 @@ class Agent {
private static final String ALARM_TAG_LEDGER_CLEANUP = "*tare.ledger_cleanup*";
private final Object mLock;
private final CompleteEconomicPolicy mCompleteEconomicPolicy;
private final Handler mHandler;
private final InternalResourceService mIrs;
@@ -184,11 +183,9 @@ class Agent {
private static final int MSG_CLEAN_LEDGER = 1;
private static final int MSG_SET_ALARMS = 2;
Agent(@NonNull InternalResourceService irs,
@NonNull CompleteEconomicPolicy completeEconomicPolicy) {
Agent(@NonNull InternalResourceService irs) {
mLock = irs.getLock();
mIrs = irs;
mCompleteEconomicPolicy = completeEconomicPolicy;
mHandler = new AgentHandler(TareHandlerThread.get().getLooper());
mAppStandbyInternal = LocalServices.getService(AppStandbyInternal.class);
}
@@ -260,19 +257,19 @@ class Agent {
final long now = getCurrentTimeMillis();
final Ledger ledger = getLedgerLocked(userId, pkgName);
final CompleteEconomicPolicy economicPolicy = mIrs.getCompleteEconomicPolicyLocked();
final int eventType = getEventType(eventId);
switch (eventType) {
case TYPE_ACTION:
final long actionCost =
mCompleteEconomicPolicy.getCostOfAction(eventId, userId, pkgName);
final long actionCost = economicPolicy.getCostOfAction(eventId, userId, pkgName);
recordTransactionLocked(userId, pkgName, ledger,
new Ledger.Transaction(now, now, eventId, tag, -actionCost), true);
break;
case TYPE_REWARD:
final EconomicPolicy.Reward reward = mCompleteEconomicPolicy.getReward(eventId);
final EconomicPolicy.Reward reward = economicPolicy.getReward(eventId);
if (reward != null) {
final long rewardSum = ledger.get24HourSum(eventId, now);
final long rewardVal = Math.max(0,
@@ -311,11 +308,11 @@ class Agent {
}
OngoingEvent ongoingEvent = ongoingEvents.get(eventId, tag);
final CompleteEconomicPolicy economicPolicy = mIrs.getCompleteEconomicPolicyLocked();
final int eventType = getEventType(eventId);
switch (eventType) {
case TYPE_ACTION:
final long actionCost =
mCompleteEconomicPolicy.getCostOfAction(eventId, userId, pkgName);
final long actionCost = economicPolicy.getCostOfAction(eventId, userId, pkgName);
if (ongoingEvent == null) {
ongoingEvents.add(eventId, tag,
@@ -326,7 +323,7 @@ class Agent {
break;
case TYPE_REWARD:
final EconomicPolicy.Reward reward = mCompleteEconomicPolicy.getReward(eventId);
final EconomicPolicy.Reward reward = economicPolicy.getReward(eventId);
if (reward != null) {
if (ongoingEvent == null) {
ongoingEvents.add(eventId, tag, new OngoingEvent(
@@ -348,8 +345,14 @@ class Agent {
@GuardedBy("mLock")
void onDeviceStateChangedLocked() {
onPricingChangedLocked();
}
@GuardedBy("mLock")
void onPricingChangedLocked() {
final long now = getCurrentTimeMillis();
final long nowElapsed = SystemClock.elapsedRealtime();
final CompleteEconomicPolicy economicPolicy = mIrs.getCompleteEconomicPolicyLocked();
mCurrentOngoingEvents.forEach((userId, pkgName, ongoingEvents) -> {
final ArraySet<ActionAffordabilityNote> actionAffordabilityNotes =
@@ -381,7 +384,7 @@ class Agent {
final int size = actionAffordabilityNotes.size();
for (int i = 0; i < size; ++i) {
final ActionAffordabilityNote note = actionAffordabilityNotes.valueAt(i);
note.recalculateModifiedPrice(mCompleteEconomicPolicy, userId, pkgName);
note.recalculateModifiedPrice(economicPolicy, userId, pkgName);
final long newBalance = getLedgerLocked(userId, pkgName).getCurrentBalance();
final boolean isAffordable = newBalance >= note.getCachedModifiedPrice();
if (wasAffordable[i] != isAffordable) {
@@ -398,6 +401,7 @@ class Agent {
void onAppStatesChangedLocked(final int userId, @NonNull ArraySet<String> pkgNames) {
final long now = getCurrentTimeMillis();
final long nowElapsed = SystemClock.elapsedRealtime();
final CompleteEconomicPolicy economicPolicy = mIrs.getCompleteEconomicPolicyLocked();
for (int i = 0; i < pkgNames.size(); ++i) {
final String pkgName = pkgNames.valueAt(i);
@@ -433,7 +437,7 @@ class Agent {
final int size = actionAffordabilityNotes.size();
for (int n = 0; n < size; ++n) {
final ActionAffordabilityNote note = actionAffordabilityNotes.valueAt(n);
note.recalculateModifiedPrice(mCompleteEconomicPolicy, userId, pkgName);
note.recalculateModifiedPrice(economicPolicy, userId, pkgName);
final long newBalance =
getLedgerLocked(userId, pkgName).getCurrentBalance();
final boolean isAffordable = newBalance >= note.getCachedModifiedPrice();
@@ -532,6 +536,7 @@ class Agent {
"Tried to adjust system balance for " + appToString(userId, pkgName));
return;
}
final CompleteEconomicPolicy economicPolicy = mIrs.getCompleteEconomicPolicyLocked();
final long maxCirculationAllowed = mIrs.getMaxCirculationLocked();
final long newArcsInCirculation = mCurrentNarcsInCirculation + transaction.delta;
if (transaction.delta > 0 && newArcsInCirculation > maxCirculationAllowed) {
@@ -549,12 +554,11 @@ class Agent {
}
final long originalBalance = ledger.getCurrentBalance();
if (transaction.delta > 0
&& originalBalance + transaction.delta
> mCompleteEconomicPolicy.getMaxSatiatedBalance()) {
&& originalBalance + transaction.delta > economicPolicy.getMaxSatiatedBalance()) {
// Set lower bound at 0 so we don't accidentally take away credits when we were trying
// to _give_ the app credits.
final long newDelta =
Math.max(0, mCompleteEconomicPolicy.getMaxSatiatedBalance() - originalBalance);
Math.max(0, economicPolicy.getMaxSatiatedBalance() - originalBalance);
Slog.i(TAG, "Would result in becoming too rich. Decreasing transaction "
+ eventToString(transaction.eventId)
+ (transaction.tag == null ? "" : ":" + transaction.tag)
@@ -601,6 +605,7 @@ class Agent {
*/
@GuardedBy("mLock")
void reclaimUnusedAssetsLocked(double percentage) {
final CompleteEconomicPolicy economicPolicy = mIrs.getCompleteEconomicPolicyLocked();
final List<PackageInfo> pkgs = mIrs.getInstalledPackages();
final long now = getCurrentTimeMillis();
for (int i = 0; i < pkgs.size(); ++i) {
@@ -613,8 +618,7 @@ class Agent {
mAppStandbyInternal.getTimeSinceLastUsedByUser(pkgName, userId);
if (timeSinceLastUsedMs >= MIN_UNUSED_TIME_MS) {
// Use a constant floor instead of the scaled floor from the IRS.
final long minBalance =
mCompleteEconomicPolicy.getMinSatiatedBalance(userId, pkgName);
final long minBalance = economicPolicy.getMinSatiatedBalance(userId, pkgName);
final long curBalance = ledger.getCurrentBalance();
long toReclaim = (long) (curBalance * percentage);
if (curBalance - toReclaim < minBalance) {
@@ -1198,8 +1202,9 @@ class Agent {
actionAffordabilityNotes = new ArraySet<>();
mActionAffordabilityNotes.add(userId, pkgName, actionAffordabilityNotes);
}
final CompleteEconomicPolicy economicPolicy = mIrs.getCompleteEconomicPolicyLocked();
final ActionAffordabilityNote note =
new ActionAffordabilityNote(bill, listener, mCompleteEconomicPolicy);
new ActionAffordabilityNote(bill, listener, economicPolicy);
if (actionAffordabilityNotes.add(note)) {
if (!mIrs.isEnabled()) {
// When TARE isn't enabled, we always say something is affordable. We also don't
@@ -1208,7 +1213,7 @@ class Agent {
note.setNewAffordability(true);
return;
}
note.recalculateModifiedPrice(mCompleteEconomicPolicy, userId, pkgName);
note.recalculateModifiedPrice(economicPolicy, userId, pkgName);
note.setNewAffordability(
getBalanceLocked(userId, pkgName) >= note.getCachedModifiedPrice());
mIrs.postAffordabilityChanged(userId, pkgName, note);
@@ -1224,8 +1229,9 @@ class Agent {
final ArraySet<ActionAffordabilityNote> actionAffordabilityNotes =
mActionAffordabilityNotes.get(userId, pkgName);
if (actionAffordabilityNotes != null) {
final CompleteEconomicPolicy economicPolicy = mIrs.getCompleteEconomicPolicyLocked();
final ActionAffordabilityNote note =
new ActionAffordabilityNote(bill, listener, mCompleteEconomicPolicy);
new ActionAffordabilityNote(bill, listener, economicPolicy);
if (actionAffordabilityNotes.remove(note)) {
// Update ongoing alarm
scheduleBalanceCheckLocked(userId, pkgName);

View File

@@ -98,12 +98,9 @@ import static com.android.server.tare.TareUtils.arcToNarc;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.KeyValueListParser;
import android.util.IndentingPrintWriter;
import android.util.KeyValueListParser;
import android.util.Slog;
import android.util.SparseArray;
@@ -145,7 +142,6 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
private long mMaxSatiatedCirculation;
private final KeyValueListParser mParser = new KeyValueListParser(',');
private final SettingsObserver mSettingsObserver;
private final InternalResourceService mInternalResourceService;
private final SparseArray<Action> mActions = new SparseArray<>();
@@ -154,7 +150,6 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
AlarmManagerEconomicPolicy(InternalResourceService irs) {
super(irs);
mInternalResourceService = irs;
mSettingsObserver = new SettingsObserver(TareHandlerThread.getHandler());
loadConstants("");
}
@@ -162,12 +157,7 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
void setup() {
super.setup();
ContentResolver resolver = mInternalResourceService.getContext().getContentResolver();
resolver.registerContentObserver(
Settings.Global.getUriFor(TARE_ALARM_MANAGER_CONSTANTS),
false, mSettingsObserver, UserHandle.USER_ALL);
loadConstants(Settings.Global.getString(
mInternalResourceService.getContext().getContentResolver(),
TARE_ALARM_MANAGER_CONSTANTS));
loadConstants(Settings.Global.getString(resolver, TARE_ALARM_MANAGER_CONSTANTS));
}
@Override
@@ -215,7 +205,7 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
}
mMinSatiatedBalance = arcToNarc(mParser.getInt(KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP,
DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP));
DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP));
mMaxSatiatedBalance = arcToNarc(mParser.getInt(KEY_AM_MAX_SATIATED_BALANCE,
DEFAULT_AM_MAX_SATIATED_BALANCE));
mMaxSatiatedCirculation = arcToNarc(mParser.getInt(KEY_AM_MAX_CIRCULATION,
@@ -312,7 +302,7 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
(long) (arcToNarc(1) * mParser.getFloat(KEY_AM_REWARD_TOP_ACTIVITY_ONGOING,
DEFAULT_AM_REWARD_TOP_ACTIVITY_ONGOING)),
arcToNarc(mParser.getInt(KEY_AM_REWARD_TOP_ACTIVITY_MAX,
DEFAULT_AM_REWARD_TOP_ACTIVITY_MAX))));
DEFAULT_AM_REWARD_TOP_ACTIVITY_MAX))));
mRewards.put(REWARD_NOTIFICATION_SEEN, new Reward(REWARD_NOTIFICATION_SEEN,
arcToNarc(mParser.getInt(KEY_AM_REWARD_NOTIFICATION_SEEN_INSTANT,
DEFAULT_AM_REWARD_NOTIFICATION_SEEN_INSTANT)),
@@ -350,19 +340,6 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_MAX))));
}
private final class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
loadConstants(Settings.Global.getString(
mInternalResourceService.getContext().getContentResolver(),
TARE_ALARM_MANAGER_CONSTANTS));
}
}
@Override
void dump(IndentingPrintWriter pw) {
pw.println("Actions:");

View File

@@ -75,7 +75,7 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
}
@Override
public long getMinSatiatedBalance(final int userId, @NonNull final String pkgName) {
long getMinSatiatedBalance(final int userId, @NonNull final String pkgName) {
long min = 0;
for (int i = 0; i < mEnabledEconomicPolicies.size(); ++i) {
min += mEnabledEconomicPolicies.valueAt(i).getMinSatiatedBalance(userId, pkgName);
@@ -84,24 +84,24 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
}
@Override
public long getMaxSatiatedBalance() {
long getMaxSatiatedBalance() {
return mMaxSatiatedBalance;
}
@Override
public long getMaxSatiatedCirculation() {
long getMaxSatiatedCirculation() {
return mMaxSatiatedCirculation;
}
@NonNull
@Override
public int[] getCostModifiers() {
int[] getCostModifiers() {
return mCostModifiers == null ? EmptyArray.INT : mCostModifiers;
}
@Nullable
@Override
public Action getAction(@AppAction int actionId) {
Action getAction(@AppAction int actionId) {
if (mActions.contains(actionId)) {
return mActions.get(actionId);
}
@@ -123,7 +123,7 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
@Nullable
@Override
public Reward getReward(@UtilityReward int rewardId) {
Reward getReward(@UtilityReward int rewardId) {
if (mRewards.contains(rewardId)) {
return mRewards.get(rewardId);
}

View File

@@ -16,6 +16,8 @@
package com.android.server.tare;
import static android.provider.Settings.Global.TARE_ALARM_MANAGER_CONSTANTS;
import static android.provider.Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
@@ -98,11 +100,13 @@ public class InternalResourceService extends SystemService {
private final PackageManagerInternal mPackageManagerInternal;
private final Agent mAgent;
private final CompleteEconomicPolicy mCompleteEconomicPolicy;
private final ConfigObserver mConfigObserver;
private final EconomyManagerStub mEconomyManagerStub;
private final Scribe mScribe;
@GuardedBy("mLock")
private CompleteEconomicPolicy mCompleteEconomicPolicy;
@NonNull
@GuardedBy("mLock")
private List<PackageInfo> mPkgCache = new ArrayList<>();
@@ -218,7 +222,7 @@ public class InternalResourceService extends SystemService {
mEconomyManagerStub = new EconomyManagerStub();
mScribe = new Scribe(this);
mCompleteEconomicPolicy = new CompleteEconomicPolicy(this);
mAgent = new Agent(this, mCompleteEconomicPolicy);
mAgent = new Agent(this);
mConfigObserver = new ConfigObserver(mHandler, context);
@@ -246,6 +250,12 @@ public class InternalResourceService extends SystemService {
}
/** Returns the installed packages for all users. */
@NonNull
@GuardedBy("mLock")
CompleteEconomicPolicy getCompleteEconomicPolicyLocked() {
return mCompleteEconomicPolicy;
}
@NonNull
List<PackageInfo> getInstalledPackages() {
synchronized (mLock) {
@@ -700,14 +710,14 @@ public class InternalResourceService extends SystemService {
long requiredBalance = 0;
final List<EconomyManagerInternal.AnticipatedAction> projectedActions =
bill.getAnticipatedActions();
for (int i = 0; i < projectedActions.size(); ++i) {
AnticipatedAction action = projectedActions.get(i);
final long cost =
mCompleteEconomicPolicy.getCostOfAction(action.actionId, userId, pkgName);
requiredBalance += cost * action.numInstantaneousCalls
+ cost * (action.ongoingDurationMs / 1000);
}
synchronized (mLock) {
for (int i = 0; i < projectedActions.size(); ++i) {
AnticipatedAction action = projectedActions.get(i);
final long cost = mCompleteEconomicPolicy.getCostOfAction(
action.actionId, userId, pkgName);
requiredBalance += cost * action.numInstantaneousCalls
+ cost * (action.ongoingDurationMs / 1000);
}
return mAgent.getBalanceLocked(userId, pkgName) >= requiredBalance;
}
}
@@ -724,16 +734,16 @@ public class InternalResourceService extends SystemService {
long totalCostPerSecond = 0;
final List<EconomyManagerInternal.AnticipatedAction> projectedActions =
bill.getAnticipatedActions();
for (int i = 0; i < projectedActions.size(); ++i) {
AnticipatedAction action = projectedActions.get(i);
final long cost =
mCompleteEconomicPolicy.getCostOfAction(action.actionId, userId, pkgName);
totalCostPerSecond += cost;
}
if (totalCostPerSecond == 0) {
return FOREVER_MS;
}
synchronized (mLock) {
for (int i = 0; i < projectedActions.size(); ++i) {
AnticipatedAction action = projectedActions.get(i);
final long cost = mCompleteEconomicPolicy.getCostOfAction(
action.actionId, userId, pkgName);
totalCostPerSecond += cost;
}
if (totalCostPerSecond == 0) {
return FOREVER_MS;
}
return mAgent.getBalanceLocked(userId, pkgName) * 1000 / totalCostPerSecond;
}
}
@@ -786,15 +796,24 @@ public class InternalResourceService extends SystemService {
public void start() {
mContentResolver.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.ENABLE_TARE), false, this);
updateConfig();
mContentResolver.registerContentObserver(
Settings.Global.getUriFor(TARE_ALARM_MANAGER_CONSTANTS), false, this);
mContentResolver.registerContentObserver(
Settings.Global.getUriFor(TARE_JOB_SCHEDULER_CONSTANTS), false, this);
updateEnabledStatus();
}
@Override
public void onChange(boolean selfChange) {
updateConfig();
public void onChange(boolean selfChange, Uri uri) {
if (uri.equals(Settings.Global.getUriFor(Settings.Global.ENABLE_TARE))) {
updateEnabledStatus();
} else if (uri.equals(Settings.Global.getUriFor(TARE_ALARM_MANAGER_CONSTANTS))
|| uri.equals(Settings.Global.getUriFor(TARE_JOB_SCHEDULER_CONSTANTS))) {
updateEconomicPolicy();
}
}
private void updateConfig() {
private void updateEnabledStatus() {
final boolean isTareEnabled = Settings.Global.getInt(mContentResolver,
Settings.Global.ENABLE_TARE, Settings.Global.DEFAULT_ENABLE_TARE) == 1;
if (mIsEnabled != isTareEnabled) {
@@ -806,6 +825,17 @@ public class InternalResourceService extends SystemService {
}
}
}
private void updateEconomicPolicy() {
synchronized (mLock) {
mCompleteEconomicPolicy.tearDown();
mCompleteEconomicPolicy = new CompleteEconomicPolicy(InternalResourceService.this);
if (mIsEnabled && mBootPhase >= PHASE_SYSTEM_SERVICES_READY) {
mCompleteEconomicPolicy.setup();
mAgent.onPricingChangedLocked();
}
}
}
}
private static void dumpHelp(PrintWriter pw) {

View File

@@ -107,12 +107,9 @@ import static com.android.server.tare.TareUtils.arcToNarc;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.KeyValueListParser;
import android.util.IndentingPrintWriter;
import android.util.KeyValueListParser;
import android.util.Slog;
import android.util.SparseArray;
@@ -147,7 +144,6 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy {
private long mMaxSatiatedCirculation;
private final KeyValueListParser mParser = new KeyValueListParser(',');
private final SettingsObserver mSettingsObserver;
private final InternalResourceService mInternalResourceService;
private final SparseArray<Action> mActions = new SparseArray<>();
@@ -156,7 +152,6 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy {
JobSchedulerEconomicPolicy(InternalResourceService irs) {
super(irs);
mInternalResourceService = irs;
mSettingsObserver = new SettingsObserver(TareHandlerThread.getHandler());
loadConstants("");
}
@@ -164,12 +159,7 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy {
void setup() {
super.setup();
ContentResolver resolver = mInternalResourceService.getContext().getContentResolver();
resolver.registerContentObserver(
Settings.Global.getUriFor(TARE_JOB_SCHEDULER_CONSTANTS),
false, mSettingsObserver, UserHandle.USER_ALL);
loadConstants(Settings.Global.getString(
mInternalResourceService.getContext().getContentResolver(),
TARE_JOB_SCHEDULER_CONSTANTS));
loadConstants(Settings.Global.getString(resolver, TARE_JOB_SCHEDULER_CONSTANTS));
}
@Override
@@ -324,19 +314,6 @@ public class JobSchedulerEconomicPolicy extends EconomicPolicy {
DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_MAX))));
}
private final class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
loadConstants(Settings.Global.getString(
mInternalResourceService.getContext().getContentResolver(),
TARE_JOB_SCHEDULER_CONSTANTS));
}
}
@Override
void dump(IndentingPrintWriter pw) {
pw.println("Actions:");

View File

@@ -59,6 +59,7 @@ public class AgentTest {
.mockStatic(LocalServices.class)
.startMocking();
when(mIrs.getContext()).thenReturn(mContext);
when(mIrs.getCompleteEconomicPolicyLocked()).thenReturn(mEconomicPolicy);
when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mock(AlarmManager.class));
}
@@ -71,7 +72,7 @@ public class AgentTest {
@Test
public void testRecordTransaction_UnderMax() {
Agent agent = new Agent(mIrs, mEconomicPolicy);
Agent agent = new Agent(mIrs);
Ledger ledger = new Ledger();
doReturn(1_000_000L).when(mIrs).getMaxCirculationLocked();
@@ -100,7 +101,7 @@ public class AgentTest {
@Test
public void testRecordTransaction_MaxCirculation() {
Agent agent = new Agent(mIrs, mEconomicPolicy);
Agent agent = new Agent(mIrs);
Ledger ledger = new Ledger();
doReturn(1000L).when(mIrs).getMaxCirculationLocked();
@@ -147,7 +148,7 @@ public class AgentTest {
@Test
public void testRecordTransaction_MaxSatiatedBalance() {
Agent agent = new Agent(mIrs, mEconomicPolicy);
Agent agent = new Agent(mIrs);
Ledger ledger = new Ledger();
doReturn(1_000_000L).when(mIrs).getMaxCirculationLocked();