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

Commit 21d3e270 authored by Kweku Adams's avatar Kweku Adams Committed by Android (Google) Code Review
Browse files

Merge "Add basic multipliers."

parents ea58f34c 00c02ac6
Loading
Loading
Loading
Loading
+100 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.tare;

import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.SystemClock;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Slog;

/** Multiplier that makes things free when the device is charging. */
class ChargingMultiplier extends Multiplier {
    private static final String TAG = "TARE-" + ChargingMultiplier.class.getSimpleName();
    private static final boolean DEBUG = InternalResourceService.DEBUG
            || Log.isLoggable(TAG, Log.DEBUG);

    private final InternalResourceService mIrs;
    private final ChargingTracker mChargingTracker;

    ChargingMultiplier(@NonNull InternalResourceService irs) {
        super(true, true);
        mIrs = irs;
        mChargingTracker = new ChargingTracker();
        mChargingTracker.startTracking(irs.getContext());
    }

    double getCurrentMultiplier() {
        if (mChargingTracker.mCharging) {
            return 0;
        }
        return 1;
    }

    @Override
    void dump(IndentingPrintWriter pw) {
        pw.print("charging=");
        pw.println(mChargingTracker.mCharging);
    }

    private final class ChargingTracker extends BroadcastReceiver {
        /**
         * Track whether we're "charging", where charging means that we're ready to commit to
         * doing work.
         */
        private volatile boolean mCharging;

        public void startTracking(@NonNull Context context) {
            final IntentFilter filter = new IntentFilter();
            filter.addAction(BatteryManager.ACTION_CHARGING);
            filter.addAction(BatteryManager.ACTION_DISCHARGING);
            context.registerReceiver(this, filter);

            // Initialise tracker state.
            final BatteryManager batteryManager = context.getSystemService(BatteryManager.class);
            mCharging = batteryManager.isCharging();
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (BatteryManager.ACTION_CHARGING.equals(action)) {
                if (DEBUG) {
                    Slog.d(TAG, "Received charging intent, fired @ "
                            + SystemClock.elapsedRealtime());
                }
                if (!mCharging) {
                    mCharging = true;
                    mIrs.onDeviceStateChanged();
                }
            } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) {
                if (DEBUG) {
                    Slog.d(TAG, "Disconnected from power.");
                }
                if (mCharging) {
                    mCharging = false;
                    mIrs.onDeviceStateChanged();
                }
            }
        }
    }
}
+99 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.tare;

import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.PowerManager;
import android.util.IndentingPrintWriter;
import android.util.Log;

/** Multiplier that makes things more expensive in light and deep doze. */
class DeviceIdleMultiplier extends Multiplier {
    private static final String TAG = "TARE-" + DeviceIdleMultiplier.class.getSimpleName();
    private static final boolean DEBUG = InternalResourceService.DEBUG
            || Log.isLoggable(TAG, Log.DEBUG);

    private final InternalResourceService mIrs;
    private final PowerManager mPowerManager;
    private final DeviceIdleTracker mDeviceIdleTracker;

    DeviceIdleMultiplier(@NonNull InternalResourceService irs) {
        super(true, false);
        mIrs = irs;
        mPowerManager = irs.getContext().getSystemService(PowerManager.class);
        mDeviceIdleTracker = new DeviceIdleTracker();
        mDeviceIdleTracker.startTracking(irs.getContext());
    }

    double getCurrentMultiplier() {
        if (mDeviceIdleTracker.mDeviceIdle) {
            return 1.2;
        }
        if (mDeviceIdleTracker.mDeviceLightIdle) {
            return 1.1;
        }
        return 1;
    }

    @Override
    void dump(IndentingPrintWriter pw) {
        pw.print("idle=");
        pw.println(mDeviceIdleTracker.mDeviceIdle);
        pw.print("lightIdle=");
        pw.println(mDeviceIdleTracker.mDeviceLightIdle);
    }

    private final class DeviceIdleTracker extends BroadcastReceiver {

        private volatile boolean mDeviceIdle;
        private volatile boolean mDeviceLightIdle;

        DeviceIdleTracker() {
        }

