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

Commit 0f8617a6 authored by Makoto Onuki's avatar Makoto Onuki
Browse files

Enhance battery saver event log

- Add reason to on/off log
- Add "threshold changed" event log

Bug: 78833408
Test: Manual test + logcat
Test:   atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
Change-Id: Iddaff8dfa585923c3581552200ea2734b2c1a16d
parent 4d099ddc
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -33,10 +33,11 @@ option java_package com.android.server
# It logs the time remaining before the device would've normally gone to sleep without the request.
2731 power_soft_sleep_requested (savedwaketimems|2)
# Power save state has changed. See BatterySaverController.java for the details.
2739 battery_saver_mode (prevOffOrOn|1|5),(nowOffOrOn|1|5),(interactive|1|5),(features|3|5)
2739 battery_saver_mode (prevOffOrOn|1|5),(nowOffOrOn|1|5),(interactive|1|5),(features|3|5),(reason|1|5)
27390 battery_saving_stats (batterySaver|1|5),(interactive|1|5),(doze|1|5),(delta_duration|2|3),(delta_battery_drain|1|1),(delta_battery_drain_percent|1|6),(total_duration|2|3),(total_battery_drain|1|1),(total_battery_drain_percent|1|6)
# Note when the user activity timeout has been overriden by ActivityManagerService
27391 user_activity_timeout_override (override|2|3)
27392 battery_saver_setting (threshold|1)

