From 740ac9a0478abe5a4d0fe7188467d343f92e8b3b Mon Sep 17 00:00:00 2001 From: ykhung Date: Fri, 9 Apr 2021 17:40:40 +0800 Subject: [PATCH] Display the chart levels data into BatteryHistoryPreference Bug: 184807417 Bug: 180607918 Test: make SettingsRoboTests Test: make SettingsGoogleRoboTests Change-Id: I78718a59671ca6775abc725432fbfbec6c0993fe --- .../BatteryChartPreferenceController.java | 108 ++++++++++++++++-- .../settings/fuelgauge/BatteryHistEntry.java | 6 +- .../fuelgauge/BatteryHistoryPreference.java | 14 +++ .../settings/fuelgauge/ConvertUtils.java | 10 ++ .../fuelgauge/PowerUsageAdvanced.java | 13 ++- 5 files changed, 136 insertions(+), 15 deletions(-) diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java index c8a7bc35869..56c18ba764a 100644 --- a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java +++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java @@ -20,6 +20,7 @@ package com.android.settings.fuelgauge; import android.content.Context; import android.util.Log; +import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceScreen; @@ -34,25 +35,49 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnDestroy; import com.android.settingslib.core.lifecycle.events.OnPause; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; -/** Cotrols the update for chart graph and the list items. */ +/** Controls the update for chart graph and the list items. */ public class BatteryChartPreferenceController extends AbstractPreferenceController - implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy { + implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy, + BatteryChartView.OnSelectListener { private static final String TAG = "BatteryChartPreferenceController"; + private static final int CHART_KEY_ARRAY_SIZE = 25; + private static final int CHART_LEVEL_ARRAY_SIZE = 13; + + @VisibleForTesting + PreferenceGroup mAppListGroup; + + private Context mPrefContext; + private BatteryChartView mBatteryChartView; + // Battery history relative data. + private int[] mBatteryHistoryLevels; + private long[] mBatteryHistoryKeys; + private Map> mBatteryHistoryMap; + + private int mTrapezoidIndex = BatteryChartView.SELECTED_INDEX_INVALID; private final String mPreferenceKey; + private final SettingsActivity mActivity; + private final InstrumentedPreferenceFragment mFragment; public BatteryChartPreferenceController( - Context context, String chartPreferenceKey, String listPreferenceKey, + Context context, String preferenceKey, Lifecycle lifecycle, SettingsActivity activity, InstrumentedPreferenceFragment fragment) { super(context); - mPreferenceKey = listPreferenceKey; + mActivity = activity; + mFragment = fragment; + mPreferenceKey = preferenceKey; + if (lifecycle != null) { + lifecycle.addObserver(this); + } } - @Override public void onPause() { } @@ -63,6 +88,9 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll @Override public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPrefContext = screen.getContext(); + mAppListGroup = screen.findPreference(mPreferenceKey); } @Override @@ -80,7 +108,73 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll return false; } - void refreshUi(Map> batteryHistoryMap) { - Log.d(TAG, "refreshUi:" + batteryHistoryMap.size()); + @Override + public void onSelect(int trapezoidIndex) { + Log.d(TAG, "onSelect:" + trapezoidIndex); + refreshUi(trapezoidIndex); + } + + void setBatteryHistoryMap(Map> batteryHistoryMap) { + // Assumes all timestamp data is consecutive and aligns to hourly time slot. + mBatteryHistoryMap = batteryHistoryMap; + // Generates battery history keys. + final List batteryHistoryKeyList = + new ArrayList(mBatteryHistoryMap.keySet()); + // Sorts all timestamp keys ordered by ASC from the map keys. + Collections.sort(batteryHistoryKeyList); + mBatteryHistoryKeys = new long[CHART_KEY_ARRAY_SIZE]; + final int elementSize = Math.min( + batteryHistoryKeyList.size(), CHART_KEY_ARRAY_SIZE); + final int offset = CHART_KEY_ARRAY_SIZE - elementSize; + for (int index = 0; index < elementSize; index++) { + mBatteryHistoryKeys[index + offset] = batteryHistoryKeyList.get(index); + } + // Generates the battery history levels. + mBatteryHistoryLevels = new int[CHART_LEVEL_ARRAY_SIZE]; + for (int index = 0; index < CHART_LEVEL_ARRAY_SIZE; index++) { + final Long timestamp = Long.valueOf(mBatteryHistoryKeys[index * 2]); + final List entryList = mBatteryHistoryMap.get(timestamp); + if (entryList != null && !entryList.isEmpty()) { + // All battery levels are the same in the same timestamp snapshot. + mBatteryHistoryLevels[index] = entryList.get(0).mBatteryLevel; + } else { + Log.w(TAG, "abnormal entry list in the timestamp:" + timestamp); + } + } + if (mBatteryChartView != null) { + mBatteryChartView.setLevels(mBatteryHistoryLevels); + } + Log.d(TAG, String.format("setBatteryHistoryMap() size=%d\nkeys=%s\nlevels=%s", + batteryHistoryKeyList.size(), + utcToLocalTime(mBatteryHistoryKeys), + Arrays.toString(mBatteryHistoryLevels))); + } + + void setBatteryChartView(BatteryChartView batteryChartView) { + mBatteryChartView = batteryChartView; + mBatteryChartView.setOnSelectListener(this); + if (mBatteryHistoryLevels != null) { + mBatteryChartView.setLevels(mBatteryHistoryLevels); + } + } + + private void refreshUi(int trapezoidIndex) { + // Invalid refresh condition. + if (mBatteryHistoryMap == null || mBatteryChartView == null || + mTrapezoidIndex == trapezoidIndex) { + return; + } + mTrapezoidIndex = trapezoidIndex; + Log.d(TAG, String.format("refreshUi: index=%d size=%d", + mTrapezoidIndex, mBatteryHistoryMap.size())); + } + + private static String utcToLocalTime(long[] timestamps) { + final StringBuilder builder = new StringBuilder(); + for (int index = 0; index < timestamps.length; index++) { + builder.append(String.format("%s| ", + ConvertUtils.utcToLocalTime(timestamps[index]))); + } + return builder.toString(); } } diff --git a/src/com/android/settings/fuelgauge/BatteryHistEntry.java b/src/com/android/settings/fuelgauge/BatteryHistEntry.java index 0ee9cf78b0c..fb46140aba6 100644 --- a/src/com/android/settings/fuelgauge/BatteryHistEntry.java +++ b/src/com/android/settings/fuelgauge/BatteryHistEntry.java @@ -17,12 +17,9 @@ import android.content.ContentValues; import android.database.Cursor; import android.util.Log; -import java.text.SimpleDateFormat; import java.time.Duration; -import java.util.Date; import java.util.TimeZone; - /** A container class to carry data from {@link ContentValues}. */ public final class BatteryHistEntry { private static final String TAG = "BatteryHistEntry"; @@ -117,8 +114,7 @@ public final class BatteryHistEntry { @Override public String toString() { - final String recordAtDateTime = - new SimpleDateFormat("MMM dd,yyyy HH:mm:ss").format(new Date(mTimestamp)); + final String recordAtDateTime = ConvertUtils.utcToLocalTime(mTimestamp); final StringBuilder builder = new StringBuilder() .append("\nBatteryHistEntry{") .append(String.format("\n\tpackage=%s|label=%s|uid=%d|userId=%d|isHidden=%b", diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java index cb22ff3ac72..5b9d5ec0285 100644 --- a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java +++ b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java @@ -39,6 +39,9 @@ public class BatteryHistoryPreference extends Preference { @VisibleForTesting BatteryInfo mBatteryInfo; + private BatteryChartView mBatteryChartView; + private BatteryChartPreferenceController mChartPreferenceController; + public BatteryHistoryPreference(Context context, AttributeSet attrs) { super(context, attrs); final boolean isChartGraphEnabled = @@ -58,6 +61,13 @@ public class BatteryHistoryPreference extends Preference { }, batteryUsageStats, false); } + void setChartPreferenceController(BatteryChartPreferenceController controller) { + mChartPreferenceController = controller; + if (mBatteryChartView != null) { + mChartPreferenceController.setBatteryChartView(mBatteryChartView); + } + } + @Override public void onBindViewHolder(PreferenceViewHolder view) { super.onBindViewHolder(view); @@ -65,6 +75,10 @@ public class BatteryHistoryPreference extends Preference { if (mBatteryInfo == null) { return; } + mBatteryChartView = (BatteryChartView) view.findViewById(R.id.battery_chart); + if (mChartPreferenceController != null) { + mChartPreferenceController.setBatteryChartView(mBatteryChartView); + } BatteryUtils.logRuntime(TAG, "onBindViewHolder", startTime); } } diff --git a/src/com/android/settings/fuelgauge/ConvertUtils.java b/src/com/android/settings/fuelgauge/ConvertUtils.java index 30ac7bf3820..5c0da636595 100644 --- a/src/com/android/settings/fuelgauge/ConvertUtils.java +++ b/src/com/android/settings/fuelgauge/ConvertUtils.java @@ -25,11 +25,16 @@ import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; import java.util.TimeZone; /** A utility class to convert data into another types. */ public final class ConvertUtils { private static final String TAG = "ConvertUtils"; + private static final SimpleDateFormat SIMPLE_DATE_FORMAT = + new SimpleDateFormat("MMM dd,yyyy HH:mm:ss", Locale.ENGLISH); /** Invalid system battery consumer drain type. */ public static final int INVALID_DRAIN_TYPE = -1; @@ -101,5 +106,10 @@ public final class ConvertUtils { return values; } + /** Converts UTC timestamp to human readable local time string. */ + public static String utcToLocalTime(long timestamp) { + return SIMPLE_DATE_FORMAT.format(new Date(timestamp)); + } + private ConvertUtils() {} } diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java index d5f443c802c..c3f299ba4d5 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java +++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java @@ -69,6 +69,7 @@ public class PowerUsageAdvanced extends PowerUsageBase { if (!mIsChartGraphEnabled) { removePreference(KEY_BATTERY_GRAPH); } + setBatteryChartPreferenceController(); } @Override @@ -101,10 +102,10 @@ public class PowerUsageAdvanced extends PowerUsageBase { // Creates based on the chart design is enabled or not. if (mIsChartGraphEnabled) { mBatteryChartPreferenceController = - new BatteryChartPreferenceController(context, - KEY_BATTERY_GRAPH, KEY_APP_LIST, + new BatteryChartPreferenceController(context, KEY_APP_LIST, getSettingsLifecycle(), (SettingsActivity) getActivity(), this); controllers.add(mBatteryChartPreferenceController); + setBatteryChartPreferenceController(); } else { mBatteryAppListPreferenceController = new BatteryAppListPreferenceController(context, KEY_APP_LIST, @@ -131,7 +132,7 @@ public class PowerUsageAdvanced extends PowerUsageBase { mBatteryUsageStats, /* showAllApps */true); } if (mBatteryChartPreferenceController != null && mBatteryHistoryMap != null) { - mBatteryChartPreferenceController.refreshUi(mBatteryHistoryMap); + mBatteryChartPreferenceController.setBatteryHistoryMap(mBatteryHistoryMap); } } @@ -156,6 +157,12 @@ public class PowerUsageAdvanced extends PowerUsageBase { } } + private void setBatteryChartPreferenceController() { + if (mHistPref != null && mBatteryChartPreferenceController != null) { + mHistPref.setChartPreferenceController(mBatteryChartPreferenceController); + } + } + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider() { @Override