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

@@ -27,10 +27,13 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import com.android.settings.R;
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.overlay.FeatureFactory;
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.ApplicationsState;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.instrumentation.Instrumentable;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.LayoutPreference;
import com.android.settingslib.widget.SelectorWithWidgetPreference;
import java.util.ArrayList;
import java.util.List;
@@ -67,8 +68,8 @@ import java.util.concurrent.Executors;
*/
public class AdvancedPowerUsageDetail extends DashboardFragment implements
ButtonActionDialogFragment.AppButtonsDialogListener,
SelectorWithWidgetPreference.OnClickListener {
Preference.OnPreferenceClickListener,
Preference.OnPreferenceChangeListener {
public static final String TAG = "AdvancedPowerDetail";
public static final String EXTRA_UID = "extra_uid";
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";
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";
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 String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
private static final int REQUEST_UNINSTALL = 0;
private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1;
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
private AppButtonsPreferenceController mAppButtonsPreferenceController;
private PowerUsageTimeController mPowerUsageTimeController;
@VisibleForTesting
LayoutPreference mHeaderPreference;
@VisibleForTesting
@@ -107,13 +105,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
@VisibleForTesting
BatteryOptimizeUtils mBatteryOptimizeUtils;
@VisibleForTesting
FooterPreference mFooterPreference;
@VisibleForTesting
SelectorWithWidgetPreference mRestrictedPreference;
@VisibleForTesting
SelectorWithWidgetPreference mOptimizePreference;
@VisibleForTesting
SelectorWithWidgetPreference mUnrestrictedPreference;
PrimarySwitchPreference mAllowBackgroundUsagePreference;
@VisibleForTesting
@BatteryOptimizeUtils.OptimizationMode
int mOptimizationMode = BatteryOptimizeUtils.MODE_UNKNOWN;
@@ -122,9 +114,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
@VisibleForTesting
StringBuilder mLogStringBuilder;
private AppButtonsPreferenceController mAppButtonsPreferenceController;
private PowerUsageTimeController mPowerUsageTimeController;
// A wrapper class to carry LaunchBatteryDetailPage required arguments.
private static final class LaunchBatteryDetailPageArgs {
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_TEXT, launchArgs.mAnomalyHintText);
final int userId = launchArgs.mIsUserEntry ? ActivityManager.getCurrentUser()
: UserHandle.getUserId(launchArgs.mUid);
: UserHandle.getUserId(launchArgs.mUid);
new SubSettingLauncher(context)
.setDestination(AdvancedPowerUsageDetail.class.getName())
@@ -257,7 +246,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
super.onCreate(icicle);
final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
onCreateForTriState(packageName);
onCreateBackgroundUsageState(packageName);
mHeaderPreference = findPreference(KEY_PREF_HEADER);
if (packageName != null) {
@@ -271,10 +260,10 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
initHeader();
mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
initPreferenceForTriState(getContext());
initFooter();
mExecutor.execute(() -> {
String packageName =
getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
final String packageName = BatteryUtils
.getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
.action(
getContext(),
@@ -288,11 +277,10 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
public void onPause() {
super.onPause();
final int selectedPreference = getSelectedPreference();
notifyBackupManager();
mLogStringBuilder.append(", onPause mode = ").append(selectedPreference);
logMetricCategory(selectedPreference);
final int currentOptimizeMode = mBatteryOptimizeUtils.getAppOptimizationMode();
mLogStringBuilder.append(", onPause mode = ").append(currentOptimizeMode);
logMetricCategory(currentOptimizeMode);
mExecutor.execute(() -> {
BatteryOptimizeLogUtils.writeLog(
@@ -302,7 +290,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
mBatteryOptimizeUtils.getPackageName(), UserHandle.myUserId()),
mLogStringBuilder.toString());
});
Log.d(TAG, "Leave with mode: " + selectedPreference);
Log.d(TAG, "Leave with mode: " + currentOptimizeMode);
}
@VisibleForTesting
@@ -353,33 +341,28 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
}
@VisibleForTesting
void initPreferenceForTriState(Context context) {
void initFooter() {
final String stateString;
final String footerString;
final String detailInfoString;
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);
detailInfoString =
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);
detailInfoString =
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));
detailInfoString =
context.getString(
R.string.manager_battery_usage_allow_background_usage_summary);
}
mAllowBackgroundUsagePreference.setSummary(detailInfoString);
}
@Override
@@ -412,9 +395,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
controllers.add(mPowerUsageTimeController);
}
controllers.add(mAppButtonsPreferenceController);
controllers.add(new UnrestrictedPreferenceController(context, uid, packageName));
controllers.add(new OptimizedPreferenceController(context, uid, packageName));
controllers.add(new RestrictedPreferenceController(context, uid, packageName));
controllers.add(new AllowBackgroundPreferenceController(context, uid, packageName));
return controllers;
}
@@ -435,34 +416,45 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
}
@Override
public void onRadioButtonClicked(SelectorWithWidgetPreference selected) {
final String selectedKey = selected.getKey();
updatePreferenceState(mUnrestrictedPreference, selectedKey);
updatePreferenceState(mOptimizePreference, selectedKey);
updatePreferenceState(mRestrictedPreference, selectedKey);
mBatteryOptimizeUtils.setAppUsageState(getSelectedPreference(), Action.APPLY);
public boolean onPreferenceClick(Preference preference) {
if (!(preference instanceof PrimarySwitchPreference)
|| !TextUtils.equals(preference.getKey(), KEY_ALLOW_BACKGROUND_USAGE)) {
return false;
}
PowerBackgroundUsageDetail.startPowerBackgroundUsageDetailPage(
getContext(), getArguments());
return true;
}
private void updatePreferenceState(SelectorWithWidgetPreference preference,
String selectedKey) {
preference.setChecked(selectedKey.equals(preference.getKey()));
@Override
public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
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) {
if (selectedKey == mOptimizationMode) {
private void logMetricCategory(int currentOptimizeMode) {
if (currentOptimizeMode == mOptimizationMode) {
return;
}
int metricCategory = 0;
switch (selectedKey) {
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;
metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_ALLOW_BACKGROUND;
break;
case BatteryOptimizeUtils.MODE_RESTRICTED:
metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_RESTRICTED;
metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_DISABLE_BACKGROUND;
break;
}
if (metricCategory == 0) {
@@ -470,8 +462,8 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
}
int finalMetricCategory = metricCategory;
mExecutor.execute(() -> {
String packageName =
getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
String packageName = BatteryUtils
.getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
.action(
/* attribution */ SettingsEnums.OPEN_APP_BATTERY_USAGE,
@@ -482,33 +474,15 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
});
}
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);
}
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 void onCreateBackgroundUsageState(String packageName) {
mAllowBackgroundUsagePreference = findPreference(KEY_ALLOW_BACKGROUND_USAGE);
if (mAllowBackgroundUsagePreference != null) {
mAllowBackgroundUsagePreference.setOnPreferenceClickListener(this);
mAllowBackgroundUsagePreference.setOnPreferenceChangeListener(this);
}
}
private static String getLoggingPackageName(Context context, String originalPackingName) {
return BatteryUtils.isAppInstalledFromGooglePlayStore(context, originalPackingName)
? originalPackingName : PACKAGE_NAME_NONE;
mBatteryOptimizeUtils =
new BatteryOptimizeUtils(
getContext(), getArguments().getInt(EXTRA_UID), packageName);
}
}