Implements the buttons layout for the extra defend

Bug: 235246949
Test: make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.fuelgauge.*
Test: make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.widget.CardPreferenceTest
Test: manual test
Change-Id: I1dc4ab31adf85c684a4c09bd6c9bcfb54b52dc3c
This commit is contained in:
Pajace Chen
2022-08-16 18:12:01 +08:00
committed by Wesley Wang
parent 662e5722b3
commit f3496399dd
13 changed files with 662 additions and 13 deletions

View File

@@ -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.
*/

View File

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

View File

@@ -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<List<BatteryTip>> {
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;
}

View File

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

View File

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

View File

@@ -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<Button> mPrimaryButton = Optional.empty();
private Optional<Button> mSecondaryButton = Optional.empty();
private Optional<View> mButtonsGroup = Optional.empty();
private boolean mPrimaryButtonVisible = false;
private boolean mSecondaryButtonVisible = false;
public CardPreference(Context context) {
this(context, null /* attrs */);
}
@@ -37,4 +55,94 @@ public class CardPreference extends Preference {
public CardPreference(Context context, AttributeSet attrs) {
super(context, attrs, R.attr.cardPreferenceStyle);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
initButtonsAndLayout(holder);
}
private void initButtonsAndLayout(PreferenceViewHolder holder) {
mPrimaryButton = Optional.ofNullable((Button) holder.findViewById(android.R.id.button1));
mSecondaryButton = Optional.ofNullable((Button) holder.findViewById(android.R.id.button2));
mButtonsGroup = Optional.ofNullable(holder.findViewById(R.id.card_preference_buttons));
setPrimaryButtonText(mPrimaryButtonText);
setPrimaryButtonClickListener(mPrimaryBtnClickListener);
setPrimaryButtonVisible(mPrimaryButtonVisible);
setSecondaryButtonText(mSecondaryButtonText);
setSecondaryButtonClickListener(mSecondaryBtnClickListener);
setSecondaryButtonVisible(mSecondaryButtonVisible);
}
/**
* Register a callback to be invoked when the primary button is clicked.
*
* @param l the callback that will run
*/
public void setPrimaryButtonClickListener(View.OnClickListener l) {
mPrimaryButton.ifPresent(button -> button.setOnClickListener(l));
mPrimaryBtnClickListener = l;
}
/**
* Register a callback to be invoked when the secondary button is clicked.
*
* @param l the callback that will run
*/
public void setSecondaryButtonClickListener(View.OnClickListener l) {
mSecondaryButton.ifPresent(button -> button.setOnClickListener(l));
mSecondaryBtnClickListener = l;
}
/**
* Sets the text to be displayed on primary button.
*
* @param text text to be displayed
*/
public void setPrimaryButtonText(String text) {
mPrimaryButton.ifPresent(button -> button.setText(text));
mPrimaryButtonText = text;
}
/**
* Sets the text to be displayed on secondary button.
*
* @param text text to be displayed
*/
public void setSecondaryButtonText(String text) {
mSecondaryButton.ifPresent(button -> button.setText(text));
mSecondaryButtonText = text;
}
/**
* Set the visible on the primary button.
*
* @param visible {@code true} for visible
*/
public void setPrimaryButtonVisible(boolean visible) {
mPrimaryButton.ifPresent(
button -> button.setVisibility(visible ? View.VISIBLE : View.GONE));
mPrimaryButtonVisible = visible;
updateButtonGroupsVisibility();
}
/**
* Set the visible on the secondary button.
*
* @param visible {@code true} for visible
*/
public void setSecondaryButtonVisible(boolean visible) {
mSecondaryButton.ifPresent(
button -> button.setVisibility(visible ? View.VISIBLE : View.GONE));
mSecondaryButtonVisible = visible;
updateButtonGroupsVisibility();
}
private void updateButtonGroupsVisibility() {
int visibility =
(mPrimaryButtonVisible || mSecondaryButtonVisible) ? View.VISIBLE : View.GONE;
mButtonsGroup.ifPresent(group -> group.setVisibility(visibility));
}
}