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

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

Make app usage page support legacy version

 - Add a flag to divide legacy and new design
 - Add new layout for tristate design

Bug: 178197718
Test: make SettingsRoboTests
Change-Id: I61f694cad8ac9cea8195191feacbe80bac2df62e
parent 3bcd6bad
Loading
Loading
Loading
Loading
+66 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  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.
  -->

<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:settings="http://schemas.android.com/apk/res-auto">

    <com.android.settingslib.widget.LayoutPreference
        android:key="header_view"
        android:layout="@layout/settings_entity_header"
        android:selectable="false"
        android:order="-10000"
        settings:allowDividerBelow="true"/>

    <com.android.settingslib.widget.ActionButtonsPreference
        android:key="action_buttons"
        android:order="-9999"/>

    <PreferenceCategory
        android:title="@string/battery_detail_manage_title"
        settings:allowDividerAbove="true">

        <com.android.settingslib.RestrictedPreference
            android:key="background_activity"
            android:title="@string/background_activity_title"
            android:selectable="true"
            settings:userRestriction="no_control_apps"/>

        <Preference
            android:key="battery_optimization"
            android:title="@string/high_power_apps"
            android:summary="@string/high_power_off"
            android:selectable="true"/>

    </PreferenceCategory>

    <PreferenceCategory
        android:title="@string/battery_detail_info_title">

        <Preference
            android:key="app_usage_foreground"
            android:title="@string/battery_detail_foreground"
            android:selectable="false"/>

        <Preference
            android:key="app_usage_background"
            android:title="@string/battery_detail_background"
            android:selectable="false"/>

    </PreferenceCategory>

</PreferenceScreen>
 No newline at end of file
+89 −42
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ import com.android.settings.applications.appinfo.ButtonActionDialogFragment;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
@@ -61,7 +63,7 @@ import java.util.List;
 */
