Refactor background optimization mode in Power Usage Detail page.

[Screenshot]:
before: https://screenshot.googleplex.com/6m5jYWHofY2pFov

after:
[App battery usage]
- [normal] https://screenshot.googleplex.com/7aurWk7cHKaWds7
- [always unrestried/optimized] https://screenshot.googleplex.com/3rGAh4ccUYTKBAr

[Allow Background usage]
- [Restricted]: https://screenshot.googleplex.com/MPXjQe5kPWw2nhr
- [Optimized]: https://screenshot.googleplex.com/6w4zTT6r34APnGc
- [Unrestricted]: https://screenshot.googleplex.com/97FgvHWMrwASqYH

Bug: 302063050
Bug: 306295660
Bug: 308359833
Test: manual
Change-Id: I3237d015549fe26e62d6d68c13403cc2cbdf0017
This commit is contained in:
mxyyiyi
2023-10-09 17:23:07 +08:00
parent 5ac8a4e281
commit 81e028931a
19 changed files with 1085 additions and 400 deletions

View File

@@ -5430,6 +5430,10 @@
<!-- Category title for battery background settings in power usage detail page [CHAR LIMIT=NONE] --> <!-- Category title for battery background settings in power usage detail page [CHAR LIMIT=NONE] -->
<string name="manager_battery_usage_category_title">Manage battery usage</string> <string name="manager_battery_usage_category_title">Manage battery usage</string>
<!-- Title for allow background usage [CHAR LIMIT=NONE] -->
<string name="manager_battery_usage_allow_background_usage_title">Allow background usage</string>
<!-- Summary for allow background usage [CHAR LIMIT=NONE] -->
<string name="manager_battery_usage_allow_background_usage_summary">Enable for real-time updates, disable to save battery</string>
<!-- Title for the battery unrestricted settings [CHAR_LIMIT=40] --> <!-- Title for the battery unrestricted settings [CHAR_LIMIT=40] -->
<string name="manager_battery_usage_unrestricted_title">Unrestricted</string> <string name="manager_battery_usage_unrestricted_title">Unrestricted</string>
<!-- Title for the battery optimized settings [CHAR_LIMIT=40] --> <!-- Title for the battery optimized settings [CHAR_LIMIT=40] -->

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2023 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"
android:title="@string/manager_battery_usage_allow_background_usage_title">
<com.android.settingslib.widget.LayoutPreference
android:key="header_view"
android:layout="@layout/settings_entity_header"
android:selectable="false"/>
<com.android.settingslib.widget.MainSwitchPreference
android:key="allow_background_usage"
android:title="@string/manager_battery_usage_allow_background_usage_title"
settings:controller="com.android.settings.fuelgauge.AllowBackgroundPreferenceController"/>
<com.android.settingslib.widget.SelectorWithWidgetPreference
android:key="optimized_preference"
android:title="@string/manager_battery_usage_optimized_title"
android:summary="@string/manager_battery_usage_optimized_summary"
settings:controller="com.android.settings.fuelgauge.OptimizedPreferenceController"/>
<com.android.settingslib.widget.SelectorWithWidgetPreference
android:key="unrestricted_preference"
android:title="@string/manager_battery_usage_unrestricted_title"
android:summary="@string/manager_battery_usage_unrestricted_summary"
settings:controller="com.android.settings.fuelgauge.UnrestrictedPreferenceController"/>
<com.android.settingslib.widget.FooterPreference
android:key="app_usage_footer_preference"
android:title="@string/manager_battery_usage_footer"
android:selectable="false"
settings:searchable="false"/>
</PreferenceScreen>

View File

@@ -50,30 +50,11 @@
android:title="@string/manager_battery_usage_category_title" android:title="@string/manager_battery_usage_category_title"
android:key="manage_battery_usage_category"> android:key="manage_battery_usage_category">
<com.android.settingslib.widget.SelectorWithWidgetPreference <com.android.settingslib.PrimarySwitchPreference
android:key="unrestricted_pref" android:key="allow_background_usage"
android:summary="@string/manager_battery_usage_unrestricted_summary" android:title="@string/manager_battery_usage_allow_background_usage_title"
android:title="@string/manager_battery_usage_unrestricted_title" settings:controller="com.android.settings.fuelgauge.AllowBackgroundPreferenceController"/>
settings:controller="com.android.settings.fuelgauge.UnrestrictedPreferenceController"/>
<com.android.settingslib.widget.SelectorWithWidgetPreference
android:key="optimized_pref"
android:summary="@string/manager_battery_usage_optimized_summary"
android:title="@string/manager_battery_usage_optimized_title"
settings:controller="com.android.settings.fuelgauge.OptimizedPreferenceController"/>
<com.android.settingslib.widget.SelectorWithWidgetPreference
android:key="restricted_pref"
android:summary="@string/manager_battery_usage_restricted_summary"
android:title="@string/manager_battery_usage_restricted_title"
settings:controller="com.android.settings.fuelgauge.RestrictedPreferenceController"/>
</PreferenceCategory> </PreferenceCategory>
<com.android.settingslib.widget.FooterPreference
android:key="app_usage_footer_preference"
android:title="@string/manager_battery_usage_footer"
android:selectable="false"
settings:searchable="false"/>
</PreferenceScreen> </PreferenceScreen>

View File

