Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f4bc3533 authored by Wesley.CW Wang's avatar Wesley.CW Wang Committed by Wesley Wang
Browse files

Update battery percentage column to UsageProgressBarPref (1/2)

 - Change battery percentage column to new design
 - Remove debug info case
 Screenshots:
   https://screenshot.googleplex.com/9rvRfK3wBtpnarZ.png
   https://screenshot.googleplex.com/5iAjNXTptDechAm.png

Bug: 177407113
Test: make RunSettingsRoboTests -j40
Change-Id: I5d046be29a036910036e72edb677b69bc2c0a03f
parent 2e47875c
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -21,11 +21,10 @@
    android:title="@string/power_usage_summary_title"
    settings:keywords="@string/keywords_battery">

    <com.android.settingslib.widget.LayoutPreference
    <com.android.settingslib.widget.UsageProgressBarPreference
        android:key="battery_header"
        android:title="@string/summary_placeholder"
        android:selectable="false"
        android:layout="@layout/battery_header"
        settings:controller="com.android.settings.fuelgauge.BatteryHeaderPreferenceController" />

    <Preference
+16 −61
Original line number Diff line number Diff line
@@ -25,11 +25,6 @@ import android.icu.text.NumberFormat;
import android.os.BatteryManager;
import android.os.PowerManager;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceFragmentCompat;
@@ -39,14 +34,12 @@ import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.utils.AnnotationSpan;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.HelpUtils;
import com.android.settingslib.Utils;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.widget.LayoutPreference;
import com.android.settingslib.widget.UsageProgressBarPreference;

/**
 * Controller that update the battery header view
@@ -57,23 +50,18 @@ public class BatteryHeaderPreferenceController extends BasePreferenceController
    @VisibleForTesting
    static final String KEY_BATTERY_HEADER = "battery_header";
    private static final String ANNOTATION_URL = "url";
    private static final int BATTERY_MAX_LEVEL = 100;

    @VisibleForTesting
    BatteryStatusFeatureProvider mBatteryStatusFeatureProvider;
    @VisibleForTesting
    BatteryMeterView mBatteryMeterView;
    @VisibleForTesting
    TextView mBatteryPercentText;
    @VisibleForTesting
    TextView mSummary1;
    UsageProgressBarPreference mBatteryUsageProgressBarPref;

    private Activity mActivity;
    private PreferenceFragmentCompat mHost;
    private Lifecycle mLifecycle;
    private final PowerManager mPowerManager;

    private LayoutPreference mBatteryLayoutPref;

    public BatteryHeaderPreferenceController(Context context, String key) {
        super(context, key);
        mPowerManager = context.getSystemService(PowerManager.class);
@@ -96,16 +84,12 @@ public class BatteryHeaderPreferenceController extends BasePreferenceController
    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mBatteryLayoutPref = screen.findPreference(getPreferenceKey());
        mBatteryMeterView = mBatteryLayoutPref
                .findViewById(R.id.battery_header_icon);
        mBatteryPercentText = mBatteryLayoutPref.findViewById(R.id.battery_percent);
        mSummary1 = mBatteryLayoutPref.findViewById(R.id.summary1);
        mBatteryUsageProgressBarPref = screen.findPreference(getPreferenceKey());

        if (com.android.settings.Utils.isBatteryPresent(mContext)) {
            quickUpdateHeaderPreference();
        } else {
            showHelpMessage();
            //TODO(b/179237551): Make new progress bar widget support help message
        }
    }

@@ -116,8 +100,7 @@ public class BatteryHeaderPreferenceController extends BasePreferenceController

    @Override
    public void onStart() {
        EntityHeaderController.newInstance(mActivity, mHost,
                mBatteryLayoutPref.findViewById(R.id.battery_entity_header))
        EntityHeaderController.newInstance(mActivity, mHost, null /* header view */)
                .setRecyclerView(mHost.getListView(), mLifecycle)
                .styleActionBar(mActivity);
    }