#
# Leave IDs through 2740 for more power logs (2730 used by battery_discharge above)
+23 −9
Original line number Diff line number Diff line
@@ -90,6 +90,16 @@ public class BatterySaverController implements BatterySaverPolicyListener {
     */
    private final Plugin[] mPlugins;

    public static final int REASON_AUTOMATIC_ON = 0;
    public static final int REASON_AUTOMATIC_OFF = 1;
    public static final int REASON_MANUAL_ON = 2;
    public static final int REASON_MANUAL_OFF = 3;
    public static final int REASON_STICKY_RESTORE = 4;
    public static final int REASON_INTERACTIVE_CHANGED = 5;
    public static final int REASON_POLICY_CHANGED = 6;
    public static final int REASON_PLUGGED_IN = 7;
    public static final int REASON_SETTING_CHANGED = 8;

    /**
     * Plugin interface. All methods are guaranteed to be called on the same (handler) thread.
     */
@@ -113,7 +123,8 @@ public class BatterySaverController implements BatterySaverPolicyListener {
                        return; // No need to send it if not enabled.
                    }
                    // Don't send the broadcast, because we never did so in this case.
                    mHandler.postStateChanged(/*sendBroadcast=*/ false);
                    mHandler.postStateChanged(/*sendBroadcast=*/ false,
                            REASON_INTERACTIVE_CHANGED);
                    break;
                case Intent.ACTION_BATTERY_CHANGED:
                    synchronized (mLock) {
@@ -184,7 +195,7 @@ public class BatterySaverController implements BatterySaverPolicyListener {
        if (!isEnabled()) {
            return; // No need to send it if not enabled.
        }
        mHandler.postStateChanged(/*sendBroadcast=*/ true);
        mHandler.postStateChanged(/*sendBroadcast=*/ true, REASON_POLICY_CHANGED);
    }

    private class MyHandler extends Handler {
@@ -199,9 +210,9 @@ public class BatterySaverController implements BatterySaverPolicyListener {
            super(looper);
        }

        public void postStateChanged(boolean sendBroadcast) {
        public void postStateChanged(boolean sendBroadcast, int reason) {
            obtainMessage(MSG_STATE_CHANGED, sendBroadcast ?
                    ARG_SEND_BROADCAST : ARG_DONT_SEND_BROADCAST, 0).sendToTarget();
                    ARG_SEND_BROADCAST : ARG_DONT_SEND_BROADCAST, reason).sendToTarget();
        }

        public void postSystemReady() {
@@ -212,7 +223,9 @@ public class BatterySaverController implements BatterySaverPolicyListener {
        public void dispatchMessage(Message msg) {
            switch (msg.what) {
                case MSG_STATE_CHANGED:
                    handleBatterySaverStateChanged(msg.arg1 == ARG_SEND_BROADCAST);
                    handleBatterySaverStateChanged(
                            msg.arg1 == ARG_SEND_BROADCAST,
                            msg.arg2);
                    break;

                case MSG_SYSTEM_READY:
@@ -227,14 +240,14 @@ public class BatterySaverController implements BatterySaverPolicyListener {
    /**
     * Called by {@link PowerManagerService} to update the battery saver stete.
     */
    public void enableBatterySaver(boolean enable) {
    public void enableBatterySaver(boolean enable, int reason) {
        synchronized (mLock) {
            if (mEnabled == enable) {
                return;
            }
            mEnabled = enable;

            mHandler.postStateChanged(/*sendBroadcast=*/ true);
            mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
        }
    }

@@ -275,7 +288,7 @@ public class BatterySaverController implements BatterySaverPolicyListener {
     * - When battery saver is on the interactive state changes.
     * - When battery saver is on the battery saver policy changes.
     */
    void handleBatterySaverStateChanged(boolean sendBroadcast) {
    void handleBatterySaverStateChanged(boolean sendBroadcast, int reason) {
        final LowPowerModeListener[] listeners;

        final boolean enabled;
@@ -287,7 +300,8 @@ public class BatterySaverController implements BatterySaverPolicyListener {
                    mPreviouslyEnabled ? 1 : 0, // Previously off or on.
                    mEnabled ? 1 : 0, // Now off or on.
                    isInteractive ?  1 : 0, // Device interactive state.
                    mEnabled ? mBatterySaverPolicy.toEventLogString() : "");
                    mEnabled ? mBatterySaverPolicy.toEventLogString() : "",
                    reason);
            mPreviouslyEnabled = mEnabled;

            listeners = mListeners.toArray(new LowPowerModeListener[mListeners.size()]);
+64 −9
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.power.batterysaver;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Global;
@@ -27,6 +28,7 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.server.EventLogTags;
import com.android.server.power.BatterySaverPolicy;
import com.android.server.power.BatterySaverStateMachineProto;

@@ -95,6 +97,18 @@ public class BatterySaverStateMachine {
    @GuardedBy("mLock")
    private boolean mBatterySaverSnoozing;

    /**
     * Last reason passed to {@link #enableBatterySaverLocked}.
     */
    @GuardedBy("mLock")
    private int mLastChangedIntReason;

    /**
     * Last reason passed to {@link #enableBatterySaverLocked}.
     */
    @GuardedBy("mLock")
    private String mLastChangedStrReason;

    private final ContentObserver mSettingsObserver = new ContentObserver(null) {
        @Override
        public void onChange(boolean selfChange) {
@@ -149,11 +163,25 @@ public class BatterySaverStateMachine {
        });
    }

    /**
     * Run a {@link Runnable} on a background handler.
     */
    @VisibleForTesting
    void runOnBgThread(Runnable r) {
        BackgroundThread.getHandler().post(r);
    }

    /**
     * Run a {@link Runnable} on a background handler, but lazily. If the same {@link Runnable},
     * it'll be first removed before a new one is posted.
     */
    @VisibleForTesting
    void runOnBgThreadLazy(Runnable r, int delayMillis) {
        final Handler h = BackgroundThread.getHandler();
        h.removeCallbacks(r);
        h.postDelayed(r, delayMillis);
    }

    void refreshSettingsLocked() {
        final ContentResolver cr = mContext.getContentResolver();

@@ -199,14 +227,23 @@ public class BatterySaverStateMachine {
        mSettingBatterySaverEnabledSticky = batterySaverEnabledSticky;
        mSettingBatterySaverTriggerThreshold = batterySaverTriggerThreshold;

        if (thresholdChanged) {
            // To avoid spamming the event log, we throttle logging here.
            runOnBgThreadLazy(mThresholdChangeLogger, 2000);
        }

        if (enabledChanged) {
            final String reason = batterySaverEnabled
                    ? "Global.low_power changed to 1" : "Global.low_power changed to 0";
            enableBatterySaverLocked(/*enable=*/ batterySaverEnabled, /*manual=*/ true,
                    reason);
                    BatterySaverController.REASON_SETTING_CHANGED, reason);
        }
    }

    private final Runnable mThresholdChangeLogger = () -> {
        EventLogTags.writeBatterySaverSetting(mSettingBatterySaverTriggerThreshold);
    };

    /**
     * {@link com.android.server.power.PowerManagerService} calls it when battery state changes.
     *
@@ -257,18 +294,26 @@ public class BatterySaverStateMachine {
        }
        if (mIsPowered) {
            updateSnoozingLocked(false, "Plugged in");
            enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false, "Plugged in");
            enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
                    BatterySaverController.REASON_PLUGGED_IN,
                    "Plugged in");

        } else if (mSettingBatterySaverEnabledSticky) {
            // Re-enable BS.
            enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ true, "Sticky restore");
            enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ true,
                    BatterySaverController.REASON_STICKY_RESTORE,
                    "Sticky restore");

        } else if (mIsBatteryLevelLow) {
            if (!mBatterySaverSnoozing && isAutoBatterySaverConfigured()) {
                enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ false, "Auto ON");
                enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ false,
                        BatterySaverController.REASON_AUTOMATIC_ON,
                        "Auto ON");
            }
        } else { // Battery not low
            enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false, "Auto OFF");
            enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
                    BatterySaverController.REASON_AUTOMATIC_OFF,
                    "Auto OFF");
        }
    }

@@ -284,6 +329,8 @@ public class BatterySaverStateMachine {
        }
        synchronized (mLock) {
            enableBatterySaverLocked(/*enable=*/ enabled, /*manual=*/ true,
                    (enabled ? BatterySaverController.REASON_MANUAL_ON
                            : BatterySaverController.REASON_MANUAL_OFF),
                    (enabled ? "Manual ON" : "Manual OFF"));
        }
    }
@@ -292,10 +339,11 @@ public class BatterySaverStateMachine {
     * Actually enable / disable battery saver. Write the new state to the global settings
     * and propagate it to {@link #mBatterySaverController}.
     */
    private void enableBatterySaverLocked(boolean enable, boolean manual, String reason) {
    private void enableBatterySaverLocked(boolean enable, boolean manual, int intReason,
            String strReason) {
        if (DEBUG) {
            Slog.d(TAG, "enableBatterySaver: enable=" + enable + " manual=" + manual
                    + " reason=" + reason);
                    + " reason=" + strReason + "(" + intReason + ")");
        }
        final boolean wasEnabled = mBatterySaverController.isEnabled();

@@ -309,6 +357,8 @@ public class BatterySaverStateMachine {
            if (DEBUG) Slog.d(TAG, "Can't enable: isPowered");
            return;
        }
        mLastChangedIntReason = intReason;
        mLastChangedStrReason = strReason;

        if (manual) {
            if (enable) {
@@ -330,12 +380,12 @@ public class BatterySaverStateMachine {
            mSettingBatterySaverEnabledSticky = enable;
            putGlobalSetting(Global.LOW_POWER_MODE_STICKY, enable ? 1 : 0);
        }
        mBatterySaverController.enableBatterySaver(enable);
        mBatterySaverController.enableBatterySaver(enable, intReason);

        if (DEBUG) {
            Slog.d(TAG, "Battery saver: Enabled=" + enable
                    + " manual=" + manual
                    + " reason=" + reason);
                    + " reason=" + strReason + "(" + intReason + ")");
        }
    }

@@ -365,6 +415,11 @@ public class BatterySaverStateMachine {
            pw.print("  Enabled=");
            pw.println(mBatterySaverController.isEnabled());

            pw.print("  mLastChangedIntReason=");
            pw.println(mLastChangedIntReason);
            pw.print("  mLastChangedStrReason=");
            pw.println(mLastChangedStrReason);

            pw.print("  mBootCompleted=");
            pw.println(mBootCompleted);
            pw.print("  mSettingsLoaded=");
+7 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package com.android.server.power.batterysaver;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -144,6 +145,11 @@ public class BatterySaverStateMachineTest {
        void runOnBgThread(Runnable r) {
            r.run();
        }

        @Override
        void runOnBgThreadLazy(Runnable r, int delayMillis) {
            r.run();
        }
    }

    @Before
@@ -153,7 +159,7 @@ public class BatterySaverStateMachineTest {
        mMockBatterySaverController = mock(BatterySaverController.class);

        doAnswer((inv) -> mDevice.batterySaverEnabled = inv.getArgument(0))
                .when(mMockBatterySaverController).enableBatterySaver(anyBoolean());
                .when(mMockBatterySaverController).enableBatterySaver(anyBoolean(), anyInt());
        when(mMockBatterySaverController.isEnabled())
                .thenAnswer((inv) -> mDevice.batterySaverEnabled);