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

Commit 6abf6254 authored by Salvador Martinez's avatar Salvador Martinez Committed by Android (Google) Code Review
Browse files

Merge "Update triggering logic for hybrid notification" into pi-dev

parents 322929af fd38aa51
Loading
Loading
Loading
Loading
+46 −30
Original line number Original line Diff line number Diff line
@@ -52,6 +52,7 @@ import com.android.systemui.statusbar.phone.StatusBar;


import java.io.FileDescriptor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.PrintWriter;
import java.time.Duration;
import java.util.Arrays;
import java.util.Arrays;


public class PowerUI extends SystemUI {
public class PowerUI extends SystemUI {
@@ -61,6 +62,8 @@ public class PowerUI extends SystemUI {
    private static final long TEMPERATURE_LOGGING_INTERVAL = DateUtils.HOUR_IN_MILLIS;
    private static final long TEMPERATURE_LOGGING_INTERVAL = DateUtils.HOUR_IN_MILLIS;
    private static final int MAX_RECENT_TEMPS = 125; // TEMPERATURE_LOGGING_INTERVAL plus a buffer
    private static final int MAX_RECENT_TEMPS = 125; // TEMPERATURE_LOGGING_INTERVAL plus a buffer
    static final long THREE_HOURS_IN_MILLIS = DateUtils.HOUR_IN_MILLIS * 3;
    static final long THREE_HOURS_IN_MILLIS = DateUtils.HOUR_IN_MILLIS * 3;
    private static final int CHARGE_CYCLE_PERCENT_RESET = 45;
    private static final long SIX_HOURS_MILLIS = Duration.ofHours(6).toMillis();


    private final Handler mHandler = new Handler();
    private final Handler mHandler = new Handler();
    private final Receiver mReceiver = new Receiver();
    private final Receiver mReceiver = new Receiver();
@@ -69,7 +72,6 @@ public class PowerUI extends SystemUI {
    private HardwarePropertiesManager mHardwarePropertiesManager;
    private HardwarePropertiesManager mHardwarePropertiesManager;
    private WarningsUI mWarnings;
    private WarningsUI mWarnings;
    private final Configuration mLastConfiguration = new Configuration();
    private final Configuration mLastConfiguration = new Configuration();
    private int mBatteryLevel = 100;
    private long mTimeRemaining = Long.MAX_VALUE;
    private long mTimeRemaining = Long.MAX_VALUE;
    private int mPlugType = 0;
    private int mPlugType = 0;
    private int mInvalidCharger = 0;
    private int mInvalidCharger = 0;
@@ -88,6 +90,7 @@ public class PowerUI extends SystemUI {
    private long mNextLogTime;
    private long mNextLogTime;
    private IThermalService mThermalService;
    private IThermalService mThermalService;


    @VisibleForTesting int mBatteryLevel = 100;
    @VisibleForTesting int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
    @VisibleForTesting int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;


    // by using the same instance (method references are not guaranteed to be the same object
    // by using the same instance (method references are not guaranteed to be the same object
@@ -205,12 +208,6 @@ public class PowerUI extends SystemUI {


                final boolean plugged = mPlugType != 0;
                final boolean plugged = mPlugType != 0;
                final boolean oldPlugged = oldPlugType != 0;
                final boolean oldPlugged = oldPlugType != 0;
                // if we are now unplugged but we were previously plugged in we should allow the
                // time based trigger again.
                if (!plugged && plugged != oldPlugged) {
                    mLowWarningShownThisChargeCycle = false;
                    mSevereWarningShownThisChargeCycle = false;
                }


                int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
                int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
                int bucket = findBatteryLevelBucket(mBatteryLevel);
                int bucket = findBatteryLevelBucket(mBatteryLevel);
@@ -261,7 +258,8 @@ public class PowerUI extends SystemUI {
        boolean isPowerSaver = mPowerManager.isPowerSaveMode();
        boolean isPowerSaver = mPowerManager.isPowerSaveMode();
        // only play SFX when the dialog comes up or the bucket changes
        // only play SFX when the dialog comes up or the bucket changes
        final boolean playSound = bucket != oldBucket || oldPlugged;
        final boolean playSound = bucket != oldBucket || oldPlugged;
        if (mEnhancedEstimates.isHybridNotificationEnabled()) {
        final boolean hybridEnabled = mEnhancedEstimates.isHybridNotificationEnabled();
        if (hybridEnabled) {
            final Estimate estimate = mEnhancedEstimates.getEstimate();
            final Estimate estimate = mEnhancedEstimates.getEstimate();
            // Turbo is not always booted once SysUI is running so we have ot make sure we actually
            // Turbo is not always booted once SysUI is running so we have ot make sure we actually
            // get data back
            // get data back
@@ -270,6 +268,14 @@ public class PowerUI extends SystemUI {
                mWarnings.updateEstimate(estimate);
                mWarnings.updateEstimate(estimate);
                mWarnings.updateThresholds(mEnhancedEstimates.getLowWarningThreshold(),
                mWarnings.updateThresholds(mEnhancedEstimates.getLowWarningThreshold(),
                        mEnhancedEstimates.getSevereWarningThreshold());
                        mEnhancedEstimates.getSevereWarningThreshold());

                // if we are now over 45% battery & 6 hours remaining we can trigger hybrid
                // notification again
                if (mBatteryLevel >= CHARGE_CYCLE_PERCENT_RESET
                        && mTimeRemaining > SIX_HOURS_MILLIS) {
                    mLowWarningShownThisChargeCycle = false;
                    mSevereWarningShownThisChargeCycle = false;
                }
            }
            }
        }
        }


@@ -277,14 +283,16 @@ public class PowerUI extends SystemUI {
                mTimeRemaining, isPowerSaver, mBatteryStatus)) {
                mTimeRemaining, isPowerSaver, mBatteryStatus)) {
            mWarnings.showLowBatteryWarning(playSound);
            mWarnings.showLowBatteryWarning(playSound);


            // mark if we've already shown a warning this cycle. This will prevent the time based
            // mark if we've already shown a warning this cycle. This will prevent the notification
            // trigger from spamming users since the time remaining can vary based on current
            // trigger from spamming users by only showing low/critical warnings once per cycle
            // device usage.
            if (hybridEnabled) {
            if (mTimeRemaining < mEnhancedEstimates.getSevereWarningThreshold()) {
                if (mTimeRemaining < mEnhancedEstimates.getSevereWarningThreshold()
                        || mBatteryLevel < mLowBatteryReminderLevels[1]) {
                    mSevereWarningShownThisChargeCycle = true;
                    mSevereWarningShownThisChargeCycle = true;
                } else {
                } else {
                    mLowWarningShownThisChargeCycle = true;
                    mLowWarningShownThisChargeCycle = true;
                }
                }
            }
        } else if (shouldDismissLowBatteryWarning(plugged, oldBucket, bucket, mTimeRemaining,
        } else if (shouldDismissLowBatteryWarning(plugged, oldBucket, bucket, mTimeRemaining,
                isPowerSaver)) {
                isPowerSaver)) {
            mWarnings.dismissLowBatteryWarning();
            mWarnings.dismissLowBatteryWarning();
@@ -295,12 +303,16 @@ public class PowerUI extends SystemUI {


    @VisibleForTesting
    @VisibleForTesting
    boolean shouldShowLowBatteryWarning(boolean plugged, boolean oldPlugged, int oldBucket,
    boolean shouldShowLowBatteryWarning(boolean plugged, boolean oldPlugged, int oldBucket,
            int bucket, long timeRemaining, boolean isPowerSaver, int mBatteryStatus) {
            int bucket, long timeRemaining, boolean isPowerSaver, int batteryStatus) {
        if (mEnhancedEstimates.isHybridNotificationEnabled()) {
            // triggering logic when enhanced estimate is available
            return isEnhancedTrigger(plugged, timeRemaining, isPowerSaver, batteryStatus);
        }
        // legacy triggering logic
        return !plugged
        return !plugged
                && !isPowerSaver
                && !isPowerSaver
                && (((bucket < oldBucket || oldPlugged) && bucket < 0)
                && (((bucket < oldBucket || oldPlugged) && bucket < 0))
                        || isTimeBasedTrigger(timeRemaining))
                && batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN;
                && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN;
    }
    }


    @VisibleForTesting
    @VisibleForTesting
@@ -315,19 +327,23 @@ public class PowerUI extends SystemUI {
                        || hybridWouldDismiss));
                        || hybridWouldDismiss));
    }
    }