@@ -27,10 +27,13 @@ import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
@@ -45,14 +48,12 @@ import com.android.settings.fuelgauge.batteryusage.BatteryDiffEntry;
import com.android.settings.fuelgauge.batteryusage.BatteryEntry; import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.EntityHeaderController; import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.HelpUtils; import com.android.settingslib.PrimarySwitchPreference;
import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.instrumentation.Instrumentable; import com.android.settingslib.core.instrumentation.Instrumentable;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.LayoutPreference; import com.android.settingslib.widget.LayoutPreference;
import com.android.settingslib.widget.SelectorWithWidgetPreference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -67,8 +68,8 @@ import java.util.concurrent.Executors;
*/ */
public class AdvancedPowerUsageDetail extends DashboardFragment implements public class AdvancedPowerUsageDetail extends DashboardFragment implements
ButtonActionDialogFragment.AppButtonsDialogListener, ButtonActionDialogFragment.AppButtonsDialogListener,
SelectorWithWidgetPreference.OnClickListener { Preference.OnPreferenceClickListener,
Preference.OnPreferenceChangeListener {
public static final String TAG = "AdvancedPowerDetail"; public static final String TAG = "AdvancedPowerDetail";
public static final String EXTRA_UID = "extra_uid"; public static final String EXTRA_UID = "extra_uid";
public static final String EXTRA_PACKAGE_NAME = "extra_package_name"; public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
@@ -85,19 +86,16 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
public static final String EXTRA_POWER_USAGE_AMOUNT = "extra_power_usage_amount"; public static final String EXTRA_POWER_USAGE_AMOUNT = "extra_power_usage_amount";
private static final String KEY_PREF_HEADER = "header_view"; private static final String KEY_PREF_HEADER = "header_view";
private static final String KEY_PREF_UNRESTRICTED = "unrestricted_pref"; private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
private static final String KEY_PREF_OPTIMIZED = "optimized_pref";
private static final String KEY_PREF_RESTRICTED = "restricted_pref";
private static final String KEY_FOOTER_PREFERENCE = "app_usage_footer_preference";
private static final String PACKAGE_NAME_NONE = "none";
private static final String HEADER_SUMMARY_FORMAT = "%s\n(%s)";
private static final int REQUEST_UNINSTALL = 0; private static final int REQUEST_UNINSTALL = 0;
private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1; private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1;
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
private AppButtonsPreferenceController mAppButtonsPreferenceController;
private PowerUsageTimeController mPowerUsageTimeController;
@VisibleForTesting @VisibleForTesting
LayoutPreference mHeaderPreference; LayoutPreference mHeaderPreference;
@VisibleForTesting @VisibleForTesting
@@ -107,13 +105,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
@VisibleForTesting @VisibleForTesting
BatteryOptimizeUtils mBatteryOptimizeUtils; BatteryOptimizeUtils mBatteryOptimizeUtils;
@VisibleForTesting @VisibleForTesting
FooterPreference mFooterPreference; PrimarySwitchPreference mAllowBackgroundUsagePreference;
@VisibleForTesting
SelectorWithWidgetPreference mRestrictedPreference;
@VisibleForTesting
SelectorWithWidgetPreference mOptimizePreference;
@VisibleForTesting
SelectorWithWidgetPreference mUnrestrictedPreference;
@VisibleForTesting @VisibleForTesting
@BatteryOptimizeUtils.OptimizationMode @BatteryOptimizeUtils.OptimizationMode
int mOptimizationMode = BatteryOptimizeUtils.MODE_UNKNOWN; int mOptimizationMode = BatteryOptimizeUtils.MODE_UNKNOWN;
@@ -122,9 +114,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
@VisibleForTesting @VisibleForTesting
StringBuilder mLogStringBuilder; StringBuilder mLogStringBuilder;
private AppButtonsPreferenceController mAppButtonsPreferenceController;
private PowerUsageTimeController mPowerUsageTimeController;
// A wrapper class to carry LaunchBatteryDetailPage required arguments. // A wrapper class to carry LaunchBatteryDetailPage required arguments.
private static final class LaunchBatteryDetailPageArgs { private static final class LaunchBatteryDetailPageArgs {
private String mUsagePercent; private String mUsagePercent;
@@ -209,7 +198,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
args.putString(EXTRA_ANOMALY_HINT_PREF_KEY, launchArgs.mAnomalyHintPrefKey); args.putString(EXTRA_ANOMALY_HINT_PREF_KEY, launchArgs.mAnomalyHintPrefKey);
args.putString(EXTRA_ANOMALY_HINT_TEXT, launchArgs.mAnomalyHintText); args.putString(EXTRA_ANOMALY_HINT_TEXT, launchArgs.mAnomalyHintText);
final int userId = launchArgs.mIsUserEntry ? ActivityManager.getCurrentUser() final int userId = launchArgs.mIsUserEntry ? ActivityManager.getCurrentUser()
: UserHandle.getUserId(launchArgs.mUid); : UserHandle.getUserId(launchArgs.mUid);
new SubSettingLauncher(context) new SubSettingLauncher(context)
.setDestination(AdvancedPowerUsageDetail.class.getName()) .setDestination(AdvancedPowerUsageDetail.class.getName())
@@ -257,7 +246,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
super.onCreate(icicle); super.onCreate(icicle);
final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME); final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
onCreateForTriState(packageName); onCreateBackgroundUsageState(packageName);
mHeaderPreference = findPreference(KEY_PREF_HEADER); mHeaderPreference = findPreference(KEY_PREF_HEADER);
if (packageName != null) { if (packageName != null) {
@@ -271,10 +260,10 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
initHeader(); initHeader();
mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode(); mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
initPreferenceForTriState(getContext()); initFooter();
mExecutor.execute(() -> { mExecutor.execute(() -> {
String packageName = final String packageName = BatteryUtils
getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName()); .getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider() FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
.action( .action(
getContext(), getContext(),
@@ -288,11 +277,10 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
final int selectedPreference = getSelectedPreference();
notifyBackupManager(); notifyBackupManager();
mLogStringBuilder.append(", onPause mode = ").append(selectedPreference); final int currentOptimizeMode = mBatteryOptimizeUtils.getAppOptimizationMode();
logMetricCategory(selectedPreference); mLogStringBuilder.append(", onPause mode = ").append(currentOptimizeMode);
logMetricCategory(currentOptimizeMode);
mExecutor.execute(() -> { mExecutor.execute(() -> {
BatteryOptimizeLogUtils.writeLog( BatteryOptimizeLogUtils.writeLog(
@@ -302,7 +290,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
mBatteryOptimizeUtils.getPackageName(), UserHandle.myUserId()), mBatteryOptimizeUtils.getPackageName(), UserHandle.myUserId()),
mLogStringBuilder.toString()); mLogStringBuilder.toString());
}); });
Log.d(TAG, "Leave with mode: " + selectedPreference); Log.d(TAG, "Leave with mode: " + currentOptimizeMode);
} }
@VisibleForTesting @VisibleForTesting
@@ -353,33 +341,28 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
} }
@VisibleForTesting @VisibleForTesting
void initPreferenceForTriState(Context context) { void initFooter() {
final String stateString; final String stateString;
final String footerString; final String detailInfoString;
final Context context = getContext();
if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) { if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
// Present optimized only string when the package name is invalid. // Present optimized only string when the package name is invalid.
stateString = context.getString(R.string.manager_battery_usage_optimized_only); stateString = context.getString(R.string.manager_battery_usage_optimized_only);
footerString = context.getString( detailInfoString =
R.string.manager_battery_usage_footer_limited, stateString); context.getString(R.string.manager_battery_usage_footer_limited, stateString);
} else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) { } else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
// Present unrestricted only string when the package is system or default active app. // Present unrestricted only string when the package is system or default active app.
stateString = context.getString(R.string.manager_battery_usage_unrestricted_only); stateString = context.getString(R.string.manager_battery_usage_unrestricted_only);
footerString = context.getString( detailInfoString =
R.string.manager_battery_usage_footer_limited, stateString); context.getString(R.string.manager_battery_usage_footer_limited, stateString);
} else { } else {
// Present default string to normal app. // Present default string to normal app.
footerString = context.getString(R.string.manager_battery_usage_footer); detailInfoString =
} context.getString(
mFooterPreference.setTitle(footerString); R.string.manager_battery_usage_allow_background_usage_summary);
final Intent helpIntent = HelpUtils.getHelpIntent(context, context.getString(
R.string.help_url_app_usage_settings), /*backupContext=*/ "");
if (helpIntent != null) {
mFooterPreference.setLearnMoreAction(v ->
startActivityForResult(helpIntent, /*requestCode=*/ 0));
mFooterPreference.setLearnMoreText(
context.getString(R.string.manager_battery_usage_link_a11y));
} }
mAllowBackgroundUsagePreference.setSummary(detailInfoString);
} }
@Override @Override
@@ -412,9 +395,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
controllers.add(mPowerUsageTimeController); controllers.add(mPowerUsageTimeController);
} }
controllers.add(mAppButtonsPreferenceController); controllers.add(mAppButtonsPreferenceController);
controllers.add(new UnrestrictedPreferenceController(context, uid, packageName)); controllers.add(new AllowBackgroundPreferenceController(context, uid, packageName));
controllers.add(new OptimizedPreferenceController(context, uid, packageName));
controllers.add(new RestrictedPreferenceController(context, uid, packageName));
return controllers; return controllers;
} }
@@ -435,34 +416,45 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
} }
@Override @Override
public void onRadioButtonClicked(SelectorWithWidgetPreference selected) { public boolean onPreferenceClick(Preference preference) {
final String selectedKey = selected.getKey(); if (!(preference instanceof PrimarySwitchPreference)
updatePreferenceState(mUnrestrictedPreference, selectedKey); || !TextUtils.equals(preference.getKey(), KEY_ALLOW_BACKGROUND_USAGE)) {
updatePreferenceState(mOptimizePreference, selectedKey); return false;
updatePreferenceState(mRestrictedPreference, selectedKey); }
mBatteryOptimizeUtils.setAppUsageState(getSelectedPreference(), Action.APPLY); PowerBackgroundUsageDetail.startPowerBackgroundUsageDetailPage(
getContext(), getArguments());
return true;
} }
private void updatePreferenceState(SelectorWithWidgetPreference preference, @Override
String selectedKey) { public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
preference.setChecked(selectedKey.equals(preference.getKey())); if (!(preference instanceof PrimarySwitchPreference)
|| !TextUtils.equals(preference.getKey(), KEY_ALLOW_BACKGROUND_USAGE)) {
return false;
}
if (newValue instanceof Boolean) {
final boolean isAllowBackgroundUsage = (boolean) newValue;
mBatteryOptimizeUtils.setAppUsageState(
isAllowBackgroundUsage
? BatteryOptimizeUtils.MODE_OPTIMIZED
: BatteryOptimizeUtils.MODE_RESTRICTED,
Action.APPLY);
}
return true;
} }
private void logMetricCategory(int selectedKey) { private void logMetricCategory(int currentOptimizeMode) {
if (selectedKey == mOptimizationMode) { if (currentOptimizeMode == mOptimizationMode) {
return; return;
} }
int metricCategory = 0; int metricCategory = 0;
switch (selectedKey) { switch (currentOptimizeMode) {
case BatteryOptimizeUtils.MODE_UNRESTRICTED: case BatteryOptimizeUtils.MODE_UNRESTRICTED:
metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_UNRESTRICTED;
break;
case BatteryOptimizeUtils.MODE_OPTIMIZED: case BatteryOptimizeUtils.MODE_OPTIMIZED:
metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED; metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_ALLOW_BACKGROUND;
break; break;
case BatteryOptimizeUtils.MODE_RESTRICTED: case BatteryOptimizeUtils.MODE_RESTRICTED:
metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_RESTRICTED; metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_DISABLE_BACKGROUND;
break; break;
} }
if (metricCategory == 0) { if (metricCategory == 0) {
@@ -470,8 +462,8 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
} }
int finalMetricCategory = metricCategory; int finalMetricCategory = metricCategory;
mExecutor.execute(() -> { mExecutor.execute(() -> {
String packageName = String packageName = BatteryUtils
getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName()); .getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider() FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
.action( .action(
/* attribution */ SettingsEnums.OPEN_APP_BATTERY_USAGE, /* attribution */ SettingsEnums.OPEN_APP_BATTERY_USAGE,
@@ -482,33 +474,15 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
}); });
} }
private void onCreateForTriState(String packageName) { private void onCreateBackgroundUsageState(String packageName) {
mUnrestrictedPreference = findPreference(KEY_PREF_UNRESTRICTED); mAllowBackgroundUsagePreference = findPreference(KEY_ALLOW_BACKGROUND_USAGE);
mOptimizePreference = findPreference(KEY_PREF_OPTIMIZED); if (mAllowBackgroundUsagePreference != null) {
mRestrictedPreference = findPreference(KEY_PREF_RESTRICTED); mAllowBackgroundUsagePreference.setOnPreferenceClickListener(this);
mFooterPreference = findPreference(KEY_FOOTER_PREFERENCE); mAllowBackgroundUsagePreference.setOnPreferenceChangeListener(this);
mUnrestrictedPreference.setOnClickListener(this);
mOptimizePreference.setOnClickListener(this);
mRestrictedPreference.setOnClickListener(this);
mBatteryOptimizeUtils = new BatteryOptimizeUtils(
getContext(), getArguments().getInt(EXTRA_UID), packageName);
}
private int getSelectedPreference() {
if (mRestrictedPreference.isChecked()) {
return BatteryOptimizeUtils.MODE_RESTRICTED;
} else if (mUnrestrictedPreference.isChecked()) {
return BatteryOptimizeUtils.MODE_UNRESTRICTED;
} else if (mOptimizePreference.isChecked()) {
return BatteryOptimizeUtils.MODE_OPTIMIZED;
} else {
return BatteryOptimizeUtils.MODE_UNKNOWN;
} }
}
private static String getLoggingPackageName(Context context, String originalPackingName) { mBatteryOptimizeUtils =
return BatteryUtils.isAppInstalledFromGooglePlayStore(context, originalPackingName) new BatteryOptimizeUtils(
? originalPackingName : PACKAGE_NAME_NONE; getContext(), getArguments().getInt(EXTRA_UID), packageName);
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2021 The Android Open Source Project * Copyright (C) 2023 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,50 +17,45 @@
package com.android.settings.fuelgauge; package com.android.settings.fuelgauge;
import android.content.Context; import android.content.Context;
import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference; import androidx.preference.Preference;
import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.PrimarySwitchPreference;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.widget.SelectorWithWidgetPreference; import com.android.settingslib.widget.MainSwitchPreference;
public class RestrictedPreferenceController extends AbstractPreferenceController /** Controller to update the app background usage state */
public class AllowBackgroundPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin { implements PreferenceControllerMixin {
private static final String TAG = "RESTRICTED_PREF"; private static final String TAG = "AllowBackgroundPreferenceController";
@VisibleForTesting static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
@VisibleForTesting String KEY_RESTRICTED_PREF = "restricted_pref";
@VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils; @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
public RestrictedPreferenceController(Context context, int uid, String packageName) { public AllowBackgroundPreferenceController(Context context, int uid, String packageName) {
super(context); super(context);
mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName); mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
} }
private void setChecked(Preference preference, boolean checked) {
if (preference instanceof PrimarySwitchPreference) {
((PrimarySwitchPreference) preference).setChecked(checked);
} else if (preference instanceof MainSwitchPreference) {
((MainSwitchPreference) preference).setChecked(checked);
}
}
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference) {
preference.setEnabled(mBatteryOptimizeUtils.isOptimizeModeMutable());
if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) { final boolean isAllowBackground = mBatteryOptimizeUtils.getAppOptimizationMode()
Log.d(TAG, "disable preference for " + mBatteryOptimizeUtils.getPackageName()); != BatteryOptimizeUtils.MODE_RESTRICTED;
preference.setEnabled(false); setChecked(preference, isAllowBackground);
return;
} else {
preference.setEnabled(true);
}
if (mBatteryOptimizeUtils.getAppOptimizationMode()
== BatteryOptimizeUtils.MODE_RESTRICTED) {
Log.d(TAG, "is restricted states");
((SelectorWithWidgetPreference) preference).setChecked(true);
} else {
((SelectorWithWidgetPreference) preference).setChecked(false);
if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
Log.d(TAG, "is system or default app, disable pref");
preference.setEnabled(false);
}
}
} }
@Override @Override
@@ -70,7 +65,7 @@ public class RestrictedPreferenceController extends AbstractPreferenceController
@Override @Override
public String getPreferenceKey() { public String getPreferenceKey() {
return KEY_RESTRICTED_PREF; return KEY_ALLOW_BACKGROUND_USAGE;
} }
@Override @Override