@@ -133,21 +116,20 @@ public class BatteryHeaderPreferenceController extends BasePreferenceController
    }

    public void updateHeaderPreference(BatteryInfo info) {
        mBatteryPercentText.setText(formatBatteryPercentageText(info.batteryLevel));
        if (!mBatteryStatusFeatureProvider.triggerBatteryStatusUpdate(this, info)) {
            mSummary1.setText(generateLabel(info));
        }

        mBatteryMeterView.setBatteryLevel(info.batteryLevel);
        mBatteryMeterView.setCharging(!info.discharging);
        mBatteryMeterView.setPowerSave(mPowerManager.isPowerSaveMode());
        //TODO(b/179237746): Make progress bar widget support battery state icon

        mBatteryUsageProgressBarPref.setUsageSummary(
                formatBatteryPercentageText(info.batteryLevel));
        mBatteryUsageProgressBarPref.setTotalSummary(generateLabel(info));
        mBatteryUsageProgressBarPref.setPercent(info.batteryLevel, BATTERY_MAX_LEVEL);
    }

    /**
     * Callback which receives text for the summary line.
     */
    public void updateBatteryStatus(String label, BatteryInfo info) {
        mSummary1.setText(label != null ? label : generateLabel(info));
        mBatteryUsageProgressBarPref.setTotalSummary(label != null ? label : generateLabel(info));
    }

    public void quickUpdateHeaderPreference() {
@@ -157,37 +139,10 @@ public class BatteryHeaderPreferenceController extends BasePreferenceController
        final boolean discharging =
                batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) == 0;

        // Set battery level and charging status
        mBatteryMeterView.setBatteryLevel(batteryLevel);
        mBatteryMeterView.setCharging(!discharging);
        mBatteryMeterView.setPowerSave(mPowerManager.isPowerSaveMode());
        mBatteryPercentText.setText(formatBatteryPercentageText(batteryLevel));
    }
        //TODO(b/179237746): Make progress bar widget support battery state icon

    @VisibleForTesting
    void showHelpMessage() {
        final LinearLayout batteryInfoLayout =
                mBatteryLayoutPref.findViewById(R.id.battery_info_layout);
        // Remove battery meter icon
        mBatteryMeterView.setVisibility(View.GONE);
        // Update the width of battery info layout
        final ViewGroup.LayoutParams params = batteryInfoLayout.getLayoutParams();
        params.width = LinearLayout.LayoutParams.WRAP_CONTENT;
        batteryInfoLayout.setLayoutParams(params);
        mBatteryPercentText.setText(mContext.getText(R.string.unknown));
        // Add linkable text for learn more
        final Intent helpIntent = HelpUtils.getHelpIntent(mContext,
                mContext.getString(R.string.help_url_battery_missing),
                mContext.getClass().getName());
        final AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan
                .LinkInfo(mContext, ANNOTATION_URL, helpIntent);
        if (linkInfo.isActionable()) {
            mSummary1.setMovementMethod(LinkMovementMethod.getInstance());
            mSummary1.setText(AnnotationSpan
                    .linkify(mContext.getText(R.string.battery_missing_help_message), linkInfo));
        } else {
            mSummary1.setText(mContext.getText(R.string.battery_missing_message));
        }
        mBatteryUsageProgressBarPref.setUsageSummary(formatBatteryPercentageText(batteryLevel));
        mBatteryUsageProgressBarPref.setPercent(batteryLevel, BATTERY_MAX_LEVEL);
    }

    private CharSequence formatBatteryPercentageText(int batteryLevel) {
+1 −77
Original line number Diff line number Diff line
@@ -25,14 +25,9 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings.Global;
import android.text.format.Formatter;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.widget.TextView;

import androidx.annotation.VisibleForTesting;
import androidx.loader.app.LoaderManager;
import androidx.loader.app.LoaderManager.LoaderCallbacks;
import androidx.loader.content.Loader;

import com.android.settings.R;
@@ -44,7 +39,6 @@ import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.utils.PowerUtil;
import com.android.settingslib.widget.LayoutPreference;

import java.util.List;
@@ -54,18 +48,15 @@ import java.util.List;
 * since the last time it was unplugged.
 */
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class PowerUsageSummary extends PowerUsageBase implements OnLongClickListener,
public class PowerUsageSummary extends PowerUsageBase implements
        BatteryTipPreferenceController.BatteryTipListener {

    static final String TAG = "PowerUsageSummary";

    private static final String KEY_BATTERY_HEADER = "battery_header";

    @VisibleForTesting
    static final int BATTERY_INFO_LOADER = 1;
    @VisibleForTesting
    static final int BATTERY_TIP_LOADER = 2;
    public static final int DEBUG_INFO_LOADER = 3;

    @VisibleForTesting
    PowerUsageFeatureProvider mPowerFeatureProvider;
@@ -112,49 +103,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
                }
            };

    LoaderManager.LoaderCallbacks<List<BatteryInfo>> mBatteryInfoDebugLoaderCallbacks =
            new LoaderCallbacks<List<BatteryInfo>>() {
                @Override
                public Loader<List<BatteryInfo>> onCreateLoader(int i, Bundle bundle) {
                    return new DebugEstimatesLoader(getContext(), mStatsHelper);
                }

                @Override
                public void onLoadFinished(Loader<List<BatteryInfo>> loader,
                        List<BatteryInfo> batteryInfos) {
                    updateViews(batteryInfos);
                }

                @Override
                public void onLoaderReset(Loader<List<BatteryInfo>> loader) {
                }
            };

    protected void updateViews(List<BatteryInfo> batteryInfos) {
        final BatteryMeterView batteryView = mBatteryLayoutPref
                .findViewById(R.id.battery_header_icon);
        final TextView percentRemaining =
                mBatteryLayoutPref.findViewById(R.id.battery_percent);
        final TextView summary1 = mBatteryLayoutPref.findViewById(R.id.summary1);
        BatteryInfo oldInfo = batteryInfos.get(0);
        BatteryInfo newInfo = batteryInfos.get(1);
        percentRemaining.setText(Utils.formatPercentage(oldInfo.batteryLevel));

        // set the text to the old estimate (copied from battery info). Note that this
        // can sometimes say 0 time remaining because battery stats requires the phone
        // be unplugged for a period of time before being willing ot make an estimate.
        final String OldEstimateString = mPowerFeatureProvider.getOldEstimateDebugString(
                Formatter.formatShortElapsedTime(getContext(),
                        PowerUtil.convertUsToMs(oldInfo.remainingTimeUs)));
        final String NewEstimateString = mPowerFeatureProvider.getEnhancedEstimateDebugString(
                Formatter.formatShortElapsedTime(getContext(),
                        PowerUtil.convertUsToMs(newInfo.remainingTimeUs)));
        summary1.setText(OldEstimateString + "\n" + NewEstimateString);

        batteryView.setBatteryLevel(oldInfo.batteryLevel);
        batteryView.setCharging(!oldInfo.discharging);
    }

    private LoaderManager.LoaderCallbacks<List<BatteryTip>> mBatteryTipsCallbacks =
            new LoaderManager.LoaderCallbacks<List<BatteryTip>>() {

@@ -197,7 +145,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
        setAnimationAllowed(true);

        initFeatureProvider();
        mBatteryLayoutPref = (LayoutPreference) findPreference(KEY_BATTERY_HEADER);

        mBatteryUtils = BatteryUtils.getInstance(getContext());

@@ -274,17 +221,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
        mBatteryLayoutPref = layoutPreference;
    }

    @VisibleForTesting
    void showBothEstimates() {
        final Context context = getContext();
        if (context == null
                || !mPowerFeatureProvider.isEnhancedBatteryPredictionEnabled(context)) {
            return;
        }
        getLoaderManager().restartLoader(DEBUG_INFO_LOADER, Bundle.EMPTY,
                mBatteryInfoDebugLoaderCallbacks);
    }

    @VisibleForTesting
    void initFeatureProvider() {
        final Context context = getContext();
@@ -303,11 +239,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
        }
        getLoaderManager().restartLoader(BATTERY_INFO_LOADER, Bundle.EMPTY,
                mBatteryInfoLoaderCallbacks);
        if (mPowerFeatureProvider.isEstimateDebugEnabled()) {
            // Set long click action for summary to show debug info
            View header = mBatteryLayoutPref.findViewById(R.id.summary1);
            header.setOnLongClickListener(this);
        }
    }

    @VisibleForTesting
