Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 739dd166 authored by Kweku Adams's avatar Kweku Adams
Browse files

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
parent 40613918
Loading
Loading
Loading
Loading
+28 −3
Original line number Original line Diff line number Diff line
@@ -196,7 +196,6 @@ class Agent {
            final int eventId, @Nullable String tag) {
            final int eventId, @Nullable String tag) {
        final long now = System.currentTimeMillis();
        final long now = System.currentTimeMillis();
        final Ledger ledger = getLedgerLocked(userId, pkgName);
        final Ledger ledger = getLedgerLocked(userId, pkgName);
        final boolean wasSolvent = getBalanceLocked(userId, pkgName) > 0;


        final int eventType = getEventType(eventId);
        final int eventType = getEventType(eventId);
        switch (eventType) {
        switch (eventType) {
@@ -400,12 +399,16 @@ class Agent {
        SparseArrayMap<String, OngoingEvent> ongoingEvents =
        SparseArrayMap<String, OngoingEvent> ongoingEvents =
                mCurrentOngoingEvents.get(userId, pkgName);
                mCurrentOngoingEvents.get(userId, pkgName);
        if (ongoingEvents == null) {
        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;
            return;
        }
        }
        final OngoingEvent ongoingEvent = ongoingEvents.get(eventId, tag);
        final OngoingEvent ongoingEvent = ongoingEvents.get(eventId, tag);
        if (ongoingEvent == null) {
        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)
                    + eventToString(eventId) + (tag == null ? "" : ":" + tag)
                    + " for <" + userId + ">" + pkgName + " ended");
                    + " for <" + userId + ">" + pkgName + " ended");
            return;
            return;
@@ -768,6 +771,15 @@ class Agent {
                SystemClock.elapsedRealtime() + timeToThresholdMs);
                SystemClock.elapsedRealtime() + timeToThresholdMs);
    }
    }


    @GuardedBy("mLock")
    void tearDownLocked() {
        mLedgers.clear();
        mCurrentNarcsInCirculation = 0;
        mCurrentOngoingEvents.clear();
        mBalanceThresholdAlarmListener.dropAllAlarmsLocked();
        mLedgerCleanupAlarmListener.dropAllAlarmsLocked();
    }

    @VisibleForTesting
    @VisibleForTesting
    static class OngoingEvent {
    static class OngoingEvent {
        public final long startTimeElapsed;
        public final long startTimeElapsed;
@@ -986,6 +998,12 @@ class Agent {
            }
            }
        }
        }


        @GuardedBy("mLock")
        void dropAllAlarmsLocked() {
            mAlarmQueue.clear();
            setNextAlarmLocked(0);
        }

        @GuardedBy("mLock")
        @GuardedBy("mLock")
        protected abstract void processExpiredAlarmLocked(int userId, @NonNull String packageName);
        protected abstract void processExpiredAlarmLocked(int userId, @NonNull String packageName);


@@ -1069,6 +1087,13 @@ class Agent {
        final ActionAffordabilityNote note =
        final ActionAffordabilityNote note =
                new ActionAffordabilityNote(bill, listener, mCompleteEconomicPolicy);
                new ActionAffordabilityNote(bill, listener, mCompleteEconomicPolicy);
        if (actionAffordabilityNotes.add(note)) {
        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.recalculateModifiedPrice(mCompleteEconomicPolicy, userId, pkgName);
            note.setNewAffordability(
            note.setNewAffordability(
                    getBalanceLocked(userId, pkgName) >= note.getCachedModifiedPrice());
                    getBalanceLocked(userId, pkgName) >= note.getCachedModifiedPrice());
+14 −1
Original line number Original line Diff line number Diff line
@@ -40,7 +40,16 @@ class ChargingModifier extends Modifier {
        super();
        super();
        mIrs = irs;
        mIrs = irs;
        mChargingTracker = new ChargingTracker();
        mChargingTracker = new ChargingTracker();
        mChargingTracker.startTracking(irs.getContext());
    }

    @Override
    public void setup() {
        mChargingTracker.startTracking(mIrs.getContext());
    }

    @Override
    public void tearDown() {
        mChargingTracker.stopTracking(mIrs.getContext());
    }
    }


    @Override
    @Override
@@ -84,6 +93,10 @@ class ChargingModifier extends Modifier {
            mCharging = batteryManager.isCharging();
            mCharging = batteryManager.isCharging();
        }
        }


        public void stopTracking(@NonNull Context context) {
            context.unregisterReceiver(this);
        }

        @Override
        @Override
        public void onReceive(Context context, Intent intent) {
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            final String action = intent.getAction();
+14 −1
Original line number Original line Diff line number Diff line
@@ -40,7 +40,16 @@ class DeviceIdleModifier extends Modifier {
        mIrs = irs;
        mIrs = irs;
        mPowerManager = irs.getContext().getSystemService(PowerManager.class);
        mPowerManager = irs.getContext().getSystemService(PowerManager.class);
        mDeviceIdleTracker = new DeviceIdleTracker();
        mDeviceIdleTracker = new DeviceIdleTracker();
        mDeviceIdleTracker.startTracking(irs.getContext());
    }

    @Override
    public void setup() {
        mDeviceIdleTracker.startTracking(mIrs.getContext());
    }

    @Override
    public void tearDown() {
        mDeviceIdleTracker.stopTracking(mIrs.getContext());
    }
    }


    @Override
    @Override
