Merge 25Q1 (ab/12770256) to aosp-main-future
Bug: 385190204 Merged-In: Iaee6792d1a27be8fa4b443f783a47a3715b6d3a1 Change-Id: I0ac29cecfec526a38cf4a120b8ef704ee7bc01b3
This commit is contained in:
@@ -26,17 +26,12 @@ 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;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.appinfo.AppButtonsPreferenceController;
|
||||
import com.android.settings.applications.appinfo.ButtonActionDialogFragment;
|
||||
import com.android.settings.core.InstrumentedPreferenceFragment;
|
||||
@@ -47,13 +42,11 @@ import com.android.settings.fuelgauge.batteryusage.AppOptModeSharedPreferencesUt
|
||||
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.PrimarySwitchPreference;
|
||||
import com.android.settingslib.applications.AppUtils;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.Instrumentable;
|
||||
import com.android.settingslib.widget.LayoutPreference;
|
||||
import com.android.settingslib.widget.IntroPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -67,9 +60,7 @@ import java.util.concurrent.Executors;
|
||||
* 2. Battery related controls for app(i.e uninstall, force stop)
|
||||
*/
|
||||
public class AdvancedPowerUsageDetail extends DashboardFragment
|
||||
implements ButtonActionDialogFragment.AppButtonsDialogListener,
|
||||
Preference.OnPreferenceClickListener,
|
||||
Preference.OnPreferenceChangeListener {
|
||||
implements ButtonActionDialogFragment.AppButtonsDialogListener {
|
||||
public static final String TAG = "AdvancedPowerDetail";
|
||||
public static final String EXTRA_UID = "extra_uid";
|
||||
public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
|
||||
@@ -86,7 +77,8 @@ public class AdvancedPowerUsageDetail extends DashboardFragment
|
||||
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_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
|
||||
private static final String KEY_BACKGROUND_USAGE_ALLOWABILITY_CATEGORY =
|
||||
"background_usage_allowability_category";
|
||||
|
||||
private static final int REQUEST_UNINSTALL = 0;
|
||||
private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1;
|
||||
@@ -96,11 +88,9 @@ public class AdvancedPowerUsageDetail extends DashboardFragment
|
||||
private AppButtonsPreferenceController mAppButtonsPreferenceController;
|
||||
private PowerUsageTimeController mPowerUsageTimeController;
|
||||
|
||||
@VisibleForTesting LayoutPreference mHeaderPreference;
|
||||
@VisibleForTesting ApplicationsState mState;
|
||||
@VisibleForTesting ApplicationsState.AppEntry mAppEntry;
|
||||
@VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
|
||||
@VisibleForTesting PrimarySwitchPreference mAllowBackgroundUsagePreference;
|
||||
|
||||
@VisibleForTesting @BatteryOptimizeUtils.OptimizationMode
|
||||
int mOptimizationMode = BatteryOptimizeUtils.MODE_UNKNOWN;
|
||||
@@ -242,17 +232,11 @@ public class AdvancedPowerUsageDetail extends DashboardFragment
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
|
||||
final Bundle bundle = getArguments();
|
||||
final int uid = bundle.getInt(EXTRA_UID, 0);
|
||||
final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
|
||||
mBatteryOptimizeUtils = new BatteryOptimizeUtils(getContext(), uid, packageName);
|
||||
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());
|
||||
}
|
||||
@@ -264,7 +248,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment
|
||||
|
||||
initHeader();
|
||||
mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
|
||||
initFooter();
|
||||
mLogStringBuilder = new StringBuilder("onResume mode = ").append(mOptimizationMode);
|
||||
}
|
||||
|
||||
@@ -299,29 +282,26 @@ public class AdvancedPowerUsageDetail extends DashboardFragment
|
||||
|
||||
@VisibleForTesting
|
||||
void initHeader() {
|
||||
final View appSnippet = mHeaderPreference.findViewById(R.id.entity_header);
|
||||
final IntroPreference introPreference = findPreference(KEY_PREF_HEADER);
|
||||
if (introPreference == null) {
|
||||
return;
|
||||
}
|
||||
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));
|
||||
introPreference.setTitle(bundle.getString(EXTRA_LABEL));
|
||||
|
||||
final int iconId = bundle.getInt(EXTRA_ICON_ID, 0);
|
||||
if (iconId == 0) {
|
||||
controller.setIcon(context.getPackageManager().getDefaultActivityIcon());
|
||||
introPreference.setIcon(context.getPackageManager().getDefaultActivityIcon());
|
||||
} else {
|
||||
controller.setIcon(context.getDrawable(bundle.getInt(EXTRA_ICON_ID)));
|
||||
introPreference.setIcon(context.getDrawable(bundle.getInt(EXTRA_ICON_ID)));
|
||||
}
|
||||
} else {
|
||||
mState.ensureIcon(mAppEntry);
|
||||
controller.setLabel(mAppEntry);
|
||||
controller.setIcon(mAppEntry);
|
||||
controller.setIsInstantApp(AppUtils.isInstant(mAppEntry.info));
|
||||
introPreference.setTitle(mAppEntry.label);
|
||||
introPreference.setIcon(Utils.getBadgedIcon(context, mAppEntry.info));
|
||||
}
|
||||
|
||||
if (mPowerUsageTimeController != null) {
|
||||
@@ -337,32 +317,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment
|
||||
anomalyHintPrefKey,
|
||||
anomalyHintText);
|
||||
}
|
||||
controller.done(true /* rebindActions */);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void initFooter() {
|
||||
final String stateString;
|
||||
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);
|
||||
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);
|
||||
detailInfoString =
|
||||
context.getString(R.string.manager_battery_usage_footer_limited, stateString);
|
||||
} else {
|
||||
// Present default string to normal app.
|
||||
detailInfoString =
|
||||
context.getString(
|
||||
R.string.manager_battery_usage_allow_background_usage_summary);
|
||||
}
|
||||
mAllowBackgroundUsagePreference.setSummary(detailInfoString);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -384,7 +338,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment
|
||||
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);
|
||||
|
||||
mAppButtonsPreferenceController =
|
||||
@@ -401,7 +354,12 @@ public class AdvancedPowerUsageDetail extends DashboardFragment
|
||||
controllers.add(mPowerUsageTimeController);
|
||||
}
|
||||
controllers.add(mAppButtonsPreferenceController);
|
||||
controllers.add(new AllowBackgroundPreferenceController(context, uid, packageName));
|
||||
controllers.add(
|
||||
new BackgroundUsageAllowabilityPreferenceController(
|
||||
context,
|
||||
/* dashboardFragment= */ this,
|
||||
KEY_BACKGROUND_USAGE_ALLOWABILITY_CATEGORY,
|
||||
mBatteryOptimizeUtils));
|
||||
|
||||
return controllers;
|
||||
}
|
||||
@@ -421,34 +379,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@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 currentOptimizeMode) {
|
||||
if (currentOptimizeMode == mOptimizationMode) {
|
||||
return;
|
||||
@@ -482,16 +412,4 @@ public class AdvancedPowerUsageDetail extends DashboardFragment
|
||||
getArguments().getInt(EXTRA_POWER_USAGE_AMOUNT));
|
||||
});
|
||||
}
|
||||
|
||||
private void onCreateBackgroundUsageState(String packageName) {
|
||||
mAllowBackgroundUsagePreference = findPreference(KEY_ALLOW_BACKGROUND_USAGE);
|
||||
if (mAllowBackgroundUsagePreference != null) {
|
||||
mAllowBackgroundUsagePreference.setOnPreferenceClickListener(this);
|
||||
mAllowBackgroundUsagePreference.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
mBatteryOptimizeUtils =
|
||||
new BatteryOptimizeUtils(
|
||||
getContext(), getArguments().getInt(EXTRA_UID), packageName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* 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 android.content.Context;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.PrimarySwitchPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.widget.MainSwitchPreference;
|
||||
|
||||
/** Controller to update the app background usage state */
|
||||
public class AllowBackgroundPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private static final String TAG = "AllowBackgroundPreferenceController";
|
||||
|
||||
@VisibleForTesting static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
|
||||
|
||||
@VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
|
||||
|
||||
public AllowBackgroundPreferenceController(Context context, int uid, String packageName) {
|
||||
super(context);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private void setEnabled(Preference preference, boolean enabled) {
|
||||
if (preference instanceof PrimarySwitchPreference) {
|
||||
((PrimarySwitchPreference) preference).setEnabled(enabled);
|
||||
((PrimarySwitchPreference) preference).setSwitchEnabled(enabled);
|
||||
} else if (preference instanceof MainSwitchPreference) {
|
||||
((MainSwitchPreference) preference).setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
setEnabled(preference, mBatteryOptimizeUtils.isOptimizeModeMutable());
|
||||
|
||||
final boolean isAllowBackground =
|
||||
mBatteryOptimizeUtils.getAppOptimizationMode()
|
||||
!= BatteryOptimizeUtils.MODE_RESTRICTED;
|
||||
setChecked(preference, isAllowBackground);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_ALLOW_BACKGROUND_USAGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlePreferenceTreeClick(Preference preference) {
|
||||
return getPreferenceKey().equals(preference.getKey());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settingslib.PrimarySwitchPreference;
|
||||
|
||||
/** Controller to update the manage battery usage preference in App Battery Usage page */
|
||||
public class BackgroundUsageAllowabilityPreferenceController extends BasePreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
@VisibleForTesting
|
||||
static final String KEY_BACKGROUND_USAGE_ALLOWABILITY_SWITCH =
|
||||
"background_usage_allowability_switch";
|
||||
|
||||
private final BatteryOptimizeUtils mBatteryOptimizeUtils;
|
||||
private final DashboardFragment mDashboardFragment;
|
||||
@Nullable @VisibleForTesting PrimarySwitchPreference mBackgroundUsageAllowabilityPreference;
|
||||
|
||||
public BackgroundUsageAllowabilityPreferenceController(
|
||||
@NonNull Context context,
|
||||
@NonNull DashboardFragment dashboardFragment,
|
||||
@NonNull String preferenceKey,
|
||||
@NonNull BatteryOptimizeUtils batteryOptimizeUtils) {
|
||||
super(context, preferenceKey);
|
||||
mDashboardFragment = dashboardFragment;
|
||||
mBatteryOptimizeUtils = batteryOptimizeUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(@NonNull Preference preference) {
|
||||
updatePreferences(mBatteryOptimizeUtils.getAppOptimizationMode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(@NonNull PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mBackgroundUsageAllowabilityPreference =
|
||||
screen.findPreference(KEY_BACKGROUND_USAGE_ALLOWABILITY_SWITCH);
|
||||
initPreferences();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void initPreferences() {
|
||||
if (mBackgroundUsageAllowabilityPreference == null) {
|
||||
return;
|
||||
}
|
||||
final String stateString;
|
||||
final String detailInfoString;
|
||||
boolean isPreferenceEnabled = true;
|
||||
if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
|
||||
// Present "Optimized" only string if the package name is invalid.
|
||||
stateString = mContext.getString(R.string.manager_battery_usage_optimized_only);
|
||||
detailInfoString =
|
||||
mContext.getString(R.string.manager_battery_usage_footer_limited, stateString);
|
||||
isPreferenceEnabled = false;
|
||||
} else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
|
||||
// Present "Unrestricted" only string if the package is system important apps.
|
||||
stateString = mContext.getString(R.string.manager_battery_usage_unrestricted_only);
|
||||
detailInfoString =
|
||||
mContext.getString(R.string.manager_battery_usage_footer_limited, stateString);
|
||||
isPreferenceEnabled = false;
|
||||
} else {
|
||||
// Present default string to normal app.
|
||||
detailInfoString =
|
||||
mContext.getString(
|
||||
R.string.manager_battery_usage_allow_background_usage_summary);
|
||||
}
|
||||
mBackgroundUsageAllowabilityPreference.setEnabled(isPreferenceEnabled);
|
||||
mBackgroundUsageAllowabilityPreference.setSwitchEnabled(isPreferenceEnabled);
|
||||
mBackgroundUsageAllowabilityPreference.setSummary(detailInfoString);
|
||||
if (isPreferenceEnabled) {
|
||||
mBackgroundUsageAllowabilityPreference.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
PowerBackgroundUsageDetail.startPowerBackgroundUsageDetailPage(
|
||||
mContext, mDashboardFragment.getArguments());
|
||||
return true;
|
||||
});
|
||||
mBackgroundUsageAllowabilityPreference.setOnPreferenceChangeListener(
|
||||
(preference, isAllowBackground) -> {
|
||||
handleBatteryOptimizeModeUpdated(
|
||||
(boolean) isAllowBackground
|
||||
? BatteryOptimizeUtils.MODE_OPTIMIZED
|
||||
: BatteryOptimizeUtils.MODE_RESTRICTED);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void handleBatteryOptimizeModeUpdated(int newBatteryOptimizeMode) {
|
||||
if (mBatteryOptimizeUtils.getAppOptimizationMode() == newBatteryOptimizeMode) {
|
||||
Log.w(TAG, "ignore same mode for: " + mBatteryOptimizeUtils.getPackageName());
|
||||
return;
|
||||
}
|
||||
mBatteryOptimizeUtils.setAppUsageState(
|
||||
newBatteryOptimizeMode, BatteryOptimizeHistoricalLogEntry.Action.APPLY);
|
||||
updatePreferences(newBatteryOptimizeMode);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void updatePreferences(int optimizationMode) {
|
||||
if (mBackgroundUsageAllowabilityPreference == null) {
|
||||
return;
|
||||
}
|
||||
mBackgroundUsageAllowabilityPreference.setChecked(
|
||||
optimizationMode != BatteryOptimizeUtils.MODE_RESTRICTED);
|
||||
}
|
||||
}
|
||||
@@ -196,7 +196,9 @@ public final class BatteryBackupHelper implements BackupHelper {
|
||||
appOptModeMap.containsKey(info.uid)
|
||||
? (int) appOptModeMap.get(info.uid).getResetOptimizationMode()
|
||||
: BatteryOptimizeUtils.getAppOptimizationMode(
|
||||
mode, allowlistedApps.contains(info.packageName));
|
||||
mode,
|
||||
allowlistedApps.contains(info.packageName),
|
||||
/* ignoreUnknownMode= */ false);
|
||||
// Ignores default optimized/unknown state or system/default apps.
|
||||
if (optimizationMode == BatteryOptimizeUtils.MODE_OPTIMIZED
|
||||
|| optimizationMode == BatteryOptimizeUtils.MODE_UNKNOWN
|
||||
|
||||
126
src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt
Normal file
126
src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 android.content.Context
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.preference.Preference
|
||||
import com.android.settings.R
|
||||
import com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_NOT_PRESENT
|
||||
import com.android.settingslib.Utils
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.NoOpKeyedObservable
|
||||
import com.android.settingslib.fuelgauge.BatteryUtils
|
||||
import com.android.settingslib.metadata.PersistentPreference
|
||||
import com.android.settingslib.metadata.PreferenceLifecycleContext
|
||||
import com.android.settingslib.metadata.PreferenceLifecycleProvider
|
||||
import com.android.settingslib.metadata.PreferenceMetadata
|
||||
import com.android.settingslib.metadata.RangeValue
|
||||
import com.android.settingslib.metadata.ReadWritePermit
|
||||
import com.android.settingslib.preference.PreferenceBinding
|
||||
import com.android.settingslib.widget.UsageProgressBarPreference
|
||||
|
||||
// LINT.IfChange
|
||||
class BatteryHeaderPreference :
|
||||
PersistentPreference<Int>,
|
||||
PreferenceMetadata,
|
||||
PreferenceBinding,
|
||||
PreferenceLifecycleProvider,
|
||||
RangeValue {
|
||||
|
||||
@VisibleForTesting var batteryBroadcastReceiver: BatteryBroadcastReceiver? = null
|
||||
|
||||
override val key: String
|
||||
get() = KEY
|
||||
|
||||
override val title: Int
|
||||
get() = R.string.summary_placeholder
|
||||
|
||||
override fun createWidget(context: Context) = UsageProgressBarPreference(context)
|
||||
|
||||
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
|
||||
super.bind(preference, metadata)
|
||||
preference.isSelectable = false
|
||||
if (preference is UsageProgressBarPreference) {
|
||||
quickUpdateHeaderPreference(preference)
|
||||
}
|
||||
}
|
||||
|
||||
override fun isIndexable(context: Context) = false
|
||||
|
||||
override fun onCreate(context: PreferenceLifecycleContext) {
|
||||
super.onCreate(context)
|
||||
batteryBroadcastReceiver =
|
||||
BatteryBroadcastReceiver(context).apply {
|
||||
setBatteryChangedListener {
|
||||
if (it != BATTERY_NOT_PRESENT) {
|
||||
context.notifyPreferenceChange(KEY)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart(context: PreferenceLifecycleContext) {
|
||||
super.onStart(context)
|
||||
batteryBroadcastReceiver?.register()
|
||||
}
|
||||
|
||||
override fun onStop(context: PreferenceLifecycleContext) {
|
||||
super.onStop(context)
|
||||
batteryBroadcastReceiver?.unRegister()
|
||||
}
|
||||
|
||||
override fun storage(context: Context): KeyValueStore =
|
||||
object : NoOpKeyedObservable<String>(), KeyValueStore {
|
||||
override fun contains(key: String) = BatteryUtils.getBatteryIntent(context) != null
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : Any> getValue(key: String, valueType: Class<T>): T? {
|
||||
val batteryIntent = BatteryUtils.getBatteryIntent(context) ?: return null
|
||||
return Utils.getBatteryLevel(batteryIntent) as T
|
||||
}
|
||||
|
||||
override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) =
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun getMinValue(context: Context): Int = 0
|
||||
|
||||
override fun getMaxValue(context: Context): Int = 100
|
||||
|
||||
override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) =
|
||||
ReadWritePermit.ALLOW
|
||||
|
||||
override fun getWritePermit(context: Context, value: Int?, myUid: Int, callingUid: Int) =
|
||||
ReadWritePermit.DISALLOW
|
||||
|
||||
companion object {
|
||||
private const val KEY = "battery_header"
|
||||
private const val BATTERY_MAX_LEVEL: Long = 100L
|
||||
|
||||
private fun quickUpdateHeaderPreference(preference: UsageProgressBarPreference) {
|
||||
val batteryIntent = BatteryUtils.getBatteryIntent(preference.context) ?: return
|
||||
val batteryLevel: Int = Utils.getBatteryLevel(batteryIntent)
|
||||
preference.apply {
|
||||
setUsageSummary(com.android.settings.Utils.formatPercentage(batteryLevel))
|
||||
setPercent(batteryLevel.toLong(), BATTERY_MAX_LEVEL)
|
||||
setBottomSummary("")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// LINT.ThenChange(BatteryHeaderPreferenceController.java)
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
* Copyright (C) 2024 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
|
||||
@@ -15,59 +16,77 @@
|
||||
|
||||
package com.android.settings.fuelgauge;
|
||||
|
||||
import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_NOT_PRESENT;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.PowerManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleEventObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.settingslib.widget.UsageProgressBarPreference;
|
||||
|
||||
// LINT.IfChange
|
||||
/** Controller that update the battery header view */
|
||||
public class BatteryHeaderPreferenceController extends BasePreferenceController
|
||||
implements PreferenceControllerMixin, BatteryPreferenceController {
|
||||
implements PreferenceControllerMixin, LifecycleEventObserver {
|
||||
private static final String TAG = "BatteryHeaderPreferenceController";
|
||||
|
||||
@VisibleForTesting static final String KEY_BATTERY_HEADER = "battery_header";
|
||||
private static final int BATTERY_MAX_LEVEL = 100;
|
||||
|
||||
@VisibleForTesting BatteryStatusFeatureProvider mBatteryStatusFeatureProvider;
|
||||
@VisibleForTesting UsageProgressBarPreference mBatteryUsageProgressBarPref;
|
||||
|
||||
private final PowerManager mPowerManager;
|
||||
private final BatterySettingsFeatureProvider mBatterySettingsFeatureProvider;
|
||||
|
||||
private BatteryTip mBatteryTip;
|
||||
@Nullable @VisibleForTesting BatteryBroadcastReceiver mBatteryBroadcastReceiver;
|
||||
@Nullable @VisibleForTesting UsageProgressBarPreference mBatteryUsageProgressBarPreference;
|
||||
|
||||
public BatteryHeaderPreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
mPowerManager = context.getSystemService(PowerManager.class);
|
||||
mBatteryStatusFeatureProvider =
|
||||
FeatureFactory.getFeatureFactory().getBatteryStatusFeatureProvider();
|
||||
mBatterySettingsFeatureProvider =
|
||||
FeatureFactory.getFeatureFactory().getBatterySettingsFeatureProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner,
|
||||
@NonNull Lifecycle.Event event) {
|
||||
switch (event) {
|
||||
case ON_CREATE:
|
||||
mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(mContext);
|
||||
mBatteryBroadcastReceiver.setBatteryChangedListener(
|
||||
type -> {
|
||||
if (type != BATTERY_NOT_PRESENT) {
|
||||
quickUpdateHeaderPreference();
|
||||
}
|
||||
});
|
||||
break;
|
||||
case ON_START:
|
||||
if (mBatteryBroadcastReceiver != null) {
|
||||
mBatteryBroadcastReceiver.register();
|
||||
}
|
||||
break;
|
||||
case ON_STOP:
|
||||
if (mBatteryBroadcastReceiver != null) {
|
||||
mBatteryBroadcastReceiver.unRegister();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mBatteryUsageProgressBarPref = screen.findPreference(getPreferenceKey());
|
||||
// Set up empty space text first to prevent layout flaky before info loaded.
|
||||
mBatteryUsageProgressBarPref.setBottomSummary(" ");
|
||||
mBatteryUsageProgressBarPreference = screen.findPreference(getPreferenceKey());
|
||||
// Hide the bottom summary from the progress bar.
|
||||
mBatteryUsageProgressBarPreference.setBottomSummary("");
|
||||
|
||||
if (com.android.settings.Utils.isBatteryPresent(mContext)) {
|
||||
quickUpdateHeaderPreference();
|
||||
} else {
|
||||
mBatteryUsageProgressBarPref.setVisible(false);
|
||||
mBatteryUsageProgressBarPreference.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,105 +95,23 @@ public class BatteryHeaderPreferenceController extends BasePreferenceController
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
private CharSequence generateLabel(BatteryInfo info) {
|
||||
if (Utils.containsIncompatibleChargers(mContext, TAG)) {
|
||||
return mContext.getString(
|
||||
com.android.settingslib.R.string.battery_info_status_not_charging);
|
||||
}
|
||||
if (BatteryUtils.isBatteryDefenderOn(info)
|
||||
|| FeatureFactory.getFeatureFactory()
|
||||
.getPowerUsageFeatureProvider()
|
||||
.isExtraDefend()) {
|
||||
return mContext.getString(
|
||||
com.android.settingslib.R.string.battery_info_status_charging_on_hold);
|
||||
}
|
||||
if (info.remainingLabel != null
|
||||
&& mBatterySettingsFeatureProvider.isChargingOptimizationMode(mContext)) {
|
||||
return info.remainingLabel;
|
||||
}
|
||||
if (info.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
|
||||
return info.statusLabel;
|
||||
}
|
||||
if (info.pluggedStatus == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
|
||||
final CharSequence wirelessChargingLabel =
|
||||
mBatterySettingsFeatureProvider.getWirelessChargingLabel(mContext, info);
|
||||
if (wirelessChargingLabel != null) {
|
||||
mBatteryUsageProgressBarPref.setBottomSummaryContentDescription(
|
||||
mBatterySettingsFeatureProvider
|
||||
.getWirelessChargingContentDescription(mContext, info));
|
||||
return wirelessChargingLabel;
|
||||
}
|
||||
}
|
||||
if (info.remainingLabel == null) {
|
||||
return info.statusLabel;
|
||||
}
|
||||
if (info.statusLabel != null && !info.discharging) {
|
||||
// Charging state
|
||||
if (com.android.settingslib.fuelgauge.BatteryUtils.isChargingStringV2Enabled()) {
|
||||
return info.isFastCharging
|
||||
? mContext.getString(
|
||||
R.string.battery_state_and_duration,
|
||||
info.statusLabel,
|
||||
info.remainingLabel)
|
||||
: info.remainingLabel;
|
||||
}
|
||||
return mContext.getString(
|
||||
R.string.battery_state_and_duration, info.statusLabel, info.remainingLabel);
|
||||
} else if (mPowerManager.isPowerSaveMode()) {
|
||||
// Power save mode is on
|
||||
final String powerSaverOn =
|
||||
mContext.getString(R.string.battery_tip_early_heads_up_done_title);
|
||||
return mContext.getString(
|
||||
R.string.battery_state_and_duration, powerSaverOn, info.remainingLabel);
|
||||
} else if (mBatteryTip != null && mBatteryTip.getType() == BatteryTip.TipType.LOW_BATTERY) {
|
||||
// Low battery state
|
||||
final String lowBattery = mContext.getString(R.string.low_battery_summary);
|
||||
return mContext.getString(
|
||||
R.string.battery_state_and_duration, lowBattery, info.remainingLabel);
|
||||
} else {
|
||||
// Discharging state
|
||||
return info.remainingLabel;
|
||||
}
|
||||
}
|
||||
|
||||
public void updateHeaderPreference(BatteryInfo info) {
|
||||
if (!mBatteryStatusFeatureProvider.triggerBatteryStatusUpdate(this, info)) {
|
||||
mBatteryUsageProgressBarPref.setBottomSummary(generateLabel(info));
|
||||
}
|
||||
|
||||
mBatteryUsageProgressBarPref.setUsageSummary(
|
||||
formatBatteryPercentageText(info.batteryLevel));
|
||||
mBatteryUsageProgressBarPref.setPercent(info.batteryLevel, BATTERY_MAX_LEVEL);
|
||||
}
|
||||
|
||||
/** Callback which receives text for the summary line. */
|
||||
public void updateBatteryStatus(String label, BatteryInfo info) {
|
||||
final CharSequence summary = label != null ? label : generateLabel(info);
|
||||
mBatteryUsageProgressBarPref.setBottomSummary(summary);
|
||||
Log.d(TAG, "updateBatteryStatus: " + label + " summary: " + summary);
|
||||
}
|
||||
|
||||
/** Updates {@link UsageProgressBarPreference} information. */
|
||||
public void quickUpdateHeaderPreference() {
|
||||
if (mBatteryUsageProgressBarPreference == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Intent batteryBroadcast =
|
||||
com.android.settingslib.fuelgauge.BatteryUtils.getBatteryIntent(mContext);
|
||||
final int batteryLevel = Utils.getBatteryLevel(batteryBroadcast);
|
||||
final boolean discharging =
|
||||
batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) == 0;
|
||||
|
||||
mBatteryUsageProgressBarPref.setUsageSummary(formatBatteryPercentageText(batteryLevel));
|
||||
mBatteryUsageProgressBarPref.setPercent(batteryLevel, BATTERY_MAX_LEVEL);
|
||||
}
|
||||
|
||||
/** Update summary when battery tips changed. */
|
||||
public void updateHeaderByBatteryTips(BatteryTip batteryTip, BatteryInfo batteryInfo) {
|
||||
mBatteryTip = batteryTip;
|
||||
|
||||
if (mBatteryTip != null && batteryInfo != null) {
|
||||
updateHeaderPreference(batteryInfo);
|
||||
}
|
||||
mBatteryUsageProgressBarPreference.setUsageSummary(
|
||||
formatBatteryPercentageText(batteryLevel));
|
||||
mBatteryUsageProgressBarPreference.setPercent(batteryLevel, BATTERY_MAX_LEVEL);
|
||||
}
|
||||
|
||||
private CharSequence formatBatteryPercentageText(int batteryLevel) {
|
||||
return com.android.settings.Utils.formatPercentage(batteryLevel);
|
||||
}
|
||||
}
|
||||
// LINT.ThenChange(BatteryHeaderPreference.kt)
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.widget.GroupSectionDividerMixin;
|
||||
|
||||
/** A preference for battery header text. */
|
||||
public class BatteryHeaderTextPreference extends Preference implements GroupSectionDividerMixin {
|
||||
private static final String TAG = "BatteryHeaderTextPreference";
|
||||
|
||||
@Nullable private CharSequence mText;
|
||||
@Nullable private CharSequence mContentDescription;
|
||||
|
||||
public BatteryHeaderTextPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setLayoutResource(R.layout.preference_battery_header_text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder view) {
|
||||
final TextView textView = (TextView) view.findViewById(R.id.text);
|
||||
textView.setText(mText);
|
||||
textView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
if (!TextUtils.isEmpty(mContentDescription)) {
|
||||
textView.setContentDescription(mContentDescription);
|
||||
}
|
||||
}
|
||||
|
||||
void setText(@Nullable CharSequence text) {
|
||||
mText = text;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
void setContentDescription(@Nullable CharSequence contentDescription) {
|
||||
mContentDescription = contentDescription;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 android.content.Context;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.PowerManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.Utils;
|
||||
|
||||
/** Controller that update the battery header view */
|
||||
public class BatteryHeaderTextPreferenceController extends BasePreferenceController
|
||||
implements PreferenceControllerMixin, BatteryPreferenceController {
|
||||
private static final String TAG = "BatteryHeaderTextPreferenceController";
|
||||
|
||||
private final PowerManager mPowerManager;
|
||||
private final BatterySettingsFeatureProvider mBatterySettingsFeatureProvider;
|
||||
|
||||
@Nullable private BatteryTip mBatteryTip;
|
||||
|
||||
@VisibleForTesting BatteryStatusFeatureProvider mBatteryStatusFeatureProvider;
|
||||
|
||||
@Nullable @VisibleForTesting BatteryHeaderTextPreference mBatteryHeaderTextPreference;
|
||||
|
||||
public BatteryHeaderTextPreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
mPowerManager = context.getSystemService(PowerManager.class);
|
||||
mBatteryStatusFeatureProvider =
|
||||
FeatureFactory.getFeatureFactory().getBatteryStatusFeatureProvider();
|
||||
mBatterySettingsFeatureProvider =
|
||||
FeatureFactory.getFeatureFactory().getBatterySettingsFeatureProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mBatteryHeaderTextPreference = screen.findPreference(getPreferenceKey());
|
||||
|
||||
if (mBatteryHeaderTextPreference != null
|
||||
&& !com.android.settings.Utils.isBatteryPresent(mContext)) {
|
||||
mBatteryHeaderTextPreference.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private CharSequence generateLabel(@NonNull BatteryInfo info) {
|
||||
if (Utils.containsIncompatibleChargers(mContext, TAG)) {
|
||||
return mContext.getString(
|
||||
com.android.settingslib.R.string.battery_info_status_not_charging);
|
||||
}
|
||||
if (BatteryUtils.isBatteryDefenderOn(info)
|
||||
|| FeatureFactory.getFeatureFactory()
|
||||
.getPowerUsageFeatureProvider()
|
||||
.isExtraDefend()) {
|
||||
return mContext.getString(
|
||||
com.android.settingslib.R.string.battery_info_status_charging_on_hold);
|
||||
}
|
||||
if (info.remainingLabel != null
|
||||
&& mBatterySettingsFeatureProvider.isChargingOptimizationMode(mContext)) {
|
||||
return info.remainingLabel;
|
||||
}
|
||||
if (info.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
|
||||
return info.statusLabel;
|
||||
}
|
||||
if (info.pluggedStatus == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
|
||||
final CharSequence wirelessChargingLabel =
|
||||
mBatterySettingsFeatureProvider.getWirelessChargingLabel(mContext, info);
|
||||
if (mBatteryHeaderTextPreference != null && wirelessChargingLabel != null) {
|
||||
mBatteryHeaderTextPreference.setContentDescription(
|
||||
mBatterySettingsFeatureProvider
|
||||
.getWirelessChargingContentDescription(mContext, info));
|
||||
return wirelessChargingLabel;
|
||||
}
|
||||
}
|
||||
if (info.remainingLabel == null) {
|
||||
return info.statusLabel;
|
||||
}
|
||||
if (info.statusLabel != null && !info.discharging) {
|
||||
// Charging state
|
||||
if (com.android.settingslib.fuelgauge.BatteryUtils.isChargingStringV2Enabled()) {
|
||||
return info.isFastCharging
|
||||
? mContext.getString(
|
||||
R.string.battery_state_and_duration,
|
||||
info.statusLabel,
|
||||
info.remainingLabel)
|
||||
: info.remainingLabel;
|
||||
}
|
||||
return mContext.getString(
|
||||
R.string.battery_state_and_duration, info.statusLabel, info.remainingLabel);
|
||||
} else if (mPowerManager.isPowerSaveMode()) {
|
||||
// Power save mode is on
|
||||
final String powerSaverOn =
|
||||
mContext.getString(R.string.battery_tip_early_heads_up_done_title);
|
||||
return mContext.getString(
|
||||
R.string.battery_state_and_duration, powerSaverOn, info.remainingLabel);
|
||||
} else if (mBatteryTip != null && mBatteryTip.getType() == BatteryTip.TipType.LOW_BATTERY) {
|
||||
// Low battery state
|
||||
final String lowBattery = mContext.getString(R.string.low_battery_summary);
|
||||
return mContext.getString(
|
||||
R.string.battery_state_and_duration, lowBattery, info.remainingLabel);
|
||||
} else {
|
||||
// Discharging state
|
||||
return info.remainingLabel;
|
||||
}
|
||||
}
|
||||
|
||||
/** Updates the battery header text with the given BatteryInfo. */
|
||||
public void updateHeaderPreference(@NonNull BatteryInfo info) {
|
||||
if (mBatteryHeaderTextPreference != null
|
||||
&& !mBatteryStatusFeatureProvider.triggerBatteryStatusUpdate(this, info)) {
|
||||
mBatteryHeaderTextPreference.setText(generateLabel(info));
|
||||
}
|
||||
}
|
||||
|
||||
/** Callback which updates the battery header text with the given label. */
|
||||
@Override
|
||||
public void updateBatteryStatus(String label, BatteryInfo info) {
|
||||
if (mBatteryHeaderTextPreference == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final CharSequence summary = label != null ? label : generateLabel(info);
|
||||
mBatteryHeaderTextPreference.setText(summary);
|
||||
Log.d(TAG, "updateBatteryStatus: " + label + " summary: " + summary);
|
||||
}
|
||||
|
||||
/** Update summary when battery tips are changed. */
|
||||
public void updateHeaderByBatteryTips(
|
||||
@Nullable BatteryTip batteryTip, @NonNull BatteryInfo batteryInfo) {
|
||||
mBatteryTip = batteryTip;
|
||||
|
||||
if (mBatteryTip != null && batteryInfo != null) {
|
||||
updateHeaderPreference(batteryInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.widget.MainSwitchPreference;
|
||||
import com.android.settingslib.widget.SelectorWithWidgetPreference;
|
||||
|
||||
/** Controller to update the app background usage mode state in Allow background usage page */
|
||||
public class BatteryOptimizationModePreferenceController extends BasePreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
@VisibleForTesting
|
||||
static final String KEY_BACKGROUND_USAGE_ALLOWABILITY_SWITCH =
|
||||
"background_usage_allowability_switch";
|
||||
|
||||
@VisibleForTesting static final String KEY_OPTIMIZED_PREF = "optimized_preference";
|
||||
@VisibleForTesting static final String KEY_UNRESTRICTED_PREF = "unrestricted_preference";
|
||||
|
||||
private final BatteryOptimizeUtils mBatteryOptimizeUtils;
|
||||
@Nullable @VisibleForTesting MainSwitchPreference mBackgroundUsageAllowabilityPreference;
|
||||
@Nullable @VisibleForTesting SelectorWithWidgetPreference mOptimizedPreference;
|
||||
@Nullable @VisibleForTesting SelectorWithWidgetPreference mUnrestrictedPreference;
|
||||
|
||||
public BatteryOptimizationModePreferenceController(
|
||||
@NonNull Context context,
|
||||
@NonNull String preferenceKey,
|
||||
@NonNull BatteryOptimizeUtils batteryOptimizeUtils) {
|
||||
super(context, preferenceKey);
|
||||
mBatteryOptimizeUtils = batteryOptimizeUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(@NonNull Preference preference) {
|
||||
updatePreferences(mBatteryOptimizeUtils.getAppOptimizationMode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(@NonNull PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mBackgroundUsageAllowabilityPreference =
|
||||
screen.findPreference(KEY_BACKGROUND_USAGE_ALLOWABILITY_SWITCH);
|
||||
mOptimizedPreference = screen.findPreference(KEY_OPTIMIZED_PREF);
|
||||
mUnrestrictedPreference = screen.findPreference(KEY_UNRESTRICTED_PREF);
|
||||
initPreferences();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void initPreferences() {
|
||||
if (mBackgroundUsageAllowabilityPreference == null
|
||||
|| mOptimizedPreference == null
|
||||
|| mUnrestrictedPreference == null) {
|
||||
return;
|
||||
}
|
||||
final boolean isEnabled = mBatteryOptimizeUtils.isOptimizeModeMutable();
|
||||
mBackgroundUsageAllowabilityPreference.setEnabled(isEnabled);
|
||||
mOptimizedPreference.setEnabled(isEnabled);
|
||||
mUnrestrictedPreference.setEnabled(isEnabled);
|
||||
if (isEnabled) {
|
||||
mBackgroundUsageAllowabilityPreference.setOnPreferenceChangeListener(
|
||||
(preference, isAllowBackground) -> {
|
||||
handleBatteryOptimizeModeUpdated(
|
||||
(boolean) isAllowBackground
|
||||
? BatteryOptimizeUtils.MODE_OPTIMIZED
|
||||
: BatteryOptimizeUtils.MODE_RESTRICTED);
|
||||
return true;
|
||||
});
|
||||
mOptimizedPreference.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
handleBatteryOptimizeModeUpdated(BatteryOptimizeUtils.MODE_OPTIMIZED);
|
||||
return true;
|
||||
});
|
||||
mUnrestrictedPreference.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
handleBatteryOptimizeModeUpdated(BatteryOptimizeUtils.MODE_UNRESTRICTED);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void updatePreferences(int optimizationMode) {
|
||||
if (mBackgroundUsageAllowabilityPreference == null
|
||||
|| mOptimizedPreference == null
|
||||
|| mUnrestrictedPreference == null) {
|
||||
return;
|
||||
}
|
||||
final boolean isAllowBackground = optimizationMode != BatteryOptimizeUtils.MODE_RESTRICTED;
|
||||
mBackgroundUsageAllowabilityPreference.setChecked(isAllowBackground);
|
||||
mOptimizedPreference.setEnabled(isAllowBackground);
|
||||
mUnrestrictedPreference.setEnabled(isAllowBackground);
|
||||
mOptimizedPreference.setChecked(optimizationMode == BatteryOptimizeUtils.MODE_OPTIMIZED);
|
||||
mUnrestrictedPreference.setChecked(
|
||||
optimizationMode == BatteryOptimizeUtils.MODE_UNRESTRICTED);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void handleBatteryOptimizeModeUpdated(int newBatteryOptimizeMode) {
|
||||
if (mBatteryOptimizeUtils.getAppOptimizationMode() == newBatteryOptimizeMode) {
|
||||
Log.w(TAG, "ignore same mode for: " + mBatteryOptimizeUtils.getPackageName());
|
||||
return;
|
||||
}
|
||||
mBatteryOptimizeUtils.setAppUsageState(
|
||||
newBatteryOptimizeMode, BatteryOptimizeHistoricalLogEntry.Action.APPLY);
|
||||
updatePreferences(newBatteryOptimizeMode);
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,8 @@ public class BatteryOptimizeUtils {
|
||||
|
||||
/** Gets the {@link OptimizationMode} based on mode and allowed list. */
|
||||
@OptimizationMode
|
||||
public static int getAppOptimizationMode(int mode, boolean isAllowListed) {
|
||||
public static int getAppOptimizationMode(
|
||||
int mode, boolean isAllowListed, boolean ignoreUnknownMode) {
|
||||
if (!isAllowListed && mode == AppOpsManager.MODE_IGNORED) {
|
||||
return MODE_RESTRICTED;
|
||||
} else if (isAllowListed && mode == AppOpsManager.MODE_ALLOWED) {
|
||||
@@ -108,13 +109,15 @@ public class BatteryOptimizeUtils {
|
||||
} else if (!isAllowListed && mode == AppOpsManager.MODE_ALLOWED) {
|
||||
return MODE_OPTIMIZED;
|
||||
} else {
|
||||
return MODE_UNKNOWN;
|
||||
// MODE_UNKNOWN = isAllowListed + AppOpsManager.MODE_IGNORED
|
||||
// Return Unrestricted mode for Unknown mode since it is in allowlist.
|
||||
return ignoreUnknownMode ? MODE_UNRESTRICTED : MODE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets the {@link OptimizationMode} for associated app. */
|
||||
@OptimizationMode
|
||||
public int getAppOptimizationMode(boolean refreshList) {
|
||||
public int getAppOptimizationMode(boolean refreshList, boolean ignoreUnknownMode) {
|
||||
if (refreshList) {
|
||||
mPowerAllowListBackend.refreshList();
|
||||
}
|
||||
@@ -127,13 +130,13 @@ public class BatteryOptimizeUtils {
|
||||
String.format(
|
||||
"refresh %s state, allowlisted = %s, mode = %d",
|
||||
mPackageName, mAllowListed, mMode));
|
||||
return getAppOptimizationMode(mMode, mAllowListed);
|
||||
return getAppOptimizationMode(mMode, mAllowListed, ignoreUnknownMode);
|
||||
}
|
||||
|
||||
/** Gets the {@link OptimizationMode} for associated app. */
|
||||
@OptimizationMode
|
||||
public int getAppOptimizationMode() {
|
||||
return getAppOptimizationMode(true);
|
||||
return getAppOptimizationMode(/* refreshList= */ true, /* ignoreUnknownMode= */ true);
|
||||
}
|
||||
|
||||
/** Resets optimization mode for all applications. */
|
||||
@@ -246,10 +249,11 @@ public class BatteryOptimizeUtils {
|
||||
@OptimizationMode
|
||||
final int optimizationMode =
|
||||
getAppOptimizationMode(
|
||||
mode, allowlistBackend.isAllowlisted(info.packageName, info.uid));
|
||||
// Ignores default optimized/unknown state or system/default apps.
|
||||
mode,
|
||||
allowlistBackend.isAllowlisted(info.packageName, info.uid),
|
||||
/* ignoreUnknownMode= */ false);
|
||||
// Ignores default optimized state or system/default apps.
|
||||
if (optimizationMode == MODE_OPTIMIZED
|
||||
|| optimizationMode == MODE_UNKNOWN
|
||||
|| isSystemOrDefaultApp(
|
||||
context, allowlistBackend, info.packageName, info.uid)) {
|
||||
continue;
|
||||
@@ -374,7 +378,8 @@ public class BatteryOptimizeUtils {
|
||||
"\tStandbyMode: %s, allowListed: %s, mode: %s",
|
||||
appStandbyMode,
|
||||
allowListed,
|
||||
getAppOptimizationMode(appStandbyMode, allowListed));
|
||||
getAppOptimizationMode(
|
||||
appStandbyMode, allowListed, /* ignoreUnknownMode= */ false));
|
||||
}
|
||||
|
||||
private static @DataChangeReason int toChangeReason(Action action) {
|
||||
|
||||
@@ -72,25 +72,22 @@ public final class BatterySettingsMigrateChecker extends BroadcastReceiver {
|
||||
Context context,
|
||||
@BatteryOptimizeUtils.OptimizationMode int optimizationMode,
|
||||
List<String> allowList) {
|
||||
allowList.forEach(
|
||||
packageName -> {
|
||||
final BatteryOptimizeUtils batteryOptimizeUtils =
|
||||
BatteryBackupHelper.newBatteryOptimizeUtils(
|
||||
context,
|
||||
packageName,
|
||||
/* testOptimizeUtils */ sBatteryOptimizeUtils);
|
||||
if (batteryOptimizeUtils == null) {
|
||||
return;
|
||||
}
|
||||
if (batteryOptimizeUtils.getAppOptimizationMode() != optimizationMode) {
|
||||
Log.w(
|
||||
TAG,
|
||||
"Reset " + packageName + " battery mode into " + optimizationMode);
|
||||
batteryOptimizeUtils.setAppUsageState(
|
||||
optimizationMode,
|
||||
BatteryOptimizeHistoricalLogEntry.Action.FORCE_RESET);
|
||||
}
|
||||
});
|
||||
for (String packageName : allowList) {
|
||||
final BatteryOptimizeUtils batteryOptimizeUtils =
|
||||
BatteryBackupHelper.newBatteryOptimizeUtils(
|
||||
context,
|
||||
packageName,
|
||||
/* testOptimizeUtils */ sBatteryOptimizeUtils);
|
||||
if (batteryOptimizeUtils == null) {
|
||||
continue;
|
||||
}
|
||||
if (batteryOptimizeUtils.getAppOptimizationMode() != optimizationMode) {
|
||||
Log.w(TAG, "Reset " + packageName + " mode into " + optimizationMode);
|
||||
batteryOptimizeUtils.setAppUsageState(
|
||||
optimizationMode,
|
||||
BatteryOptimizeHistoricalLogEntry.Action.FORCE_RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void verifySaverConfiguration(Context context) {
|
||||
|
||||
@@ -347,7 +347,9 @@ public final class BatterySettingsStorage extends ObservableBackupRestoreStorage
|
||||
appOptModeMap.containsKey(info.uid)
|
||||
? (int) appOptModeMap.get(info.uid).getResetOptimizationMode()
|
||||
: BatteryOptimizeUtils.getAppOptimizationMode(
|
||||
mode, mAllowlistedApps.contains(info.packageName));
|
||||
mode,
|
||||
mAllowlistedApps.contains(info.packageName),
|
||||
/* ignoreUnknownMode= */ false);
|
||||
// Ignores default optimized/unknown state or system/default apps.
|
||||
if (optimizationMode == BatteryOptimizeUtils.MODE_OPTIMIZED
|
||||
|| optimizationMode == BatteryOptimizeUtils.MODE_UNKNOWN
|
||||
|
||||
@@ -1,66 +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 android.content.Context;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.widget.SelectorWithWidgetPreference;
|
||||
|
||||
public class OptimizedPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private static final String TAG = "OPTIMIZED_PREF";
|
||||
|
||||
@VisibleForTesting static final String KEY_OPTIMIZED_PREF = "optimized_preference";
|
||||
@VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
|
||||
|
||||
public OptimizedPreferenceController(Context context, int uid, String packageName) {
|
||||
super(context);
|
||||
mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
preference.setEnabled(mBatteryOptimizeUtils.isSelectorPreferenceEnabled());
|
||||
|
||||
final boolean isOptimized =
|
||||
mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()
|
||||
|| mBatteryOptimizeUtils.getAppOptimizationMode()
|
||||
== BatteryOptimizeUtils.MODE_OPTIMIZED;
|
||||
((SelectorWithWidgetPreference) preference).setChecked(isOptimized);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_OPTIMIZED_PREF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlePreferenceTreeClick(Preference preference) {
|
||||
return getPreferenceKey().equals(preference.getKey());
|
||||
}
|
||||
}
|
||||
@@ -24,11 +24,7 @@ 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.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
@@ -37,15 +33,12 @@ import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.fuelgauge.batteryusage.AppOptModeSharedPreferencesUtils;
|
||||
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.Utils;
|
||||
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.SelectorWithWidgetPreference;
|
||||
import com.android.settingslib.widget.IntroPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -53,8 +46,7 @@ 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, OnCheckedChangeListener {
|
||||
public class PowerBackgroundUsageDetail extends DashboardFragment {
|
||||
private static final String TAG = "PowerBackgroundUsageDetail";
|
||||
|
||||
public static final String EXTRA_UID = "extra_uid";
|
||||
@@ -63,21 +55,15 @@ public class PowerBackgroundUsageDetail extends DashboardFragment
|
||||
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 static final String KEY_BATTERY_OPTIMIZATION_MODE_CATEGORY =
|
||||
"battery_optimization_mode_category";
|
||||
|
||||
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 StringBuilder mLogStringBuilder;
|
||||
|
||||
@VisibleForTesting @BatteryOptimizeUtils.OptimizationMode
|
||||
@@ -87,17 +73,11 @@ public class PowerBackgroundUsageDetail extends DashboardFragment
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
|
||||
final Bundle bundle = getArguments();
|
||||
final int uid = bundle.getInt(EXTRA_UID, 0);
|
||||
final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
|
||||
mBatteryOptimizeUtils = new BatteryOptimizeUtils(getContext(), uid, packageName);
|
||||
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());
|
||||
}
|
||||
@@ -107,8 +87,8 @@ public class PowerBackgroundUsageDetail extends DashboardFragment
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
initHeader();
|
||||
mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
|
||||
initFooter();
|
||||
mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
|
||||
mLogStringBuilder = new StringBuilder("onResume mode = ").append(mOptimizationMode);
|
||||
}
|
||||
|
||||
@@ -136,20 +116,6 @@ public class PowerBackgroundUsageDetail extends DashboardFragment
|
||||
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 onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
mMainSwitchPreference.setChecked(isChecked);
|
||||
updateSelectorPreference(isChecked);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.FUELGAUGE_POWER_USAGE_MANAGE_BACKGROUND;
|
||||
@@ -157,14 +123,10 @@ public class PowerBackgroundUsageDetail extends DashboardFragment
|
||||
|
||||
@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));
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>(1);
|
||||
controllers.add(
|
||||
new BatteryOptimizationModePreferenceController(
|
||||
context, KEY_BATTERY_OPTIMIZATION_MODE_CATEGORY, mBatteryOptimizeUtils));
|
||||
|
||||
return controllers;
|
||||
}
|
||||
@@ -179,26 +141,6 @@ public class PowerBackgroundUsageDetail extends DashboardFragment
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void updateSelectorPreference(boolean isEnabled) {
|
||||
mOptimizePreference.setEnabled(isEnabled);
|
||||
mUnrestrictedPreference.setEnabled(isEnabled);
|
||||
onRadioButtonClicked(isEnabled ? mOptimizePreference : null);
|
||||
}
|
||||
|
||||
@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())
|
||||
@@ -209,88 +151,50 @@ public class PowerBackgroundUsageDetail extends DashboardFragment
|
||||
|
||||
@VisibleForTesting
|
||||
void initHeader() {
|
||||
final View appSnippet = mHeaderPreference.findViewById(R.id.entity_header);
|
||||
final IntroPreference introPreference = findPreference(KEY_PREF_HEADER);
|
||||
if (introPreference == null) {
|
||||
return;
|
||||
}
|
||||
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));
|
||||
introPreference.setTitle(bundle.getString(EXTRA_LABEL));
|
||||
|
||||
final int iconId = bundle.getInt(EXTRA_ICON_ID, 0);
|
||||
if (iconId == 0) {
|
||||
controller.setIcon(context.getPackageManager().getDefaultActivityIcon());
|
||||
introPreference.setIcon(context.getPackageManager().getDefaultActivityIcon());
|
||||
} else {
|
||||
controller.setIcon(context.getDrawable(bundle.getInt(EXTRA_ICON_ID)));
|
||||
introPreference.setIcon(context.getDrawable(bundle.getInt(EXTRA_ICON_ID)));
|
||||
}
|
||||
} else {
|
||||
mState.ensureIcon(mAppEntry);
|
||||
controller.setLabel(mAppEntry);
|
||||
controller.setIcon(mAppEntry);
|
||||
controller.setIsInstantApp(AppUtils.isInstant(mAppEntry.info));
|
||||
introPreference.setTitle(mAppEntry.label);
|
||||
introPreference.setIcon(Utils.getBadgedIcon(context, 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);
|
||||
final FooterPreference footerPreference = findPreference(KEY_FOOTER_PREFERENCE);
|
||||
if (footerPreference == null) {
|
||||
return;
|
||||
}
|
||||
mFooterPreference.setTitle(footerString);
|
||||
final Context context = getContext();
|
||||
footerPreference.setTitle(context.getString(R.string.manager_battery_usage_footer));
|
||||
final Intent helpIntent =
|
||||
HelpUtils.getHelpIntent(
|
||||
context,
|
||||
context.getString(R.string.help_url_app_usage_settings),
|
||||
/* backupContext= */ "");
|
||||
if (helpIntent != null) {
|
||||
mFooterPreference.setLearnMoreAction(
|
||||
footerPreference.setLearnMoreAction(
|
||||
v -> startActivityForResult(helpIntent, /* requestCode= */ 0));
|
||||
mFooterPreference.setLearnMoreText(
|
||||
footerPreference.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;
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.fuelgauge;
|
||||
|
||||
import static com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_UNRESTRICTED;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
@@ -24,20 +26,20 @@ import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerManager;
|
||||
import android.os.PowerWhitelistManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.app.AlertActivity;
|
||||
import com.android.internal.app.AlertController;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
|
||||
|
||||
public class RequestIgnoreBatteryOptimizations extends AlertActivity
|
||||
implements DialogInterface.OnClickListener {
|
||||
private static final String TAG = "RequestIgnoreBatteryOptimizations";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private PowerWhitelistManager mPowerWhitelistManager;
|
||||
private String mPackageName;
|
||||
private ApplicationInfo mApplicationInfo;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -47,8 +49,6 @@ public class RequestIgnoreBatteryOptimizations extends AlertActivity
|
||||
android.view.WindowManager.LayoutParams
|
||||
.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
|
||||
|
||||
mPowerWhitelistManager = getSystemService(PowerWhitelistManager.class);
|
||||
|
||||
Uri data = getIntent().getData();
|
||||
if (data == null) {
|
||||
debugLog(
|
||||
@@ -56,17 +56,18 @@ public class RequestIgnoreBatteryOptimizations extends AlertActivity
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
mPackageName = data.getSchemeSpecificPart();
|
||||
if (mPackageName == null) {
|
||||
final String packageName = data.getSchemeSpecificPart();
|
||||
if (TextUtils.isEmpty(packageName)) {
|
||||
debugLog(
|
||||
"No data supplied for IGNORE_BATTERY_OPTIMIZATION_SETTINGS in: " + getIntent());
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
// Package in Unrestricted mode already ignoring the battery optimizations.
|
||||
PowerManager power = getSystemService(PowerManager.class);
|
||||
if (power.isIgnoringBatteryOptimizations(mPackageName)) {
|
||||
debugLog("Not should prompt, already ignoring optimizations: " + mPackageName);
|
||||
if (power.isIgnoringBatteryOptimizations(packageName)) {
|
||||
debugLog("Not should prompt, already ignoring optimizations: " + packageName);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
@@ -74,29 +75,28 @@ public class RequestIgnoreBatteryOptimizations extends AlertActivity
|
||||
if (getPackageManager()
|
||||
.checkPermission(
|
||||
Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
|
||||
mPackageName)
|
||||
packageName)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
debugLog(
|
||||
"Requested package "
|
||||
+ mPackageName
|
||||
+ packageName
|
||||
+ " does not hold permission "
|
||||
+ Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
ApplicationInfo ai;
|
||||
try {
|
||||
ai = getPackageManager().getApplicationInfo(mPackageName, 0);
|
||||
mApplicationInfo = getPackageManager().getApplicationInfo(packageName, 0);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
debugLog("Requested package doesn't exist: " + mPackageName);
|
||||
debugLog("Requested package doesn't exist: " + packageName);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
final AlertController.AlertParams p = mAlertParams;
|
||||
final CharSequence appLabel =
|
||||
ai.loadSafeLabel(
|
||||
mApplicationInfo.loadSafeLabel(
|
||||
getPackageManager(),
|
||||
PackageItemInfo.DEFAULT_MAX_LABEL_SIZE_PX,
|
||||
PackageItemInfo.SAFE_LABEL_FLAG_TRIM
|
||||
@@ -114,7 +114,12 @@ public class RequestIgnoreBatteryOptimizations extends AlertActivity
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
switch (which) {
|
||||
case BUTTON_POSITIVE:
|
||||
mPowerWhitelistManager.addToWhitelist(mPackageName);
|
||||
BatteryOptimizeUtils batteryOptimizeUtils =
|
||||
new BatteryOptimizeUtils(
|
||||
getApplicationContext(),
|
||||
mApplicationInfo.uid,
|
||||
mApplicationInfo.packageName);
|
||||
batteryOptimizeUtils.setAppUsageState(MODE_UNRESTRICTED, Action.APPLY);
|
||||
break;
|
||||
case BUTTON_NEGATIVE:
|
||||
break;
|
||||
|
||||
@@ -1,66 +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 android.content.Context;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.widget.SelectorWithWidgetPreference;
|
||||
|
||||
public class UnrestrictedPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private static final String TAG = "UNRESTRICTED_PREF";
|
||||
|
||||
@VisibleForTesting static final String KEY_UNRESTRICTED_PREF = "unrestricted_preference";
|
||||
|
||||
@VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
|
||||
|
||||
public UnrestrictedPreferenceController(Context context, int uid, String packageName) {
|
||||
super(context);
|
||||
mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
preference.setEnabled(mBatteryOptimizeUtils.isSelectorPreferenceEnabled());
|
||||
|
||||
final boolean isUnrestricted =
|
||||
mBatteryOptimizeUtils.getAppOptimizationMode()
|
||||
== BatteryOptimizeUtils.MODE_UNRESTRICTED;
|
||||
((SelectorWithWidgetPreference) preference).setChecked(isUnrestricted);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_UNRESTRICTED_PREF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlePreferenceTreeClick(Preference preference) {
|
||||
return getPreferenceKey().equals(preference.getKey());
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ import com.android.settingslib.fuelgauge.BatterySaverUtils;
|
||||
import com.android.settingslib.widget.MainSwitchPreference;
|
||||
|
||||
/** Controller to update the battery saver button */
|
||||
// LINT.IfChange
|
||||
public class BatterySaverButtonPreferenceController extends TogglePreferenceController
|
||||
implements LifecycleObserver, OnStart, OnStop, BatterySaverReceiver.BatterySaverListener {
|
||||
private static final long SWITCH_ANIMATION_DURATION = 350L;
|
||||
@@ -129,3 +130,4 @@ public class BatterySaverButtonPreferenceController extends TogglePreferenceCont
|
||||
}
|
||||
}
|
||||
}
|
||||
// LINT.ThenChange(BatterySaverPreference.kt)
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.batterysaver
|
||||
|
||||
import android.content.Context
|
||||
import android.os.PowerManager
|
||||
import com.android.settings.R
|
||||
import com.android.settings.fuelgauge.BatterySaverReceiver
|
||||
import com.android.settings.fuelgauge.BatterySaverReceiver.BatterySaverListener
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.NoOpKeyedObservable
|
||||
import com.android.settingslib.fuelgauge.BatterySaverLogging.SAVER_ENABLED_SETTINGS
|
||||
import com.android.settingslib.fuelgauge.BatterySaverUtils
|
||||
import com.android.settingslib.fuelgauge.BatteryStatus
|
||||
import com.android.settingslib.fuelgauge.BatteryUtils
|
||||
import com.android.settingslib.metadata.MainSwitchPreference
|
||||
import com.android.settingslib.metadata.PreferenceLifecycleContext
|
||||
import com.android.settingslib.metadata.PreferenceLifecycleProvider
|
||||
import com.android.settingslib.metadata.ReadWritePermit
|
||||
import com.android.settingslib.metadata.SensitivityLevel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
// LINT.IfChange
|
||||
class BatterySaverPreference :
|
||||
MainSwitchPreference(KEY, R.string.battery_saver_master_switch_title),
|
||||
PreferenceLifecycleProvider {
|
||||
|
||||
private var batterySaverReceiver: BatterySaverReceiver? = null
|
||||
|
||||
override fun storage(context: Context) = BatterySaverStore(context)
|
||||
|
||||
override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) =
|
||||
ReadWritePermit.ALLOW
|
||||
|
||||
override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) =
|
||||
ReadWritePermit.ALLOW
|
||||
|
||||
override val sensitivityLevel
|
||||
get() = SensitivityLevel.NO_SENSITIVITY
|
||||
|
||||
override fun isEnabled(context: Context) =
|
||||
!BatteryStatus(BatteryUtils.getBatteryIntent(context)).isPluggedIn
|
||||
|
||||
override fun onStart(context: PreferenceLifecycleContext) {
|
||||
BatterySaverReceiver(context).apply {
|
||||
batterySaverReceiver = this
|
||||
setBatterySaverListener(
|
||||
object : BatterySaverListener {
|
||||
override fun onPowerSaveModeChanged() {
|
||||
context.lifecycleScope.launch {
|
||||
delay(SWITCH_ANIMATION_DURATION)
|
||||
context.notifyPreferenceChange(KEY)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBatteryChanged(pluggedIn: Boolean) =
|
||||
context.notifyPreferenceChange(KEY)
|
||||
}
|
||||
)
|
||||
setListening(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop(context: PreferenceLifecycleContext) {
|
||||
batterySaverReceiver?.setListening(false)
|
||||
batterySaverReceiver = null
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class BatterySaverStore(private val context: Context) :
|
||||
NoOpKeyedObservable<String>(), KeyValueStore {
|
||||
override fun contains(key: String) = key == KEY
|
||||
|
||||
override fun <T : Any> getValue(key: String, valueType: Class<T>) =
|
||||
context.isPowerSaveMode() as T
|
||||
|
||||
override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
|
||||
BatterySaverUtils.setPowerSaveMode(
|
||||
context,
|
||||
value as Boolean,
|
||||
/* needFirstTimeWarning= */ false,
|
||||
SAVER_ENABLED_SETTINGS,
|
||||
)
|
||||
}
|
||||
|
||||
private fun Context.isPowerSaveMode() =
|
||||
getSystemService(PowerManager::class.java)?.isPowerSaveMode == true
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY = "battery_saver"
|
||||
private const val SWITCH_ANIMATION_DURATION: Long = 350L
|
||||
}
|
||||
}
|
||||
// LINT.ThenChange(BatterySaverButtonPreferenceController.java)
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.batterysaver
|
||||
|
||||
import android.content.Context
|
||||
import com.android.settings.R
|
||||
import com.android.settings.flags.Flags
|
||||
import com.android.settingslib.metadata.ProvidePreferenceScreen
|
||||
import com.android.settingslib.metadata.preferenceHierarchy
|
||||
import com.android.settingslib.preference.PreferenceScreenCreator
|
||||
|
||||
@ProvidePreferenceScreen
|
||||
open class BatterySaverScreen : PreferenceScreenCreator {
|
||||
override val key: String
|
||||
get() = KEY
|
||||
|
||||
override val title: Int
|
||||
get() = R.string.battery_saver
|
||||
|
||||
override val keywords: Int
|
||||
get() = R.string.keywords_battery_saver
|
||||
|
||||
override fun isFlagEnabled(context: Context) = Flags.catalystBatterySaverScreen()
|
||||
|
||||
override fun fragmentClass() = BatterySaverSettings::class.java
|
||||
|
||||
override fun hasCompleteHierarchy() = false
|
||||
|
||||
override fun getPreferenceHierarchy(context: Context) =
|
||||
preferenceHierarchy(this) { +BatterySaverPreference() order -100 }
|
||||
|
||||
companion object {
|
||||
const val KEY = "battery_saver_screen"
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,11 @@
|
||||
package com.android.settings.fuelgauge.batterysaver;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.R;
|
||||
@@ -93,4 +96,9 @@ public class BatterySaverSettings extends DashboardFragment {
|
||||
pref.setLearnMoreText(getString(R.string.battery_saver_link_a11y));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
|
||||
return BatterySaverScreen.KEY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings.fuelgauge.batterytip;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.BadParcelableException;
|
||||
import android.os.Bundle;
|
||||
@@ -27,7 +28,6 @@ import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.InstrumentedPreferenceFragment;
|
||||
import com.android.settings.fuelgauge.batterytip.actions.BatteryTipAction;
|
||||
@@ -52,7 +52,7 @@ public class BatteryTipPreferenceController extends BasePreferenceController {
|
||||
private BatteryTipListener mBatteryTipListener;
|
||||
private List<BatteryTip> mBatteryTips;
|
||||
private Map<String, BatteryTip> mBatteryTipMap;
|
||||
private SettingsActivity mSettingsActivity;
|
||||
private Activity mActivity;
|
||||
private MetricsFeatureProvider mMetricsFeatureProvider;
|
||||
private boolean mNeedUpdate;
|
||||
@VisibleForTesting TipCardPreference mCardPreference;
|
||||
@@ -66,8 +66,8 @@ public class BatteryTipPreferenceController extends BasePreferenceController {
|
||||
mNeedUpdate = true;
|
||||
}
|
||||
|
||||
public void setActivity(SettingsActivity activity) {
|
||||
mSettingsActivity = activity;
|
||||
public void setActivity(Activity activity) {
|
||||
mActivity = activity;
|
||||
}
|
||||
|
||||
public void setFragment(InstrumentedPreferenceFragment fragment) {
|
||||
@@ -126,7 +126,7 @@ public class BatteryTipPreferenceController extends BasePreferenceController {
|
||||
} else {
|
||||
final BatteryTipAction action =
|
||||
BatteryTipUtils.getActionForBatteryTip(
|
||||
batteryTip, mSettingsActivity, mFragment);
|
||||
batteryTip, mActivity, mFragment);
|
||||
if (action != null) {
|
||||
action.handlePositiveAction(mFragment.getMetricsCategory());
|
||||
}
|
||||
|
||||
@@ -16,16 +16,15 @@
|
||||
|
||||
package com.android.settings.fuelgauge.batterytip;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.internal.util.CollectionUtils;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.core.InstrumentedPreferenceFragment;
|
||||
import com.android.settings.fuelgauge.batterytip.actions.BatteryTipAction;
|
||||
import com.android.settings.fuelgauge.batterytip.actions.OpenBatterySaverAction;
|
||||
@@ -33,8 +32,6 @@ import com.android.settings.fuelgauge.batterytip.actions.OpenRestrictAppFragment
|
||||
import com.android.settings.fuelgauge.batterytip.actions.RestrictAppAction;
|
||||
import com.android.settings.fuelgauge.batterytip.actions.SmartBatteryAction;
|
||||
import com.android.settings.fuelgauge.batterytip.actions.UnrestrictAppAction;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.AppLabelPredicate;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.AppRestrictionPredicate;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
|
||||
@@ -52,7 +49,7 @@ public class BatteryTipUtils {
|
||||
AppOpsManager appOpsManager, UserManager userManager) {
|
||||
final List<UserHandle> userHandles = userManager.getUserProfiles();
|
||||
final List<AppOpsManager.PackageOps> packageOpsList =
|
||||
appOpsManager.getPackagesForOps(new int[] {AppOpsManager.OP_RUN_ANY_IN_BACKGROUND});
|
||||
appOpsManager.getPackagesForOps(new int[]{AppOpsManager.OP_RUN_ANY_IN_BACKGROUND});
|
||||
final List<AppInfo> appInfos = new ArrayList<>();
|
||||
|
||||
for (int i = 0, size = CollectionUtils.size(packageOpsList); i < size; i++) {
|
||||
@@ -65,7 +62,7 @@ public class BatteryTipUtils {
|
||||
}
|
||||
if (entry.getMode() != AppOpsManager.MODE_ALLOWED
|
||||
&& userHandles.contains(
|
||||
new UserHandle(UserHandle.getUserId(packageOps.getUid())))) {
|
||||
new UserHandle(UserHandle.getUserId(packageOps.getUid())))) {
|
||||
appInfos.add(
|
||||
new AppInfo.Builder()
|
||||
.setPackageName(packageOps.getPackageName())
|
||||
@@ -82,34 +79,34 @@ public class BatteryTipUtils {
|
||||
* Get a corresponding action based on {@code batteryTip}
|
||||
*
|
||||
* @param batteryTip used to detect which action to choose
|
||||
* @param settingsActivity used to populate {@link BatteryTipAction}
|
||||
* @param fragment used to populate {@link BatteryTipAction}
|
||||
* @param activity used to populate {@link BatteryTipAction}
|
||||
* @param fragment used to populate {@link BatteryTipAction}
|
||||
* @return an action for {@code batteryTip}
|
||||
*/
|
||||
public static BatteryTipAction getActionForBatteryTip(
|
||||
BatteryTip batteryTip,
|
||||
SettingsActivity settingsActivity,
|
||||
Activity activity,
|
||||
InstrumentedPreferenceFragment fragment) {
|
||||
switch (batteryTip.getType()) {
|
||||
case BatteryTip.TipType.SMART_BATTERY_MANAGER:
|
||||
return new SmartBatteryAction(settingsActivity, fragment);
|
||||
return new SmartBatteryAction(activity, fragment);
|
||||
case BatteryTip.TipType.BATTERY_SAVER:
|
||||
case BatteryTip.TipType.LOW_BATTERY:
|
||||
return new OpenBatterySaverAction(settingsActivity);
|
||||
return new OpenBatterySaverAction(activity);
|
||||
case BatteryTip.TipType.APP_RESTRICTION:
|
||||
if (batteryTip.getState() == BatteryTip.StateType.HANDLED) {
|
||||
return new OpenRestrictAppFragmentAction(fragment, (RestrictAppTip) batteryTip);
|
||||
} else {
|
||||
return new RestrictAppAction(settingsActivity, (RestrictAppTip) batteryTip);
|
||||
return new RestrictAppAction(activity, (RestrictAppTip) batteryTip);
|
||||
}
|
||||
case BatteryTip.TipType.REMOVE_APP_RESTRICTION:
|
||||
return new UnrestrictAppAction(settingsActivity, (UnrestrictAppTip) batteryTip);
|
||||
return new UnrestrictAppAction(activity, (UnrestrictAppTip) batteryTip);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Detect and return anomaly apps after {@code timeAfterMs} */
|
||||
/** Detect and return anomaly apps after {@code timeAfterMs} */
|
||||
public static List<AppInfo> detectAnomalies(Context context, long timeAfterMs) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@@ -16,23 +16,23 @@
|
||||
|
||||
package com.android.settings.fuelgauge.batterytip.actions;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.settings.SettingsEnums;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.fuelgauge.SmartBatterySettings;
|
||||
import com.android.settingslib.core.instrumentation.Instrumentable;
|
||||
|
||||
public class SmartBatteryAction extends BatteryTipAction {
|
||||
private SettingsActivity mSettingsActivity;
|
||||
private Activity mActivity;
|
||||
private Fragment mFragment;
|
||||
|
||||
public SmartBatteryAction(SettingsActivity settingsActivity, Fragment fragment) {
|
||||
super(settingsActivity.getApplicationContext());
|
||||
mSettingsActivity = settingsActivity;
|
||||
public SmartBatteryAction(Activity activity, Fragment fragment) {
|
||||
super(activity.getApplicationContext());
|
||||
mActivity = activity;
|
||||
mFragment = fragment;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public class SmartBatteryAction extends BatteryTipAction {
|
||||
public void handlePositiveAction(int metricsKey) {
|
||||
mMetricsFeatureProvider.action(
|
||||
mContext, SettingsEnums.ACTION_TIP_OPEN_SMART_BATTERY, metricsKey);
|
||||
new SubSettingLauncher(mSettingsActivity)
|
||||
new SubSettingLauncher(mActivity)
|
||||
.setSourceMetricsCategory(
|
||||
mFragment instanceof Instrumentable
|
||||
? ((Instrumentable) mFragment).getMetricsCategory()
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings.fuelgauge.batteryusage;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
@@ -37,7 +38,7 @@ class AnomalyAppItemPreference extends PowerGaugePreference {
|
||||
setLayoutResource(R.layout.anomaly_app_item_preference);
|
||||
}
|
||||
|
||||
void setAnomalyHint(CharSequence anomalyHintText) {
|
||||
void setAnomalyHint(@Nullable CharSequence anomalyHintText) {
|
||||
if (!TextUtils.equals(mAnomalyHintText, anomalyHintText)) {
|
||||
mAnomalyHintText = anomalyHintText;
|
||||
notifyChanged();
|
||||
|
||||
@@ -332,9 +332,8 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
|
||||
setBackgroundColor(Color.TRANSPARENT);
|
||||
mTrapezoidSolidColor = Utils.getColorAccentDefaultColor(context);
|
||||
mTrapezoidColor = Utils.getDisabled(context, mTrapezoidSolidColor);
|
||||
mTrapezoidHoverColor =
|
||||
Utils.getColorAttrDefaultColor(
|
||||
context, com.android.internal.R.attr.materialColorSecondaryContainer);
|
||||
mTrapezoidHoverColor = context.getColor(
|
||||
com.android.internal.R.color.materialColorSecondaryContainer);
|
||||
// Initializes the divider line paint.
|
||||
final Resources resources = getContext().getResources();
|
||||
mDividerWidth = resources.getDimensionPixelSize(R.dimen.chartview_divider_width);
|
||||
|
||||
@@ -169,6 +169,7 @@ public class BatteryDiffData {
|
||||
}
|
||||
if (packageName != null && hideBackgroundUsageTimeSet.contains(packageName)) {
|
||||
entry.mBackgroundUsageTimeInMs = 0;
|
||||
entry.mForegroundServiceUsageTimeInMs = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ final class BatteryOptimizationModeCache {
|
||||
Pair.create(
|
||||
BatteryOptimizationMode.forNumber(
|
||||
batteryOptimizeUtils.getAppOptimizationMode(
|
||||
/* refreshList= */ false)),
|
||||
/* refreshList= */ false,
|
||||
/* ignoreUnknownMode= */ false)),
|
||||
batteryOptimizeUtils.isOptimizeModeMutable()));
|
||||
}
|
||||
final Pair<BatteryOptimizationMode, Boolean> batteryOptimizeModeInfo =
|
||||
|
||||
@@ -31,7 +31,6 @@ import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
@@ -68,11 +67,11 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
|
||||
private static final String ROOT_PREFERENCE_KEY = "battery_usage_breakdown";
|
||||
private static final String FOOTER_PREFERENCE_KEY = "battery_usage_footer";
|
||||
private static final String SPINNER_PREFERENCE_KEY = "battery_usage_spinner";
|
||||
private static final String APP_LIST_PREFERENCE_KEY = "app_list";
|
||||
private static final String PACKAGE_NAME_NONE = "none";
|
||||
private static final String SLOT_TIMESTAMP = "slot_timestamp";
|
||||
private static final String ANOMALY_KEY = "anomaly_key";
|
||||
private static final String KEY_SPINNER_POSITION = "spinner_position";
|
||||
private static final int ENTRY_PREF_ORDER_OFFSET = 100;
|
||||
private static final List<BatteryDiffEntry> EMPTY_ENTRY_LIST = new ArrayList<>();
|
||||
|
||||
private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
|
||||
@@ -89,8 +88,7 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
|
||||
private SettingsSpinnerAdapter<CharSequence> mSpinnerAdapter;
|
||||
|
||||
@VisibleForTesting Context mPrefContext;
|
||||
@VisibleForTesting PreferenceCategory mRootPreference;
|
||||
@VisibleForTesting PreferenceGroup mAppListPreferenceGroup;
|
||||
@VisibleForTesting PreferenceGroup mRootPreferenceGroup;
|
||||
@VisibleForTesting FooterPreference mFooterPreference;
|
||||
@VisibleForTesting BatteryDiffData mBatteryDiffData;
|
||||
@VisibleForTesting String mBatteryUsageBreakdownTitleLastFullChargeText;
|
||||
@@ -143,7 +141,7 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
|
||||
public void onDestroy() {
|
||||
mHandler.removeCallbacksAndMessages(/* token= */ null);
|
||||
mPreferenceCache.clear();
|
||||
mAppListPreferenceGroup.removeAll();
|
||||
mRootPreferenceGroup.removeAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -226,9 +224,8 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mPrefContext = screen.getContext();
|
||||
mRootPreference = screen.findPreference(ROOT_PREFERENCE_KEY);
|
||||
mRootPreferenceGroup = screen.findPreference(ROOT_PREFERENCE_KEY);
|
||||
mSpinnerPreference = screen.findPreference(SPINNER_PREFERENCE_KEY);
|
||||
mAppListPreferenceGroup = screen.findPreference(APP_LIST_PREFERENCE_KEY);
|
||||
mFooterPreference = screen.findPreference(FOOTER_PREFERENCE_KEY);
|
||||
mBatteryUsageBreakdownTitleLastFullChargeText =
|
||||
mPrefContext.getString(
|
||||
@@ -242,7 +239,7 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
|
||||
R.string.battery_usage_less_than_percent_content_description,
|
||||
formatPercentage);
|
||||
|
||||
mAppListPreferenceGroup.setOrderingAsAdded(false);
|
||||
mRootPreferenceGroup.setOrderingAsAdded(false);
|
||||
mSpinnerAdapter = new SettingsSpinnerAdapter<>(mPrefContext);
|
||||
mSpinnerAdapter.addAll(
|
||||
new String[] {
|
||||
@@ -328,8 +325,9 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
|
||||
: mPrefContext.getString(
|
||||
R.string.battery_usage_breakdown_title_for_slot,
|
||||
accessibilitySlotTimestamp);
|
||||
mRootPreference.setTitle(Utils.createAccessibleSequence(displayTitle, accessibilityTitle));
|
||||
mRootPreference.setVisible(true);
|
||||
mRootPreferenceGroup.setTitle(
|
||||
Utils.createAccessibleSequence(displayTitle, accessibilityTitle));
|
||||
mRootPreferenceGroup.setVisible(true);
|
||||
}
|
||||
|
||||
private void showFooterPreference(boolean isAllBatteryUsageEmpty) {
|
||||
@@ -350,7 +348,6 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
|
||||
return;
|
||||
}
|
||||
mSpinnerPreference.setVisible(true);
|
||||
mAppListPreferenceGroup.setVisible(true);
|
||||
mHandler.post(
|
||||
() -> {
|
||||
removeAndCacheAllUnusedPreferences();
|
||||
@@ -374,7 +371,7 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
|
||||
}
|
||||
final long start = System.currentTimeMillis();
|
||||
final List<BatteryDiffEntry> entries = getBatteryDiffEntries();
|
||||
int prefIndex = mAppListPreferenceGroup.getPreferenceCount();
|
||||
int preferenceOrder = ENTRY_PREF_ORDER_OFFSET;
|
||||
for (BatteryDiffEntry entry : entries) {
|
||||
boolean isAdded = false;
|
||||
final String appLabel = entry.getAppLabel();
|
||||
@@ -384,33 +381,32 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
|
||||
continue;
|
||||
}
|
||||
final String prefKey = entry.getKey();
|
||||
AnomalyAppItemPreference pref = mAppListPreferenceGroup.findPreference(prefKey);
|
||||
if (pref != null) {
|
||||
AnomalyAppItemPreference preference = mRootPreferenceGroup.findPreference(prefKey);
|
||||
if (preference != null) {
|
||||
isAdded = true;
|
||||
} else {
|
||||
pref = (AnomalyAppItemPreference) mPreferenceCache.get(prefKey);
|
||||
preference = (AnomalyAppItemPreference) mPreferenceCache.get(prefKey);
|
||||
}
|
||||
// Creates new instance if cached preference is not found.
|
||||
if (pref == null) {
|
||||
pref = new AnomalyAppItemPreference(mPrefContext);
|
||||
pref.setKey(prefKey);
|
||||
mPreferenceCache.put(prefKey, pref);
|
||||
if (preference == null) {
|
||||
preference = new AnomalyAppItemPreference(mPrefContext);
|
||||
preference.setKey(prefKey);
|
||||
mPreferenceCache.put(prefKey, preference);
|
||||
}
|
||||
pref.setIcon(appIcon);
|
||||
pref.setTitle(appLabel);
|
||||
pref.setOrder(prefIndex);
|
||||
pref.setSingleLineTitle(true);
|
||||
preference.setIcon(appIcon);
|
||||
preference.setTitle(appLabel);
|
||||
preference.setOrder(++preferenceOrder);
|
||||
preference.setSingleLineTitle(true);
|
||||
// Updates App item preference style
|
||||
pref.setAnomalyHint(isAnomalyBatteryDiffEntry(entry) ? mAnomalyHintString : null);
|
||||
preference.setAnomalyHint(isAnomalyBatteryDiffEntry(entry) ? mAnomalyHintString : null);
|
||||
// Sets the BatteryDiffEntry to preference for launching detailed page.
|
||||
pref.setBatteryDiffEntry(entry);
|
||||
pref.setSelectable(entry.validForRestriction());
|
||||
setPreferencePercentage(pref, entry);
|
||||
setPreferenceSummary(pref, entry);
|
||||
preference.setBatteryDiffEntry(entry);
|
||||
preference.setSelectable(entry.validForRestriction());
|
||||
setPreferencePercentage(preference, entry);
|
||||
setPreferenceSummary(preference, entry);
|
||||
if (!isAdded) {
|
||||
mAppListPreferenceGroup.addPreference(pref);
|
||||
mRootPreferenceGroup.addPreference(preference);
|
||||
}
|
||||
prefIndex++;
|
||||
}
|
||||
Log.d(
|
||||
TAG,
|
||||
@@ -424,17 +420,22 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
|
||||
List<BatteryDiffEntry> entries = getBatteryDiffEntries();
|
||||
Set<String> entryKeySet = new ArraySet<>(entries.size());
|
||||
entries.forEach(entry -> entryKeySet.add(entry.getKey()));
|
||||
final int prefsCount = mAppListPreferenceGroup.getPreferenceCount();
|
||||
for (int index = prefsCount - 1; index >= 0; index--) {
|
||||
final Preference pref = mAppListPreferenceGroup.getPreference(index);
|
||||
if (entryKeySet.contains(pref.getKey())) {
|
||||
// The pref is still used, don't remove.
|
||||
final int preferenceCount = mRootPreferenceGroup.getPreferenceCount();
|
||||
for (int index = preferenceCount - 1; index >= 0; index--) {
|
||||
final Preference preference = mRootPreferenceGroup.getPreference(index);
|
||||
if ((preference instanceof SettingsSpinnerPreference)
|
||||
|| (preference instanceof FooterPreference)) {
|
||||
// Consider the app preference only and skip others
|
||||
continue;
|
||||
}
|
||||
if (!TextUtils.isEmpty(pref.getKey())) {
|
||||
mPreferenceCache.put(pref.getKey(), pref);
|
||||
if (entryKeySet.contains(preference.getKey())) {
|
||||
// Don't remove the preference if it is still in use
|
||||
continue;
|
||||
}
|
||||
mAppListPreferenceGroup.removePreference(pref);
|
||||
if (!TextUtils.isEmpty(preference.getKey())) {
|
||||
mPreferenceCache.put(preference.getKey(), preference);
|
||||
}
|
||||
mRootPreferenceGroup.removePreference(preference);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@ import android.app.usage.UsageEvents;
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.BatteryUsageStats;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
@@ -117,11 +115,9 @@ public final class BatteryUsageDataLoader {
|
||||
private static void preprocessBatteryUsageSlots(
|
||||
final Context context, final UserIdsSeries userIdsSeries) {
|
||||
final long start = System.currentTimeMillis();
|
||||
final Handler handler = new Handler(Looper.getMainLooper());
|
||||
final BatteryLevelData batteryLevelData =
|
||||
DataProcessManager.getBatteryLevelData(
|
||||
context,
|
||||
handler,
|
||||
userIdsSeries,
|
||||
/* isFromPeriodJob= */ true,
|
||||
batteryDiffDataMap -> {
|
||||
|
||||
@@ -19,8 +19,6 @@ package com.android.settings.fuelgauge.batteryusage;
|
||||
import android.app.usage.UsageEvents;
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -82,7 +80,6 @@ public class DataProcessManager {
|
||||
private final long mLastFullChargeTimestamp;
|
||||
private final boolean mIsFromPeriodJob;
|
||||
private final Context mContext;
|
||||
private final Handler mHandler;
|
||||
private final UserIdsSeries mUserIdsSeries;
|
||||
private final OnBatteryDiffDataMapLoadedListener mCallbackFunction;
|
||||
private final List<AppUsageEvent> mAppUsageEventList = new ArrayList<>();
|
||||
@@ -123,7 +120,6 @@ public class DataProcessManager {
|
||||
/** Constructor when there exists battery level data. */
|
||||
DataProcessManager(
|
||||
Context context,
|
||||
Handler handler,
|
||||
final UserIdsSeries userIdsSeries,
|
||||
final boolean isFromPeriodJob,
|
||||
final long rawStartTimestamp,
|
||||
@@ -132,7 +128,6 @@ public class DataProcessManager {
|
||||
@NonNull final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay,
|
||||
@NonNull final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
|
||||
mContext = context.getApplicationContext();
|
||||
mHandler = handler;
|
||||
mUserIdsSeries = userIdsSeries;
|
||||
mIsFromPeriodJob = isFromPeriodJob;
|
||||
mRawStartTimestamp = rawStartTimestamp;
|
||||
@@ -145,11 +140,9 @@ public class DataProcessManager {
|
||||
/** Constructor when there is no battery level data. */
|
||||
DataProcessManager(
|
||||
Context context,
|
||||
Handler handler,
|
||||
final UserIdsSeries userIdsSeries,
|
||||
@NonNull final OnBatteryDiffDataMapLoadedListener callbackFunction) {
|
||||
mContext = context.getApplicationContext();
|
||||
mHandler = handler;
|
||||
mUserIdsSeries = userIdsSeries;
|
||||
mCallbackFunction = callbackFunction;
|
||||
mIsFromPeriodJob = false;
|
||||
@@ -444,12 +437,8 @@ public class DataProcessManager {
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Map<Long, BatteryDiffData> batteryDiffDataMap) {
|
||||
// Post results back to main thread to refresh UI.
|
||||
if (mHandler != null && mCallbackFunction != null) {
|
||||
mHandler.post(
|
||||
() -> {
|
||||
mCallbackFunction.onBatteryDiffDataMapLoaded(batteryDiffDataMap);
|
||||
});
|
||||
if (mCallbackFunction != null) {
|
||||
mCallbackFunction.onBatteryDiffDataMapLoaded(batteryDiffDataMap);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
@@ -534,12 +523,8 @@ public class DataProcessManager {
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Map<Long, BatteryDiffData> batteryDiffDataMap) {
|
||||
// Post results back to main thread to refresh UI.
|
||||
if (mHandler != null && mCallbackFunction != null) {
|
||||
mHandler.post(
|
||||
() -> {
|
||||
mCallbackFunction.onBatteryDiffDataMapLoaded(batteryDiffDataMap);
|
||||
});
|
||||
if (mCallbackFunction != null) {
|
||||
mCallbackFunction.onBatteryDiffDataMapLoaded(batteryDiffDataMap);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
@@ -581,7 +566,6 @@ public class DataProcessManager {
|
||||
@Nullable
|
||||
public static BatteryLevelData getBatteryLevelData(
|
||||
Context context,
|
||||
@Nullable Handler handler,
|
||||
final UserIdsSeries userIdsSeries,
|
||||
final boolean isFromPeriodJob,
|
||||
final OnBatteryDiffDataMapLoadedListener onBatteryUsageMapLoadedListener) {
|
||||
@@ -601,7 +585,6 @@ public class DataProcessManager {
|
||||
final BatteryLevelData batteryLevelData =
|
||||
getPeriodBatteryLevelData(
|
||||
context,
|
||||
handler,
|
||||
userIdsSeries,
|
||||
startTimestamp,
|
||||
lastFullChargeTime,
|
||||
@@ -621,7 +604,6 @@ public class DataProcessManager {
|
||||
|
||||
private static BatteryLevelData getPeriodBatteryLevelData(
|
||||
Context context,
|
||||
@Nullable Handler handler,
|
||||
final UserIdsSeries userIdsSeries,
|
||||
final long startTimestamp,
|
||||
final long lastFullChargeTime,
|
||||
@@ -639,7 +621,6 @@ public class DataProcessManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
handler = handler != null ? handler : new Handler(Looper.getMainLooper());
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
|
||||
sFakeBatteryHistoryMap != null
|
||||
? sFakeBatteryHistoryMap
|
||||
@@ -650,8 +631,7 @@ public class DataProcessManager {
|
||||
lastFullChargeTime);
|
||||
if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) {
|
||||
Log.d(TAG, "batteryHistoryMap is null in getPeriodBatteryLevelData()");
|
||||
new DataProcessManager(
|
||||
context, handler, userIdsSeries, onBatteryDiffDataMapLoadedListener)
|
||||
new DataProcessManager(context, userIdsSeries, onBatteryDiffDataMapLoadedListener)
|
||||
.start();
|
||||
return null;
|
||||
}
|
||||
@@ -680,8 +660,7 @@ public class DataProcessManager {
|
||||
DataProcessor.getLevelDataThroughProcessedHistoryMap(
|
||||
context, processedBatteryHistoryMap);
|
||||
if (batteryLevelData == null) {
|
||||
new DataProcessManager(
|
||||
context, handler, userIdsSeries, onBatteryDiffDataMapLoadedListener)
|
||||
new DataProcessManager(context, userIdsSeries, onBatteryDiffDataMapLoadedListener)
|
||||
.start();
|
||||
Log.d(TAG, "getBatteryLevelData() returns null");
|
||||
return null;
|
||||
@@ -690,7 +669,6 @@ public class DataProcessManager {
|
||||
// Start the async task to compute diff usage data and load labels and icons.
|
||||
new DataProcessManager(
|
||||
context,
|
||||
handler,
|
||||
userIdsSeries,
|
||||
isFromPeriodJob,
|
||||
startTimestamp,
|
||||
|
||||
@@ -31,8 +31,6 @@ import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.BatteryUsageStats;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserManager;
|
||||
@@ -66,12 +64,6 @@ import java.util.stream.Collectors;
|
||||
public final class DatabaseUtils {
|
||||
private static final String TAG = "DatabaseUtils";
|
||||
private static final String SHARED_PREFS_FILE = "battery_usage_shared_prefs";
|
||||
private static final boolean EXPLICIT_CLEAR_MEMORY_ENABLED = false;
|
||||
|
||||
/** Clear memory threshold for device booting phase. */
|
||||
private static final long CLEAR_MEMORY_THRESHOLD_MS = Duration.ofMinutes(5).toMillis();
|
||||
|
||||
private static final long CLEAR_MEMORY_DELAYED_MS = Duration.ofSeconds(2).toMillis();
|
||||
private static final long INVALID_TIMESTAMP = 0L;
|
||||
|
||||
static final int DATA_RETENTION_INTERVAL_DAY = 9;
|
||||
@@ -593,7 +585,6 @@ public final class DatabaseUtils {
|
||||
String.format(
|
||||
"sendAppUsageEventData() size=%d in %d/ms",
|
||||
size, (System.currentTimeMillis() - startTime)));
|
||||
clearMemory();
|
||||
return valuesList;
|
||||
}
|
||||
|
||||
@@ -613,7 +604,6 @@ public final class DatabaseUtils {
|
||||
String.format(
|
||||
"sendBatteryEventData() in %d/ms",
|
||||
(System.currentTimeMillis() - startTime)));
|
||||
clearMemory();
|
||||
return contentValues;
|
||||
}
|
||||
|
||||
@@ -647,7 +637,6 @@ public final class DatabaseUtils {
|
||||
String.format(
|
||||
"sendBatteryEventData() size=%d in %d/ms",
|
||||
size, (System.currentTimeMillis() - startTime)));
|
||||
clearMemory();
|
||||
return valuesList;
|
||||
}
|
||||
|
||||
@@ -681,7 +670,6 @@ public final class DatabaseUtils {
|
||||
String.format(
|
||||
"sendBatteryUsageSlotData() size=%d in %d/ms",
|
||||
size, (System.currentTimeMillis() - startTime)));
|
||||
clearMemory();
|
||||
return valuesList;
|
||||
}
|
||||
|
||||
@@ -695,7 +683,6 @@ public final class DatabaseUtils {
|
||||
final Intent intent = BatteryUtils.getBatteryIntent(context);
|
||||
if (intent == null) {
|
||||
Log.e(TAG, "sendBatteryEntryData(): cannot fetch battery intent");
|
||||
clearMemory();
|
||||
return null;
|
||||
}
|
||||
final int batteryLevel = BatteryStatus.getBatteryLevel(intent);
|
||||
@@ -796,7 +783,6 @@ public final class DatabaseUtils {
|
||||
if (isFullChargeStart) {
|
||||
recordDateTime(context, KEY_LAST_UPLOAD_FULL_CHARGE_TIME);
|
||||
}
|
||||
clearMemory();
|
||||
return valuesList;
|
||||
}
|
||||
|
||||
@@ -992,20 +978,4 @@ public final class DatabaseUtils {
|
||||
writer.println(String.format("\t\t%s: %s", prefix, results.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
private static void clearMemory() {
|
||||
if (!EXPLICIT_CLEAR_MEMORY_ENABLED
|
||||
|| SystemClock.uptimeMillis() > CLEAR_MEMORY_THRESHOLD_MS) {
|
||||
return;
|
||||
}
|
||||
final Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
mainHandler.postDelayed(
|
||||
() -> {
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
System.gc();
|
||||
Log.w(TAG, "invoke clearMemory()");
|
||||
},
|
||||
CLEAR_MEMORY_DELAYED_MS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,20 +214,22 @@ public class PowerUsageAdvanced extends PowerUsageBase {
|
||||
if (!isResumed() || mBatteryLevelData == null) {
|
||||
return;
|
||||
}
|
||||
mBatteryUsageMap =
|
||||
DataProcessor.generateBatteryUsageMap(
|
||||
getContext(), batteryDiffDataMap, mBatteryLevelData.orElse(null));
|
||||
Log.d(TAG, "onBatteryDiffDataMapUpdate: " + mBatteryUsageMap);
|
||||
DataProcessor.loadLabelAndIcon(mBatteryUsageMap);
|
||||
onSelectedSlotDataUpdated();
|
||||
detectAnomaly();
|
||||
logScreenUsageTime();
|
||||
if (mBatteryChartPreferenceController != null
|
||||
&& mBatteryLevelData.isEmpty()
|
||||
&& isBatteryUsageMapNullOrEmpty()) {
|
||||
// No available battery usage and battery level data.
|
||||
mBatteryChartPreferenceController.showEmptyChart();
|
||||
}
|
||||
mHandler.post(() -> {
|
||||
mBatteryUsageMap =
|
||||
DataProcessor.generateBatteryUsageMap(
|
||||
getContext(), batteryDiffDataMap, mBatteryLevelData.orElse(null));
|
||||
Log.d(TAG, "onBatteryDiffDataMapUpdate: " + mBatteryUsageMap);
|
||||
DataProcessor.loadLabelAndIcon(mBatteryUsageMap);
|
||||
onSelectedSlotDataUpdated();
|
||||
detectAnomaly();
|
||||
logScreenUsageTime();
|
||||
if (mBatteryChartPreferenceController != null
|
||||
&& mBatteryLevelData.isEmpty()
|
||||
&& isBatteryUsageMapNullOrEmpty()) {
|
||||
// No available battery usage and battery level data.
|
||||
mBatteryChartPreferenceController.showEmptyChart();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onSelectedSlotDataUpdated() {
|
||||
@@ -503,7 +505,6 @@ public class PowerUsageAdvanced extends PowerUsageBase {
|
||||
public BatteryLevelData loadInBackground() {
|
||||
return DataProcessManager.getBatteryLevelData(
|
||||
getContext(),
|
||||
mHandler,
|
||||
new UserIdsSeries(getContext(), /* isNonUIRequest= */ false),
|
||||
/* isFromPeriodJob= */ false,
|
||||
PowerUsageAdvanced.this::onBatteryDiffDataMapUpdate);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.settings.fuelgauge.batteryusage;
|
||||
|
||||
import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
@@ -26,15 +27,16 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings.Global;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.content.Loader;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.fuelgauge.BatteryHeaderPreferenceController;
|
||||
import com.android.settings.fuelgauge.BatteryHeaderTextPreferenceController;
|
||||
import com.android.settings.fuelgauge.BatteryInfo;
|
||||
import com.android.settings.fuelgauge.BatteryInfoLoader;
|
||||
import com.android.settings.fuelgauge.BatteryUtils;
|
||||
@@ -65,7 +67,7 @@ public class PowerUsageSummary extends PowerUsageBase
|
||||
@VisibleForTesting BatteryUtils mBatteryUtils;
|
||||
@VisibleForTesting BatteryInfo mBatteryInfo;
|
||||
|
||||
@VisibleForTesting BatteryHeaderPreferenceController mBatteryHeaderPreferenceController;
|
||||
@VisibleForTesting BatteryHeaderTextPreferenceController mBatteryHeaderTextPreferenceController;
|
||||
@VisibleForTesting BatteryTipPreferenceController mBatteryTipPreferenceController;
|
||||
@VisibleForTesting boolean mNeedUpdateBatteryTip;
|
||||
@VisibleForTesting Preference mHelpPreference;
|
||||
@@ -91,8 +93,8 @@ public class PowerUsageSummary extends PowerUsageBase
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<BatteryInfo> loader, BatteryInfo batteryInfo) {
|
||||
mBatteryHeaderPreferenceController.updateHeaderPreference(batteryInfo);
|
||||
mBatteryHeaderPreferenceController.updateHeaderByBatteryTips(
|
||||
mBatteryHeaderTextPreferenceController.updateHeaderPreference(batteryInfo);
|
||||
mBatteryHeaderTextPreferenceController.updateHeaderByBatteryTips(
|
||||
mBatteryTipPreferenceController.getCurrentBatteryTip(), batteryInfo);
|
||||
mBatteryInfo = batteryInfo;
|
||||
}
|
||||
@@ -114,7 +116,7 @@ public class PowerUsageSummary extends PowerUsageBase
|
||||
@Override
|
||||
public void onLoadFinished(Loader<List<BatteryTip>> loader, List<BatteryTip> data) {
|
||||
mBatteryTipPreferenceController.updateBatteryTips(data);
|
||||
mBatteryHeaderPreferenceController.updateHeaderByBatteryTips(
|
||||
mBatteryHeaderTextPreferenceController.updateHeaderByBatteryTips(
|
||||
mBatteryTipPreferenceController.getCurrentBatteryTip(), mBatteryInfo);
|
||||
}
|
||||
|
||||
@@ -125,9 +127,9 @@ public class PowerUsageSummary extends PowerUsageBase
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
final SettingsActivity activity = (SettingsActivity) getActivity();
|
||||
final Activity activity = getActivity();
|
||||
|
||||
mBatteryHeaderPreferenceController = use(BatteryHeaderPreferenceController.class);
|
||||
mBatteryHeaderTextPreferenceController = use(BatteryHeaderTextPreferenceController.class);
|
||||
|
||||
mBatteryTipPreferenceController = use(BatteryTipPreferenceController.class);
|
||||
mBatteryTipPreferenceController.setActivity(activity);
|
||||
@@ -248,15 +250,6 @@ public class PowerUsageSummary extends PowerUsageBase
|
||||
mNeedUpdateBatteryTip = icicle == null || mBatteryTipPreferenceController.needUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void restartBatteryStatsLoader(@BatteryUpdateType int refreshType) {
|
||||
super.restartBatteryStatsLoader(refreshType);
|
||||
// Update battery header if battery is present.
|
||||
if (mIsBatteryPresent) {
|
||||
mBatteryHeaderPreferenceController.quickUpdateHeaderPreference();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
@@ -270,4 +263,9 @@ public class PowerUsageSummary extends PowerUsageBase
|
||||
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider(R.xml.power_usage_summary);
|
||||
|
||||
@Override
|
||||
public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
|
||||
return PowerUsageSummaryScreen.KEY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.batteryusage
|
||||
|
||||
import android.content.Context
|
||||
import com.android.settings.R
|
||||
import com.android.settings.display.BatteryPercentageSwitchPreference
|
||||
import com.android.settings.flags.Flags
|
||||
import com.android.settings.fuelgauge.BatteryHeaderPreference
|
||||
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
|
||||
import com.android.settingslib.metadata.PreferenceIconProvider
|
||||
import com.android.settingslib.metadata.ProvidePreferenceScreen
|
||||
import com.android.settingslib.metadata.preferenceHierarchy
|
||||
import com.android.settingslib.preference.PreferenceScreenCreator
|
||||
|
||||
@ProvidePreferenceScreen
|
||||
class PowerUsageSummaryScreen :
|
||||
PreferenceScreenCreator, PreferenceAvailabilityProvider, PreferenceIconProvider {
|
||||
override val key: String
|
||||
get() = KEY
|
||||
|
||||
override val title: Int
|
||||
get() = R.string.power_usage_summary_title
|
||||
|
||||
override val keywords: Int
|
||||
get() = R.string.keywords_battery
|
||||
|
||||
override fun isFlagEnabled(context: Context) = Flags.catalystPowerUsageSummaryScreen()
|
||||
|
||||
override fun hasCompleteHierarchy() = false
|
||||
|
||||
override fun fragmentClass() = PowerUsageSummary::class.java
|
||||
|
||||
override fun isAvailable(context: Context) =
|
||||
context.resources.getBoolean(R.bool.config_show_top_level_battery)
|
||||
|
||||
override fun getIcon(context: Context): Int =
|
||||
if (Flags.homepageRevamp()) {
|
||||
R.drawable.ic_settings_battery_filled
|
||||
} else {
|
||||
R.drawable.ic_settings_battery_white
|
||||
}
|
||||
|
||||
override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {
|
||||
+BatteryHeaderPreference()
|
||||
+BatteryPercentageSwitchPreference()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KEY = "power_usage_summary_screen"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user