@@ -315,13 +246,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
        mNeedUpdateBatteryTip = icicle == null || mBatteryTipPreferenceController.needUpdate();
    }

    @Override
    public boolean onLongClick(View view) {
        showBothEstimates();
        view.setOnLongClickListener(null);
        return true;
    }

    @Override
    protected void restartBatteryStatsLoader(@BatteryUpdateType int refreshType) {
        super.restartBatteryStatsLoader(refreshType);
+21 −52
Original line number Diff line number Diff line
@@ -32,9 +32,10 @@ import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.icu.text.NumberFormat;
import android.os.BatteryManager;
import android.os.PowerManager;
import android.widget.TextView;
import android.text.TextUtils;

import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceFragmentCompat;
@@ -47,7 +48,7 @@ import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.widget.LayoutPreference;
import com.android.settingslib.widget.UsageProgressBarPreference;

import org.junit.After;
import org.junit.Before;
@@ -57,9 +58,7 @@ import org.mockito.Mock;
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})
@@ -67,6 +66,7 @@ public class BatteryHeaderPreferenceControllerTest {

    private static final String PREF_KEY = "battery_header";
    private static final int BATTERY_LEVEL = 60;
    private static final int BATTERY_MAX_LEVEL = 100;
    private static final String TIME_LEFT = "2h30min";
    private static final String BATTERY_STATUS = "Charging";

@@ -80,13 +80,11 @@ public class BatteryHeaderPreferenceControllerTest {
    private BatteryInfo mBatteryInfo;
    @Mock
    private EntityHeaderController mEntityHeaderController;
    @Mock
    private UsageProgressBarPreference mBatteryUsageProgressBarPref;
    private BatteryHeaderPreferenceController mController;
    private Context mContext;
    private PowerManager mPowerManager;
    private BatteryMeterView mBatteryMeterView;
    private TextView mBatteryPercentText;
    private TextView mSummary;
    private LayoutPreference mBatteryLayoutPref;
    private Intent mBatteryIntent;
    private LifecycleOwner mLifecycleOwner;
    private Lifecycle mLifecycle;
@@ -98,9 +96,6 @@ public class BatteryHeaderPreferenceControllerTest {
        mLifecycleOwner = () -> mLifecycle;
        mLifecycle = new Lifecycle(mLifecycleOwner);
        mContext = spy(RuntimeEnvironment.application);
        mBatteryMeterView = new BatteryMeterView(mContext);
        mBatteryPercentText = new TextView(mContext);
        mSummary = new TextView(mContext);
        ShadowEntityHeaderController.setUseMock(mEntityHeaderController);

        mBatteryIntent = new Intent();
@@ -109,8 +104,7 @@ public class BatteryHeaderPreferenceControllerTest {
        mBatteryIntent.putExtra(BatteryManager.EXTRA_PLUGGED, 1);
        doReturn(mBatteryIntent).when(mContext).registerReceiver(any(), any());

        mBatteryLayoutPref = new LayoutPreference(mContext, R.layout.battery_header);
        doReturn(mBatteryLayoutPref).when(mPreferenceScreen)
        doReturn(mBatteryUsageProgressBarPref).when(mPreferenceScreen)
            .findPreference(BatteryHeaderPreferenceController.KEY_BATTERY_HEADER);

        mBatteryInfo.batteryLevel = BATTERY_LEVEL;
@@ -122,9 +116,7 @@ public class BatteryHeaderPreferenceControllerTest {
        mController.setActivity(mActivity);
        mController.setFragment(mPreferenceFragment);
        mController.setLifecycle(mLifecycle);
        mController.mBatteryMeterView = mBatteryMeterView;
        mController.mBatteryPercentText = mBatteryPercentText;
        mController.mSummary1 = mSummary;
        mController.mBatteryUsageProgressBarPref = mBatteryUsageProgressBarPref;
    }

    @After
@@ -137,11 +129,8 @@ public class BatteryHeaderPreferenceControllerTest {
    public void displayPreference_displayBatteryLevel() {
        mController.displayPreference(mPreferenceScreen);

        assertThat(((BatteryMeterView) mBatteryLayoutPref.findViewById(
                R.id.battery_header_icon)).getBatteryLevel()).isEqualTo(BATTERY_LEVEL);
        assertThat(((TextView) mBatteryLayoutPref.findViewById(R.id.battery_percent))
                .getText().toString())
                .isEqualTo("60 %");
        verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
        verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
    }

    @Test
@@ -150,7 +139,7 @@ public class BatteryHeaderPreferenceControllerTest {

        mController.updateHeaderPreference(mBatteryInfo);

        assertThat(mSummary.getText()).isEqualTo(mBatteryInfo.remainingLabel);
        verify(mBatteryUsageProgressBarPref).setTotalSummary(mBatteryInfo.remainingLabel);
    }

    @Test
@@ -161,8 +150,9 @@ public class BatteryHeaderPreferenceControllerTest {

        mController.updateHeaderPreference(mBatteryInfo);

        assertThat(mBatteryMeterView.mDrawable.getBatteryLevel()).isEqualTo(BATTERY_LEVEL);
        assertThat(mBatteryMeterView.mDrawable.getCharging()).isEqualTo(false);
        verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
        verify(mBatteryUsageProgressBarPref).setTotalSummary(mBatteryInfo.remainingLabel);
        verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
    }

    @Test
@@ -172,7 +162,7 @@ public class BatteryHeaderPreferenceControllerTest {

        mController.updateHeaderPreference(mBatteryInfo);

        assertThat(mSummary.getText()).isEqualTo(BATTERY_STATUS);
        verify(mBatteryUsageProgressBarPref).setTotalSummary(BATTERY_STATUS);
    }

    @Test
@@ -181,7 +171,7 @@ public class BatteryHeaderPreferenceControllerTest {

        mController.updateHeaderPreference(mBatteryInfo);

        assertThat(mSummary.getText().toString().isEmpty()).isTrue();
        verify(mBatteryUsageProgressBarPref).setTotalSummary(null);
    }

    @Test
@@ -197,27 +187,10 @@ public class BatteryHeaderPreferenceControllerTest {

    @Test
    public void quickUpdateHeaderPreference_onlyUpdateBatteryLevelAndChargingState() {
        mSummary.setText(BATTERY_STATUS);

        mController.quickUpdateHeaderPreference();

        assertThat(mBatteryMeterView.getBatteryLevel()).isEqualTo(BATTERY_LEVEL);
        assertThat(mBatteryMeterView.getCharging()).isTrue();
        assertThat(mBatteryPercentText.getText().toString()).isEqualTo("60 %");
        assertThat(mSummary.getText()).isEqualTo(BATTERY_STATUS);
    }

    @Test
    public void quickUpdateHeaderPreference_showPowerSave() {
        boolean testValues[] = {false, true};

        ShadowPowerManager shadowPowerManager = Shadows.shadowOf(mPowerManager);
        for (boolean value : testValues) {
            shadowPowerManager.setIsPowerSaveMode(value);
            mController.quickUpdateHeaderPreference();

            assertThat(mBatteryMeterView.getPowerSave()).isEqualTo(value);
        }
        verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
        verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
    }

    @Test
@@ -226,12 +199,8 @@ public class BatteryHeaderPreferenceControllerTest {
                BasePreferenceController.AVAILABLE_UNSEARCHABLE);
    }

    @Test
    public void displayPreference_batteryNotPresent_shouldShowHelpMessage() {
        ShadowUtils.setIsBatteryPresent(false);

        mController.displayPreference(mPreferenceScreen);

        verify(mController).showHelpMessage();
    private CharSequence formatBatteryPercentageText() {
        return TextUtils.expandTemplate(mContext.getText(R.string.battery_header_title_alternate),
                NumberFormat.getIntegerInstance().format(BATTERY_LEVEL));
    }
}
+0 −93

File changed.

Preview size limit exceeded, changes collapsed.