View File

@@ -146,6 +146,22 @@ public class BatteryOptimizeUtils {
return isSystemOrDefaultApp(mContext, mPowerAllowListBackend, mPackageName, mUid); return isSystemOrDefaultApp(mContext, mPowerAllowListBackend, mPackageName, mUid);
} }
/**
* Return {@code true} if the optimization mode of this package can be changed
*/
public boolean isOptimizeModeMutable() {
return !isDisabledForOptimizeModeOnly() && !isSystemOrDefaultApp();
}
/**
* Return {@code true} if the optimization mode is mutable and current state is not restricted
*/
public boolean isSelectorPreferenceEnabled() {
// Enable the preference if apps are not set into restricted mode, otherwise disable it
return isOptimizeModeMutable()
&& getAppOptimizationMode() != BatteryOptimizeUtils.MODE_RESTRICTED;
}
/** /**
* Gets the list of installed applications. * Gets the list of installed applications.
*/ */

View File

@@ -88,6 +88,7 @@ public class BatteryUtils {
public static final String BYPASS_DOCK_DEFENDER_ACTION = "battery.dock.defender.bypass"; public static final String BYPASS_DOCK_DEFENDER_ACTION = "battery.dock.defender.bypass";
private static final String GOOGLE_PLAY_STORE_PACKAGE = "com.android.vending"; private static final String GOOGLE_PLAY_STORE_PACKAGE = "com.android.vending";
private static final String PACKAGE_NAME_NONE = "none";
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({StatusType.SCREEN_USAGE, @IntDef({StatusType.SCREEN_USAGE,
@@ -140,6 +141,12 @@ public class BatteryUtils {
FeatureFactory.getFeatureFactory().getPowerUsageFeatureProvider(); FeatureFactory.getFeatureFactory().getPowerUsageFeatureProvider();
} }
/** For test to reset single instance. */
@VisibleForTesting
public void reset() {
sInstance = null;
}
public long getProcessTimeMs(@StatusType int type, @Nullable BatteryStats.Uid uid, public long getProcessTimeMs(@StatusType int type, @Nullable BatteryStats.Uid uid,
int which) { int which) {
if (uid == null) { if (uid == null) {
@@ -616,6 +623,12 @@ public class BatteryUtils {
&& GOOGLE_PLAY_STORE_PACKAGE.equals(installSourceInfo.getInitiatingPackageName()); && GOOGLE_PLAY_STORE_PACKAGE.equals(installSourceInfo.getInitiatingPackageName());
} }
/** Gets the logging package name. */
public static String getLoggingPackageName(Context context, String originalPackingName) {
return BatteryUtils.isAppInstalledFromGooglePlayStore(context, originalPackingName)
? originalPackingName : PACKAGE_NAME_NONE;
}
/** Gets the latest sticky battery intent from the Android system. */ /** Gets the latest sticky battery intent from the Android system. */
public static Intent getBatteryIntent(Context context) { public static Intent getBatteryIntent(Context context) {
return com.android.settingslib.fuelgauge.BatteryUtils.getBatteryIntent(context); return com.android.settingslib.fuelgauge.BatteryUtils.getBatteryIntent(context);

View File

@@ -17,7 +17,6 @@
package com.android.settings.fuelgauge; package com.android.settings.fuelgauge;
import android.content.Context; import android.content.Context;
import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference; import androidx.preference.Preference;
@@ -31,8 +30,10 @@ public class OptimizedPreferenceController extends AbstractPreferenceController
private static final String TAG = "OPTIMIZED_PREF"; private static final String TAG = "OPTIMIZED_PREF";
@VisibleForTesting String KEY_OPTIMIZED_PREF = "optimized_pref"; @VisibleForTesting
@VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils; static final String KEY_OPTIMIZED_PREF = "optimized_preference";
@VisibleForTesting
BatteryOptimizeUtils mBatteryOptimizeUtils;
public OptimizedPreferenceController(Context context, int uid, String packageName) { public OptimizedPreferenceController(Context context, int uid, String packageName) {
super(context); super(context);
@@ -46,24 +47,12 @@ public class OptimizedPreferenceController extends AbstractPreferenceController
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference) {
if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) { preference.setEnabled(mBatteryOptimizeUtils.isSelectorPreferenceEnabled());
Log.d(TAG, "disable preference for " + mBatteryOptimizeUtils.getPackageName());
preference.setEnabled(true);
((SelectorWithWidgetPreference) preference).setChecked(true);
return;
}
if (mBatteryOptimizeUtils.getAppOptimizationMode() final boolean isOptimized = mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()
== BatteryOptimizeUtils.MODE_OPTIMIZED) { || mBatteryOptimizeUtils.getAppOptimizationMode()
Log.d(TAG, "is optimized states"); == BatteryOptimizeUtils.MODE_OPTIMIZED;
((SelectorWithWidgetPreference) preference).setChecked(true); ((SelectorWithWidgetPreference) preference).setChecked(isOptimized);
} else {
((SelectorWithWidgetPreference) preference).setChecked(false);
if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
Log.d(TAG, "is system or default app, disable pref");
preference.setEnabled(false);
}
}
} }
@Override @Override

View File

@@ -0,0 +1,351 @@
/*
* Copyright (C) 2023 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;
import static com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
import android.app.Activity;
import android.app.backup.BackupManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Switch;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.HelpUtils;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.LayoutPreference;
import com.android.settingslib.widget.MainSwitchPreference;
import com.android.settingslib.widget.OnMainSwitchChangeListener;
import com.android.settingslib.widget.SelectorWithWidgetPreference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Allow background usage fragment for each app
*/
public class PowerBackgroundUsageDetail extends DashboardFragment implements
SelectorWithWidgetPreference.OnClickListener,
OnMainSwitchChangeListener {
private static final String TAG = "PowerBackgroundUsageDetail";
public static final String EXTRA_UID = "extra_uid";
public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
public static final String EXTRA_LABEL = "extra_label";
public static final String EXTRA_POWER_USAGE_AMOUNT = "extra_power_usage_amount";
public static final String EXTRA_ICON_ID = "extra_icon_id";
private static final String KEY_PREF_HEADER = "header_view";
private static final String KEY_PREF_UNRESTRICTED = "unrestricted_preference";
private static final String KEY_PREF_OPTIMIZED = "optimized_preference";
private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
private static final String KEY_FOOTER_PREFERENCE = "app_usage_footer_preference";
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
@VisibleForTesting
LayoutPreference mHeaderPreference;
@VisibleForTesting
ApplicationsState mState;
@VisibleForTesting
ApplicationsState.AppEntry mAppEntry;
@VisibleForTesting
BatteryOptimizeUtils mBatteryOptimizeUtils;
@VisibleForTesting
SelectorWithWidgetPreference mOptimizePreference;
@VisibleForTesting
SelectorWithWidgetPreference mUnrestrictedPreference;
@VisibleForTesting
MainSwitchPreference mMainSwitchPreference;
@VisibleForTesting
FooterPreference mFooterPreference;
@VisibleForTesting
BackupManager mBackupManager;
@VisibleForTesting
StringBuilder mLogStringBuilder;
@VisibleForTesting
@BatteryOptimizeUtils.OptimizationMode
int mOptimizationMode = BatteryOptimizeUtils.MODE_UNKNOWN;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mState = ApplicationsState.getInstance(getActivity().getApplication());
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
onCreateBackgroundUsageState(packageName);
mHeaderPreference = findPreference(KEY_PREF_HEADER);
if (packageName != null) {
mAppEntry = mState.getEntry(packageName, UserHandle.myUserId());
}
}
@Override
public void onResume() {
super.onResume();
initHeader();
mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
initFooter();
mExecutor.execute(() -> {
String packageName = BatteryUtils
.getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
.action(
getContext(),
SettingsEnums.OPEN_APP_BATTERY_USAGE,
packageName);
});
mLogStringBuilder = new StringBuilder("onResume mode = ").append(mOptimizationMode);
}
@Override
public void onPause() {
super.onPause();
notifyBackupManager();
final int currentOptimizeMode = mBatteryOptimizeUtils.getAppOptimizationMode();
mLogStringBuilder.append(", onPause mode = ").append(currentOptimizeMode);
logMetricCategory(currentOptimizeMode);
mExecutor.execute(() -> {
BatteryOptimizeLogUtils.writeLog(
getContext().getApplicationContext(),
Action.LEAVE,
BatteryOptimizeLogUtils.getPackageNameWithUserId(
mBatteryOptimizeUtils.getPackageName(), UserHandle.myUserId()),
mLogStringBuilder.toString());
});
Log.d(TAG, "Leave with mode: " + currentOptimizeMode);
}
@Override
public void onRadioButtonClicked(SelectorWithWidgetPreference selected) {
final String selectedKey = selected == null ? null : selected.getKey();
updateSelectorPreferenceState(mUnrestrictedPreference, selectedKey);
updateSelectorPreferenceState(mOptimizePreference, selectedKey);
mBatteryOptimizeUtils.setAppUsageState(getSelectedPreference(), Action.APPLY);
}
@Override
public void onSwitchChanged(Switch switchView, boolean isChecked) {
mMainSwitchPreference.setChecked(isChecked);
updateSelectorPreference(isChecked);
}
@Override
public int getMetricsCategory() {
return SettingsEnums.FUELGAUGE_POWER_USAGE_MANAGE_BACKGROUND;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
final Bundle bundle = getArguments();
final int uid = bundle.getInt(EXTRA_UID, 0);
final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
controllers.add(new AllowBackgroundPreferenceController(context, uid, packageName));
controllers.add(new OptimizedPreferenceController(context, uid, packageName));
controllers.add(new UnrestrictedPreferenceController(context, uid, packageName));
return controllers;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.power_background_usage_detail;
}
@Override
protected String getLogTag() {
return TAG;
}
@VisibleForTesting
void updateSelectorPreference(boolean isEnabled) {
mOptimizePreference.setEnabled(isEnabled);
mUnrestrictedPreference.setEnabled(isEnabled);
onRadioButtonClicked(isEnabled ? mOptimizePreference : null);
}
@VisibleForTesting
void notifyBackupManager() {
if (mOptimizationMode != mBatteryOptimizeUtils.getAppOptimizationMode()) {
final BackupManager backupManager = mBackupManager != null
? mBackupManager : new BackupManager(getContext());
backupManager.dataChanged();
}
}
@VisibleForTesting
int getSelectedPreference() {
if (!mMainSwitchPreference.isChecked()) {
return BatteryOptimizeUtils.MODE_RESTRICTED;
} else if (mUnrestrictedPreference.isChecked()) {
return BatteryOptimizeUtils.MODE_UNRESTRICTED;
} else if (mOptimizePreference.isChecked()) {
return BatteryOptimizeUtils.MODE_OPTIMIZED;
} else {
return BatteryOptimizeUtils.MODE_UNKNOWN;
}
}
static void startPowerBackgroundUsageDetailPage(
Context context, Bundle args) {
new SubSettingLauncher(context)
.setDestination(PowerBackgroundUsageDetail.class.getName())
.setArguments(args)
.setSourceMetricsCategory(SettingsEnums.FUELGAUGE_POWER_USAGE_MANAGE_BACKGROUND)
.launch();
}
@VisibleForTesting
void initHeader() {
final View appSnippet = mHeaderPreference.findViewById(R.id.entity_header);
final Activity context = getActivity();
final Bundle bundle = getArguments();
EntityHeaderController controller = EntityHeaderController
.newInstance(context, this, appSnippet)
.setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
EntityHeaderController.ActionType.ACTION_NONE);
if (mAppEntry == null) {
controller.setLabel(bundle.getString(EXTRA_LABEL));
final int iconId = bundle.getInt(EXTRA_ICON_ID, 0);
if (iconId == 0) {
controller.setIcon(context.getPackageManager().getDefaultActivityIcon());
} else {
controller.setIcon(context.getDrawable(bundle.getInt(EXTRA_ICON_ID)));
}
} else {
mState.ensureIcon(mAppEntry);
controller.setLabel(mAppEntry);
controller.setIcon(mAppEntry);
controller.setIsInstantApp(AppUtils.isInstant(mAppEntry.info));
}
controller.done(true /* rebindActions */);
}
@VisibleForTesting
void initFooter() {
final String stateString;
final String footerString;
final Context context = getContext();
if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
// Present optimized only string when the package name is invalid.
stateString = context.getString(R.string.manager_battery_usage_optimized_only);
footerString = context.getString(
R.string.manager_battery_usage_footer_limited, stateString);
} else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
// Present unrestricted only string when the package is system or default active app.
stateString = context.getString(R.string.manager_battery_usage_unrestricted_only);
footerString = context.getString(
R.string.manager_battery_usage_footer_limited, stateString);
} else {
// Present default string to normal app.
footerString = context.getString(R.string.manager_battery_usage_footer);
}
mFooterPreference.setTitle(footerString);
final Intent helpIntent = HelpUtils.getHelpIntent(context, context.getString(
R.string.help_url_app_usage_settings), /*backupContext=*/ "");
if (helpIntent != null) {
mFooterPreference.setLearnMoreAction(v ->
startActivityForResult(helpIntent, /*requestCode=*/ 0));
mFooterPreference.setLearnMoreText(
context.getString(R.string.manager_battery_usage_link_a11y));
}
}
private void onCreateBackgroundUsageState(String packageName) {
mOptimizePreference = findPreference(KEY_PREF_OPTIMIZED);
mUnrestrictedPreference = findPreference(KEY_PREF_UNRESTRICTED);
mMainSwitchPreference = findPreference(KEY_ALLOW_BACKGROUND_USAGE);
mFooterPreference = findPreference(KEY_FOOTER_PREFERENCE);
mOptimizePreference.setOnClickListener(this);
mUnrestrictedPreference.setOnClickListener(this);
mMainSwitchPreference.addOnSwitchChangeListener(this);
mBatteryOptimizeUtils = new BatteryOptimizeUtils(
getContext(), getArguments().getInt(EXTRA_UID), packageName);
}
private void updateSelectorPreferenceState(SelectorWithWidgetPreference preference,
String selectedKey) {
preference.setChecked(TextUtils.equals(selectedKey, preference.getKey()));
}
private void logMetricCategory(int currentOptimizeMode) {
if (currentOptimizeMode == mOptimizationMode) {
return;
}
int metricCategory = 0;
switch (currentOptimizeMode) {
case BatteryOptimizeUtils.MODE_UNRESTRICTED:
metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_UNRESTRICTED;
break;
case BatteryOptimizeUtils.MODE_OPTIMIZED:
metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED;
break;
case BatteryOptimizeUtils.MODE_RESTRICTED:
metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_RESTRICTED;
break;
}
if (metricCategory == 0) {
return;
}
int finalMetricCategory = metricCategory;
mExecutor.execute(() -> {
String packageName = BatteryUtils
.getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
.action(
/* attribution */ SettingsEnums.OPEN_APP_BATTERY_USAGE,
/* action */ finalMetricCategory,
/* pageId */ SettingsEnums.OPEN_APP_BATTERY_USAGE,
packageName,
getArguments().getInt(EXTRA_POWER_USAGE_AMOUNT));
});
}
}

View File

@@ -17,7 +17,6 @@
package com.android.settings.fuelgauge; package com.android.settings.fuelgauge;
import android.content.Context; import android.content.Context;
import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference; import androidx.preference.Preference;
@@ -31,7 +30,9 @@ public class UnrestrictedPreferenceController extends AbstractPreferenceControll
private static final String TAG = "UNRESTRICTED_PREF"; private static final String TAG = "UNRESTRICTED_PREF";
@VisibleForTesting String KEY_UNRESTRICTED_PREF = "unrestricted_pref"; @VisibleForTesting
static final String KEY_UNRESTRICTED_PREF = "unrestricted_preference";
@VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils; @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
public UnrestrictedPreferenceController(Context context, int uid, String packageName) { public UnrestrictedPreferenceController(Context context, int uid, String packageName) {
@@ -41,26 +42,11 @@ public class UnrestrictedPreferenceController extends AbstractPreferenceControll
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference) {
preference.setEnabled(mBatteryOptimizeUtils.isSelectorPreferenceEnabled());
if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) { final boolean isUnrestricted = mBatteryOptimizeUtils.getAppOptimizationMode()
Log.d(TAG, "disable preference for " + mBatteryOptimizeUtils.getPackageName()); == BatteryOptimizeUtils.MODE_UNRESTRICTED;
preference.setEnabled(false); ((SelectorWithWidgetPreference) preference).setChecked(isUnrestricted);
return;
} else {
preference.setEnabled(true);
}
if (mBatteryOptimizeUtils.getAppOptimizationMode()
== BatteryOptimizeUtils.MODE_UNRESTRICTED) {
Log.d(TAG, "is unrestricted states");
((SelectorWithWidgetPreference) preference).setChecked(true);
} else {
((SelectorWithWidgetPreference) preference).setChecked(false);
if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
Log.d(TAG, "is system or default app, disable pref");
preference.setEnabled(false);
}
}
} }
@Override @Override

View File

@@ -17,6 +17,7 @@
package com.android.settings.fuelgauge; package com.android.settings.fuelgauge;
import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS; import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS;
import static com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
@@ -53,13 +54,12 @@ import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowActivityManager; import com.android.settings.testutils.shadow.ShadowActivityManager;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController; import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settings.widget.EntityHeaderController; import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.PrimarySwitchPreference;
import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider; import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.LayoutPreference; import com.android.settingslib.widget.LayoutPreference;
import com.android.settingslib.widget.SelectorWithWidgetPreference;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@@ -95,9 +95,7 @@ public class AdvancedPowerUsageDetailTest {
private static final long FOREGROUND_SERVICE_TIME_MS = 444; private static final long FOREGROUND_SERVICE_TIME_MS = 444;
private static final long FOREGROUND_TIME_MS = private static final long FOREGROUND_TIME_MS =
FOREGROUND_ACTIVITY_TIME_MS + FOREGROUND_SERVICE_TIME_MS; FOREGROUND_ACTIVITY_TIME_MS + FOREGROUND_SERVICE_TIME_MS;
private static final String KEY_PREF_UNRESTRICTED = "unrestricted_pref"; private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
private static final String KEY_PREF_OPTIMIZED = "optimized_pref";
private static final String KEY_PREF_RESTRICTED = "restricted_pref";
@Mock(answer = Answers.RETURNS_DEEP_STUBS) @Mock(answer = Answers.RETURNS_DEEP_STUBS)
private FragmentActivity mActivity; private FragmentActivity mActivity;
@@ -127,10 +125,7 @@ public class AdvancedPowerUsageDetailTest {
private BackupManager mBackupManager; private BackupManager mBackupManager;
private Context mContext; private Context mContext;
private FooterPreference mFooterPreference; private PrimarySwitchPreference mAllowBackgroundUsagePreference;
private SelectorWithWidgetPreference mRestrictedPreference;
private SelectorWithWidgetPreference mOptimizePreference;
private SelectorWithWidgetPreference mUnrestrictedPreference;
private AdvancedPowerUsageDetail mFragment; private AdvancedPowerUsageDetail mFragment;
private SettingsActivity mTestActivity; private SettingsActivity mTestActivity;
private FakeFeatureFactory mFeatureFactory; private FakeFeatureFactory mFeatureFactory;
@@ -198,14 +193,9 @@ public class AdvancedPowerUsageDetailTest {
nullable(UserHandle.class)); nullable(UserHandle.class));
doAnswer(callable).when(mActivity).startActivity(captor.capture()); doAnswer(callable).when(mActivity).startActivity(captor.capture());
mFooterPreference = new FooterPreference(mContext); mAllowBackgroundUsagePreference = new PrimarySwitchPreference(mContext);
mRestrictedPreference = new SelectorWithWidgetPreference(mContext); mAllowBackgroundUsagePreference.setKey(KEY_ALLOW_BACKGROUND_USAGE);
mOptimizePreference = new SelectorWithWidgetPreference(mContext); mFragment.mAllowBackgroundUsagePreference = mAllowBackgroundUsagePreference;
mUnrestrictedPreference = new SelectorWithWidgetPreference(mContext);
mFragment.mFooterPreference = mFooterPreference;
mFragment.mRestrictedPreference = mRestrictedPreference;
mFragment.mOptimizePreference = mOptimizePreference;
mFragment.mUnrestrictedPreference = mUnrestrictedPreference;
} }
@After @After
@@ -307,70 +297,60 @@ public class AdvancedPowerUsageDetailTest {
} }
@Test @Test
public void initPreferenceForTriState_isValidPackageName_hasCorrectString() { public void initFooter_isValidPackageName_hasCorrectString() {
when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
mFragment.initPreferenceForTriState(mContext); mFragment.initFooter();
assertThat(mFooterPreference.getTitle().toString()) assertThat(mAllowBackgroundUsagePreference.getSummary().toString())
.isEqualTo("This app requires optimized battery usage."); .isEqualTo("This app requires optimized battery usage.");
} }
@Test @Test
public void initPreferenceForTriState_isSystemOrDefaultApp_hasCorrectString() { public void initFooter_isSystemOrDefaultApp_hasCorrectString() {
when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true); when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
mFragment.initPreferenceForTriState(mContext); mFragment.initFooter();
assertThat(mFooterPreference.getTitle() assertThat(mAllowBackgroundUsagePreference.getSummary().toString())
.toString()).isEqualTo("This app requires unrestricted battery usage."); .isEqualTo("This app requires unrestricted battery usage.");
} }
@Test @Test
public void initPreferenceForTriState_hasCorrectString() { public void initFooter_hasCorrectString() {
when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false); when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
mFragment.initPreferenceForTriState(mContext); mFragment.initFooter();
assertThat(mFooterPreference.getTitle().toString()) assertThat(mAllowBackgroundUsagePreference.getSummary().toString())
.isEqualTo("Changing how an app uses your battery can affect its performance."); .isEqualTo("Enable for real-time updates, disable to save battery");
}
@Test
public void onRadioButtonClicked_clickOptimizePref_optimizePreferenceChecked() {
mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
mRestrictedPreference.setKey(KEY_PREF_RESTRICTED);
mUnrestrictedPreference.setKey(KEY_PREF_UNRESTRICTED);
mFragment.onRadioButtonClicked(mOptimizePreference);
assertThat(mOptimizePreference.isChecked()).isTrue();
assertThat(mRestrictedPreference.isChecked()).isFalse();
assertThat(mUnrestrictedPreference.isChecked()).isFalse();
} }
@Test @Test
public void onPause_optimizationModeChanged_logPreference() public void onPause_optimizationModeChanged_logPreference()
throws PackageManager.NameNotFoundException, InterruptedException { throws PackageManager.NameNotFoundException, InterruptedException {
final String packageName = "testPackageName"; final String packageName = "testPackageName";
final int mode = BatteryOptimizeUtils.MODE_RESTRICTED; final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
mFragment.mOptimizationMode = mode; final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode); mFragment.mOptimizationMode = restrictedMode;
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(restrictedMode);
when(mBatteryOptimizeUtils.getPackageName()).thenReturn(packageName); when(mBatteryOptimizeUtils.getPackageName()).thenReturn(packageName);
when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo); when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);
when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending"); when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending");
mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
mFragment.onRadioButtonClicked(mOptimizePreference); mFragment.onPreferenceChange(mAllowBackgroundUsagePreference, true);
verify(mBatteryOptimizeUtils).setAppUsageState(optimizedMode, Action.APPLY);
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(optimizedMode);
mFragment.onPause(); mFragment.onPause();
TimeUnit.SECONDS.sleep(1); TimeUnit.SECONDS.sleep(1);
verify(mMetricsFeatureProvider) verify(mMetricsFeatureProvider)
.action( .action(
SettingsEnums.OPEN_APP_BATTERY_USAGE, SettingsEnums.OPEN_APP_BATTERY_USAGE,
SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED, SettingsEnums.ACTION_APP_BATTERY_USAGE_ALLOW_BACKGROUND,
SettingsEnums.OPEN_APP_BATTERY_USAGE, SettingsEnums.OPEN_APP_BATTERY_USAGE,
packageName, packageName,
/* consumed battery */ 0); /* consumed battery */ 0);
@@ -379,15 +359,20 @@ public class AdvancedPowerUsageDetailTest {
@Test @Test
public void onPause_optimizationModeIsNotChanged_notInvokeLogging() public void onPause_optimizationModeIsNotChanged_notInvokeLogging()
throws PackageManager.NameNotFoundException, InterruptedException { throws PackageManager.NameNotFoundException, InterruptedException {
final int mode = BatteryOptimizeUtils.MODE_OPTIMIZED; final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
mFragment.mOptimizationMode = mode; final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode); mFragment.mOptimizationMode = restrictedMode;
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(restrictedMode);
when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo); when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);
when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending"); when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending");
mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
mFragment.onRadioButtonClicked(mOptimizePreference); mFragment.onPreferenceChange(mAllowBackgroundUsagePreference, true);
verify(mBatteryOptimizeUtils).setAppUsageState(optimizedMode, Action.APPLY);
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(optimizedMode);
mFragment.onPreferenceChange(mAllowBackgroundUsagePreference, false);
verify(mBatteryOptimizeUtils).setAppUsageState(restrictedMode, Action.APPLY);
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(restrictedMode);
mFragment.onPause(); mFragment.onPause();
TimeUnit.SECONDS.sleep(1); TimeUnit.SECONDS.sleep(1);