        void startTracking(@NonNull Context context) {
            IntentFilter filter = new IntentFilter();
            filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
            filter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
            context.registerReceiver(this, filter);

            // Initialise tracker state.
            mDeviceIdle = mPowerManager.isDeviceIdleMode();
            mDeviceLightIdle = mPowerManager.isLightDeviceIdleMode();
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) {
                if (mDeviceIdle != mPowerManager.isDeviceIdleMode()) {
                    mDeviceIdle = mPowerManager.isDeviceIdleMode();
                    mIrs.onDeviceStateChanged();
                }
            } else if (PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED.equals(action)) {
                if (mDeviceIdle != mPowerManager.isLightDeviceIdleMode()) {
                    mDeviceLightIdle = mPowerManager.isLightDeviceIdleMode();
                    mIrs.onDeviceStateChanged();
                }
            }
        }
    }
}
+6 −5
Original line number Diff line number Diff line
@@ -64,14 +64,15 @@ public class InternalResourceService extends SystemService {
    private final BatteryManagerInternal mBatteryManagerInternal;
    private final PackageManager mPackageManager;

    @GuardedBy("mLock")
    private final CopyOnWriteArraySet<BalanceChangeListener> mBalanceChangeListeners =
            new CopyOnWriteArraySet<>();

    @NonNull
    @GuardedBy("mLock")
    private List<PackageInfo> mPkgCache = new ArrayList<>();

    /** Cached mapping of UIDs (for all users) to a list of packages in the UID. */
    @GuardedBy("mLock")
    private final SparseSetArray<String> mUidToPackageCache = new SparseSetArray<>();

    @GuardedBy("mLock")
@@ -185,7 +186,7 @@ public class InternalResourceService extends SystemService {
    ArraySet<String> getPackagesForUidLocked(final int uid) {
        ArraySet<String> packages = mUidToPackageCache.get(uid);
        if (packages == null) {
            String[] pkgs = mPackageManager.getPackagesForUid(uid);
            final String[] pkgs = mPackageManager.getPackagesForUid(uid);
            if (pkgs != null) {
                for (String pkg : pkgs) {
                    mUidToPackageCache.add(uid, pkg);
@@ -196,9 +197,6 @@ public class InternalResourceService extends SystemService {
        return packages;
    }

    void onAppStateChanged(final int userId, @NonNull final ArraySet<String> pkgNames) {
    }

    void onBatteryLevelChanged() {
        synchronized (mLock) {
            final int newBatteryLevel = getCurrentBatteryLevel();
@@ -245,6 +243,9 @@ public class InternalResourceService extends SystemService {
        }
    }

    void onUidStateChanged(final int uid) {
    }

    void onUserAdded(final int userId) {
        synchronized (mLock) {
            loadInstalledPackageListLocked();
+70 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.tare;

import android.annotation.IntDef;
import android.util.IndentingPrintWriter;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Base class of a multiplier that can affect end pricing.
 */
abstract class Multiplier {
    static final int STATE_MULTIPLIER_CHARGING = 0;
    static final int STATE_MULTIPLIER_DEVICE_IDLE = 1;
    static final int STATE_MULTIPLIER_POWER_SAVE_MODE = 2;
    static final int STATE_MULTIPLIER_PROCESS_STATE = 3;
    static final int NUM_STATE_MULTIPLIERS = STATE_MULTIPLIER_PROCESS_STATE + 1;

    @IntDef({
            STATE_MULTIPLIER_CHARGING,
            STATE_MULTIPLIER_DEVICE_IDLE,
            STATE_MULTIPLIER_POWER_SAVE_MODE,
            STATE_MULTIPLIER_PROCESS_STATE,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface StateMultiplier {
    }

    /**
     * Affects the "cost to produce" (perform) the action
     *
     * @see EconomicPolicy.Action#costToProduce
     */
    public final boolean affectsCtp;
    /**
     * Affects the final price of the action
     *
     * @see EconomicPolicy.Action#basePrice
     */
    public final boolean affectsPrice;

    Multiplier(boolean affectsCtp, boolean affectsPrice) {
        this.affectsCtp = affectsCtp;
        this.affectsPrice = affectsPrice;
    }

    /** Get the multiplier based on the current device state. */
    abstract double getCurrentMultiplier();

    void onSystemServicesReady() {
    }

    abstract void dump(IndentingPrintWriter pw);
}
+50 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.tare;

import android.annotation.NonNull;
import android.os.PowerManager;
import android.util.IndentingPrintWriter;

/** Multiplier that makes things more expensive in adaptive and full battery saver are active. */
class PowerSaveModeMultiplier extends Multiplier {
    private final InternalResourceService mIrs;
    private final PowerManager mPowerManager;

    PowerSaveModeMultiplier(@NonNull InternalResourceService irs) {
        super(true, false);
        mIrs = irs;
        mPowerManager = irs.getContext().getSystemService(PowerManager.class);
    }

    double getCurrentMultiplier() {
        if (mPowerManager.isPowerSaveMode()) {
            return 1.5;
        }
        // TODO: get adaptive power save mode
        if (mPowerManager.isPowerSaveMode()) {
            return 1.25;
        }
        return 1;
    }

    @Override
    void dump(IndentingPrintWriter pw) {
        pw.print("power save=");
        pw.println(mPowerManager.isPowerSaveMode());
    }
}
Loading