Refactor battery usage page contollers interaction logic
(1) Move controllers interaction logic from BatteryChartPreferenceController to main page PowerUsageAdvanced. (2) Move query power anomaly logic to DataProcessManager async job. Bug: 284893240 Test: manual Change-Id: Ib23b338fe3946e68ff73a372342ec5d86494c566 Merged-In: Ib23b338fe3946e68ff73a372342ec5d86494c566
This commit is contained in:
@@ -35,6 +35,8 @@ import androidx.loader.content.Loader;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.fuelgauge.BatteryBroadcastReceiver;
|
||||
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
@@ -42,9 +44,13 @@ import com.android.settingslib.utils.AsyncLoaderCompat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/** Advanced power usage. */
|
||||
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
|
||||
@@ -61,9 +67,14 @@ public class PowerUsageAdvanced extends PowerUsageBase {
|
||||
|
||||
private boolean mIsChartDataLoaded = false;
|
||||
private long mResumeTimestamp;
|
||||
private BatteryTipsController mBatteryTipsController;
|
||||
private BatteryChartPreferenceController mBatteryChartPreferenceController;
|
||||
private ScreenOnTimeController mScreenOnTimeController;
|
||||
private BatteryUsageBreakdownController mBatteryUsageBreakdownController;
|
||||
private Optional<BatteryLevelData> mBatteryLevelData;
|
||||
private Map<Integer, Map<Integer, BatteryDiffData>> mBatteryUsageMap;
|
||||
|
||||
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
|
||||
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
private final ContentObserver mBatteryObserver =
|
||||
new ContentObserver(mHandler) {
|
||||
@@ -90,6 +101,7 @@ public class PowerUsageAdvanced extends PowerUsageBase {
|
||||
if (getActivity().isChangingConfigurations()) {
|
||||
BatteryEntry.clearUidCache();
|
||||
}
|
||||
mExecutor.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,7 +124,6 @@ public class PowerUsageAdvanced extends PowerUsageBase {
|
||||
super.onPause();
|
||||
// Resets the flag to reload usage data in onResume() callback.
|
||||
mIsChartDataLoaded = false;
|
||||
mBatteryLevelData = null;
|
||||
final Uri uri = DatabaseUtils.BATTERY_CONTENT_URI;
|
||||
if (uri != null) {
|
||||
getContext().getContentResolver().unregisterContentObserver(mBatteryObserver);
|
||||
@@ -133,28 +144,25 @@ public class PowerUsageAdvanced extends PowerUsageBase {
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
mBatteryTipsController = new BatteryTipsController(context);
|
||||
mBatteryChartPreferenceController =
|
||||
new BatteryChartPreferenceController(
|
||||
context, getSettingsLifecycle(), (SettingsActivity) getActivity());
|
||||
final ScreenOnTimeController screenOnTimeController = new ScreenOnTimeController(context);
|
||||
final BatteryUsageBreakdownController batteryUsageBreakdownController =
|
||||
mScreenOnTimeController = new ScreenOnTimeController(context);
|
||||
mBatteryUsageBreakdownController =
|
||||
new BatteryUsageBreakdownController(
|
||||
context, getSettingsLifecycle(), (SettingsActivity) getActivity(), this);
|
||||
final BatteryTipsController batteryTipsController = new BatteryTipsController(context);
|
||||
|
||||
mBatteryChartPreferenceController.setOnScreenOnTimeUpdatedListener(
|
||||
screenOnTimeController::handleSceenOnTimeUpdated);
|
||||
mBatteryChartPreferenceController.setOnBatteryUsageUpdatedListener(
|
||||
batteryUsageBreakdownController::handleBatteryUsageUpdated);
|
||||
mBatteryChartPreferenceController.setOnBatteryTipsUpdatedListener(
|
||||
batteryTipsController::handleBatteryTipsCardUpdated);
|
||||
|
||||
controllers.add(mBatteryTipsController);
|
||||
controllers.add(mBatteryChartPreferenceController);
|
||||
controllers.add(screenOnTimeController);
|
||||
controllers.add(batteryUsageBreakdownController);
|
||||
controllers.add(batteryTipsController);
|
||||
controllers.add(mScreenOnTimeController);
|
||||
controllers.add(mBatteryUsageBreakdownController);
|
||||
setBatteryChartPreferenceController();
|
||||
mBatteryChartPreferenceController.setOnSelectedIndexUpdatedListener(
|
||||
this::onSelectedSlotDataUpdated);
|
||||
|
||||
// Force UI refresh if battery usage data was loaded before UI initialization.
|
||||
onSelectedSlotDataUpdated();
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@@ -169,12 +177,17 @@ public class PowerUsageAdvanced extends PowerUsageBase {
|
||||
bundle.putInt(KEY_REFRESH_TYPE, refreshType);
|
||||
if (!mIsChartDataLoaded) {
|
||||
mIsChartDataLoaded = true;
|
||||
mBatteryLevelData = null;
|
||||
mBatteryUsageMap = null;
|
||||
restartLoader(LoaderIndex.BATTERY_LEVEL_DATA_LOADER, bundle,
|
||||
mBatteryLevelDataLoaderCallbacks);
|
||||
}
|
||||
}
|
||||
|
||||
private void onBatteryLevelDataUpdate(BatteryLevelData batteryLevelData) {
|
||||
if (!isResumed()) {
|
||||
return;
|
||||
}
|
||||
mBatteryLevelData = Optional.ofNullable(batteryLevelData);
|
||||
if (mBatteryChartPreferenceController != null) {
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(batteryLevelData);
|
||||
@@ -184,23 +197,131 @@ public class PowerUsageAdvanced extends PowerUsageBase {
|
||||
}
|
||||
|
||||
private void onBatteryDiffDataMapUpdate(Map<Long, BatteryDiffData> batteryDiffDataMap) {
|
||||
if (mBatteryLevelData != null && mBatteryChartPreferenceController != null) {
|
||||
Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap =
|
||||
DataProcessor.generateBatteryUsageMap(
|
||||
getContext(), batteryDiffDataMap, mBatteryLevelData.orElse(null));
|
||||
DataProcessor.loadLabelAndIcon(batteryUsageMap);
|
||||
mBatteryChartPreferenceController.onBatteryUsageMapUpdate(batteryUsageMap);
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
private void onSelectedSlotDataUpdated() {
|
||||
if (mBatteryChartPreferenceController == null
|
||||
|| mScreenOnTimeController == null
|
||||
|| mBatteryUsageBreakdownController == null
|
||||
|| mBatteryUsageMap == null) {
|
||||
return;
|
||||
}
|
||||
final int dailyIndex = mBatteryChartPreferenceController.getDailyChartIndex();
|
||||
final int hourlyIndex = mBatteryChartPreferenceController.getHourlyChartIndex();
|
||||
final String slotInformation = mBatteryChartPreferenceController.getSlotInformation();
|
||||
final BatteryDiffData slotUsageData = mBatteryUsageMap.get(dailyIndex).get(hourlyIndex);
|
||||
if (slotUsageData != null) {
|
||||
mScreenOnTimeController.handleSceenOnTimeUpdated(
|
||||
slotUsageData.getScreenOnTime(), slotInformation);
|
||||
}
|
||||
mBatteryUsageBreakdownController.handleBatteryUsageUpdated(
|
||||
slotUsageData, slotInformation, isBatteryUsageMapNullOrEmpty());
|
||||
Log.d(TAG, String.format("Battery usage list shows in %d millis",
|
||||
System.currentTimeMillis() - mResumeTimestamp));
|
||||
}
|
||||
|
||||
private void detectAnomaly() {
|
||||
mExecutor.execute(() -> {
|
||||
final PowerUsageFeatureProvider powerUsageFeatureProvider =
|
||||
FeatureFactory.getFactory(getContext())
|
||||
.getPowerUsageFeatureProvider(getContext());
|
||||
final PowerAnomalyEventList anomalyEventList =
|
||||
powerUsageFeatureProvider.detectSettingsAnomaly(
|
||||
getContext(), /* displayDrain= */ 0);
|
||||
mHandler.post(() -> onAnomalyDetected(anomalyEventList));
|
||||
});
|
||||
}
|
||||
|
||||
private void onAnomalyDetected(PowerAnomalyEventList anomalyEventList) {
|
||||
if (!isResumed() || anomalyEventList == null) {
|
||||
return;
|
||||
}
|
||||
Log.d(TAG, "anomalyEventList = " + anomalyEventList);
|
||||
final PowerAnomalyEvent displayEvent =
|
||||
getHighestScoreAnomalyEvent(getContext(), anomalyEventList);
|
||||
if (displayEvent == null) {
|
||||
return;
|
||||
}
|
||||
if (mBatteryTipsController != null) {
|
||||
mBatteryTipsController.handleBatteryTipsCardUpdated(displayEvent);
|
||||
}
|
||||
}
|
||||
|
||||
private void setBatteryChartPreferenceController() {
|
||||
if (mHistPref != null && mBatteryChartPreferenceController != null) {
|
||||
mHistPref.setChartPreferenceController(mBatteryChartPreferenceController);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBatteryUsageMapNullOrEmpty() {
|
||||
final BatteryDiffData allBatteryDiffData = getAllBatteryDiffData(mBatteryUsageMap);
|
||||
// If all data is null or empty, each slot must be null or empty.
|
||||
return allBatteryDiffData == null
|
||||
|| (allBatteryDiffData.getAppDiffEntryList().isEmpty()
|
||||
&& allBatteryDiffData.getSystemDiffEntryList().isEmpty());
|
||||
}
|
||||
|
||||
private void logScreenUsageTime() {
|
||||
final BatteryDiffData allBatteryDiffData = getAllBatteryDiffData(mBatteryUsageMap);
|
||||
if (allBatteryDiffData == null) {
|
||||
return;
|
||||
}
|
||||
long totalForegroundUsageTime = 0;
|
||||
for (final BatteryDiffEntry entry : allBatteryDiffData.getAppDiffEntryList()) {
|
||||
totalForegroundUsageTime += entry.mForegroundUsageTimeInMs;
|
||||
}
|
||||
mMetricsFeatureProvider.action(
|
||||
getContext(),
|
||||
SettingsEnums.ACTION_BATTERY_USAGE_SCREEN_ON_TIME,
|
||||
(int) allBatteryDiffData.getScreenOnTime());
|
||||
mMetricsFeatureProvider.action(
|
||||
getContext(),
|
||||
SettingsEnums.ACTION_BATTERY_USAGE_FOREGROUND_USAGE_TIME,
|
||||
(int) totalForegroundUsageTime);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static PowerAnomalyEvent getHighestScoreAnomalyEvent(
|
||||
Context context, PowerAnomalyEventList anomalyEventList) {
|
||||
if (anomalyEventList == null || anomalyEventList.getPowerAnomalyEventsCount() == 0) {
|
||||
return null;
|
||||
}
|
||||
final Set<String> dismissedPowerAnomalyKeys =
|
||||
DatabaseUtils.getDismissedPowerAnomalyKeys(context);
|
||||
Log.d(TAG, "dismissedPowerAnomalyKeys = " + dismissedPowerAnomalyKeys);
|
||||
|
||||
final PowerAnomalyEvent highestScoreEvent = anomalyEventList.getPowerAnomalyEventsList()
|
||||
.stream()
|
||||
.filter(event -> event.hasKey()
|
||||
&& !dismissedPowerAnomalyKeys.contains(event.getKey().name()))
|
||||
.max(Comparator.comparing(PowerAnomalyEvent::getScore))
|
||||
.orElse(null);
|
||||
Log.d(TAG, "highestScoreAnomalyEvent = " + highestScoreEvent);
|
||||
return highestScoreEvent;
|
||||
}
|
||||
|
||||
private static BatteryDiffData getAllBatteryDiffData(
|
||||
Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap) {
|
||||
return batteryUsageMap == null ? null : batteryUsageMap
|
||||
.get(BatteryChartViewModel.SELECTED_INDEX_ALL)
|
||||
.get(BatteryChartViewModel.SELECTED_INDEX_ALL);
|
||||
}
|
||||
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
@@ -237,7 +358,7 @@ public class PowerUsageAdvanced extends PowerUsageBase {
|
||||
public BatteryLevelData loadInBackground() {
|
||||
return DataProcessManager.getBatteryLevelData(
|
||||
getContext(), mHandler, /*isFromPeriodJob=*/ false,
|
||||
map -> PowerUsageAdvanced.this.onBatteryDiffDataMapUpdate(map));
|
||||
PowerUsageAdvanced.this::onBatteryDiffDataMapUpdate);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user