View File

@@ -0,0 +1,150 @@
/*
* Copyright (C) 2023 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;
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.when;
import android.content.Context;
import android.content.pm.PackageManager;
import com.android.settingslib.widget.MainSwitchPreference;
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 class AllowBackgroundPreferenceControllerTest {
private static final int UID = 12345;
private static final String PACKAGE_NAME = "com.android.app";
private AllowBackgroundPreferenceController mController;
private MainSwitchPreference mMainSwitchPreference;
private BatteryOptimizeUtils mBatteryOptimizeUtils;
@Mock private PackageManager mMockPackageManager;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
Context context = spy(RuntimeEnvironment.application);
BatteryUtils.getInstance(context).reset();
doReturn(UID)
.when(mMockPackageManager)
.getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
mController = new AllowBackgroundPreferenceController(context, UID, PACKAGE_NAME);
mMainSwitchPreference = new MainSwitchPreference(RuntimeEnvironment.application);
mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(context, UID, PACKAGE_NAME));
mController.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
}
@Test
public void testUpdateState_isValidPackage_prefEnabled() {
when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
mController.updateState(mMainSwitchPreference);
assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isTrue();
assertThat(mMainSwitchPreference.isEnabled()).isTrue();
}
@Test
public void testUpdateState_invalidPackage_prefDisabled() {
when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
mController.updateState(mMainSwitchPreference);
assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isFalse();
assertThat(mMainSwitchPreference.isEnabled()).isFalse();
}
@Test
public void testUpdateState_isSystemOrDefaultAppAndRestrictedStates_prefChecked() {
when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_RESTRICTED);
mController.updateState(mMainSwitchPreference);
assertThat(mMainSwitchPreference.isEnabled()).isFalse();
assertThat(mMainSwitchPreference.isChecked()).isFalse();
}
@Test
public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_OPTIMIZED);
mController.updateState(mMainSwitchPreference);
assertThat(mMainSwitchPreference.isEnabled()).isFalse();
assertThat(mMainSwitchPreference.isChecked()).isTrue();
}
@Test
public void testUpdateState_isRestrictedStates_prefChecked() {
when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_RESTRICTED);
mController.updateState(mMainSwitchPreference);
assertThat(mMainSwitchPreference.isEnabled()).isTrue();
assertThat(mMainSwitchPreference.isChecked()).isFalse();
}
@Test
public void testUpdateState_prefUnchecked() {
when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_OPTIMIZED);
mController.updateState(mMainSwitchPreference);
assertThat(mMainSwitchPreference.isEnabled()).isTrue();
assertThat(mMainSwitchPreference.isChecked()).isTrue();
}
@Test
public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
mMainSwitchPreference.setKey(
AllowBackgroundPreferenceController.KEY_ALLOW_BACKGROUND_USAGE);
mController.handlePreferenceTreeClick(mMainSwitchPreference);
assertThat(mController.handlePreferenceTreeClick(mMainSwitchPreference)).isTrue();
}
@Test
public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
assertThat(mController.handlePreferenceTreeClick(mMainSwitchPreference)).isFalse();
}
}

View File

@@ -121,6 +121,7 @@ public final class BatteryBackupHelperTest {
mContext = spy(RuntimeEnvironment.application); mContext = spy(RuntimeEnvironment.application);
mStringWriter = new StringWriter(); mStringWriter = new StringWriter();
mPrintWriter = new PrintWriter(mStringWriter); mPrintWriter = new PrintWriter(mStringWriter);
BatteryUtils.getInstance(mContext).reset();
doReturn(mContext).when(mContext).getApplicationContext(); doReturn(mContext).when(mContext).getApplicationContext();
doReturn(mAppOpsManager).when(mContext).getSystemService(AppOpsManager.class); doReturn(mAppOpsManager).when(mContext).getSystemService(AppOpsManager.class);
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class); doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);

View File

@@ -31,10 +31,8 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager;
import com.android.settings.TestUtils; import com.android.settings.TestUtils;
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry;
import com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleRadioButtonsController; import com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleRadioButtonsController;
import org.junit.After; import org.junit.After;
@@ -75,6 +73,7 @@ public final class BatterySettingsMigrateCheckerTest {
public void setUp() throws Exception { public void setUp() throws Exception {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application); mContext = spy(RuntimeEnvironment.application);
BatteryUtils.getInstance(mContext).reset();
doReturn(mContext).when(mContext).getApplicationContext(); doReturn(mContext).when(mContext).getApplicationContext();
doReturn(mPackageManager).when(mContext).getPackageManager(); doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(UID).when(mPackageManager) doReturn(UID).when(mPackageManager)

View File

@@ -18,8 +18,13 @@ package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat; 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.when; import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.PackageManager;
import com.android.settingslib.widget.SelectorWithWidgetPreference; import com.android.settingslib.widget.SelectorWithWidgetPreference;
import org.junit.Before; import org.junit.Before;
@@ -37,34 +42,41 @@ public class OptimizedPreferenceControllerTest {
private OptimizedPreferenceController mController; private OptimizedPreferenceController mController;
private SelectorWithWidgetPreference mPreference; private SelectorWithWidgetPreference mPreference;
private BatteryOptimizeUtils mBatteryOptimizeUtils;
@Mock BatteryOptimizeUtils mockBatteryOptimizeUtils; @Mock PackageManager mMockPackageManager;
@Before @Before
public void setUp() { public void setUp() throws Exception {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mController = new OptimizedPreferenceController( Context context = spy(RuntimeEnvironment.application);
RuntimeEnvironment.application, UID, PACKAGE_NAME); BatteryUtils.getInstance(context).reset();
doReturn(UID)
.when(mMockPackageManager)
.getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
mController = new OptimizedPreferenceController(context, UID, PACKAGE_NAME);
mPreference = new SelectorWithWidgetPreference(RuntimeEnvironment.application); mPreference = new SelectorWithWidgetPreference(RuntimeEnvironment.application);
mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils; mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(context, UID, PACKAGE_NAME));
mController.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
} }
@Test @Test
public void testUpdateState_invalidPackage_prefEnabled() { public void testUpdateState_invalidPackage_prefEnabled() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
mController.updateState(mPreference); mController.updateState(mPreference);
assertThat(mPreference.isEnabled()).isTrue(); assertThat(mPreference.isEnabled()).isFalse();
assertThat(mPreference.isChecked()).isTrue(); assertThat(mPreference.isChecked()).isTrue();
} }
@Test @Test
public void testUpdateState_isSystemOrDefaultAppAndOptimizeStates_prefChecked() { public void testUpdateState_isSystemOrDefaultAppAndOptimizeStates_prefChecked() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true); when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn( when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_OPTIMIZED); BatteryOptimizeUtils.MODE_OPTIMIZED);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -74,8 +86,8 @@ public class OptimizedPreferenceControllerTest {
@Test @Test
public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() { public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true); when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -85,8 +97,8 @@ public class OptimizedPreferenceControllerTest {
@Test @Test
public void testUpdateState_isOptimizedStates_prefChecked() { public void testUpdateState_isOptimizedStates_prefChecked() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn( when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_OPTIMIZED); BatteryOptimizeUtils.MODE_OPTIMIZED);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -96,7 +108,7 @@ public class OptimizedPreferenceControllerTest {
@Test @Test
public void testUpdateState_prefUnchecked() { public void testUpdateState_prefUnchecked() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
mController.updateState(mPreference); mController.updateState(mPreference);

View File

@@ -0,0 +1,285 @@
/*
* Copyright (C) 2023 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;
import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS;
import static com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
import android.app.backup.BackupManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.widget.Switch;
import androidx.fragment.app.FragmentActivity;
import androidx.loader.app.LoaderManager;
import com.android.settings.SettingsActivity;
import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
import com.android.settings.testutils.shadow.ShadowActivityManager;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.LayoutPreference;
import com.android.settingslib.widget.MainSwitchPreference;
import com.android.settingslib.widget.SelectorWithWidgetPreference;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
ShadowEntityHeaderController.class,
ShadowActivityManager.class,
com.android.settings.testutils.shadow.ShadowFragment.class,
})
public class PowerBackgroundUsageDetailTest {
private static final String APP_LABEL = "app label";
private static final String SUMMARY = "summary";
private static final int ICON_ID = 123;
private static final int UID = 1;
private static final String KEY_PREF_UNRESTRICTED = "unrestricted_preference";
private static final String KEY_PREF_OPTIMIZED = "optimized_preference";
private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
private Context mContext;
private PowerBackgroundUsageDetail mFragment;
private FooterPreference mFooterPreference;
private MainSwitchPreference mMainSwitchPreference;
private SelectorWithWidgetPreference mOptimizePreference;
private SelectorWithWidgetPreference mUnrestrictedPreference;
private SettingsActivity mTestActivity;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private FragmentActivity mActivity;
@Mock
private EntityHeaderController mEntityHeaderController;
@Mock
private BatteryOptimizeUtils mBatteryOptimizeUtils;
@Mock
private LayoutPreference mHeaderPreference;
@Mock
private ApplicationsState mState;
@Mock
private Bundle mBundle;
@Mock
private LoaderManager mLoaderManager;
@Mock
private ApplicationsState.AppEntry mAppEntry;
@Mock
private BatteryEntry mBatteryEntry;
@Mock
private BackupManager mBackupManager;
@Mock
private PackageManager mPackageManager;
@Mock
private AppOpsManager mAppOpsManager;
@Mock
private Switch mMockSwitch;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
when(mContext.getPackageName()).thenReturn("foo");
mFragment = spy(new PowerBackgroundUsageDetail());
doReturn(mContext).when(mFragment).getContext();
doReturn(mActivity).when(mFragment).getActivity();
doReturn(SUMMARY).when(mFragment).getString(anyInt());
doReturn(APP_LABEL).when(mBundle).getString(nullable(String.class));
when(mFragment.getArguments()).thenReturn(mBundle);
doReturn(mLoaderManager).when(mFragment).getLoaderManager();
ShadowEntityHeaderController.setUseMock(mEntityHeaderController);
doReturn(mEntityHeaderController).when(mEntityHeaderController)
.setButtonActions(anyInt(), anyInt());
doReturn(mEntityHeaderController).when(mEntityHeaderController)
.setIcon(nullable(Drawable.class));
doReturn(mEntityHeaderController).when(mEntityHeaderController).setIcon(nullable(
ApplicationsState.AppEntry.class));
doReturn(mEntityHeaderController).when(mEntityHeaderController)
.setLabel(nullable(String.class));
doReturn(mEntityHeaderController).when(mEntityHeaderController)
.setLabel(nullable(String.class));
doReturn(mEntityHeaderController).when(mEntityHeaderController)
.setLabel(nullable(ApplicationsState.AppEntry.class));
doReturn(mEntityHeaderController).when(mEntityHeaderController)
.setSummary(nullable(String.class));
when(mBatteryEntry.getUid()).thenReturn(UID);
when(mBatteryEntry.getLabel()).thenReturn(APP_LABEL);
mBatteryEntry.mIconId = ICON_ID;
mFragment.mHeaderPreference = mHeaderPreference;
mFragment.mState = mState;
mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
mFragment.mBackupManager = mBackupManager;
mAppEntry.info = mock(ApplicationInfo.class);
mTestActivity = spy(new SettingsActivity());
doReturn(mPackageManager).when(mTestActivity).getPackageManager();
doReturn(mPackageManager).when(mActivity).getPackageManager();
doReturn(mAppOpsManager).when(mTestActivity).getSystemService(Context.APP_OPS_SERVICE);
final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
Answer<Void> callable = invocation -> {
mBundle = captor.getValue().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
System.out.println("mBundle = " + mBundle);
return null;
};
doAnswer(callable).when(mActivity).startActivityAsUser(captor.capture(),
nullable(UserHandle.class));
doAnswer(callable).when(mActivity).startActivity(captor.capture());
mFooterPreference = spy(new FooterPreference(mContext));
mMainSwitchPreference = spy(new MainSwitchPreference(mContext));
mMainSwitchPreference.setKey(KEY_ALLOW_BACKGROUND_USAGE);
mOptimizePreference = spy(new SelectorWithWidgetPreference(mContext));
mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
mUnrestrictedPreference = spy(new SelectorWithWidgetPreference(mContext));
mUnrestrictedPreference.setKey(KEY_PREF_UNRESTRICTED);
mFragment.mFooterPreference = mFooterPreference;
mFragment.mMainSwitchPreference = mMainSwitchPreference;
mFragment.mOptimizePreference = mOptimizePreference;
mFragment.mUnrestrictedPreference = mUnrestrictedPreference;
}
@After
public void reset() {
ShadowEntityHeaderController.reset();
}
@Test
public void initHeader_NoAppEntry_BuildByBundle() {
mFragment.mAppEntry = null;
mFragment.initHeader();
verify(mEntityHeaderController).setIcon(nullable(Drawable.class));
verify(mEntityHeaderController).setLabel(APP_LABEL);
}
@Test
public void initHeader_HasAppEntry_BuildByAppEntry() {
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
new InstantAppDataProvider() {
@Override
public boolean isInstantApp(ApplicationInfo info) {
return false;
}
});
mFragment.mAppEntry = mAppEntry;
mFragment.initHeader();
verify(mEntityHeaderController).setIcon(mAppEntry);
verify(mEntityHeaderController).setLabel(mAppEntry);
verify(mEntityHeaderController).setIsInstantApp(false);
}
@Test
public void initHeader_HasAppEntry_InstantApp() {
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
new InstantAppDataProvider() {
@Override
public boolean isInstantApp(ApplicationInfo info) {
return true;
}
});
mFragment.mAppEntry = mAppEntry;
mFragment.initHeader();
verify(mEntityHeaderController).setIcon(mAppEntry);
verify(mEntityHeaderController).setLabel(mAppEntry);
verify(mEntityHeaderController).setIsInstantApp(true);
}
@Test
public void initFooter_hasCorrectString() {
when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
mFragment.initFooter();
assertThat(mFooterPreference.getTitle().toString())
.isEqualTo("Changing how an app uses your battery can affect its performance.");
}
@Test
public void onSwitchChanged_fromUnrestrictedModeSetDisabled_becomeRestrictedMode() {
final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
mFragment.mOptimizationMode = optimizedMode;
mFragment.onSwitchChanged(mMockSwitch, /*isChecked=*/ false);
verify(mOptimizePreference).setEnabled(false);
verify(mUnrestrictedPreference).setEnabled(false);
verify(mFragment).onRadioButtonClicked(null);
verify(mMainSwitchPreference).setChecked(false);
assertThat(mFragment.getSelectedPreference()).isEqualTo(restrictedMode);
verify(mBatteryOptimizeUtils).setAppUsageState(restrictedMode, Action.APPLY);
}
@Test
public void onSwitchChanged_fromRestrictedModeSetEnabled_becomeOptimizedMode() {
final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
mFragment.mOptimizationMode = restrictedMode;
mFragment.onSwitchChanged(mMockSwitch, /*isChecked=*/ true);
verify(mOptimizePreference).setEnabled(true);
verify(mUnrestrictedPreference).setEnabled(true);
verify(mFragment).onRadioButtonClicked(mOptimizePreference);
verify(mMainSwitchPreference).setChecked(true);
verify(mOptimizePreference).setChecked(true);
assertThat(mFragment.getSelectedPreference()).isEqualTo(optimizedMode);
verify(mBatteryOptimizeUtils).setAppUsageState(optimizedMode, Action.APPLY);
}
}

