Add TARE enable constant.

Add a Settings constant to control the overall enabling of TARE. If
disabled, it will clean up and drop as much as possible. Set the default
value to 0/false.

Bug: 158300259
Test: look at dumpsys output after changing setting constant value
Test: atest SettingsProviderTest:SettingsBackupTest
Change-Id: I252f792444423fe5dc801125f9e7d3a0b6ed5b42
This commit is contained in:
Kweku Adams
2021-07-20 12:07:12 -07:00
parent 40613918aa
commit 739dd166c1
10 changed files with 221 additions and 38 deletions

View File

@@ -196,7 +196,6 @@ class Agent {
final int eventId, @Nullable String tag) {
final long now = System.currentTimeMillis();
final Ledger ledger = getLedgerLocked(userId, pkgName);
final boolean wasSolvent = getBalanceLocked(userId, pkgName) > 0;
final int eventType = getEventType(eventId);
switch (eventType) {
@@ -400,12 +399,16 @@ class Agent {
SparseArrayMap<String, OngoingEvent> ongoingEvents =
mCurrentOngoingEvents.get(userId, pkgName);
if (ongoingEvents == null) {
Slog.wtf(TAG, "No ongoing transactions :/");
// This may occur if TARE goes from disabled to enabled while an event is already
// occurring.
Slog.w(TAG, "No ongoing transactions for <" + userId + ">" + pkgName);
return;
}
final OngoingEvent ongoingEvent = ongoingEvents.get(eventId, tag);
if (ongoingEvent == null) {
Slog.wtf(TAG, "Nonexistent ongoing transaction "
// This may occur if TARE goes from disabled to enabled while an event is already
// occurring.
Slog.w(TAG, "Nonexistent ongoing transaction "
+ eventToString(eventId) + (tag == null ? "" : ":" + tag)
+ " for <" + userId + ">" + pkgName + " ended");
return;
@@ -768,6 +771,15 @@ class Agent {
SystemClock.elapsedRealtime() + timeToThresholdMs);
}
@GuardedBy("mLock")
void tearDownLocked() {
mLedgers.clear();
mCurrentNarcsInCirculation = 0;
mCurrentOngoingEvents.clear();
mBalanceThresholdAlarmListener.dropAllAlarmsLocked();
mLedgerCleanupAlarmListener.dropAllAlarmsLocked();
}
@VisibleForTesting
static class OngoingEvent {
public final long startTimeElapsed;
@@ -986,6 +998,12 @@ class Agent {
}
}
@GuardedBy("mLock")
void dropAllAlarmsLocked() {
mAlarmQueue.clear();
setNextAlarmLocked(0);
}
@GuardedBy("mLock")
protected abstract void processExpiredAlarmLocked(int userId, @NonNull String packageName);
@@ -1069,6 +1087,13 @@ class Agent {
final ActionAffordabilityNote note =
new ActionAffordabilityNote(bill, listener, mCompleteEconomicPolicy);
if (actionAffordabilityNotes.add(note)) {
if (!mIrs.isEnabled()) {
// When TARE isn't enabled, we always say something is affordable. We also don't
// want to silently drop affordability change listeners in case TARE becomes enabled
// because then clients will be in an ambiguous state.
note.setNewAffordability(true);
return;
}
note.recalculateModifiedPrice(mCompleteEconomicPolicy, userId, pkgName);
note.setNewAffordability(
getBalanceLocked(userId, pkgName) >= note.getCachedModifiedPrice());

View File

@@ -40,7 +40,16 @@ class ChargingModifier extends Modifier {
super();
mIrs = irs;
mChargingTracker = new ChargingTracker();
mChargingTracker.startTracking(irs.getContext());
}
@Override
public void setup() {
mChargingTracker.startTracking(mIrs.getContext());
}
@Override
public void tearDown() {
mChargingTracker.stopTracking(mIrs.getContext());
}
@Override
@@ -84,6 +93,10 @@ class ChargingModifier extends Modifier {
mCharging = batteryManager.isCharging();
}
public void stopTracking(@NonNull Context context) {
context.unregisterReceiver(this);
}
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();

View File

@@ -40,7 +40,16 @@ class DeviceIdleModifier extends Modifier {
mIrs = irs;
mPowerManager = irs.getContext().getSystemService(PowerManager.class);
mDeviceIdleTracker = new DeviceIdleTracker();
mDeviceIdleTracker.startTracking(irs.getContext());
}
@Override
public void setup() {
mDeviceIdleTracker.startTracking(mIrs.getContext());
}
@Override
public void tearDown() {
mDeviceIdleTracker.stopTracking(mIrs.getContext());
}
@Override
@@ -81,6 +90,10 @@ class DeviceIdleModifier extends Modifier {
mDeviceLightIdle = mPowerManager.isLightDeviceIdleMode();
}
void stopTracking(@NonNull Context context) {
context.unregisterReceiver(this);
}
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();

View File

@@ -157,11 +157,21 @@ public abstract class EconomicPolicy {
}
@CallSuper
void onSystemServicesReady() {
void setup() {
for (int i = 0; i < NUM_COST_MODIFIERS; ++i) {
final Modifier modifier = COST_MODIFIER_BY_INDEX[i];
if (modifier != null) {
modifier.onSystemServicesReady();
modifier.setup();
}
}
}
@CallSuper
void tearDown() {
for (int i = 0; i < NUM_COST_MODIFIERS; ++i) {
final Modifier modifier = COST_MODIFIER_BY_INDEX[i];
if (modifier != null) {
modifier.tearDown();
}
}
}

View File

@@ -24,11 +24,13 @@ import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.tare.IEconomyManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.BatteryManagerInternal;
import android.os.Binder;
@@ -38,6 +40,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import android.util.Log;
@@ -81,6 +84,7 @@ public class InternalResourceService extends SystemService {
private final Agent mAgent;
private final CompleteEconomicPolicy mCompleteEconomicPolicy;
private final ConfigObserver mConfigObserver;
private final EconomyManagerStub mEconomyManagerStub;
@NonNull
@@ -91,8 +95,8 @@ public class InternalResourceService extends SystemService {
@GuardedBy("mLock")
private final SparseSetArray<String> mUidToPackageCache = new SparseSetArray<>();
@GuardedBy("mLock")
private boolean mIsSetup;
private volatile boolean mIsEnabled;
private volatile int mBootPhase;
// In the range [0,100] to represent 0% to 100% battery.
@GuardedBy("mLock")
private int mCurrentBatteryLevel;
@@ -185,18 +189,7 @@ public class InternalResourceService extends SystemService {
mCompleteEconomicPolicy = new CompleteEconomicPolicy(this);
mAgent = new Agent(this, mCompleteEconomicPolicy);
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_LEVEL_CHANGED);
context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
final IntentFilter pkgFilter = new IntentFilter();
pkgFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
pkgFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
pkgFilter.addDataScheme("package");
context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, pkgFilter, null, null);
final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
userFilter.addAction(Intent.ACTION_USER_ADDED);
context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
mConfigObserver = new ConfigObserver(mHandler, context);
publishLocalService(EconomyManagerInternal.class, new LocalService());
}
@@ -208,19 +201,11 @@ public class InternalResourceService extends SystemService {
@Override
public void onBootPhase(int phase) {
mBootPhase = phase;
if (PHASE_SYSTEM_SERVICES_READY == phase) {
synchronized (mLock) {
mCurrentBatteryLevel = getCurrentBatteryLevel();
// TODO: base on if we have anything persisted
final boolean isFirstSetup = true;
if (isFirstSetup) {
mHandler.post(this::setupEconomy);
} else {
mIsSetup = true;
}
scheduleUnusedWealthReclamationLocked();
mCompleteEconomicPolicy.onSystemServicesReady();
}
mConfigObserver.start();
setupEverything();
}
}
@@ -247,6 +232,10 @@ public class InternalResourceService extends SystemService {
/ 100;
}
boolean isEnabled() {
return mIsEnabled;
}
void onBatteryLevelChanged() {
synchronized (mLock) {
final int newBatteryLevel = getCurrentBatteryLevel();
@@ -396,11 +385,67 @@ public class InternalResourceService extends SystemService {
mPkgCache = mPackageManager.getInstalledPackages(0);
}
private void setupEconomy() {
private void registerReceivers() {
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_LEVEL_CHANGED);
getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
final IntentFilter pkgFilter = new IntentFilter();
pkgFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
pkgFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
pkgFilter.addDataScheme("package");
getContext()
.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, pkgFilter, null, null);
final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
userFilter.addAction(Intent.ACTION_USER_ADDED);
getContext()
.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
}
/** Perform long-running and/or heavy setup work. This should be called off the main thread. */
private void setupHeavyWork() {
synchronized (mLock) {
loadInstalledPackageListLocked();
mAgent.grantBirthrightsLocked();
mIsSetup = true;
// TODO: base on if we have anything persisted
final boolean isFirstSetup = true;
if (isFirstSetup) {
mAgent.grantBirthrightsLocked();
}
}
}
private void setupEverything() {
if (mBootPhase < PHASE_SYSTEM_SERVICES_READY || !mIsEnabled) {
return;
}
synchronized (mLock) {
registerReceivers();
mCurrentBatteryLevel = getCurrentBatteryLevel();
mHandler.post(this::setupHeavyWork);
scheduleUnusedWealthReclamationLocked();
mCompleteEconomicPolicy.setup();
}
}
private void tearDownEverything() {
if (mIsEnabled) {
return;
}
synchronized (mLock) {
mAgent.tearDownLocked();
mCompleteEconomicPolicy.tearDown();
mHandler.post(() -> {
// Never call out to AlarmManager with the lock held. This sits below AM.
AlarmManager alarmManager = getContext().getSystemService(AlarmManager.class);
if (alarmManager != null) {
alarmManager.cancel(mUnusedWealthReclamationListener);
}
});
mPkgCache.clear();
mUidToPackageCache.clear();
getContext().unregisterReceiver(mBroadcastReceiver);
}
}
@@ -487,6 +532,9 @@ public class InternalResourceService extends SystemService {
@Override
public boolean canPayFor(int userId, @NonNull String pkgName, @NonNull ActionBill bill) {
if (!mIsEnabled) {
return true;
}
// TODO: take temp-allowlist into consideration
long requiredBalance = 0;
final List<EconomyManagerInternal.AnticipatedAction> projectedActions =
@@ -506,6 +554,9 @@ public class InternalResourceService extends SystemService {
@Override
public void noteInstantaneousEvent(int userId, @NonNull String pkgName, int eventId,
@Nullable String tag) {
if (!mIsEnabled) {
return;
}
synchronized (mLock) {
mAgent.noteInstantaneousEventLocked(userId, pkgName, eventId, tag);
}
@@ -514,6 +565,9 @@ public class InternalResourceService extends SystemService {
@Override
public void noteOngoingEventStarted(int userId, @NonNull String pkgName, int eventId,
@Nullable String tag) {
if (!mIsEnabled) {
return;
}
synchronized (mLock) {
final long nowElapsed = SystemClock.elapsedRealtime();
mAgent.noteOngoingEventLocked(userId, pkgName, eventId, tag, nowElapsed);
@@ -523,6 +577,9 @@ public class InternalResourceService extends SystemService {
@Override
public void noteOngoingEventStopped(int userId, @NonNull String pkgName, int eventId,
@Nullable String tag) {
if (!mIsEnabled) {
return;
}
final long nowElapsed = SystemClock.elapsedRealtime();
final long now = System.currentTimeMillis();
synchronized (mLock) {
@@ -531,6 +588,39 @@ public class InternalResourceService extends SystemService {
}
}
private class ConfigObserver extends ContentObserver {
private final ContentResolver mContentResolver;
ConfigObserver(Handler handler, Context context) {
super(handler);
mContentResolver = context.getContentResolver();
}
public void start() {
mContentResolver.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.ENABLE_TARE), false, this);
updateConfig();
}
@Override
public void onChange(boolean selfChange) {
updateConfig();
}
private void updateConfig() {
final boolean isTareEnabled = Settings.Global.getInt(mContentResolver,
Settings.Global.ENABLE_TARE, Settings.Global.DEFAULT_ENABLE_TARE) == 1;
if (mIsEnabled != isTareEnabled) {
mIsEnabled = isTareEnabled;
if (mIsEnabled) {
setupEverything();
} else {
tearDownEverything();
}
}
}
}
private static void dumpHelp(PrintWriter pw) {
pw.println("Resource Economy (economy) dump options:");
pw.println(" [-h|--help] [package] ...");

View File

@@ -60,7 +60,10 @@ abstract class Modifier {
return price;
}
void onSystemServicesReady() {
void setup() {
}
void tearDown() {
}
abstract void dump(IndentingPrintWriter pw);

View File

@@ -110,7 +110,7 @@ class ProcessStateModifier extends Modifier {
@Override
@GuardedBy("mLock")
void onSystemServicesReady() {
void setup() {
try {
ActivityManager.getService().registerUidObserver(mUidObserver,
ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE,
@@ -120,6 +120,18 @@ class ProcessStateModifier extends Modifier {
}
}
@Override
@GuardedBy("mLock")
void tearDown() {
try {
ActivityManager.getService().unregisterUidObserver(mUidObserver);
} catch (RemoteException e) {
// ignored; both services live in system_server
}
mPackageToUidCache.clear();
mUidProcStateBucketCache.clear();
}
/**
* Get the final modified price based on an app's process state.
*

View File

@@ -13433,6 +13433,21 @@ public final class Settings {
public static final String FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED
= "forced_app_standby_for_small_battery_enabled";
/**
* Whether to enable the TARE subsystem as a whole or not.
* 1 means enable, 0 means disable.
*
* @hide
*/
public static final String ENABLE_TARE = "enable_tare";
/**
* Default value for {@link #ENABLE_TARE}.
*
* @hide
*/
public static final int DEFAULT_ENABLE_TARE = 0;
/**
* Whether or not to enable the User Absent, Radios Off feature on small battery devices.
* Type: int (0 for false, 1 for true)

View File

@@ -116,6 +116,7 @@ public class GlobalSettingsValidators {
VALIDATORS.put(Global.CLOCKWORK_SYSUI_MAIN_ACTIVITY_NAME, ANY_STRING_VALIDATOR);
VALIDATORS.put(Global.CLOCKWORK_SYSUI_PACKAGE_NAME, ANY_STRING_VALIDATOR);
VALIDATORS.put(Global.CLOCKWORK_HOME_READY, ANY_STRING_VALIDATOR);
VALIDATORS.put(Global.ENABLE_TARE, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.PRIVATE_DNS_MODE, ANY_STRING_VALIDATOR);
VALIDATORS.put(Global.PRIVATE_DNS_SPECIFIER, ANY_STRING_VALIDATOR);
VALIDATORS.put(Global.SOFT_AP_TIMEOUT_ENABLED, BOOLEAN_VALIDATOR);

View File

@@ -265,6 +265,7 @@ public class SettingsBackupTest {
Settings.Global.ENABLE_DISKSTATS_LOGGING,
Settings.Global.ENABLE_EPHEMERAL_FEATURE,
Settings.Global.ENABLE_RESTRICTED_BUCKET,
Settings.Global.ENABLE_TARE,
Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,