public class AdvancedPowerUsageDetail extends DashboardFragment implements
        ButtonActionDialogFragment.AppButtonsDialogListener,
        RadioButtonPreference.OnClickListener {
        BatteryTipPreferenceController.BatteryTipListener, RadioButtonPreference.OnClickListener {

    public static final String TAG = "AdvancedPowerDetail";
    public static final String EXTRA_UID = "extra_uid";
@@ -73,6 +75,8 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
    public static final String EXTRA_POWER_USAGE_PERCENT = "extra_power_usage_percent";
    public static final String EXTRA_POWER_USAGE_AMOUNT = "extra_power_usage_amount";

    private static final String KEY_PREF_FOREGROUND = "app_usage_foreground";
    private static final String KEY_PREF_BACKGROUND = "app_usage_background";
    private static final String KEY_PREF_HEADER = "header_view";
    private static final String KEY_PREF_UNRESTRICTED = "unrestricted_pref";
    private static final String KEY_PREF_OPTIMIZED = "optimized_pref";
@@ -92,7 +96,10 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
    BatteryUtils mBatteryUtils;
    @VisibleForTesting
    BatteryOptimizeUtils mBatteryOptimizeUtils;

    @VisibleForTesting
    Preference mForegroundPreference;
    @VisibleForTesting
    Preference mBackgroundPreference;
    @VisibleForTesting
    Preference mFooterPreference;
    @VisibleForTesting
@@ -101,12 +108,11 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
    RadioButtonPreference mOptimizePreference;
    @VisibleForTesting
    RadioButtonPreference mUnrestrictedPreference;
    private AppButtonsPreferenceController mAppButtonsPreferenceController;
    private UnrestrictedPreferenceController mUnrestrictedPreferenceController;
    private OptimizedPreferenceController mOptimizedPreferenceController;
    private RestrictedPreferenceController mRestrictedPreferenceController;
    @VisibleForTesting
    boolean enableTriState = true;

    private String mPackageName;
    private AppButtonsPreferenceController mAppButtonsPreferenceController;
    private BackgroundActivityPreferenceController mBackgroundActivityPreferenceController;

    // A wrapper class to carry LaunchBatteryDetailPage required arguments.
    private static final class LaunchBatteryDetailPageArgs {
@@ -227,22 +233,17 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        mPackageName = getArguments().getString(EXTRA_PACKAGE_NAME);
        mFooterPreference = findPreference(KEY_FOOTER_PREFERENCE);
        mHeaderPreference = (LayoutPreference) findPreference(KEY_PREF_HEADER);

        mUnrestrictedPreference  = findPreference(KEY_PREF_UNRESTRICTED);
        mOptimizePreference  = findPreference(KEY_PREF_OPTIMIZED);
        mRestrictedPreference  = findPreference(KEY_PREF_RESTRICTED);
        mUnrestrictedPreference.setOnClickListener(this);
        mOptimizePreference.setOnClickListener(this);
        mRestrictedPreference.setOnClickListener(this);

        mBatteryOptimizeUtils = new BatteryOptimizeUtils(
                getContext(), getArguments().getInt(EXTRA_UID), mPackageName);
        final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
        if (enableTriState) {
            onCreateForTriState(packageName);
        } else {
            mForegroundPreference = findPreference(KEY_PREF_FOREGROUND);
            mBackgroundPreference = findPreference(KEY_PREF_BACKGROUND);
        }
        mHeaderPreference = findPreference(KEY_PREF_HEADER);

        if (mPackageName != null) {
            mAppEntry = mState.getEntry(mPackageName, UserHandle.myUserId());
        if (packageName != null) {
            mAppEntry = mState.getEntry(packageName, UserHandle.myUserId());
        }
    }

@@ -251,7 +252,11 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
        super.onResume();

        initHeader();
        initPreference();
        if (enableTriState) {
            initPreferenceForTriState(getContext());
        } else {
            initPreference(getContext());
        }
    }

    @VisibleForTesting
@@ -281,17 +286,39 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
            controller.setIsInstantApp(AppUtils.isInstant(mAppEntry.info));
        }

        if (enableTriState) {
            final long foregroundTimeMs = bundle.getLong(EXTRA_FOREGROUND_TIME);
            final long backgroundTimeMs = bundle.getLong(EXTRA_BACKGROUND_TIME);
            //TODO(b/178197718) Update layout to support multiple lines
            controller.setSummary(getAppActiveTime(foregroundTimeMs, backgroundTimeMs));
        }

        controller.done(context, true /* rebindActions */);
    }

    @VisibleForTesting
    void initPreference() {
        final Context context = getContext();
    void initPreference(Context context) {
        final Bundle bundle = getArguments();
        final long foregroundTimeMs = bundle.getLong(EXTRA_FOREGROUND_TIME);
        final long backgroundTimeMs = bundle.getLong(EXTRA_BACKGROUND_TIME);
        mForegroundPreference.setSummary(
                TextUtils.expandTemplate(getText(R.string.battery_used_for),
                        StringUtil.formatElapsedTime(
                                context,
                                foregroundTimeMs,
                                /* withSeconds */ false,
                                /* collapseTimeUnit */ false)));
        mBackgroundPreference.setSummary(
                TextUtils.expandTemplate(getText(R.string.battery_active_for),
                        StringUtil.formatElapsedTime(
                                context,
                                backgroundTimeMs,
                                /* withSeconds */ false,
                                /* collapseTimeUnit */ false)));
    }

    @VisibleForTesting
    void initPreferenceForTriState(Context context) {
        final String stateString;
        final String footerString;
        //TODO(b/178197718) Update strings
@@ -308,7 +335,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
        } else {
            //Present default string to normal app.
            footerString = context.getString(R.string.manager_battery_usage_footer);

        }
        mFooterPreference.setTitle(Html.fromHtml(footerString, Html.FROM_HTML_MODE_COMPACT));
    }
@@ -325,7 +351,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements

    @Override
    protected int getPreferenceScreenResId() {
        return R.xml.power_usage_detail;
        return enableTriState ? R.xml.power_usage_detail : R.xml.power_usage_detail_legacy;
    }

    @Override