View File

@@ -1,126 +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;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import com.android.settingslib.widget.SelectorWithWidgetPreference;
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 class RestrictedPreferenceControllerTest {
private static final int UID = 12345;
private static final String PACKAGE_NAME = "com.android.app";
private RestrictedPreferenceController mController;
private SelectorWithWidgetPreference mPreference;
@Mock BatteryOptimizeUtils mockBatteryOptimizeUtils;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mController = new RestrictedPreferenceController(
RuntimeEnvironment.application, UID, PACKAGE_NAME);
mPreference = new SelectorWithWidgetPreference(RuntimeEnvironment.application);
mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils;
}
@Test
public void testUpdateState_isValidPackage_prefEnabled() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
mController.updateState(mPreference);
assertThat(mPreference.isEnabled()).isTrue();
}
@Test
public void testUpdateState_invalidPackage_prefDisabled() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
mController.updateState(mPreference);
assertThat(mPreference.isEnabled()).isFalse();
}
@Test
public void testUpdateState_isSystemOrDefaultAppAndRestrictedStates_prefChecked() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_RESTRICTED);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isTrue();
}
@Test
public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isFalse();
assertThat(mPreference.isEnabled()).isFalse();
}
@Test
public void testUpdateState_isRestrictedStates_prefChecked() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_RESTRICTED);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isTrue();
}
@Test
public void testUpdateState_prefUnchecked() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isFalse();
}
@Test
public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
mPreference.setKey(mController.KEY_RESTRICTED_PREF);
mController.handlePreferenceTreeClick(mPreference);
assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
}
@Test
public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
}
}

