Merge "Enhance battery settings limit charge tip" into sc-qpr1-dev am: daaf1728b4

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/15747143

Change-Id: If2c47f007a67865ad9aaf8040eddc638f46f7964
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 25eab7f..2480adb 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6198,6 +6198,12 @@
     <string name="battery_tip_limited_temporarily_title">Charging temporarily limited</string>
     <!-- Summary for the battery limited temporarily tip [CHAR LIMIT=NONE] -->
     <string name="battery_tip_limited_temporarily_summary">To preserve your battery. Learn more.</string>
+    <!-- Text of battery limited temporarily tip resume charge button. [CHAR LIMIT=NONE] -->
+    <string name="battery_tip_limited_temporarily_dialog_resume_charge">Resume charging</string>
+    <!-- Message of battery limited temporarily tip. [CHAR LIMIT=NONE] -->
+    <string name="battery_tip_limited_temporarily_dialog_msg" product="default">In certain conditions, like high temperatures and long charging periods, charging may be limited to <xliff:g id="percent" example="50%">%1$s</xliff:g> to help preserve battery health.\n\nWhen those conditions end, your phone will automatically charge normally.</string>
+    <!-- Message of battery limited temporarily tip. [CHAR LIMIT=NONE] -->
+    <string name="battery_tip_limited_temporarily_dialog_msg" product="tablet">In certain conditions, like high temperatures and long charging periods, charging may be limited to <xliff:g id="percent" example="50%">%1$s</xliff:g> to help preserve battery health.\n\nWhen those conditions end, your tablet will automatically charge normally.</string>
     <!-- Message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
     <string name="battery_tip_dialog_message" product="default">Because you’ve used your phone more than usual, your battery may run out sooner than it normally would.\n\nApps using most battery:</string>
     <!-- Message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index d5fd6ee..559c72b 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -140,6 +140,11 @@
     boolean isChartGraphSlotsEnabled(Context context);
 
     /**
+     * Gets a intent for one time bypass charge limited to resume charging.
+     */
+    Intent getResumeChargeIntent();
+
+    /**
      * Returns battery history data with corresponding timestamp key.
      */
     Map<Long, Map<String, BatteryHistEntry>> getBatteryHistory(Context context);
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index c3ca9ee..1380e2e 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -167,6 +167,11 @@
     }
 
     @Override
+    public Intent getResumeChargeIntent() {
+        return null;
+    }
+
+    @Override
     public Map<Long, Map<String, BatteryHistEntry>> getBatteryHistory(Context context) {
         return null;
     }
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java
index 58038cd..e9e5d68 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java
@@ -20,6 +20,9 @@
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 
@@ -40,6 +43,7 @@
 import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
 import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
 
+import java.text.NumberFormat;
 import java.util.List;
 
 /**
@@ -50,6 +54,7 @@
 
     private static final String ARG_BATTERY_TIP = "battery_tip";
     private static final String ARG_METRICS_KEY = "metrics_key";
+    private static final double CHARGE_LIMIT_LEVEL = 0.8f;
 
     @VisibleForTesting
     BatteryTip mBatteryTip;
@@ -138,6 +143,28 @@
                         .setPositiveButton(R.string.battery_tip_unrestrict_app_dialog_ok, this)
                         .setNegativeButton(R.string.battery_tip_unrestrict_app_dialog_cancel, null)
                         .create();
+            case BatteryTip.TipType.BATTERY_DEFENDER:
+                mMetricsFeatureProvider.action(context,
+                        SettingsEnums.ACTION_TIP_BATTERY_DEFENDER, mMetricsKey);
+                final String percentage =
+                        NumberFormat.getPercentInstance().format(CHARGE_LIMIT_LEVEL);
+                final String message = context.getString(
+                        R.string.battery_tip_limited_temporarily_dialog_msg, percentage);
+                final boolean isPluggedIn = isPluggedIn();
+                final AlertDialog.Builder dialogBuilder =
+                        new AlertDialog.Builder(context)
+                                .setTitle(R.string.battery_tip_limited_temporarily_title)
+                                .setMessage(message);
+                if (isPluggedIn) {
+                    dialogBuilder
+                            .setPositiveButton(
+                                    R.string.battery_tip_limited_temporarily_dialog_resume_charge,
+                                    this)
+                            .setNegativeButton(R.string.okay, null);
+                } else {
+                    dialogBuilder.setPositiveButton(R.string.okay, null);
+                }
+                return dialogBuilder.create();
             default:
                 throw new IllegalArgumentException("unknown type " + mBatteryTip.getType());
         }
@@ -163,4 +190,11 @@
         lsn.onBatteryTipHandled(mBatteryTip);
     }
 
+    private boolean isPluggedIn() {
+        final Intent batteryIntent = getContext().registerReceiver(null /* receiver */,
+                new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+        return batteryIntent != null && batteryIntent.getIntExtra(
+                BatteryManager.EXTRA_PLUGGED, 0) != 0;
+    }
+
 }
diff --git a/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderAction.java b/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderAction.java
index 24cddcd..af16952 100644
--- a/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderAction.java
+++ b/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderAction.java
@@ -16,12 +16,11 @@
 
 package com.android.settings.fuelgauge.batterytip.actions;
 
-import android.app.settings.SettingsEnums;
 import android.content.Intent;
 
-import com.android.settings.R;
 import com.android.settings.SettingsActivity;