@@ -81,6 +90,10 @@ class DeviceIdleModifier extends Modifier {
            mDeviceLightIdle = mPowerManager.isLightDeviceIdleMode();
            mDeviceLightIdle = mPowerManager.isLightDeviceIdleMode();
        }
        }


        void stopTracking(@NonNull Context context) {
            context.unregisterReceiver(this);
        }

        @Override
        @Override
        public void onReceive(Context context, Intent intent) {
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            final String action = intent.getAction();
+12 −2
Original line number Original line Diff line number Diff line
@@ -157,11 +157,21 @@ public abstract class EconomicPolicy {
    }
    }


    @CallSuper
    @CallSuper
    void onSystemServicesReady() {
    void setup() {
        for (int i = 0; i < NUM_COST_MODIFIERS; ++i) {
        for (int i = 0; i < NUM_COST_MODIFIERS; ++i) {
            final Modifier modifier = COST_MODIFIER_BY_INDEX[i];
            final Modifier modifier = COST_MODIFIER_BY_INDEX[i];
            if (modifier != null) {
            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();
            }
            }
        }
        }
    }
    }
+119 −29
Original line number Original line Diff line number Diff line
@@ -24,11 +24,13 @@ import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.AlarmManager;
import android.app.tare.IEconomyManager;
import android.app.tare.IEconomyManager;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.Uri;
import android.net.Uri;
import android.os.BatteryManagerInternal;
import android.os.BatteryManagerInternal;
import android.os.Binder;
import android.os.Binder;
@@ -38,6 +40,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.Message;
import android.os.SystemClock;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.ArraySet;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Log;
@@ -81,6 +84,7 @@ public class InternalResourceService extends SystemService {


    private final Agent mAgent;
    private final Agent mAgent;
    private final CompleteEconomicPolicy mCompleteEconomicPolicy;
    private final CompleteEconomicPolicy mCompleteEconomicPolicy;
    private final ConfigObserver mConfigObserver;
    private final EconomyManagerStub mEconomyManagerStub;
    private final EconomyManagerStub mEconomyManagerStub;


    @NonNull
    @NonNull
@@ -91,8 +95,8 @@ public class InternalResourceService extends SystemService {
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private final SparseSetArray<String> mUidToPackageCache = new SparseSetArray<>();
    private final SparseSetArray<String> mUidToPackageCache = new SparseSetArray<>();


    @GuardedBy("mLock")
    private volatile boolean mIsEnabled;
    private boolean mIsSetup;
    private volatile int mBootPhase;
    // In the range [0,100] to represent 0% to 100% battery.
    // In the range [0,100] to represent 0% to 100% battery.
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private int mCurrentBatteryLevel;
    private int mCurrentBatteryLevel;
@@ -185,18 +189,7 @@ public class InternalResourceService extends SystemService {
        mCompleteEconomicPolicy = new CompleteEconomicPolicy(this);
        mCompleteEconomicPolicy = new CompleteEconomicPolicy(this);
        mAgent = new Agent(this, mCompleteEconomicPolicy);
        mAgent = new Agent(this, mCompleteEconomicPolicy);


        final IntentFilter filter = new IntentFilter();
        mConfigObserver = new ConfigObserver(mHandler, context);
        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);


        publishLocalService(EconomyManagerInternal.class, new LocalService());
        publishLocalService(EconomyManagerInternal.class, new LocalService());
    }
    }