View File

@@ -18,8 +18,13 @@ package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat; 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.when; import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.PackageManager;
import com.android.settingslib.widget.SelectorWithWidgetPreference; import com.android.settingslib.widget.SelectorWithWidgetPreference;
import org.junit.Before; import org.junit.Before;
@@ -37,42 +42,53 @@ public class UnrestrictedPreferenceControllerTest {
private UnrestrictedPreferenceController mController; private UnrestrictedPreferenceController mController;
private SelectorWithWidgetPreference mPreference; private SelectorWithWidgetPreference mPreference;
private BatteryOptimizeUtils mBatteryOptimizeUtils;
@Mock BatteryOptimizeUtils mockBatteryOptimizeUtils; @Mock PackageManager mMockPackageManager;
@Before @Before
public void setUp() { public void setUp() throws Exception {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mController = new UnrestrictedPreferenceController( Context context = spy(RuntimeEnvironment.application);
RuntimeEnvironment.application, UID, PACKAGE_NAME); BatteryUtils.getInstance(context).reset();
doReturn(UID)
.when(mMockPackageManager)
.getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
mController = new UnrestrictedPreferenceController(context, UID, PACKAGE_NAME);
mPreference = new SelectorWithWidgetPreference(RuntimeEnvironment.application); mPreference = new SelectorWithWidgetPreference(RuntimeEnvironment.application);
mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils; mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(context, UID, PACKAGE_NAME));
mController.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
} }
@Test @Test
public void testUpdateState_isValidPackage_prefEnabled() { public void testUpdateState_isValidPackage_prefEnabled() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
mController.updateState(mPreference); mController.updateState(mPreference);
assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isTrue();
assertThat(mPreference.isEnabled()).isTrue(); assertThat(mPreference.isEnabled()).isTrue();
} }
@Test @Test
public void testUpdateState_invalidPackage_prefDisabled() { public void testUpdateState_invalidPackage_prefDisabled() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
mController.updateState(mPreference); mController.updateState(mPreference);
assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isFalse();
assertThat(mPreference.isEnabled()).isFalse(); assertThat(mPreference.isEnabled()).isFalse();
} }
@Test @Test
public void testUpdateState_isSystemOrDefaultAppAndUnrestrictedStates_prefChecked() { public void testUpdateState_isSystemOrDefaultAppAndUnrestrictedStates_prefChecked() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true); when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn( when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_UNRESTRICTED); BatteryOptimizeUtils.MODE_UNRESTRICTED);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -82,32 +98,38 @@ public class UnrestrictedPreferenceControllerTest {
@Test @Test
public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() { public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false); when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true); when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_OPTIMIZED);
mController.updateState(mPreference); mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isFalse();
assertThat(mPreference.isEnabled()).isFalse(); assertThat(mPreference.isEnabled()).isFalse();
assertThat(mPreference.isChecked()).isFalse();
} }
@Test @Test
public void testUpdateState_isUnrestrictedStates_prefChecked() { public void testUpdateState_isUnrestrictedStates_prefChecked() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false); when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn( when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_UNRESTRICTED); BatteryOptimizeUtils.MODE_UNRESTRICTED);
mController.updateState(mPreference); mController.updateState(mPreference);
assertThat(mPreference.isEnabled()).isTrue();
assertThat(mPreference.isChecked()).isTrue(); assertThat(mPreference.isChecked()).isTrue();
} }
@Test @Test
public void testUpdateState_prefUnchecked() { public void testUpdateState_prefUnchecked() {
when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false); when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_OPTIMIZED);
mController.updateState(mPreference); mController.updateState(mPreference);
assertThat(mPreference.isEnabled()).isTrue();
assertThat(mPreference.isChecked()).isFalse(); assertThat(mPreference.isChecked()).isFalse();
} }

