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
This commit is contained in:
TreeHugger Robot
2021-09-09 15:40:14 +00:00
committed by Automerger Merge Worker
10 changed files with 82 additions and 86 deletions

View File

@@ -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 youve 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] -->

View File

@@ -139,6 +139,11 @@ public interface PowerUsageFeatureProvider {
*/
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.
*/

View File

@@ -166,6 +166,11 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider
return false;
}
@Override
public Intent getResumeChargeIntent() {
return null;
}
@Override
public Map<Long, Map<String, BatteryHistEntry>> getBatteryHistory(Context context) {
return null;

View File

@@ -20,6 +20,9 @@ import android.app.Dialog;
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.HighUsageTip;
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 @@ public class BatteryTipDialogFragment extends InstrumentedDialogFragment impleme
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 @@ public class BatteryTipDialogFragment extends InstrumentedDialogFragment impleme
.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 @@ public class BatteryTipDialogFragment extends InstrumentedDialogFragment impleme
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;
}
}

View File

@@ -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 @@ public class BatteryDefenderAction extends BatteryTipAction {
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));
}
}
}

View File

@@ -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 @@ public class BatteryDefenderDetector implements BatteryTipDetector {
@Override
public BatteryTip detect() {
final int state =
BatteryUtils.isBatteryDefenderOn(mBatteryInfo)
mBatteryInfo.isOverheated
? BatteryTip.StateType.NEW
: BatteryTip.StateType.INVISIBLE;
return new BatteryDefenderTip(state);

View File

@@ -29,7 +29,7 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
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) {

View File

@@ -155,4 +155,9 @@ public class PowerUsageFeatureProviderImplTest {
assertThat(mPowerFeatureProvider.isSmartBatterySupported()).isFalse();
}
@Test
public void testGetResumeChargeIntent_returnNull() {
assertThat(mPowerFeatureProvider.getResumeChargeIntent()).isNull();
}
}

View File

@@ -31,6 +31,7 @@ import androidx.appcompat.app.AlertDialog;
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 @@ public class BatteryTipDialogFragmentTest {
private RestrictAppTip mRestrictTwoAppsTip;
private UnrestrictAppTip mUnrestrictAppTip;
private SummaryTip mSummaryTip;
private BatteryDefenderTip mDefenderTip;
private AppInfo mAppInfo;
private ShadowPackageManager mPackageManager;
@@ -116,6 +118,7 @@ public class BatteryTipDialogFragmentTest {
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 @@ public class BatteryTipDialogFragmentTest {
+ "your phone will suggest actions you can take.\n\nYou can always turn"
+ " on Battery Saver if youre 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%"));
}
}

View File

@@ -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);
}
}