@@ -208,19 +201,11 @@ public class InternalResourceService extends SystemService {


    @Override
    @Override
    public void onBootPhase(int phase) {
    public void onBootPhase(int phase) {
        mBootPhase = phase;

        if (PHASE_SYSTEM_SERVICES_READY == phase) {
        if (PHASE_SYSTEM_SERVICES_READY == phase) {
            synchronized (mLock) {
            mConfigObserver.start();
                mCurrentBatteryLevel = getCurrentBatteryLevel();
            setupEverything();
                // TODO: base on if we have anything persisted
                final boolean isFirstSetup = true;
                if (isFirstSetup) {
                    mHandler.post(this::setupEconomy);
                } else {
                    mIsSetup = true;
                }
                scheduleUnusedWealthReclamationLocked();
                mCompleteEconomicPolicy.onSystemServicesReady();
            }
        }
        }
    }
    }


@@ -247,6 +232,10 @@ public class InternalResourceService extends SystemService {
                / 100;
                / 100;
    }
    }


    boolean isEnabled() {
        return mIsEnabled;
    }

    void onBatteryLevelChanged() {
    void onBatteryLevelChanged() {
        synchronized (mLock) {
        synchronized (mLock) {
            final int newBatteryLevel = getCurrentBatteryLevel();
            final int newBatteryLevel = getCurrentBatteryLevel();
@@ -396,11 +385,67 @@ public class InternalResourceService extends SystemService {
        mPkgCache = mPackageManager.getInstalledPackages(0);
        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) {
        synchronized (mLock) {
            loadInstalledPackageListLocked();
            loadInstalledPackageListLocked();
            // TODO: base on if we have anything persisted
            final boolean isFirstSetup = true;
            if (isFirstSetup) {
                mAgent.grantBirthrightsLocked();
                mAgent.grantBirthrightsLocked();
            mIsSetup = true;
            }
        }
    }

    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
        @Override
        public boolean canPayFor(int userId, @NonNull String pkgName, @NonNull ActionBill bill) {
        public boolean canPayFor(int userId, @NonNull String pkgName, @NonNull ActionBill bill) {
            if (!mIsEnabled) {
                return true;
            }
            // TODO: take temp-allowlist into consideration
            // TODO: take temp-allowlist into consideration
            long requiredBalance = 0;
            long requiredBalance = 0;
            final List<EconomyManagerInternal.AnticipatedAction> projectedActions =
            final List<EconomyManagerInternal.AnticipatedAction> projectedActions =
@@ -506,6 +554,9 @@ public class InternalResourceService extends SystemService {
        @Override
        @Override
        public void noteInstantaneousEvent(int userId, @NonNull String pkgName, int eventId,
        public void noteInstantaneousEvent(int userId, @NonNull String pkgName, int eventId,
                @Nullable String tag) {
                @Nullable String tag) {
            if (!mIsEnabled) {
                return;
            }
            synchronized (mLock) {
            synchronized (mLock) {
                mAgent.noteInstantaneousEventLocked(userId, pkgName, eventId, tag);
                mAgent.noteInstantaneousEventLocked(userId, pkgName, eventId, tag);
            }
            }
@@ -514,6 +565,9 @@ public class InternalResourceService extends SystemService {
        @Override
        @Override
        public void noteOngoingEventStarted(int userId, @NonNull String pkgName, int eventId,
        public void noteOngoingEventStarted(int userId, @NonNull String pkgName, int eventId,
                @Nullable String tag) {
                @Nullable String tag) {
            if (!mIsEnabled) {
                return;
            }
            synchronized (mLock) {
            synchronized (mLock) {
                final long nowElapsed = SystemClock.elapsedRealtime();
                final long nowElapsed = SystemClock.elapsedRealtime();
                mAgent.noteOngoingEventLocked(userId, pkgName, eventId, tag, nowElapsed);
                mAgent.noteOngoingEventLocked(userId, pkgName, eventId, tag, nowElapsed);
@@ -523,6 +577,9 @@ public class InternalResourceService extends SystemService {
        @Override
        @Override
        public void noteOngoingEventStopped(int userId, @NonNull String pkgName, int eventId,
        public void noteOngoingEventStopped(int userId, @NonNull String pkgName, int eventId,
                @Nullable String tag) {
                @Nullable String tag) {
            if (!mIsEnabled) {
                return;
            }
            final long nowElapsed = SystemClock.elapsedRealtime();
            final long nowElapsed = SystemClock.elapsedRealtime();
            final long now = System.currentTimeMillis();
            final long now = System.currentTimeMillis();
            synchronized (mLock) {
            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) {
    private static void dumpHelp(PrintWriter pw) {
        pw.println("Resource Economy (economy) dump options:");
        pw.println("Resource Economy (economy) dump options:");
        pw.println("  [-h|--help] [package] ...");
        pw.println("  [-h|--help] [package] ...");
Loading