@@ -336,18 +362,20 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
        final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);

        mAppButtonsPreferenceController = new AppButtonsPreferenceController(
                (SettingsActivity) getActivity(), this, getSettingsLifecycle(), packageName, mState,
                REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN);
                (SettingsActivity) getActivity(), this, getSettingsLifecycle(), packageName,
                mState, REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN);
        controllers.add(mAppButtonsPreferenceController);
        mUnrestrictedPreferenceController =
                new UnrestrictedPreferenceController(context, uid, packageName);
        mOptimizedPreferenceController =
                new OptimizedPreferenceController(context, uid, packageName);
        mRestrictedPreferenceController =
                new RestrictedPreferenceController(context, uid, packageName);
        controllers.add(mUnrestrictedPreferenceController);
        controllers.add(mOptimizedPreferenceController);
        controllers.add(mRestrictedPreferenceController);
        if (enableTriState) {
            controllers.add(new UnrestrictedPreferenceController(context, uid, packageName));
            controllers.add(new OptimizedPreferenceController(context, uid, packageName));
            controllers.add(new RestrictedPreferenceController(context, uid, packageName));
        } else {
            mBackgroundActivityPreferenceController = new BackgroundActivityPreferenceController(
                    context, this, uid, packageName);
            controllers.add(mBackgroundActivityPreferenceController);
            controllers.add(new BatteryOptimizationPreferenceController(
                    (SettingsActivity) getActivity(), this, packageName));
        }

        return controllers;
    }
