diff options
author | 2018-01-16 16:29:33 +0000 | |
---|---|---|
committer | 2018-01-16 16:29:33 +0000 | |
commit | 6644e252cda745842af86d1583d21f5db60d4b2d (patch) | |
tree | 380e2b2c10838956d77bdfc183502de66db6ced0 | |
parent | d406ccab42ae2aed387f7109cb918767843fba56 (diff) | |
parent | f9e4750af778ede346003c47d211828389955270 (diff) |
Merge "Refactor code to support overridden low battery warning"
9 files changed, 394 insertions, 35 deletions
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 6ff239ebd2ee..dde4dcfb23fe 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -61,11 +61,26 @@ <!-- When the battery is low, this is displayed to the user in a dialog. The title of the low battery alert. [CHAR LIMIT=NONE]--> <string name="battery_low_title">Battery is low</string> + <!-- When the battery is low and hybrid notifications are enabled, this is displayed to the user in a dialog. + The title of the low battery alert. [CHAR LIMIT=NONE]--> + <string name="battery_low_title_hybrid">Battery is low. Turn on Battery Saver</string> + <!-- A message that appears when the battery level is getting low in a dialog. This is - appened to the subtitle of the low battery alert. "percentage" is the percentage of battery + appended to the subtitle of the low battery alert. "percentage" is the percentage of battery remaining [CHAR LIMIT=none]--> <string name="battery_low_percent_format"><xliff:g id="percentage">%s</xliff:g> remaining</string> + <!-- A message that appears when the battery remaining estimate is low in a dialog. This is + appended to the subtitle of the low battery alert. "percentage" is the percentage of battery + remaining. "time" is the amount of time remaining before the phone runs out of battery [CHAR LIMIT=none]--> + <string name="battery_low_percent_format_hybrid"><xliff:g id="percentage">%s</xliff:g> remaining, about <xliff:g id="time">%s</xliff:g> left based on your usage</string> + + <!-- A message that appears when the battery remaining estimate is low in a dialog and insufficient + data was present to say it is customized to the user. This is appended to the subtitle of the + low battery alert. "percentage" is the percentage of battery remaining. "time" is the amount + of time remaining before the phone runs out of battery [CHAR LIMIT=none]--> + <string name="battery_low_percent_format_hybrid_short"><xliff:g id="percentage">%s</xliff:g> remaining, about <xliff:g id="time">%s</xliff:g> left</string> + <!-- Same as battery_low_percent_format, with a notice about battery saver if on. [CHAR LIMIT=none]--> <string name="battery_low_percent_format_saver_started"><xliff:g id="percentage">%s</xliff:g> remaining. Battery Saver is on.</string> diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index e7e70afa20ce..7403ddc441f6 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -40,6 +40,8 @@ import com.android.systemui.plugins.PluginDependencyProvider; import com.android.systemui.plugins.PluginManager; import com.android.systemui.plugins.PluginManagerImpl; import com.android.systemui.plugins.VolumeDialogController; +import com.android.systemui.power.EnhancedEstimates; +import com.android.systemui.power.EnhancedEstimatesImpl; import com.android.systemui.power.PowerNotificationWarnings; import com.android.systemui.power.PowerUI; import com.android.systemui.statusbar.phone.ConfigurationControllerImpl; @@ -310,6 +312,8 @@ public class Dependency extends SystemUI { mProviders.put(OverviewProxyService.class, () -> new OverviewProxyService(mContext)); + mProviders.put(EnhancedEstimates.class, () -> new EnhancedEstimatesImpl()); + // Put all dependencies above here so the factory can override them if it wants. SystemUIFactory.getInstance().injectDependencies(mProviders, mContext); } diff --git a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java new file mode 100644 index 000000000000..8f41a6036072 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java @@ -0,0 +1,8 @@ +package com.android.systemui.power; + +public interface EnhancedEstimates { + + boolean isHybridNotificationEnabled(); + + Estimate getEstimate(); +} diff --git a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java new file mode 100644 index 000000000000..d447542588c5 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java @@ -0,0 +1,16 @@ +package com.android.systemui.power; + +import android.util.Log; + +public class EnhancedEstimatesImpl implements EnhancedEstimates { + + @Override + public boolean isHybridNotificationEnabled() { + return false; + } + + @Override + public Estimate getEstimate() { + return null; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/power/Estimate.java b/packages/SystemUI/src/com/android/systemui/power/Estimate.java new file mode 100644 index 000000000000..12a8f0a435b4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/power/Estimate.java @@ -0,0 +1,11 @@ +package com.android.systemui.power; + +public class Estimate { + public final long estimateMillis; + public final boolean isBasedOnUsage; + + public Estimate(long estimateMillis, boolean isBasedOnUsage) { + this.estimateMillis = estimateMillis; + this.isBasedOnUsage = isBasedOnUsage; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java index c29b362bda13..736286f21bfe 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java @@ -17,40 +17,40 @@ package com.android.systemui.power; import android.app.Notification; -import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; -import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.DialogInterface.OnDismissListener; import android.content.Intent; import android.content.IntentFilter; +import android.icu.text.MeasureFormat; +import android.icu.text.MeasureFormat.FormatWidth; +import android.icu.util.Measure; +import android.icu.util.MeasureUnit; import android.media.AudioAttributes; -import android.net.Uri; import android.os.AsyncTask; import android.os.Handler; import android.os.Looper; import android.os.PowerManager; -import android.os.SystemClock; import android.os.UserHandle; -import android.provider.Settings; import android.support.annotation.VisibleForTesting; +import android.text.format.DateUtils; import android.util.Slog; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; -import com.android.internal.notification.SystemNotificationChannels; import com.android.settingslib.Utils; import com.android.systemui.R; import com.android.systemui.SystemUI; -import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.util.NotificationChannels; import java.io.PrintWriter; import java.text.NumberFormat; +import java.util.Locale; +import java.util.concurrent.TimeUnit; public class PowerNotificationWarnings implements PowerUI.WarningsUI { private static final String TAG = PowerUI.TAG + ".Notification"; @@ -96,8 +96,9 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { private long mScreenOffTime; private int mShowing; - private long mBucketDroppedNegativeTimeMs; + private long mWarningTriggerTimeMs; + private Estimate mEstimate; private boolean mWarning; private boolean mPlaySound; private boolean mInvalidCharger; @@ -130,14 +131,22 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { public void update(int batteryLevel, int bucket, long screenOffTime) { mBatteryLevel = batteryLevel; if (bucket >= 0) { - mBucketDroppedNegativeTimeMs = 0; + mWarningTriggerTimeMs = 0; } else if (bucket < mBucket) { - mBucketDroppedNegativeTimeMs = System.currentTimeMillis(); + mWarningTriggerTimeMs = System.currentTimeMillis(); } mBucket = bucket; mScreenOffTime = screenOffTime; } + @Override + public void updateEstimate(Estimate estimate) { + mEstimate = estimate; + if (estimate.estimateMillis <= PowerUI.THREE_HOURS_IN_MILLIS) { + mWarningTriggerTimeMs = System.currentTimeMillis(); + } + } + private void updateNotification() { if (DEBUG) Slog.d(TAG, "updateNotification mWarning=" + mWarning + " mPlaySound=" + mPlaySound + " mInvalidCharger=" + mInvalidCharger); @@ -171,25 +180,43 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { mNoMan.notifyAsUser(TAG_BATTERY, SystemMessage.NOTE_BAD_CHARGER, n, UserHandle.ALL); } - private void showWarningNotification() { - final int textRes = R.string.battery_low_percent_format; + protected void showWarningNotification() { final String percentage = NumberFormat.getPercentInstance().format((double) mBatteryLevel / 100.0); + // get standard notification copy + String title = mContext.getString(R.string.battery_low_title); + String contentText = mContext.getString(R.string.battery_low_percent_format, percentage); + + // override notification copy if hybrid notification enabled + if (mEstimate != null) { + title = mContext.getString(R.string.battery_low_title_hybrid); + contentText = mContext.getString( + mEstimate.isBasedOnUsage + ? R.string.battery_low_percent_format_hybrid + : R.string.battery_low_percent_format_hybrid_short, + percentage, + getTimeRemainingFormatted()); + } + final Notification.Builder nb = new Notification.Builder(mContext, NotificationChannels.BATTERY) .setSmallIcon(R.drawable.ic_power_low) // Bump the notification when the bucket dropped. - .setWhen(mBucketDroppedNegativeTimeMs) + .setWhen(mWarningTriggerTimeMs) .setShowWhen(false) - .setContentTitle(mContext.getString(R.string.battery_low_title)) - .setContentText(mContext.getString(textRes, percentage)) + .setContentTitle(title) + .setContentText(contentText) .setOnlyAlertOnce(true) .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_WARNING)) - .setVisibility(Notification.VISIBILITY_PUBLIC) - .setColor(Utils.getColorAttr(mContext, android.R.attr.colorError)); + .setVisibility(Notification.VISIBILITY_PUBLIC); if (hasBatterySettings()) { nb.setContentIntent(pendingBroadcast(ACTION_SHOW_BATTERY_SETTINGS)); } + // Make the notification red if the percentage goes below a certain amount or the time + // remaining estimate is disabled + if (mEstimate == null || mBucket < 0) { + nb.setColor(Utils.getColorAttr(mContext, android.R.attr.colorError)); + } nb.addAction(0, mContext.getString(R.string.battery_saver_start_action), pendingBroadcast(ACTION_START_SAVER)); @@ -201,6 +228,23 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { mNoMan.notifyAsUser(TAG_BATTERY, SystemMessage.NOTE_POWER_LOW, n, UserHandle.ALL); } + @VisibleForTesting + String getTimeRemainingFormatted() { + final Locale currentLocale = mContext.getResources().getConfiguration().getLocales().get(0); + MeasureFormat frmt = MeasureFormat.getInstance(currentLocale, FormatWidth.NARROW); + + final long remainder = mEstimate.estimateMillis % DateUtils.HOUR_IN_MILLIS; + final long hours = TimeUnit.MILLISECONDS.toHours( + mEstimate.estimateMillis - remainder); + // round down to the nearest 15 min for now to not appear overly precise + final long minutes = TimeUnit.MILLISECONDS.toMinutes( + remainder - (remainder % TimeUnit.MINUTES.toMillis(15))); + final Measure hoursMeasure = new Measure(hours, MeasureUnit.HOUR); + final Measure minutesMeasure = new Measure(minutes, MeasureUnit.MINUTE); + + return frmt.formatMeasures(hoursMeasure, minutesMeasure); + } + private PendingIntent pendingBroadcast(String action) { return PendingIntent.getBroadcastAsUser(mContext, 0, new Intent(action), 0, UserHandle.CURRENT); diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index a351c09f68b7..c5aab601283c 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -52,6 +52,7 @@ import com.android.systemui.statusbar.phone.StatusBar; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Arrays; +import java.util.concurrent.TimeUnit; public class PowerUI extends SystemUI { static final String TAG = "PowerUI"; @@ -59,6 +60,7 @@ public class PowerUI extends SystemUI { private static final long TEMPERATURE_INTERVAL = 30 * DateUtils.SECOND_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 + static final long THREE_HOURS_IN_MILLIS = DateUtils.HOUR_IN_MILLIS * 3; private final Handler mHandler = new Handler(); private final Receiver mReceiver = new Receiver(); @@ -68,9 +70,11 @@ public class PowerUI extends SystemUI { private WarningsUI mWarnings; private final Configuration mLastConfiguration = new Configuration(); private int mBatteryLevel = 100; + private long mTimeRemaining = Long.MAX_VALUE; private int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN; private int mPlugType = 0; private int mInvalidCharger = 0; + private EnhancedEstimates mEnhancedEstimates; private int mLowBatteryAlertCloseLevel; private final int[] mLowBatteryReminderLevels = new int[2]; @@ -83,8 +87,8 @@ public class PowerUI extends SystemUI { private long mNextLogTime; private IThermalService mThermalService; - // We create a method reference here so that we are guaranteed that we can remove a callback // by using the same instance (method references are not guaranteed to be the same object + // We create a method reference here so that we are guaranteed that we can remove a callback // each time they are created). private final Runnable mUpdateTempCallback = this::updateTemperatureWarning; @@ -94,6 +98,7 @@ public class PowerUI extends SystemUI { mContext.getSystemService(Context.HARDWARE_PROPERTIES_SERVICE); mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime(); mWarnings = Dependency.get(WarningsUI.class); + mEnhancedEstimates = Dependency.get(EnhancedEstimates.class); mLastConfiguration.setTo(mContext.getResources().getConfiguration()); ContentObserver obs = new ContentObserver(mHandler) { @@ -236,21 +241,9 @@ public class PowerUI extends SystemUI { return; } - boolean isPowerSaver = mPowerManager.isPowerSaveMode(); - if (!plugged - && !isPowerSaver - && (bucket < oldBucket || oldPlugged) - && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN - && bucket < 0) { - - // only play SFX when the dialog comes up or the bucket changes - final boolean playSound = bucket != oldBucket || oldPlugged; - mWarnings.showLowBatteryWarning(playSound); - } else if (isPowerSaver || plugged || (bucket > oldBucket && bucket > 0)) { - mWarnings.dismissLowBatteryWarning(); - } else { - mWarnings.updateLowBatteryWarning(); - } + // Show the correct version of low battery warning if needed + maybeShowBatteryWarning(plugged, oldPlugged, oldBucket, bucket); + } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { mScreenOffTime = SystemClock.elapsedRealtime(); } else if (Intent.ACTION_SCREEN_ON.equals(action)) { @@ -261,7 +254,65 @@ public class PowerUI extends SystemUI { Slog.w(TAG, "unknown intent: " + intent); } } - }; + } + + protected void maybeShowBatteryWarning(boolean plugged, boolean oldPlugged, int oldBucket, + int bucket) { + boolean isPowerSaver = mPowerManager.isPowerSaveMode(); + // only play SFX when the dialog comes up or the bucket changes + final boolean playSound = bucket != oldBucket || oldPlugged; + long oldTimeRemaining = mTimeRemaining; + if (mEnhancedEstimates.isHybridNotificationEnabled()) { + final Estimate estimate = mEnhancedEstimates.getEstimate(); + // Turbo is not always booted once SysUI is running so we have ot make sure we actually + // get data back + if (estimate != null) { + mTimeRemaining = estimate.estimateMillis; + mWarnings.updateEstimate(estimate); + } + } + + if (shouldShowLowBatteryWarning(plugged, oldPlugged, oldBucket, bucket, oldTimeRemaining, + mTimeRemaining, + isPowerSaver, mBatteryStatus)) { + mWarnings.showLowBatteryWarning(playSound); + } else if (shouldDismissLowBatteryWarning(plugged, oldBucket, bucket, mTimeRemaining, + isPowerSaver)) { + mWarnings.dismissLowBatteryWarning(); + } else { + mWarnings.updateLowBatteryWarning(); + } + } + + @VisibleForTesting + boolean shouldShowLowBatteryWarning(boolean plugged, boolean oldPlugged, int oldBucket, + int bucket, long oldTimeRemaining, long timeRemaining, + boolean isPowerSaver, int mBatteryStatus) { + return !plugged + && !isPowerSaver + && (((bucket < oldBucket || oldPlugged) && bucket < 0) + || (mEnhancedEstimates.isHybridNotificationEnabled() + && timeRemaining < THREE_HOURS_IN_MILLIS + && isHourLess(oldTimeRemaining, timeRemaining))) + && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN; + } + + private boolean isHourLess(long oldTimeRemaining, long timeRemaining) { + final long dif = oldTimeRemaining - timeRemaining; + return dif >= TimeUnit.HOURS.toMillis(1); + } + + @VisibleForTesting + boolean shouldDismissLowBatteryWarning(boolean plugged, int oldBucket, int bucket, + long timeRemaining, boolean isPowerSaver) { + final boolean hybridWouldDismiss = mEnhancedEstimates.isHybridNotificationEnabled() + && timeRemaining > THREE_HOURS_IN_MILLIS; + final boolean standardWouldDismiss = (bucket > oldBucket && bucket > 0); + return isPowerSaver + || plugged + || (standardWouldDismiss && (!mEnhancedEstimates.isHybridNotificationEnabled() + || hybridWouldDismiss)); + } private void initTemperatureWarning() { ContentResolver resolver = mContext.getContentResolver(); @@ -433,6 +484,7 @@ public class PowerUI extends SystemUI { public interface WarningsUI { void update(int batteryLevel, int bucket, long screenOffTime); + void updateEstimate(Estimate estimate); void dismissLowBatteryWarning(); void showLowBatteryWarning(boolean playSound); void dismissInvalidChargerWarning(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java index 7f07e0c70e8a..3e37cfe75e0f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java @@ -38,6 +38,7 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.systemui.SysuiTestCase; import com.android.systemui.util.NotificationChannels; +import java.util.concurrent.TimeUnit; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -46,6 +47,9 @@ import org.mockito.ArgumentCaptor; @SmallTest @RunWith(AndroidJUnit4.class) public class PowerNotificationWarningsTest extends SysuiTestCase { + + public static final String FORMATTED_45M = "0h 45m"; + public static final String FORMATTED_HOUR = "1h 0m"; private final NotificationManager mMockNotificationManager = mock(NotificationManager.class); private PowerNotificationWarnings mPowerNotificationWarnings; @@ -147,4 +151,22 @@ public class PowerNotificationWarningsTest extends SysuiTestCase { verify(mMockNotificationManager, times(1)).cancelAsUser(anyString(), eq(SystemMessage.NOTE_THERMAL_SHUTDOWN), any()); } + + @Test + public void testGetTimeRemainingFormatted_roundsDownTo15() { + mPowerNotificationWarnings.updateEstimate( + new Estimate(TimeUnit.MINUTES.toMillis(57), true)); + String time = mPowerNotificationWarnings.getTimeRemainingFormatted(); + + assertTrue("time:" + time + ", expected: " + FORMATTED_45M, time.equals(FORMATTED_45M)); + } + + @Test + public void testGetTimeRemainingFormatted_keepsMinutesWhenZero() { + mPowerNotificationWarnings.updateEstimate( + new Estimate(TimeUnit.MINUTES.toMillis(65), true)); + String time = mPowerNotificationWarnings.getTimeRemainingFormatted(); + + assertTrue("time:" + time + ", expected: " + FORMATTED_HOUR, time.equals(FORMATTED_HOUR)); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java index e4734a474b62..fdb7f8d005b6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java @@ -19,12 +19,15 @@ import static android.os.HardwarePropertiesManager.TEMPERATURE_CURRENT; import static android.os.HardwarePropertiesManager.TEMPERATURE_SHUTDOWN; import static android.provider.Settings.Global.SHOW_TEMPERATURE_WARNING; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; +import android.os.BatteryManager; import android.os.HardwarePropertiesManager; import android.provider.Settings; import android.testing.AndroidTestingRunner; @@ -37,6 +40,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.power.PowerUI.WarningsUI; import com.android.systemui.statusbar.phone.StatusBar; +import java.util.concurrent.TimeUnit; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -46,14 +50,23 @@ import org.junit.runner.RunWith; @SmallTest public class PowerUITest extends SysuiTestCase { + private static final boolean UNPLUGGED = false; + private static final boolean POWER_SAVER_OFF = false; + private static final int ABOVE_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 ABOVE_HYBRID_THRESHOLD = TimeUnit.HOURS.toMillis(4); private HardwarePropertiesManager mHardProps; private WarningsUI mMockWarnings; private PowerUI mPowerUI; + private EnhancedEstimates mEnhacedEstimates; @Before public void setup() { mMockWarnings = mDependency.injectMockDependency(WarningsUI.class); + mEnhacedEstimates = mDependency.injectMockDependency(EnhancedEstimates.class); mHardProps = mock(HardwarePropertiesManager.class); + mContext.putComponent(StatusBar.class, mock(StatusBar.class)); mContext.addMockSystemService(Context.HARDWARE_PROPERTIES_SERVICE, mHardProps); @@ -128,6 +141,180 @@ public class PowerUITest extends SysuiTestCase { verify(mMockWarnings).showHighTemperatureWarning(); } + @Test + public void testShouldShowLowBatteryWarning_showHybridOnly_returnsShow() { + when(mEnhacedEstimates.isHybridNotificationEnabled()).thenReturn(true); + mPowerUI.start(); + + // unplugged device that would not show the non-hybrid notification but would show the + // hybrid + boolean shouldShow = + mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, + ABOVE_WARNING_BUCKET, Long.MAX_VALUE, BELOW_HYBRID_THRESHOLD, + POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); + assertTrue(shouldShow); + } + + @Test + public void testShouldShowLowBatteryWarning_showHybrid_showStandard_returnsShow() { + when(mEnhacedEstimates.isHybridNotificationEnabled()).thenReturn(true); + mPowerUI.start(); + + // unplugged device that would show the non-hybrid notification and the hybrid + boolean shouldShow = + mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, + BELOW_WARNING_BUCKET, Long.MAX_VALUE, BELOW_HYBRID_THRESHOLD, + POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); + assertTrue(shouldShow); + } + + @Test + public void testShouldShowLowBatteryWarning_showStandardOnly_returnsShow() { + when(mEnhacedEstimates.isHybridNotificationEnabled()).thenReturn(true); + mPowerUI.start(); + + // unplugged device that would show the non-hybrid but not the hybrid + boolean shouldShow = + mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, + BELOW_WARNING_BUCKET, Long.MAX_VALUE, ABOVE_HYBRID_THRESHOLD, + POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); + assertTrue(shouldShow); + } + + @Test + public void testShouldShowLowBatteryWarning_deviceHighBattery_returnsNoShow() { + when(mEnhacedEstimates.isHybridNotificationEnabled()).thenReturn(true); + mPowerUI.start(); + + // unplugged device that would show the neither due to battery level being good + boolean shouldShow = + mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, + ABOVE_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, ABOVE_HYBRID_THRESHOLD, + POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); + assertFalse(shouldShow); + } + + @Test + public void testShouldShowLowBatteryWarning_devicePlugged_returnsNoShow() { + when(mEnhacedEstimates.isHybridNotificationEnabled()).thenReturn(true); + mPowerUI.start(); + + // plugged device that would show the neither due to being plugged + boolean shouldShow = + mPowerUI.shouldShowLowBatteryWarning(!UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, + BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, BELOW_HYBRID_THRESHOLD, + POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); + assertFalse(shouldShow); + } + + @Test + public void testShouldShowLowBatteryWarning_deviceBatteryStatusUnkown_returnsNoShow() { + when(mEnhacedEstimates.isHybridNotificationEnabled()).thenReturn(true); + mPowerUI.start(); + + // Unknown battery status device that would show the neither due + boolean shouldShow = + mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, + BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, BELOW_HYBRID_THRESHOLD, + !POWER_SAVER_OFF, BatteryManager.BATTERY_STATUS_UNKNOWN); + assertFalse(shouldShow); + } + + @Test + public void testShouldShowLowBatteryWarning_batterySaverEnabled_returnsNoShow() { + when(mEnhacedEstimates.isHybridNotificationEnabled()).thenReturn(true); + mPowerUI.start(); + + // BatterySaverEnabled device that would show the neither due to battery saver + boolean shouldShow = + mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET, + BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, BELOW_HYBRID_THRESHOLD, + !POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD); + assertFalse(shouldShow); + } + + @Test + public void testShouldDismissLowBatteryWarning_dismissWhenPowerSaverEnabled() { + mPowerUI.start(); + when(mEnhacedEstimates.isHybridNotificationEnabled()).thenReturn(true); + // device that gets power saver turned on should dismiss + boolean shouldDismiss = + mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET, + BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, !POWER_SAVER_OFF); + assertTrue(shouldDismiss); + } + + @Test + public void testShouldDismissLowBatteryWarning_dismissWhenPlugged() { + mPowerUI.start(); + when(mEnhacedEstimates.isHybridNotificationEnabled()).thenReturn(true); + + // device that gets plugged in should dismiss + boolean shouldDismiss = + mPowerUI.shouldDismissLowBatteryWarning(!UNPLUGGED, BELOW_WARNING_BUCKET, + BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, POWER_SAVER_OFF); + assertTrue(shouldDismiss); + } + + @Test + public void testShouldDismissLowBatteryWarning_dismissHybridSignal_showStandardSignal_shouldShow() { + mPowerUI.start(); + when(mEnhacedEstimates.isHybridNotificationEnabled()).thenReturn(true); + // would dismiss hybrid but not non-hybrid should not dismiss + boolean shouldDismiss = + mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET, + BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, POWER_SAVER_OFF); + assertFalse(shouldDismiss); + } + + @Test + public void testShouldDismissLowBatteryWarning_showHybridSignal_dismissStandardSignal_shouldShow() { + mPowerUI.start(); + when(mEnhacedEstimates.isHybridNotificationEnabled()).thenReturn(true); + + // would dismiss non-hybrid but not hybrid should not dismiss + boolean shouldDismiss = + mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET, + ABOVE_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD, POWER_SAVER_OFF); + assertFalse(shouldDismiss); + } + + @Test + public void testShouldDismissLowBatteryWarning_showBothSignal_shouldShow() { + mPowerUI.start(); + when(mEnhacedEstimates.isHybridNotificationEnabled()).thenReturn(true); + + // should not dismiss when both would not dismiss + boolean shouldDismiss = + mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET, + BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD, POWER_SAVER_OFF); + assertFalse(shouldDismiss); + } + + @Test + public void testShouldDismissLowBatteryWarning_dismissBothSignal_shouldDismiss() { + mPowerUI.start(); + when(mEnhacedEstimates.isHybridNotificationEnabled()).thenReturn(true); + + //should dismiss if both would dismiss + boolean shouldDismiss = + mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET, + ABOVE_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, POWER_SAVER_OFF); + assertTrue(shouldDismiss); + } + + @Test + public void testShouldDismissLowBatteryWarning_dismissStandardSignal_hybridDisabled_shouldDismiss() { + mPowerUI.start(); + when(mEnhacedEstimates.isHybridNotificationEnabled()).thenReturn(false); + + // would dismiss non-hybrid with hybrid disabled should dismiss + boolean shouldDismiss = + mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET, + ABOVE_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, POWER_SAVER_OFF); + assertTrue(shouldDismiss); + } + private void setCurrentTemp(float temp) { when(mHardProps.getDeviceTemperatures(DEVICE_TEMPERATURE_SKIN, TEMPERATURE_CURRENT)) .thenReturn(new float[] { temp }); |