-import com.android.settingslib.HelpUtils;
+import com.android.settings.overlay.FeatureFactory;
+import android.os.AsyncTask;
 
 /**
  * Action to open the Support Center article
@@ -34,19 +33,13 @@
         mSettingsActivity = settingsActivity;
     }
 
-    /**
-     * Handle the action when user clicks positive button
-     */
     @Override
     public void handlePositiveAction(int metricsKey) {
-        mMetricsFeatureProvider.action(mContext,
-                SettingsEnums.ACTION_TIP_BATTERY_DEFENDER, metricsKey);
-        final Intent intent = HelpUtils.getHelpIntent(
-                mContext,
-                mContext.getString(R.string.help_url_battery_defender),
-                getClass().getName());
+        final Intent intent = FeatureFactory.getFactory(mContext)
+                .getPowerUsageFeatureProvider(mContext).getResumeChargeIntent();
         if (intent != null) {
-            mSettingsActivity.startActivityForResult(intent, 0);
+            // Post intent to background thread to avoid UI flaky
+            AsyncTask.execute(() -> mContext.sendBroadcast(intent));
         }
     }
 }
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java
index dc33026..5befa33 100644
--- a/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java
@@ -17,7 +17,6 @@
 package com.android.settings.fuelgauge.batterytip.detectors;
 
 import com.android.settings.fuelgauge.BatteryInfo;
-import com.android.settings.fuelgauge.BatteryUtils;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryDefenderTip;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
 
@@ -34,7 +33,7 @@
     @Override
     public BatteryTip detect() {
         final int state =
-                BatteryUtils.isBatteryDefenderOn(mBatteryInfo)
+                mBatteryInfo.isOverheated
                     ? BatteryTip.StateType.NEW
                     : BatteryTip.StateType.INVISIBLE;
         return new BatteryDefenderTip(state);
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java
index 242be24..a2890ad 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java
@@ -29,7 +29,7 @@
 public class BatteryDefenderTip extends BatteryTip {
 
     public BatteryDefenderTip(@StateType int state) {
-        super(TipType.BATTERY_DEFENDER, state, false /* showDialog */);
+        super(TipType.BATTERY_DEFENDER, state, true /* showDialog */);
     }
 
     private BatteryDefenderTip(Parcel in) {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
index e8a9c5c..c0b566a 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
@@ -155,4 +155,9 @@
 
         assertThat(mPowerFeatureProvider.isSmartBatterySupported()).isFalse();
     }
+
+    @Test
+    public void testGetResumeChargeIntent_returnNull() {
+        assertThat(mPowerFeatureProvider.getResumeChargeIntent()).isNull();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java
index 331fb34..99fbaf3 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java
@@ -31,6 +31,7 @@
 import androidx.fragment.app.FragmentActivity;
 
 import com.android.settings.R;
+import com.android.settings.fuelgauge.batterytip.tips.BatteryDefenderTip;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
 import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip;
 import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
@@ -74,6 +75,7 @@
     private RestrictAppTip mRestrictTwoAppsTip;
     private UnrestrictAppTip mUnrestrictAppTip;
     private SummaryTip mSummaryTip;
+    private BatteryDefenderTip mDefenderTip;
     private AppInfo mAppInfo;
     private ShadowPackageManager mPackageManager;
 
@@ -116,6 +118,7 @@
         mUnrestrictAppTip = new UnrestrictAppTip(BatteryTip.StateType.NEW, mAppInfo);
         mSummaryTip = spy(new SummaryTip(BatteryTip.StateType.NEW,
                 EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN));
+        mDefenderTip = new BatteryDefenderTip(BatteryTip.StateType.NEW);
     }
 
     @After
@@ -243,4 +246,20 @@
                         + "your phone will suggest actions you can take.\n\nYou can always turn"
                         + " on Battery Saver if you’re running low on battery.");
     }
+
+    @Test
+    public void testOnCreateDialog_defenderTip_fireDialog() {
+        mDialogFragment = BatteryTipDialogFragment.newInstance(mDefenderTip, METRICS_KEY);
+
+        FragmentController.setupFragment(mDialogFragment, FragmentActivity.class,
+                0 /* containerViewId */, null /* bundle */);
+
+        final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+        ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
+
+        assertThat(shadowDialog.getTitle()).isEqualTo(
+                mContext.getString(R.string.battery_tip_limited_temporarily_title));
+        assertThat(shadowDialog.getMessage()).isEqualTo(
+                mContext.getString(R.string.battery_tip_limited_temporarily_dialog_msg, "80%"));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderActionTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderActionTest.java
deleted file mode 100644
index ad5dc54..0000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderActionTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.settings.fuelgauge.batterytip.actions;
-
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-
-import com.android.settings.R;
-import com.android.settings.SettingsActivity;
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public final class BatteryDefenderActionTest {
-
-    private Context mContext;
-    private FakeFeatureFactory mFeatureFactory;
-    private BatteryDefenderAction mBatteryDefenderAction;
-    private MetricsFeatureProvider mMetricsFeatureProvider;
-
-    @Mock private SettingsActivity mSettingsActivity;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mFeatureFactory = FakeFeatureFactory.setupForTest();
-        mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
-        mContext = spy(RuntimeEnvironment.application);
-        doReturn(mContext).when(mSettingsActivity).getApplicationContext();
-        mBatteryDefenderAction = new BatteryDefenderAction(mSettingsActivity);
-    }
-
-    @Test
-    public void testHandlePositiveAction_logMetric() {
-        final int metricKey = 10;
-        mBatteryDefenderAction.handlePositiveAction(metricKey);
-
-        verify(mMetricsFeatureProvider).action(mContext,
-                SettingsEnums.ACTION_TIP_BATTERY_DEFENDER, metricKey);
-    }
-}