diff --git a/res/layout/card_preference.xml b/res/layout/card_preference.xml
index be49ca3d41d..39523eb6cae 100644
--- a/res/layout/card_preference.xml
+++ b/res/layout/card_preference.xml
@@ -57,6 +57,30 @@
android:maxLines="10"
style="@style/PreferenceSummaryTextStyle"/>
+
+
+
+
diff --git a/res/values/config.xml b/res/values/config.xml
index bb792815b66..3aa5f0a633e 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -625,6 +625,9 @@
false
+
+ 12
+
false
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 455a2c39cc2..c889dbb3343 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6283,6 +6283,8 @@
Charging temporarily limited
To preserve your battery. Learn more.
+
+ %1$s
Resume charging
@@ -6339,6 +6341,8 @@
Remove
Cancel
+
+ Charge to full
Your apps are using a normal amount of battery. If apps use too much battery, your phone will suggest actions you can take.\n\nYou can always turn on Battery Saver if you\u2019re running low on battery.
diff --git a/res/values/styles.xml b/res/values/styles.xml
index f147ce98903..8dee0821fd4 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -969,4 +969,19 @@
- ?android:attr/textColorPrimary
- locale
+
+
+
+
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index 83d7a33287a..94a93b83be0 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -139,6 +139,11 @@ public interface PowerUsageFeatureProvider {
*/
boolean isAdaptiveChargingSupported();
+ /**
+ * Returns {@code true} if current defender mode is extra defend
+ */
+ boolean isExtraDefend();
+
/**
* Gets a intent for one time bypass charge limited to resume charging.
*/
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index 12626414e44..0adfc9d1537 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -160,6 +160,11 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider
return null;
}
+ @Override
+ public boolean isExtraDefend() {
+ return false;
+ }
+
@Override
public Map> getBatteryHistory(Context context) {
return null;
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
index 4b9858753da..ea493a38f6b 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
@@ -31,6 +31,7 @@ import com.android.settings.fuelgauge.batterytip.detectors.SmartBatteryDetector;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.LowBatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.SummaryTip;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.fuelgauge.EstimateKt;
import com.android.settingslib.utils.AsyncLoaderCompat;
@@ -66,13 +67,16 @@ public class BatteryTipLoader extends AsyncLoaderCompat> {
final BatteryTipPolicy policy = new BatteryTipPolicy(getContext());
final BatteryInfo batteryInfo = mBatteryUtils.getBatteryInfo(TAG);
final Context context = getContext();
+ final boolean extraDefend = FeatureFactory.getFactory(context)
+ .getPowerUsageFeatureProvider(context)
+ .isExtraDefend();
tips.add(new LowBatteryDetector(context, policy, batteryInfo).detect());
tips.add(new HighUsageDetector(context, policy, mBatteryUsageStats, batteryInfo).detect());
tips.add(new SmartBatteryDetector(
context, policy, batteryInfo, context.getContentResolver()).detect());
tips.add(new EarlyWarningDetector(policy, context).detect());
- tips.add(new BatteryDefenderDetector(batteryInfo).detect());
+ tips.add(new BatteryDefenderDetector(batteryInfo, extraDefend).detect());
Collections.sort(tips);
return tips;
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java
index 5befa330b0a..367b2b1f5a3 100644
--- a/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java
@@ -24,10 +24,12 @@ import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
* Detect whether the battery is overheated
*/
public class BatteryDefenderDetector implements BatteryTipDetector {
- private BatteryInfo mBatteryInfo;
+ private final BatteryInfo mBatteryInfo;
+ private final boolean mExtraDefend;
- public BatteryDefenderDetector(BatteryInfo batteryInfo) {
+ public BatteryDefenderDetector(BatteryInfo batteryInfo, boolean extraDefend) {
mBatteryInfo = batteryInfo;
+ mExtraDefend = extraDefend;
}
@Override
@@ -36,6 +38,6 @@ public class BatteryDefenderDetector implements BatteryTipDetector {
mBatteryInfo.isOverheated
? BatteryTip.StateType.NEW
: BatteryTip.StateType.INVISIBLE;
- return new BatteryDefenderTip(state);
+ return new BatteryDefenderTip(state, mExtraDefend);
}
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java
index a2890ad9b40..0a133bbe42e 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java
@@ -18,18 +18,36 @@ package com.android.settings.fuelgauge.batterytip.tips;
import android.app.settings.SettingsEnums;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
import android.os.Parcel;
+import android.util.Log;
+
+import androidx.preference.Preference;
import com.android.settings.R;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.CardPreference;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import java.text.NumberFormat;
+
/**
* Tip to show current battery is overheated
*/
public class BatteryDefenderTip extends BatteryTip {
+ private static final String TAG = "BatteryDefenderTip";
+ private boolean mExtraDefend = false;
+
public BatteryDefenderTip(@StateType int state) {
+ this(state, false);
+ }
+
+ public BatteryDefenderTip(@StateType int state, boolean extraDefend) {
super(TipType.BATTERY_DEFENDER, state, true /* showDialog */);
+ mExtraDefend = extraDefend;
}
private BatteryDefenderTip(Parcel in) {
@@ -43,6 +61,14 @@ public class BatteryDefenderTip extends BatteryTip {
@Override
public CharSequence getSummary(Context context) {
+ if (mExtraDefend) {
+ final int extraValue = context.getResources()
+ .getInteger(R.integer.config_battery_extra_tip_value);
+ final String extraPercentage = NumberFormat.getPercentInstance()
+ .format(extraValue * 0.01f);
+ return context.getString(
+ R.string.battery_tip_limited_temporarily_extra_summary, extraPercentage);
+ }
return context.getString(R.string.battery_tip_limited_temporarily_summary);
}
@@ -62,6 +88,55 @@ public class BatteryDefenderTip extends BatteryTip {
mState);
}
+ @Override
+ public void updatePreference(Preference preference) {
+ super.updatePreference(preference);
+ final Context context = preference.getContext();
+
+ CardPreference cardPreference = castToCardPreferenceSafely(preference);
+ if (cardPreference == null) {
+ Log.e(TAG, "cast Preference to CardPreference failed");
+ return;
+ }
+
+ cardPreference.setPrimaryButtonText(
+ context.getString(R.string.battery_tip_charge_to_full_button));
+ cardPreference.setPrimaryButtonClickListener(
+ unused -> {
+ resumeCharging(context);
+ preference.setVisible(false);
+ });
+ cardPreference.setPrimaryButtonVisible(isPluggedIn(context));
+
+ cardPreference.setSecondaryButtonText(context.getString(R.string.see_more));
+ cardPreference.setSecondaryButtonClickListener(unused -> cardPreference.performClick());
+ cardPreference.setSecondaryButtonVisible(true);
+ }
+
+ private CardPreference castToCardPreferenceSafely(Preference preference) {
+ return preference instanceof CardPreference ? (CardPreference) preference : null;
+ }
+
+ private void resumeCharging(Context context) {
+ final Intent intent =
+ FeatureFactory.getFactory(context)
+ .getPowerUsageFeatureProvider(context)
+ .getResumeChargeIntent();
+ if (intent != null) {
+ context.sendBroadcast(intent);
+ }
+
+ Log.i(TAG, "send resume charging broadcast intent=" + intent);
+ }
+
+ private boolean isPluggedIn(Context context) {
+ final Intent batteryIntent =
+ context.registerReceiver(
+ /* receiver= */ null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+ return batteryIntent != null
+ && batteryIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
+ }
+
public static final Creator CREATOR = new Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new BatteryDefenderTip(in);
diff --git a/src/com/android/settings/widget/CardPreference.java b/src/com/android/settings/widget/CardPreference.java
index c04155222a0..afccfac9489 100644
--- a/src/com/android/settings/widget/CardPreference.java
+++ b/src/com/android/settings/widget/CardPreference.java
@@ -18,18 +18,36 @@ package com.android.settings.widget;
import android.content.Context;
import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Button;
import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.google.android.material.card.MaterialCardView;
+import java.util.Optional;
+
/**
* Preference that wrapped by {@link MaterialCardView}, only support to set icon, title and summary
*/
public class CardPreference extends Preference {
+ private View.OnClickListener mPrimaryBtnClickListener = null;
+ private View.OnClickListener mSecondaryBtnClickListener = null;
+
+ private String mPrimaryButtonText = null;
+ private String mSecondaryButtonText = null;
+
+ private Optional