View File

@@ -82,6 +82,7 @@ public final class BatteryDiffEntryTest {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
ShadowUserHandle.reset(); ShadowUserHandle.reset();
mContext = spy(RuntimeEnvironment.application); mContext = spy(RuntimeEnvironment.application);
BatteryUtils.getInstance(mContext).reset();
doReturn(mContext).when(mContext).getApplicationContext(); doReturn(mContext).when(mContext).getApplicationContext();
doReturn(mMockUserManager).when(mContext).getSystemService(UserManager.class); doReturn(mMockUserManager).when(mContext).getSystemService(UserManager.class);
doReturn(mMockPackageManager).when(mContext).getPackageManager(); doReturn(mMockPackageManager).when(mContext).getPackageManager();
@@ -461,9 +462,6 @@ public final class BatteryDiffEntryTest {
@Test @Test
public void testIsUninstalledEntry_uninstalledApp_returnTrue() throws Exception { public void testIsUninstalledEntry_uninstalledApp_returnTrue() throws Exception {
doReturn(BatteryUtils.UID_NULL)
.when(mMockPackageManager)
.getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
final ContentValues values = final ContentValues values =
getContentValuesWithType(ConvertUtils.CONSUMER_TYPE_UID_BATTERY); getContentValuesWithType(ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
values.put(BatteryHistEntry.KEY_UID, UNINSTALLED_UID); values.put(BatteryHistEntry.KEY_UID, UNINSTALLED_UID);