Merge "Fix that the padding top/bottom of the preview was wrong when display size is smallest."
diff --git a/res/values/strings.xml b/res/values/strings.xml
index fd186af..28055ab 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -11261,6 +11261,21 @@
<!-- [CHAR_LIMIT=NONE] Label for when app is ignoring battery optimizations -->
<string name="not_battery_optimizing">Not using battery optimization</string>
+ <!-- Preference title for battery optimization list page[CHAR_LIMIT=50]-->
+ <string name="app_battery_optimization_title">Manage battery usage</string>
+
+ <!-- Preference summary for battery optimization list page[CHAR_LIMIT=50]-->
+ <string name="app_battery_optimization_summary">Set battery usage for apps</string>
+
+ <!-- Filter title for battery unrestricted[CHAR_LIMIT=50]-->
+ <string name="filter_battery_unrestricted_title">Unrestricted</string>
+
+ <!-- Filter title for battery optimized[CHAR_LIMIT=50]-->
+ <string name="filter_battery_optimized_title">Optimized</string>
+
+ <!-- Filter title for battery restricted[CHAR_LIMIT=50]-->
+ <string name="filter_battery_restricted_title">Restricted</string>
+
<!-- Text for the setting on whether you can type text into notifications without unlocking the device. -->
<string name="lockscreen_remote_input">If device is locked, prevent typing replies or other text in notifications</string>
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index c3ab8e2..f7ba017 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -326,6 +326,8 @@
public static class ChangeWifiStateActivity extends SettingsActivity { /* empty */ }
public static class AppDrawOverlaySettingsActivity extends SettingsActivity { /* empty */ }
public static class AppWriteSettingsActivity extends SettingsActivity { /* empty */ }
+ /** Activity to manage app battery optimization details. */
+ public static class AppBatteryOptimizationActivity extends SettingsActivity { /* empty */ }
public static class ManageExternalSourcesActivity extends SettingsActivity {/* empty */ }
public static class ManageAppExternalSourcesActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/applications/AppStateBatteryOptimizationBridge.java b/src/com/android/settings/applications/AppStateBatteryOptimizationBridge.java
new file mode 100644
index 0000000..6301c85
--- /dev/null
+++ b/src/com/android/settings/applications/AppStateBatteryOptimizationBridge.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2022 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.applications;
+
+import android.annotation.IntDef;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.os.Build;
+import android.util.Log;
+
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.applications.ApplicationsState.AppFilter;
+import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Class for bridging the Battery optimization information to ApplicationState.
+ */
+public class AppStateBatteryOptimizationBridge extends AppStateBaseBridge {
+ private static final String TAG = AppStateBatteryOptimizationBridge.class.getSimpleName();
+ static final boolean DEBUG = Build.IS_DEBUGGABLE;
+
+ private final Context mContext;
+ private final AppOpsManager mAppOpsManager;
+ private final PowerAllowlistBackend mPowerAllowlistBackend;
+
+ private static final int MODE_UNKNOWN = 0;
+ private static final int MODE_UNRESTRICTED = 1;
+ private static final int MODE_OPTIMIZED = 2;
+ private static final int MODE_RESTRICTED = 3;
+
+ @IntDef(
+ prefix = {"MODE_"},
+ value = {
+ MODE_UNKNOWN,
+ MODE_RESTRICTED,
+ MODE_UNRESTRICTED,
+ MODE_OPTIMIZED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface OptimizationMode {
+ }
+
+ public AppStateBatteryOptimizationBridge(
+ Context context, ApplicationsState appState, Callback callback) {
+ super(appState, callback);
+ mContext = context;
+ mAppOpsManager = context.getSystemService(AppOpsManager.class);
+ mPowerAllowlistBackend = PowerAllowlistBackend.getInstance(mContext);
+ }
+
+ @Override
+ protected void updateExtraInfo(AppEntry app, String pkg, int uid) {
+ app.extraInfo = getAppBatteryOptimizationState(pkg, uid);
+ }
+
+ @Override
+ protected void loadAllExtraInfo() {
+ if (DEBUG) {
+ Log.d(TAG, "Start loadAllExtraInfo()");
+ }
+ mAppSession.getAllApps().stream().forEach(appEntry ->
+ updateExtraInfo(appEntry, appEntry.info.packageName, appEntry.info.uid));
+ if (DEBUG) {
+ Log.d(TAG, "End loadAllExtraInfo()");
+ }
+ }
+
+ protected Object getAppBatteryOptimizationState(String pkg, int uid) {
+ // Restricted = AppOpsManager.MODE_IGNORED + !allowListed
+ // Unrestricted = AppOpsManager.MODE_ALLOWED + allowListed
+ // Optimized = AppOpsManager.MODE_ALLOWED + !allowListed
+
+ boolean allowListed = mPowerAllowlistBackend.isAllowlisted(pkg);
+ int aomMode =
+ mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, pkg);
+ @OptimizationMode int mode = MODE_UNKNOWN;
+ String modeName = "";
+ if (aomMode == AppOpsManager.MODE_IGNORED && !allowListed) {
+ mode = MODE_RESTRICTED;
+ if (DEBUG) {
+ modeName = "RESTRICTED";
+ }
+ } else if (aomMode == AppOpsManager.MODE_ALLOWED) {
+ mode = allowListed ? MODE_UNRESTRICTED : MODE_OPTIMIZED;
+ if (DEBUG) {
+ modeName = allowListed ? "UNRESTRICTED" : "OPTIMIZED";
+ }
+ }
+ if (DEBUG) {
+ Log.d(TAG, "Pkg: " + pkg + ", mode: " + modeName);
+ }
+ return new BatteryOptimizationDetails(mode);
+ }
+
+ @OptimizationMode
+ private static int getBatteryOptimizationDetailsMode(AppEntry entry) {
+ if (entry == null || entry.extraInfo == null) {
+ return MODE_UNKNOWN;
+ }
+
+ return entry.extraInfo instanceof BatteryOptimizationDetails
+ ? ((BatteryOptimizationDetails) entry.extraInfo).mMode
+ : MODE_UNKNOWN;
+ }
+
+ /**
+ * Used by {@link com.android.settings.applications.manageapplications.AppFilterRegistry} to
+ * determine which apps are unrestricted.
+ */
+ public static final AppFilter FILTER_BATTERY_UNRESTRICTED_APPS =
+ new AppFilter() {
+ @Override
+ public void init() {}
+
+ @Override
+ public boolean filterApp(AppEntry info) {
+ return getBatteryOptimizationDetailsMode(info) == MODE_UNRESTRICTED;
+ }
+ };
+
+ /**
+ * Used by {@link com.android.settings.applications.manageapplications.AppFilterRegistry} to
+ * determine which apps are optimized.
+ */
+ public static final AppFilter FILTER_BATTERY_OPTIMIZED_APPS =
+ new AppFilter() {
+ @Override
+ public void init() {}
+
+ @Override
+ public boolean filterApp(AppEntry info) {
+ return getBatteryOptimizationDetailsMode(info) == MODE_OPTIMIZED;
+ }
+ };
+
+ /**
+ * Used by {@link com.android.settings.applications.manageapplications.AppFilterRegistry} to
+ * determine which apps are restricted.
+ */
+ public static final AppFilter FILTER_BATTERY_RESTRICTED_APPS =
+ new AppFilter() {
+ @Override
+ public void init() {}
+
+ @Override
+ public boolean filterApp(AppEntry info) {
+ return getBatteryOptimizationDetailsMode(info) == MODE_RESTRICTED;
+ }
+ };
+
+ /**
+ * Extra details for battery optimization app data.
+ */
+ static final class BatteryOptimizationDetails {
+ @OptimizationMode
+ int mMode;
+
+ BatteryOptimizationDetails(@OptimizationMode int mode) {
+ mMode = mode;
+ }
+ }
+}
diff --git a/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java b/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java
index 3c00b73..35de16e 100644
--- a/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java
+++ b/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java
@@ -20,6 +20,7 @@
import com.android.settings.R;
import com.android.settings.applications.AppStateAlarmsAndRemindersBridge;
+import com.android.settings.applications.AppStateBatteryOptimizationBridge;
import com.android.settings.applications.AppStateInstallAppsBridge;
import com.android.settings.applications.AppStateLocaleBridge;
import com.android.settings.applications.AppStateManageExternalStorageBridge;
@@ -37,28 +38,31 @@
*/
public class AppFilterRegistry {
- @IntDef(value = {
- FILTER_APPS_POWER_ALLOWLIST,
- FILTER_APPS_POWER_ALLOWLIST_ALL,
- FILTER_APPS_ALL,
- FILTER_APPS_ENABLED,
- FILTER_APPS_INSTANT,
- FILTER_APPS_DISABLED,
- FILTER_APPS_RECENT,
- FILTER_APPS_FREQUENT,
- FILTER_APPS_PERSONAL,
- FILTER_APPS_WORK,
- FILTER_APPS_USAGE_ACCESS,
- FILTER_APPS_WITH_OVERLAY,
- FILTER_APPS_WRITE_SETTINGS,
- FILTER_APPS_INSTALL_SOURCES,
- FILTER_APPS_BLOCKED,
- FILTER_ALARMS_AND_REMINDERS,
- FILTER_APPS_MEDIA_MANAGEMENT,
- FILTER_APPS_LOCALE,
- })
- @interface FilterType {
- }
+ @IntDef(
+ value = {
+ FILTER_APPS_POWER_ALLOWLIST,
+ FILTER_APPS_POWER_ALLOWLIST_ALL,
+ FILTER_APPS_ALL,
+ FILTER_APPS_ENABLED,
+ FILTER_APPS_INSTANT,
+ FILTER_APPS_DISABLED,
+ FILTER_APPS_RECENT,
+ FILTER_APPS_FREQUENT,
+ FILTER_APPS_PERSONAL,
+ FILTER_APPS_WORK,
+ FILTER_APPS_USAGE_ACCESS,
+ FILTER_APPS_WITH_OVERLAY,
+ FILTER_APPS_WRITE_SETTINGS,
+ FILTER_APPS_INSTALL_SOURCES,
+ FILTER_APPS_BLOCKED,
+ FILTER_ALARMS_AND_REMINDERS,
+ FILTER_APPS_MEDIA_MANAGEMENT,
+ FILTER_APPS_LOCALE,
+ FILTER_APPS_BATTERY_UNRESTRICTED,
+ FILTER_APPS_BATTERY_OPTIMIZED,
+ FILTER_APPS_BATTERY_RESTRICTED,
+ })
+ @interface FilterType {}
// Filter options used for displayed list of applications
// Filters will appear sorted based on their value defined here.
@@ -82,14 +86,18 @@
public static final int FILTER_ALARMS_AND_REMINDERS = 18;
public static final int FILTER_APPS_MEDIA_MANAGEMENT = 19;
public static final int FILTER_APPS_LOCALE = 20;
- // Next id: 21. If you add an entry here, length of mFilters should be updated
+ public static final int FILTER_APPS_BATTERY_UNRESTRICTED = 21;
+ public static final int FILTER_APPS_BATTERY_OPTIMIZED = 22;
+ public static final int FILTER_APPS_BATTERY_RESTRICTED = 23;
+ // Next id: 24. If you add an entry here, please change NUM_FILTER_ENTRIES.
+ private static final int NUM_FILTER_ENTRIES = 24;
private static AppFilterRegistry sRegistry;
private final AppFilterItem[] mFilters;
private AppFilterRegistry() {
- mFilters = new AppFilterItem[21];
+ mFilters = new AppFilterItem[NUM_FILTER_ENTRIES];
// High power allowlist, on
mFilters[FILTER_APPS_POWER_ALLOWLIST] = new AppFilterItem(
@@ -212,6 +220,28 @@
AppStateLocaleBridge.FILTER_APPS_LOCALE,
FILTER_APPS_LOCALE,
R.string.app_locale_picker_title);
+
+ // Battery optimization app states:
+ // Unrestricted
+ mFilters[FILTER_APPS_BATTERY_UNRESTRICTED] =
+ new AppFilterItem(
+ AppStateBatteryOptimizationBridge.FILTER_BATTERY_UNRESTRICTED_APPS,
+ FILTER_APPS_BATTERY_UNRESTRICTED,
+ R.string.filter_battery_unrestricted_title);
+
+ // Optimized
+ mFilters[FILTER_APPS_BATTERY_OPTIMIZED] =
+ new AppFilterItem(
+ AppStateBatteryOptimizationBridge.FILTER_BATTERY_OPTIMIZED_APPS,
+ FILTER_APPS_BATTERY_OPTIMIZED,
+ R.string.filter_battery_optimized_title);
+
+ // Unrestricted
+ mFilters[FILTER_APPS_BATTERY_RESTRICTED] =
+ new AppFilterItem(
+ AppStateBatteryOptimizationBridge.FILTER_BATTERY_RESTRICTED_APPS,
+ FILTER_APPS_BATTERY_RESTRICTED,
+ R.string.filter_battery_restricted_title);
}
@@ -248,6 +278,8 @@
return FILTER_APPS_MEDIA_MANAGEMENT;
case ManageApplications.LIST_TYPE_APPS_LOCALE:
return FILTER_APPS_LOCALE;
+ case ManageApplications.LIST_TYPE_BATTERY_OPTIMIZATION:
+ return FILTER_APPS_BATTERY_OPTIMIZED;
default:
return FILTER_APPS_ALL;
}
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 0b7d522..d020f33 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -21,6 +21,9 @@
import static com.android.settings.ChangeIds.CHANGE_RESTRICT_SAW_INTENT;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_ALL;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_BATTERY_OPTIMIZED;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_BATTERY_RESTRICTED;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_BATTERY_UNRESTRICTED;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_BLOCKED;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_DISABLED;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_ENABLED;
@@ -96,6 +99,7 @@
import com.android.settings.applications.AppStateAlarmsAndRemindersBridge;
import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
import com.android.settings.applications.AppStateBaseBridge;
+import com.android.settings.applications.AppStateBatteryOptimizationBridge;
import com.android.settings.applications.AppStateInstallAppsBridge;
import com.android.settings.applications.AppStateLocaleBridge;
import com.android.settings.applications.AppStateManageExternalStorageBridge;
@@ -120,6 +124,7 @@
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
+import com.android.settings.fuelgauge.AdvancedPowerUsageDetail;
import com.android.settings.fuelgauge.HighPowerDetail;
import com.android.settings.localepicker.AppLocalePickerActivity;
import com.android.settings.notification.ConfigureNotificationSettings;
@@ -229,6 +234,7 @@
public static final int LIST_TYPE_ALARMS_AND_REMINDERS = 12;
public static final int LIST_TYPE_MEDIA_MANAGEMENT_APPS = 13;
public static final int LIST_TYPE_APPS_LOCALE = 14;
+ public static final int LIST_TYPE_BATTERY_OPTIMIZATION = 15;
// List types that should show instant apps.
public static final Set<Integer> LIST_TYPES_WITH_INSTANT = new ArraySet<>(Arrays.asList(
@@ -327,6 +333,8 @@
}
} else if (className.equals(AppLocaleDetails.class.getName())) {
mListType = LIST_TYPE_APPS_LOCALE;
+ } else if (className.equals(Settings.AppBatteryOptimizationActivity.class.getName())) {
+ mListType = LIST_TYPE_BATTERY_OPTIMIZATION;
} else {
mListType = LIST_TYPE_MAIN;
}
@@ -460,6 +468,12 @@
if (mListType == LIST_TYPE_HIGH_POWER) {
mFilterAdapter.enableFilter(FILTER_APPS_POWER_ALLOWLIST_ALL);
}
+ if (mListType == LIST_TYPE_BATTERY_OPTIMIZATION) {
+ mFilterAdapter.enableFilter(FILTER_APPS_ALL);
+ mFilterAdapter.enableFilter(FILTER_APPS_BATTERY_UNRESTRICTED);
+ mFilterAdapter.enableFilter(FILTER_APPS_BATTERY_OPTIMIZED);
+ mFilterAdapter.enableFilter(FILTER_APPS_BATTERY_RESTRICTED);
+ }
setCompositeFilter();
}
@@ -511,6 +525,8 @@
return SettingsEnums.MEDIA_MANAGEMENT_APPS;
case LIST_TYPE_APPS_LOCALE:
return SettingsEnums.APPS_LOCALE_LIST;
+ case LIST_TYPE_BATTERY_OPTIMIZATION:
+ return SettingsEnums.BATTERY_OPTIMIZED_APPS_LIST;
default:
return SettingsEnums.PAGE_UNKNOWN;
}
@@ -641,6 +657,10 @@
intent.putExtra(AppInfoBase.ARG_PACKAGE_UID, mCurrentUid);
startActivity(intent);
break;
+ case LIST_TYPE_BATTERY_OPTIMIZATION:
+ AdvancedPowerUsageDetail.startBatteryDetailPage(
+ getActivity(), this, mCurrentPkgName);
+ break;
// TODO: Figure out if there is a way where we can spin up the profile's settings
// process ahead of time, to avoid a long load of data when user clicks on a managed
// app. Maybe when they load the list of apps that contains managed profile apps.
@@ -923,6 +943,8 @@
screenTitle = R.string.app_notifications_title;
} else if (className.equals(AppLocaleDetails.class.getName())) {
screenTitle = R.string.app_locales_picker_menu_title;
+ } else if (className.equals(Settings.AppBatteryOptimizationActivity.class.getName())) {
+ screenTitle = R.string.app_battery_optimization_title;
} else {
if (screenTitle == -1) {
screenTitle = R.string.all_apps;
@@ -1115,6 +1137,8 @@
mExtraInfoBridge = new AppStateMediaManagementAppsBridge(mContext, mState, this);
} else if (mManageApplications.mListType == LIST_TYPE_APPS_LOCALE) {
mExtraInfoBridge = new AppStateLocaleBridge(mContext, mState, this);
+ } else if (mManageApplications.mListType == LIST_TYPE_BATTERY_OPTIMIZATION) {
+ mExtraInfoBridge = new AppStateBatteryOptimizationBridge(mContext, mState, this);
} else {
mExtraInfoBridge = null;
}
@@ -1146,18 +1170,21 @@
public void setFilter(AppFilterItem appFilter) {
mAppFilter = appFilter;
+ final int filterType = appFilter.getFilterType();
// Notification filters require resorting the list
if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
- if (FILTER_APPS_FREQUENT == appFilter.getFilterType()) {
+ if (FILTER_APPS_FREQUENT == filterType) {
rebuild(R.id.sort_order_frequent_notification, false);
- } else if (FILTER_APPS_RECENT == appFilter.getFilterType()) {
+ } else if (FILTER_APPS_RECENT == filterType) {
rebuild(R.id.sort_order_recent_notification, false);
- } else if (FILTER_APPS_BLOCKED == appFilter.getFilterType()) {
+ } else if (FILTER_APPS_BLOCKED == filterType) {
rebuild(R.id.sort_order_alpha, true);
} else {
rebuild(R.id.sort_order_alpha, true);
}
+ } else if (mManageApplications.mListType == LIST_TYPE_BATTERY_OPTIMIZATION) {
+ logBatteryOptimization(filterType);
} else {
rebuild();
}
@@ -1294,6 +1321,26 @@
});
}
+ private void logBatteryOptimization(int filterType) {
+ switch(filterType) {
+ case FILTER_APPS_BATTERY_UNRESTRICTED:
+ logAction(SettingsEnums.ACTION_BATTERY_OPTIMIZED_APPS_FILTER_UNRESTRICTED);
+ break;
+ case FILTER_APPS_BATTERY_OPTIMIZED:
+ logAction(SettingsEnums.ACTION_BATTERY_OPTIMIZED_APPS_FILTER_OPTIMIZED);
+ break;
+ case FILTER_APPS_BATTERY_RESTRICTED:
+ logAction(SettingsEnums.ACTION_BATTERY_OPTIMIZED_APPS_FILTER_RESTRICTED);
+ break;
+ default:
+ logAction(SettingsEnums.ACTION_BATTERY_OPTIMIZED_APPS_FILTER_ALL_APPS);
+ }
+ }
+
+ private void logAction(int action) {
+ mManageApplications.mMetricsFeatureProvider.action(mContext, action);
+ }
+
@VisibleForTesting
void filterSearch(String query) {
if (mSearchFilter == null) {
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index cf58c3c..c813a57 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -41,15 +41,16 @@
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.overlay.FeatureFactory;
import com.android.settings.fuelgauge.batteryusage.BatteryDiffEntry;
import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
import com.android.settings.fuelgauge.batteryusage.BatteryHistEntry;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.HelpUtils;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.instrumentation.Instrumentable;
import com.android.settingslib.utils.StringUtil;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.LayoutPreference;
@@ -209,8 +210,11 @@
return UserHandle.getUserId(batteryEntry.getUid());
}
- public static void startBatteryDetailPage(Activity caller,
- InstrumentedPreferenceFragment fragment, String packageName) {
+ /**
+ * Start packageName's battery detail page.
+ */
+ public static void startBatteryDetailPage(
+ Activity caller, Instrumentable instrumentable, String packageName) {
final Bundle args = new Bundle(3);
final PackageManager packageManager = caller.getPackageManager();
args.putString(EXTRA_PACKAGE_NAME, packageName);
@@ -225,7 +229,7 @@
.setDestination(AdvancedPowerUsageDetail.class.getName())
.setTitleRes(R.string.battery_details_title)
.setArguments(args)
- .setSourceMetricsCategory(fragment.getMetricsCategory())
+ .setSourceMetricsCategory(instrumentable.getMetricsCategory())
.launch();
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java
index 2932984..45d145a 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java
@@ -79,7 +79,7 @@
private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
@VisibleForTesting
- Map<Integer, List<BatteryDiffEntry>> mBatteryIndexedMap;
+ Map<Integer, Map<Integer, BatteryDiffData>> mBatteryUsageMap;
@VisibleForTesting
Context mPrefContext;
@@ -112,7 +112,6 @@
private final String mPreferenceKey;
private final SettingsActivity mActivity;
private final InstrumentedPreferenceFragment mFragment;
- private final CharSequence[] mNotAllowShowEntryPackages;
private final CharSequence[] mNotAllowShowSummaryPackages;
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -120,8 +119,6 @@
// Preference cache to avoid create new instance each time.
@VisibleForTesting
final Map<String, Preference> mPreferenceCache = new HashMap<>();
- @VisibleForTesting
- final List<BatteryDiffEntry> mSystemEntries = new ArrayList<>();
public BatteryChartPreferenceControllerV2(
Context context, String preferenceKey,
@@ -134,10 +131,6 @@
mIs24HourFormat = DateFormat.is24HourFormat(context);
mMetricsFeatureProvider =
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
- mNotAllowShowEntryPackages =
- FeatureFactory.getFactory(context)
- .getPowerUsageFeatureProvider(context)
- .getHideApplicationEntries(context);
mNotAllowShowSummaryPackages =
FeatureFactory.getFactory(context)
.getPowerUsageFeatureProvider(context)
@@ -266,9 +259,12 @@
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
Log.d(TAG, "setBatteryHistoryMap() " + (batteryHistoryMap == null ? "null"
: ("size=" + batteryHistoryMap.size())));
- // TODO: implement the callback function.
final BatteryLevelData batteryLevelData =
- DataProcessor.getBatteryLevelData(mContext, mHandler, batteryHistoryMap, null);
+ DataProcessor.getBatteryLevelData(mContext, mHandler, batteryHistoryMap,
+ batteryUsageMap -> {
+ mBatteryUsageMap = batteryUsageMap;
+ refreshUi();
+ });
Log.d(TAG, "getBatteryLevelData: " + batteryLevelData);
if (batteryLevelData == null) {
mDailyViewModel = null;
@@ -293,7 +289,6 @@
BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
}
refreshUi();
- // TODO: Loads item icon and label and build mBatteryIndexedMap.
}
void setBatteryChartView(@NonNull final BatteryChartViewV2 dailyChartView,
@@ -335,7 +330,7 @@
@VisibleForTesting
boolean refreshUi() {
- if (mBatteryIndexedMap == null || mDailyChartView == null || mHourlyChartView == null) {
+ if (mBatteryUsageMap == null || mDailyChartView == null || mHourlyChartView == null) {
return false;
}
@@ -378,45 +373,22 @@
}
private void addAllPreferences() {
- // TODO: Get the right diff entry according to daily and hourly chart selection.
- final int index = mDailyChartIndex;
- final List<BatteryDiffEntry> entries =
- mBatteryIndexedMap.get(Integer.valueOf(index));
- addFooterPreferenceIfNeeded(entries != null && !entries.isEmpty());
- if (entries == null) {
- Log.w(TAG, "cannot find BatteryDiffEntry for:" + index);
+ final BatteryDiffData batteryDiffData =
+ mBatteryUsageMap.get(mDailyChartIndex).get(mHourlyChartIndex);
+ addFooterPreferenceIfNeeded(batteryDiffData != null
+ && (!batteryDiffData.getAppDiffEntryList().isEmpty()
+ || !batteryDiffData.getSystemDiffEntryList().isEmpty()));
+ if (batteryDiffData == null) {
+ Log.w(TAG, "cannot find BatteryDiffEntry for daily_index: " + mDailyChartIndex
+ + " hourly_index: " + mHourlyChartIndex);
return;
}
- // Separates data into two groups and sort them individually.
- final List<BatteryDiffEntry> appEntries = new ArrayList<>();
- mSystemEntries.clear();
- entries.forEach(entry -> {
- final String packageName = entry.getPackageName();
- if (!isValidToShowEntry(packageName)) {
- Log.w(TAG, "ignore showing item:" + packageName);
- return;
- }
- if (entry.isSystemEntry()) {
- mSystemEntries.add(entry);
- } else {
- appEntries.add(entry);
- }
- // Validates the usage time if users click a specific slot.
- if (index >= 0) {
- validateUsageTime(entry);
- }
- });
- Collections.sort(appEntries, BatteryDiffEntry.COMPARATOR);
- Collections.sort(mSystemEntries, BatteryDiffEntry.COMPARATOR);
- Log.d(TAG, String.format("addAllPreferences() app=%d system=%d",
- appEntries.size(), mSystemEntries.size()));
-
// Adds app entries to the list if it is not empty.
- if (!appEntries.isEmpty()) {
- addPreferenceToScreen(appEntries);
+ if (!batteryDiffData.getAppDiffEntryList().isEmpty()) {
+ addPreferenceToScreen(batteryDiffData.getAppDiffEntryList());
}
// Adds the expabable divider if we have system entries data.
- if (!mSystemEntries.isEmpty()) {
+ if (!batteryDiffData.getSystemDiffEntryList().isEmpty()) {
if (mExpandDividerPreference == null) {
mExpandDividerPreference = new ExpandDividerPreference(mPrefContext);
mExpandDividerPreference.setOnExpandListener(this);
@@ -490,11 +462,13 @@
}
private void refreshExpandUi() {
+ final List<BatteryDiffEntry> systemEntries = mBatteryUsageMap.get(mDailyChartIndex).get(
+ mHourlyChartIndex).getSystemDiffEntryList();
if (mIsExpanded) {
- addPreferenceToScreen(mSystemEntries);
+ addPreferenceToScreen(systemEntries);
} else {
// Removes and recycles all system entries to hide all of them.
- for (BatteryDiffEntry entry : mSystemEntries) {
+ for (BatteryDiffEntry entry : systemEntries) {
final String prefKey = entry.mBatteryHistEntry.getKey();
final Preference pref = mAppListPrefGroup.findPreference(prefKey);
if (pref != null) {
@@ -592,11 +566,6 @@
return !contains(packageName, mNotAllowShowSummaryPackages);
}
- @VisibleForTesting
- boolean isValidToShowEntry(String packageName) {
- return !contains(packageName, mNotAllowShowEntryPackages);
- }
-
private void addFooterPreferenceIfNeeded(boolean containAppItems) {
if (mIsFooterPrefAdded || mFooterPreference == null) {
return;
@@ -643,20 +612,6 @@
return false;
}
- @VisibleForTesting
- static boolean validateUsageTime(BatteryDiffEntry entry) {
- final long foregroundUsageTimeInMs = entry.mForegroundUsageTimeInMs;
- final long backgroundUsageTimeInMs = entry.mBackgroundUsageTimeInMs;
- final long totalUsageTimeInMs = foregroundUsageTimeInMs + backgroundUsageTimeInMs;
- if (foregroundUsageTimeInMs > VALID_USAGE_TIME_DURATION
- || backgroundUsageTimeInMs > VALID_USAGE_TIME_DURATION
- || totalUsageTimeInMs > VALID_USAGE_TIME_DURATION) {
- Log.e(TAG, "validateUsageTime() fail for\n" + entry);
- return false;
- }
- return true;
- }
-
// TODO: Change this method to fromLastFullCharged.
/** Used for {@link AppBatteryPreferenceController}. */
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
index a004a51..a51fbec 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
@@ -218,7 +218,7 @@
*
* The valid result should be composed of 3 parts:
* 1) start timestamp
- * 2) every 0am timestamp (default timezone) between the start and end
+ * 2) every 00:00 timestamp (default timezone) between the start and end
* 3) end timestamp
* Otherwise, returns an empty list.
*/
@@ -277,18 +277,27 @@
}
/**
- * @return Returns the timestamp for 0am 1 day after the given timestamp based on local
+ * @return Returns the timestamp for 00:00 1 day after the given timestamp based on local
* timezone.
*/
@VisibleForTesting
static long getTimestampOfNextDay(long timestamp) {
- final Calendar nextDayCalendar = Calendar.getInstance();
- nextDayCalendar.setTimeInMillis(timestamp);
- nextDayCalendar.add(Calendar.DAY_OF_YEAR, 1);
- nextDayCalendar.set(Calendar.HOUR_OF_DAY, 0);
- nextDayCalendar.set(Calendar.MINUTE, 0);
- nextDayCalendar.set(Calendar.SECOND, 0);
- return nextDayCalendar.getTimeInMillis();
+ return getTimestampWithDayDiff(timestamp, /*dayDiff=*/ 1);
+ }
+
+ /**
+ * Returns whether currentSlot will be used in daily chart.
+ */
+ @VisibleForTesting
+ static boolean isForDailyChart(final boolean isStartOrEnd, final long currentSlot) {
+ // The start and end timestamps will always be used in daily chart.
+ if (isStartOrEnd) {
+ return true;
+ }
+
+ // The timestamps for 00:00 will be used in daily chart.
+ final long startOfTheDay = getTimestampWithDayDiff(currentSlot, /*dayDiff=*/ 0);
+ return currentSlot == startOfTheDay;
}
/**
@@ -350,10 +359,13 @@
startIndex = 1;
resultMap.put(expectedStartTimestamp, batteryHistoryMap.get(rawStartTimestamp));
}
- for (int index = startIndex; index < expectedTimestampSlots.size(); index++) {
+ final int expectedTimestampSlotsSize = expectedTimestampSlots.size();
+ for (int index = startIndex; index < expectedTimestampSlotsSize; index++) {
final long currentSlot = expectedTimestampSlots.get(index);
+ final boolean isStartOrEnd = index == 0 || index == expectedTimestampSlotsSize - 1;
interpolateHistoryForSlot(
- context, currentSlot, rawTimestampList, batteryHistoryMap, resultMap);
+ context, currentSlot, rawTimestampList, batteryHistoryMap, resultMap,
+ isStartOrEnd);
}
}
@@ -362,7 +374,8 @@
final long currentSlot,
final List<Long> rawTimestampList,
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap,
- final Map<Long, Map<String, BatteryHistEntry>> resultMap) {
+ final Map<Long, Map<String, BatteryHistEntry>> resultMap,
+ final boolean isStartOrEnd) {
final long[] nearestTimestamps = findNearestTimestamp(rawTimestampList, currentSlot);
final long lowerTimestamp = nearestTimestamps[0];
final long upperTimestamp = nearestTimestamps[1];
@@ -385,7 +398,8 @@
return;
}
interpolateHistoryForSlot(context,
- currentSlot, lowerTimestamp, upperTimestamp, batteryHistoryMap, resultMap);
+ currentSlot, lowerTimestamp, upperTimestamp, batteryHistoryMap, resultMap,
+ isStartOrEnd);
}
private static void interpolateHistoryForSlot(
@@ -394,7 +408,8 @@
final long lowerTimestamp,
final long upperTimestamp,
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap,
- final Map<Long, Map<String, BatteryHistEntry>> resultMap) {
+ final Map<Long, Map<String, BatteryHistEntry>> resultMap,
+ final boolean isStartOrEnd) {
final Map<String, BatteryHistEntry> lowerEntryDataMap =
batteryHistoryMap.get(lowerTimestamp);
final Map<String, BatteryHistEntry> upperEntryDataMap =
@@ -405,7 +420,10 @@
final long upperEntryDataBootTimestamp =
upperEntryDataFirstEntry.mTimestamp - upperEntryDataFirstEntry.mBootTimestamp;
// Lower data is captured before upper data corresponding device is booting.
- if (lowerTimestamp < upperEntryDataBootTimestamp) {
+ // Skips the booting-specific logics and always does interpolation for daily chart level
+ // data.
+ if (lowerTimestamp < upperEntryDataBootTimestamp
+ && !isForDailyChart(isStartOrEnd, currentSlot)) {
// Provides an opportunity to force align the slot directly.
if ((upperTimestamp - currentSlot) < 10 * DateUtils.MINUTE_IN_MILLIS) {
log(context, "force align into the nearest slot", currentSlot, null);
@@ -877,6 +895,16 @@
return true;
}
+ private static long getTimestampWithDayDiff(final long timestamp, final int dayDiff) {
+ final Calendar calendar = Calendar.getInstance();
+ calendar.setTimeInMillis(timestamp);
+ calendar.add(Calendar.DAY_OF_YEAR, dayDiff);
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.SECOND, 0);
+ return calendar.getTimeInMillis();
+ }
+
private static boolean contains(String target, Set<CharSequence> packageNames) {
if (target != null && packageNames != null) {
for (CharSequence packageName : packageNames) {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2Test.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2Test.java
index a5f193b..16e0459 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2Test.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2Test.java
@@ -19,6 +19,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -168,13 +169,10 @@
@Test
public void setBatteryChartViewModel_6Hours() {
- // TODO: Removes the following line after loading mBatteryIndexedMap is supported.
- mBatteryChartPreferenceController.mBatteryIndexedMap = new HashMap<>();
-
mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
- verify(mDailyChartView).setVisibility(View.GONE);
- verify(mHourlyChartView).setVisibility(View.VISIBLE);
+ verify(mDailyChartView, atLeastOnce()).setVisibility(View.GONE);
+ verify(mHourlyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
List.of(100, 97, 95),
List.of("8 am", "10 am", "12 pm"),
@@ -184,13 +182,10 @@
@Test
public void setBatteryChartViewModel_60Hours() {
- // TODO: Removes the following line after loading mBatteryIndexedMap is supported.
- mBatteryChartPreferenceController.mBatteryIndexedMap = new HashMap<>();
-
mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
- verify(mDailyChartView).setVisibility(View.VISIBLE);
- verify(mHourlyChartView).setVisibility(View.GONE);
+ verify(mDailyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
+ verify(mHourlyChartView, atLeastOnce()).setVisibility(View.GONE);
verify(mDailyChartView).setViewModel(new BatteryChartViewModel(
List.of(100, 83, 59, 41),
List.of("SAT", "SUN", "MON", "MON"),
@@ -256,6 +251,12 @@
}
@Test
+ public void refreshUi_normalCase_returnTrue() {
+ mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
+ assertThat(mBatteryChartPreferenceController.refreshUi()).isTrue();
+ }
+
+ @Test
public void refreshUi_batteryIndexedMapIsNull_ignoreRefresh() {
mBatteryChartPreferenceController.setBatteryHistoryMap(null);
assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse();
@@ -275,7 +276,8 @@
@Test
public void removeAndCacheAllPrefs_emptyContent_ignoreRemoveAll() {
- mBatteryChartPreferenceController.mHourlyChartIndex = 1;
+ mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
+ mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
doReturn(0).when(mAppListGroup).getPreferenceCount();
mBatteryChartPreferenceController.refreshUi();
@@ -283,6 +285,25 @@
}
@Test
+ public void removeAndCacheAllPrefs_buildCacheAndRemoveAllPreference() {
+ mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
+ mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
+ doReturn(1).when(mAppListGroup).getPreferenceCount();
+ doReturn(mPowerGaugePreference).when(mAppListGroup).getPreference(0);
+ doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+ doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
+ doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
+ // Ensures the testing data is correct.
+ assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
+
+ mBatteryChartPreferenceController.refreshUi();
+
+ assertThat(mBatteryChartPreferenceController.mPreferenceCache.get(PREF_KEY))
+ .isEqualTo(mPowerGaugePreference);
+ verify(mAppListGroup).removeAll();
+ }
+
+ @Test
public void addPreferenceToScreen_emptyContent_ignoreAddPreference() {
mBatteryChartPreferenceController.addPreferenceToScreen(
new ArrayList<BatteryDiffEntry>());
@@ -454,36 +475,9 @@
}
@Test
- public void validateUsageTime_returnTrueIfBatteryDiffEntryIsValid() {
- assertThat(BatteryChartPreferenceControllerV2.validateUsageTime(
- createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
- /*backgroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS)))
- .isTrue();
- }
-
- @Test
- public void validateUsageTime_foregroundTimeExceedThreshold_returnFalse() {
- assertThat(BatteryChartPreferenceControllerV2.validateUsageTime(
- createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ DateUtils.HOUR_IN_MILLIS * 3,
- /*backgroundUsageTimeInMs=*/ 0)))
- .isFalse();
- }
-
- @Test
- public void validateUsageTime_backgroundTimeExceedThreshold_returnFalse() {
- assertThat(BatteryChartPreferenceControllerV2.validateUsageTime(
- createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ 0,
- /*backgroundUsageTimeInMs=*/ DateUtils.HOUR_IN_MILLIS * 3)))
- .isFalse();
- }
-
- @Test
public void onExpand_expandedIsTrue_addSystemEntriesToPreferenceGroup() {
doReturn(1).when(mAppListGroup).getPreferenceCount();
- mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
+ mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
doReturn("label").when(mBatteryDiffEntry).getAppLabel();
doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
@@ -505,7 +499,7 @@
public void onExpand_expandedIsFalse_removeSystemEntriesFromPreferenceGroup() {
doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
- mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
+ mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
// Verifies the cache is empty first.
assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
@@ -580,18 +574,6 @@
.isFalse();
}
- @Test
- public void isValidToShowEntry_returnExpectedResult() {
- assertThat(mBatteryChartPreferenceController
- .isValidToShowEntry("com.google.android.apps.scone"))
- .isTrue();
-
- // Verifies the items which are defined in the array list.
- assertThat(mBatteryChartPreferenceController
- .isValidToShowEntry("com.android.gms.persistent"))
- .isFalse();
- }
-
private static Long generateTimestamp(int index) {
// "2021-04-23 07:00:00 UTC" + index hours
return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS;
@@ -603,6 +585,7 @@
for (int index = 0; index < numOfHours; index++) {
final ContentValues values = new ContentValues();
values.put("batteryLevel", Integer.valueOf(100 - index));
+ values.put("consumePower", Integer.valueOf(100 - index));
final BatteryHistEntry entry = new BatteryHistEntry(values);
final Map<String, BatteryHistEntry> entryMap = new HashMap<>();
entryMap.put("fake_entry_key" + index, entry);
@@ -611,6 +594,22 @@
return batteryHistoryMap;
}
+ private Map<Integer, Map<Integer, BatteryDiffData>> createBatteryUsageMap() {
+ final int selectedAll = BatteryChartViewModel.SELECTED_INDEX_ALL;
+ return Map.of(
+ selectedAll, Map.of(
+ selectedAll, new BatteryDiffData(
+ Arrays.asList(mBatteryDiffEntry),
+ Arrays.asList(mBatteryDiffEntry))),
+ 0, Map.of(
+ selectedAll, new BatteryDiffData(
+ Arrays.asList(mBatteryDiffEntry),
+ Arrays.asList(mBatteryDiffEntry)),
+ 0, new BatteryDiffData(
+ Arrays.asList(mBatteryDiffEntry),
+ Arrays.asList(mBatteryDiffEntry))));
+ }
+
private BatteryDiffEntry createBatteryDiffEntry(
long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) {
return new BatteryDiffEntry(
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
index 1b1e469..af1030c 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
@@ -402,6 +402,17 @@
}
@Test
+ public void isForDailyChart_returnExpectedResult() {
+ assertThat(DataProcessor.isForDailyChart(/*isStartOrEnd=*/ true, 0L)).isTrue();
+ // 2022-01-01 00:00:00
+ assertThat(DataProcessor.isForDailyChart(/*isStartOrEnd=*/ false, 1640966400000L))
+ .isTrue();
+ // 2022-01-01 01:00:05
+ assertThat(DataProcessor.isForDailyChart(/*isStartOrEnd=*/ false, 1640970005000L))
+ .isFalse();
+ }
+
+ @Test
public void getBatteryUsageMap_emptyHistoryMap_returnNull() {
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
new ArrayList<>();
diff --git a/tests/unit/src/com/android/settings/applications/manageapplications/AppFilterRegistryTest.java b/tests/unit/src/com/android/settings/applications/manageapplications/AppFilterRegistryTest.java
index 4c271c6..13bc3db 100644
--- a/tests/unit/src/com/android/settings/applications/manageapplications/AppFilterRegistryTest.java
+++ b/tests/unit/src/com/android/settings/applications/manageapplications/AppFilterRegistryTest.java
@@ -18,6 +18,7 @@
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_ALARMS_AND_REMINDERS;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_ALL;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_BATTERY_OPTIMIZED;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_INSTALL_SOURCES;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_MEDIA_MANAGEMENT;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_POWER_ALLOWLIST;
@@ -26,6 +27,7 @@
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_WITH_OVERLAY;
import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_WRITE_SETTINGS;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_ALARMS_AND_REMINDERS;
+import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_BATTERY_OPTIMIZATION;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_GAMES;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_HIGH_POWER;
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_MAIN;
@@ -66,6 +68,8 @@
assertThat(registry.getDefaultFilterType(LIST_TYPE_MEDIA_MANAGEMENT_APPS))
.isEqualTo(FILTER_APPS_MEDIA_MANAGEMENT);
+ assertThat(registry.getDefaultFilterType(LIST_TYPE_BATTERY_OPTIMIZATION))
+ .isEqualTo(FILTER_APPS_BATTERY_OPTIMIZED);
assertThat(registry.getDefaultFilterType(LIST_TYPE_MAIN)).isEqualTo(FILTER_APPS_ALL);
assertThat(registry.getDefaultFilterType(LIST_TYPE_NOTIFICATION))