    private boolean isTimeBasedTrigger(long timeRemaining) {
    private boolean isEnhancedTrigger(boolean plugged, long timeRemaining, boolean isPowerSaver,
        if (!mEnhancedEstimates.isHybridNotificationEnabled()) {
            int batteryStatus) {
        if (plugged || isPowerSaver || batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
            return false;
            return false;
        }
        }
        int warnLevel = mLowBatteryReminderLevels[0];
        int critLevel = mLowBatteryReminderLevels[1];


        // Only show the time based warning once per charge cycle
        // Only show the low warning once per charge cycle
        final boolean canShowWarning = timeRemaining < mEnhancedEstimates.getLowWarningThreshold()
        final boolean canShowWarning = !mLowWarningShownThisChargeCycle
                && !mLowWarningShownThisChargeCycle;
                && (timeRemaining < mEnhancedEstimates.getLowWarningThreshold()
                        || mBatteryLevel <= warnLevel);


        // Only show the severe time based warning once per charge cycle
        // Only show the severe warning once per charge cycle
        final boolean canShowSevereWarning =
        final boolean canShowSevereWarning = !mSevereWarningShownThisChargeCycle
                timeRemaining < mEnhancedEstimates.getSevereWarningThreshold()
                && (timeRemaining < mEnhancedEstimates.getSevereWarningThreshold()
                        && !mSevereWarningShownThisChargeCycle;
                        || mBatteryLevel <= critLevel);


        return canShowWarning || canShowSevereWarning;
        return canShowWarning || canShowSevereWarning;
    }
    }
+9 −2
Original line number Original line Diff line number Diff line
@@ -58,6 +58,7 @@ public class PowerUITest extends SysuiTestCase {
    public static final int BELOW_WARNING_BUCKET = -1;
    public static final int BELOW_WARNING_BUCKET = -1;
    public static final long BELOW_HYBRID_THRESHOLD = TimeUnit.HOURS.toMillis(2);
    public static final long BELOW_HYBRID_THRESHOLD = TimeUnit.HOURS.toMillis(2);
    public static final long ABOVE_HYBRID_THRESHOLD = TimeUnit.HOURS.toMillis(4);
    public static final long ABOVE_HYBRID_THRESHOLD = TimeUnit.HOURS.toMillis(4);
    private static final long ABOVE_CHARGE_CYCLE_THRESHOLD = Duration.ofHours(8).toMillis();
    private HardwarePropertiesManager mHardProps;
    private HardwarePropertiesManager mHardProps;
    private WarningsUI mMockWarnings;
    private WarningsUI mMockWarnings;
    private PowerUI mPowerUI;
    private PowerUI mPowerUI;
@@ -198,6 +199,7 @@ public class PowerUITest extends SysuiTestCase {
        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
        mPowerUI.mBatteryLevel = 10;
        mPowerUI.start();
        mPowerUI.start();


        // unplugged device that would show the non-hybrid notification and the hybrid
        // unplugged device that would show the non-hybrid notification and the hybrid
@@ -213,6 +215,7 @@ public class PowerUITest extends SysuiTestCase {
        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
        mPowerUI.mBatteryLevel = 10;
        mPowerUI.start();
        mPowerUI.start();


        // unplugged device that would show the non-hybrid but not the hybrid
        // unplugged device that would show the non-hybrid but not the hybrid
@@ -254,13 +257,14 @@ public class PowerUITest extends SysuiTestCase {
   }
   }


    @Test
    @Test
    public void testShouldShowLowBatteryWarning_deviceBatteryStatusUnkown_returnsNoShow() {
    public void testShouldShowLowBatteryWarning_deviceBatteryStatusUnknown_returnsNoShow() {
        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
        mPowerUI.start();
        mPowerUI.start();


        // Unknown battery status device that would show the neither due
        // Unknown battery status device that would show the neither due to the battery status being
        // unknown
        boolean shouldShow =
        boolean shouldShow =
                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
                        BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
                        BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
@@ -295,6 +299,9 @@ public class PowerUITest extends SysuiTestCase {


        mPowerUI.maybeShowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
        mPowerUI.maybeShowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
                ABOVE_WARNING_BUCKET);
                ABOVE_WARNING_BUCKET);

        // reduce battery level to handle time based trigger -> level trigger interactions
        mPowerUI.mBatteryLevel = 10;
        boolean shouldShow =
        boolean shouldShow =
                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
                        ABOVE_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
                        ABOVE_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,