Update battery states text

 - Update progress bar bottom text when battery states changed(charging,
 discharging, power saver and low battery)

Bug: 183689347
Bug: 177407113
Test: make SettingsRoboTests
Change-Id: I0397eb1dea7fcb14357750f84d1d5b1a7dc7d19a
diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
index ff8ff58..a2cb9ae 100644
--- a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java
@@ -33,6 +33,7 @@
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.Utils;
@@ -60,6 +61,7 @@
     private Activity mActivity;
     private PreferenceFragmentCompat mHost;
     private Lifecycle mLifecycle;
+    private BatteryTip mBatteryTip;
     private final PowerManager mPowerManager;
 
     public BatteryHeaderPreferenceController(Context context, String key) {
@@ -109,8 +111,26 @@
         if (BatteryUtils.isBatteryDefenderOn(info)) {
             return null;
         } else if (info.remainingLabel == null) {
+            // Present status independently if no remaining time
             return info.statusLabel;
+        } else if (info.statusLabel != null && !info.discharging) {
+            // Charging state
+            return mContext.getString(
+                    R.string.battery_state_and_duration, info.statusLabel, info.remainingLabel);
+        } else if (mPowerManager.isPowerSaveMode()) {
+            // Power save mode is on
+            final String powerSaverOn = mContext.getString(
+                    R.string.battery_tip_early_heads_up_done_title);
+            return mContext.getString(
+                    R.string.battery_state_and_duration, powerSaverOn, info.remainingLabel);
+        } else if (mBatteryTip != null
+                && mBatteryTip.getType() == BatteryTip.TipType.LOW_BATTERY) {
+            // Low battery state
+            final String lowBattery = mContext.getString(R.string.low_battery_summary);
+            return mContext.getString(
+                    R.string.battery_state_and_duration, lowBattery, info.remainingLabel);
         } else {
+            // Discharging state
             return info.remainingLabel;
         }
     }
@@ -140,6 +160,17 @@
         mBatteryUsageProgressBarPref.setPercent(batteryLevel, BATTERY_MAX_LEVEL);
     }
 
+    /**
+     * Update summary when battery tips changed.
+     */
+    public void updateHeaderByBatteryTips(BatteryTip batteryTip, BatteryInfo batteryInfo) {
+        mBatteryTip = batteryTip;
+
+        if (mBatteryTip != null && batteryInfo != null) {
+            updateHeaderPreference(batteryInfo);
+        }
+    }
+
     private CharSequence formatBatteryPercentageText(int batteryLevel) {
         return TextUtils.expandTemplate(mContext.getText(R.string.battery_header_title_alternate),
                 NumberFormat.getIntegerInstance().format(batteryLevel));
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 9e61997..7dfca22 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -94,6 +94,8 @@
                 @Override
                 public void onLoadFinished(Loader<BatteryInfo> loader, BatteryInfo batteryInfo) {
                     mBatteryHeaderPreferenceController.updateHeaderPreference(batteryInfo);
+                    mBatteryHeaderPreferenceController.updateHeaderByBatteryTips(
+                            mBatteryTipPreferenceController.getCurrentBatteryTip(), batteryInfo);
                     mBatteryInfo = batteryInfo;
                 }
 
@@ -115,6 +117,8 @@
                 public void onLoadFinished(Loader<List<BatteryTip>> loader,
                         List<BatteryTip> data) {
                     mBatteryTipPreferenceController.updateBatteryTips(data);
+                    mBatteryHeaderPreferenceController.updateHeaderByBatteryTips(
+                            mBatteryTipPreferenceController.getCurrentBatteryTip(), mBatteryInfo);
                 }
 
                 @Override
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
index 00b1e87..c6afefe 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.fuelgauge.batterytip;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.os.Bundle;
 
@@ -163,6 +164,19 @@
     }
 
     /**
+     * @return current battery tips, null if unavailable.
+     */
+    @Nullable
+    public BatteryTip getCurrentBatteryTip() {
+        if (mBatteryTips == null) {
+            return null;
+        }
+
+        return mBatteryTips.stream().anyMatch(BatteryTip::isVisible)
+                ? mBatteryTips.stream().filter(BatteryTip::isVisible).findFirst().get() : null;
+    }
+
+    /**
      * Listener to give the control back to target fragment
      */
     public interface BatteryTipListener {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
index ad10fa8..038798a 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
@@ -27,6 +27,7 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 import android.app.Activity;
@@ -44,6 +45,9 @@
 
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
+import com.android.settings.fuelgauge.batterytip.tips.LowBatteryTip;
+import com.android.settings.fuelgauge.batterytip.tips.SmartBatteryTip;
 import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
 import com.android.settings.testutils.shadow.ShadowUtils;
 import com.android.settings.widget.EntityHeaderController;
@@ -58,7 +62,9 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
 import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowPowerManager;
 
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = {ShadowEntityHeaderController.class, ShadowUtils.class})
@@ -84,7 +90,7 @@
     private UsageProgressBarPreference mBatteryUsageProgressBarPref;
     private BatteryHeaderPreferenceController mController;
     private Context mContext;