@@ -367,6 +395,12 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
        }
    }

    @Override
    public void onBatteryTipHandled(BatteryTip batteryTip) {
        mBackgroundActivityPreferenceController.updateSummary(
                findPreference(mBackgroundActivityPreferenceController.getPreferenceKey()));
    }

    @Override
    public void onRadioButtonClicked(RadioButtonPreference selected) {
        updatePreferenceState(mUnrestrictedPreference, selected.getKey());
@@ -378,6 +412,19 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
        preference.setChecked(selectedKey.equals(preference.getKey()));
    }

    private void onCreateForTriState(String packageName) {
        mUnrestrictedPreference = findPreference(KEY_PREF_UNRESTRICTED);
        mOptimizePreference = findPreference(KEY_PREF_OPTIMIZED);
        mRestrictedPreference = findPreference(KEY_PREF_RESTRICTED);
        mFooterPreference = findPreference(KEY_FOOTER_PREFERENCE);
        mUnrestrictedPreference.setOnClickListener(this);
        mOptimizePreference.setOnClickListener(this);
        mRestrictedPreference.setOnClickListener(this);

        mBatteryOptimizeUtils = new BatteryOptimizeUtils(
                getContext(), getArguments().getInt(EXTRA_UID), packageName);
    }

    //TODO(b/178197718) Update method to support time period
    private CharSequence getAppActiveTime(long foregroundTimeMs, long backgroundTimeMs) {
        final long totalTimeMs = foregroundTimeMs + backgroundTimeMs;
+46 −6
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import androidx.loader.app.LoaderManager;
import androidx.preference.Preference;
import androidx.recyclerview.widget.RecyclerView;

import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowActivityManager;
@@ -82,6 +83,7 @@ public class AdvancedPowerUsageDetailTest {
    private static final String USAGE_PERCENT = "16%";
    private static final int ICON_ID = 123;
    private static final int UID = 1;
    private static final int POWER_MAH = 150;
    private static final long BACKGROUND_TIME_MS = 100;
    private static final long FOREGROUND_ACTIVITY_TIME_MS = 123;
    private static final long FOREGROUND_SERVICE_TIME_MS = 444;
@@ -117,6 +119,8 @@ public class AdvancedPowerUsageDetailTest {
    @Mock
    private BatteryOptimizeUtils mBatteryOptimizeUtils;
    private Context mContext;
    private Preference mForegroundPreference;
    private Preference mBackgroundPreference;
    private Preference mFooterPreference;
    private RadioButtonPreference mRestrictedPreference;
    private RadioButtonPreference mOptimizePreference;
@@ -166,6 +170,7 @@ public class AdvancedPowerUsageDetailTest {

        mFragment.mHeaderPreference = mHeaderPreference;
        mFragment.mState = mState;
        mFragment.enableTriState = true;
        mFragment.mBatteryUtils = new BatteryUtils(RuntimeEnvironment.application);
        mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
        mAppEntry.info = mock(ApplicationInfo.class);
@@ -190,10 +195,14 @@ public class AdvancedPowerUsageDetailTest {
                nullable(UserHandle.class));
        doAnswer(callable).when(mActivity).startActivity(captor.capture());

        mForegroundPreference = new Preference(mContext);
        mBackgroundPreference = new Preference(mContext);
        mFooterPreference = new Preference(mContext);
        mRestrictedPreference = new RadioButtonPreference(mContext);
        mOptimizePreference = new RadioButtonPreference(mContext);
        mUnrestrictedPreference = new RadioButtonPreference(mContext);
        mFragment.mForegroundPreference = mForegroundPreference;
        mFragment.mBackgroundPreference = mBackgroundPreference;
        mFragment.mFooterPreference = mFooterPreference;
        mFragment.mRestrictedPreference = mRestrictedPreference;
        mFragment.mOptimizePreference = mOptimizePreference;
@@ -205,6 +214,17 @@ public class AdvancedPowerUsageDetailTest {
        ShadowEntityHeaderController.reset();
    }

    @Test
    public void testGetPreferenceScreenResId_returnNewLayout() {
        assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(R.xml.power_usage_detail);
    }

    @Test
    public void testGetPreferenceScreenResId_disableTriState_returnLegacyLayout() {
        mFragment.enableTriState = false;
        assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(R.xml.power_usage_detail_legacy);
    }

    @Test
    public void testInitHeader_NoAppEntry_BuildByBundle() {
        mFragment.mAppEntry = null;
@@ -455,32 +475,52 @@ public class AdvancedPowerUsageDetailTest {
    }

    @Test
    public void testInitPreference_isValidPackageName_hasCorrectString() {
    public void testInitPreference_hasCorrectSummary() {
        Bundle bundle = new Bundle(4);
        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, BACKGROUND_TIME_MS);
        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, FOREGROUND_TIME_MS);
        bundle.putString(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_PERCENT, USAGE_PERCENT);
        bundle.putInt(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_AMOUNT, POWER_MAH);
        when(mFragment.getArguments()).thenReturn(bundle);

        doReturn(mContext.getText(R.string.battery_used_for)).when(mFragment).getText(
                R.string.battery_used_for);
        doReturn(mContext.getText(R.string.battery_active_for)).when(mFragment).getText(
                R.string.battery_active_for);

        mFragment.initPreference(mContext);

        assertThat(mForegroundPreference.getSummary().toString()).isEqualTo("Used for 0 min");
        assertThat(mBackgroundPreference.getSummary().toString()).isEqualTo("Active for 0 min");
    }

    @Test
    public void testInitPreferenceForTriState_isValidPackageName_hasCorrectString() {
        when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(false);

        mFragment.initPreference();
        mFragment.initPreferenceForTriState(mContext);

        assertThat(mFooterPreference.getTitle().toString())
                .isEqualTo("This app requires Optimized battery usage.");
    }

    @Test
    public void testInitPreference_isSystemOrDefaultApp_hasCorrectString() {
    public void testInitPreferenceForTriState_isSystemOrDefaultApp_hasCorrectString() {
        when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
        when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);

        mFragment.initPreference();
        mFragment.initPreferenceForTriState(mContext);

        assertThat(mFooterPreference.getTitle()
                .toString()).isEqualTo("This app requires Unrestricted battery usage.");
    }

    @Test
    public void testInitPreference_hasCorrectString() {
    public void testInitPreferenceForTriState_hasCorrectString() {
        when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
        when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);

        mFragment.initPreference();
        mFragment.initPreferenceForTriState(mContext);

        assertThat(mFooterPreference.getTitle().toString())
                .isEqualTo("Changing how an app uses your battery can affect its performance.");