-    private PowerManager mPowerManager;
+    private ShadowPowerManager mShadowPowerManager;
     private Intent mBatteryIntent;
     private LifecycleOwner mLifecycleOwner;
     private Lifecycle mLifecycle;
@@ -109,7 +115,7 @@
 
         mBatteryInfo.batteryLevel = BATTERY_LEVEL;
 
-        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        mShadowPowerManager = Shadows.shadowOf(mContext.getSystemService(PowerManager.class));
 
         mController = spy(new BatteryHeaderPreferenceController(mContext, PREF_KEY));
         mLifecycle.addObserver(mController);
@@ -144,9 +150,7 @@
 
     @Test
     public void updatePreference_updateBatteryInfo() {
-        mBatteryInfo.remainingLabel = TIME_LEFT;
-        mBatteryInfo.batteryLevel = BATTERY_LEVEL;
-        mBatteryInfo.discharging = true;
+        setChargingState(/* isDischarging */ true);
 
         mController.updateHeaderPreference(mBatteryInfo);
 
@@ -166,6 +170,68 @@
     }
 
     @Test
+    public void updatePreference_charging_showFullText() {
+        setChargingState(/* isDischarging */ false);
+
+        mController.updateHeaderPreference(mBatteryInfo);
+
+        final String expectedResult = BATTERY_STATUS + " • " + TIME_LEFT;
+        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedResult);
+    }
+
+    @Test
+    public void updatePreference_powerSaverOn_showPowerSaverOn() {
+        setChargingState(/* isDischarging */ true);
+        mShadowPowerManager.setIsPowerSaveMode(true);
+
+        mController.updateHeaderPreference(mBatteryInfo);
+
+        final String expectedResult = "Battery Saver is on • " + TIME_LEFT;
+        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedResult);
+    }
+
+    @Test
+    public void updateHeaderByBatteryTips_lowBatteryTip_showLowBattery() {
+        setChargingState(/* isDischarging */ true);
+        BatteryTip lowBatteryTip = new LowBatteryTip(
+                BatteryTip.StateType.NEW, /* powerSaveModeOn */false);
+
+        mController.updateHeaderByBatteryTips(lowBatteryTip, mBatteryInfo);
+
+        final String expectedResult = "Low battery • " + TIME_LEFT;
+        verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedResult);
+    }
+
+    @Test
+    public void updateHeaderByBatteryTips_notLowBatteryTip_showRemainingLabel() {
+        setChargingState(/* isDischarging */ true);
+        BatteryTip lowBatteryTip = new SmartBatteryTip(BatteryTip.StateType.NEW);
+
+        mController.updateHeaderByBatteryTips(lowBatteryTip, mBatteryInfo);
+
+        verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
+    }
+
+    @Test
+    public void updateHeaderByBatteryTips_noTip_noAction() {
+        setChargingState(/* isDischarging */ true);
+
+        mController.updateHeaderByBatteryTips(null, mBatteryInfo);
+
+        verifyZeroInteractions(mBatteryUsageProgressBarPref);
+    }
+
+    @Test
+    public void updateHeaderByBatteryTips_noBatteryInfo_noAction() {
+        BatteryTip lowBatteryTip = new LowBatteryTip(
+                BatteryTip.StateType.NEW, /* powerSaveModeOn */false);
+
+        mController.updateHeaderByBatteryTips(lowBatteryTip, null);
+
+        verifyZeroInteractions(mBatteryUsageProgressBarPref);
+    }
+
+    @Test
     public void updatePreference_isOverheat_showEmptyText() {
         mBatteryInfo.isOverheated = true;
 
@@ -203,4 +269,10 @@
         return TextUtils.expandTemplate(mContext.getText(R.string.battery_header_title_alternate),
                 NumberFormat.getIntegerInstance().format(BATTERY_LEVEL));
     }
+
+    private void setChargingState(boolean isDischarging) {
+        mBatteryInfo.remainingLabel = TIME_LEFT;
+        mBatteryInfo.statusLabel = BATTERY_STATUS;
+        mBatteryInfo.discharging = isDischarging;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
index e919288..dbde3a7 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
@@ -128,6 +128,25 @@
     }
 
     @Test
+    public void testGetCurrentBatteryTip_noTips_isNull() {
+        assertThat(mBatteryTipPreferenceController.getCurrentBatteryTip()).isNull();
+    }
+
+    @Test
+    public void testGetCurrentBatteryTip_tipsInvisible_isNull() {
+        mBatteryTipPreferenceController.updateBatteryTips(mNewBatteryTips);
+        assertThat(mBatteryTipPreferenceController.getCurrentBatteryTip()).isNull();
+    }
+
+    @Test
+    public void testGetCurrentBatteryTip_tipsVisible_returnTips() {
+        mBatteryTipPreferenceController.updateBatteryTips(mOldBatteryTips);
+
+        assertThat(mBatteryTipPreferenceController.getCurrentBatteryTip().getType()).isEqualTo(
+                BatteryTip.TipType.SUMMARY);
+    }
+
+    @Test
     public void testSaveAndRestore() {
         mBatteryTipPreferenceController.updateBatteryTips(mOldBatteryTips);
         final Bundle bundle = new Bundle();