From 05bf785859d7242cde9d5a81afadf702e2667191 Mon Sep 17 00:00:00 2001 From: Zaiyue Xue Date: Tue, 19 Jul 2022 17:39:11 +0800 Subject: [PATCH] Add battery chart view model. Test: manual Bug: 239491373 Bug: 236101166 Change-Id: I1ae0e5fcc006855ac552fbbdfb4cd73f3dec52e7 --- .../BatteryChartPreferenceControllerV2.java | 89 +++++------ .../batteryusage/BatteryChartViewModel.java | 98 ++++++++++++ .../batteryusage/BatteryChartViewV2.java | 147 ++++++++---------- ...atteryChartPreferenceControllerV2Test.java | 116 ++++---------- .../batteryusage/BatteryChartViewV2Test.java | 20 ++- 5 files changed, 251 insertions(+), 219 deletions(-) create mode 100644 src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewModel.java diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java index d5491018ba9..6fd5f5841ba 100644 --- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java +++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java @@ -29,6 +29,7 @@ import android.text.format.DateFormat; import android.text.format.DateUtils; import android.util.Log; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceGroup; @@ -53,7 +54,6 @@ import com.android.settingslib.utils.StringUtil; import com.android.settingslib.widget.FooterPreference; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -98,13 +98,13 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro @VisibleForTesting boolean mIsExpanded = false; @VisibleForTesting - int[] mBatteryHistoryLevels; - @VisibleForTesting long[] mBatteryHistoryKeys; @VisibleForTesting - int mTrapezoidIndex = BatteryChartViewV2.SELECTED_INDEX_INVALID; + BatteryChartViewModel mViewModel; + @VisibleForTesting + int mTrapezoidIndex = BatteryChartViewModel.SELECTED_INDEX_ALL; - private boolean mIs24HourFormat = false; + private boolean mIs24HourFormat; private boolean mIsFooterPrefAdded = false; private PreferenceScreen mPreferenceScreen; private FooterPreference mFooterPreference; @@ -252,10 +252,11 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro @Override public void onSelect(int trapezoidIndex) { Log.d(TAG, "onChartSelect:" + trapezoidIndex); - refreshUi(trapezoidIndex, /*isForce=*/ false); + mTrapezoidIndex = trapezoidIndex; + refreshUi(); mMetricsFeatureProvider.action( mPrefContext, - trapezoidIndex == BatteryChartViewV2.SELECTED_INDEX_ALL + trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_ALL ? SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL : SettingsEnums.ACTION_BATTERY_USAGE_TIME_SLOT); } @@ -276,18 +277,19 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) { mBatteryIndexedMap = null; mBatteryHistoryKeys = null; - mBatteryHistoryLevels = null; + mViewModel = null; addFooterPreferenceIfNeeded(false); return; } mBatteryHistoryKeys = getBatteryHistoryKeys(batteryHistoryMap); - mBatteryHistoryLevels = new int[CHART_LEVEL_ARRAY_SIZE]; + List levels = new ArrayList(); for (int index = 0; index < CHART_LEVEL_ARRAY_SIZE; index++) { final long timestamp = mBatteryHistoryKeys[index * 2]; final Map entryMap = batteryHistoryMap.get(timestamp); if (entryMap == null || entryMap.isEmpty()) { Log.e(TAG, "abnormal entry list in the timestamp:" + ConvertUtils.utcToLocalTime(mPrefContext, timestamp)); + levels.add(0); continue; } // Averages the battery level in each time slot to avoid corner conditions. @@ -295,16 +297,17 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro for (BatteryHistEntry entry : entryMap.values()) { batteryLevelCounter += entry.mBatteryLevel; } - mBatteryHistoryLevels[index] = - Math.round(batteryLevelCounter / entryMap.size()); + levels.add(Math.round(batteryLevelCounter / entryMap.size())); } - forceRefreshUi(); + final List texts = generateTimestampTexts(mBatteryHistoryKeys, mContext); + mViewModel = new BatteryChartViewModel(levels, texts, mTrapezoidIndex); + refreshUi(); Log.d(TAG, String.format( - "setBatteryHistoryMap() size=%d key=%s\nlevels=%s", + "setBatteryHistoryMap() size=%d key=%s\nview model=%s", batteryHistoryMap.size(), ConvertUtils.utcToLocalTime(mPrefContext, mBatteryHistoryKeys[mBatteryHistoryKeys.length - 1]), - Arrays.toString(mBatteryHistoryLevels))); + mViewModel)); // Loads item icon and label in the background. new LoadAllItemsInfoTask(batteryHistoryMap).execute(); @@ -319,35 +322,20 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro private void setBatteryChartViewInner(final BatteryChartViewV2 batteryChartView) { mBatteryChartView = batteryChartView; mBatteryChartView.setOnSelectListener(this); - forceRefreshUi(); - } - - private void forceRefreshUi() { - final int refreshIndex = - mTrapezoidIndex == BatteryChartViewV2.SELECTED_INDEX_INVALID - ? BatteryChartViewV2.SELECTED_INDEX_ALL - : mTrapezoidIndex; - if (mBatteryChartView != null) { - mBatteryChartView.setLevels(mBatteryHistoryLevels); - mBatteryChartView.setSelectedIndex(refreshIndex); - setTimestampLabel(); - } - refreshUi(refreshIndex, /*isForce=*/ true); + refreshUi(); } @VisibleForTesting - boolean refreshUi(int trapezoidIndex, boolean isForce) { + boolean refreshUi() { // Invalid refresh condition. - if (mBatteryIndexedMap == null - || mBatteryChartView == null - || (mTrapezoidIndex == trapezoidIndex && !isForce)) { + if (mBatteryIndexedMap == null || mBatteryChartView == null) { return false; } - Log.d(TAG, String.format("refreshUi: index=%d size=%d isForce:%b", - trapezoidIndex, mBatteryIndexedMap.size(), isForce)); + if (mViewModel != null) { + mViewModel.setSelectedIndex(mTrapezoidIndex); + } + mBatteryChartView.setViewModel(mViewModel); - mTrapezoidIndex = trapezoidIndex; - mBatteryChartView.setSelectedIndex(mTrapezoidIndex); mHandler.post(() -> { final long start = System.currentTimeMillis(); removeAndCacheAllPrefs(); @@ -584,20 +572,6 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro return !contains(packageName, mNotAllowShowEntryPackages); } - @VisibleForTesting - void setTimestampLabel() { - if (mBatteryChartView == null || mBatteryHistoryKeys == null) { - return; - } - final boolean is24HourFormat = DateFormat.is24HourFormat(mContext); - final String[] labels = new String[mBatteryHistoryKeys.length]; - for (int i = 0; i < mBatteryHistoryKeys.length; i++) { - labels[i] = ConvertUtils.utcToLocalTimeHour(mContext, mBatteryHistoryKeys[i], - is24HourFormat); - } - mBatteryChartView.setAxisLabels(labels); - } - private void addFooterPreferenceIfNeeded(boolean containAppItems) { if (mIsFooterPrefAdded || mFooterPreference == null) { return; @@ -610,6 +584,17 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro mHandler.post(() -> mPreferenceScreen.addPreference(mFooterPreference)); } + private static List generateTimestampTexts( + @NonNull long[] timestamps, Context context) { + final boolean is24HourFormat = DateFormat.is24HourFormat(context); + final List texts = new ArrayList(); + for (int index = 0; index < CHART_LEVEL_ARRAY_SIZE; index++) { + texts.add(ConvertUtils.utcToLocalTimeHour(context, timestamps[index * 2], + is24HourFormat)); + } + return texts; + } + private static boolean contains(String target, CharSequence[] packageNames) { if (target != null && packageNames != null) { for (CharSequence packageName : packageNames) { @@ -654,7 +639,7 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro getBatteryHistoryKeys(batteryHistoryMap), batteryHistoryMap, /*purgeLowPercentageAndFakeData=*/ true); - return batteryIndexedMap.get(BatteryChartViewV2.SELECTED_INDEX_ALL); + return batteryIndexedMap.get(BatteryChartViewModel.SELECTED_INDEX_ALL); } /** Used for {@link AppBatteryPreferenceController}. */ @@ -735,7 +720,7 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro // Posts results back to main thread to refresh UI. mHandler.post(() -> { mBatteryIndexedMap = indexedUsageMap; - forceRefreshUi(); + refreshUi(); }); } } diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewModel.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewModel.java new file mode 100644 index 00000000000..74f87fd29d9 --- /dev/null +++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewModel.java @@ -0,0 +1,98 @@ +/* + * 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.fuelgauge.batteryusage; + +import androidx.annotation.NonNull; +import androidx.core.util.Preconditions; + +import java.util.List; +import java.util.Locale; +import java.util.Objects; + +/** The view model of {@code BatteryChartViewV2} */ +class BatteryChartViewModel { + private static final String TAG = "BatteryChartViewModel"; + + public static final int SELECTED_INDEX_ALL = -1; + public static final int SELECTED_INDEX_INVALID = -2; + + // We need at least 2 levels to draw a trapezoid. + private static final int MIN_LEVELS_DATA_SIZE = 2; + + private final List mLevels; + private final List mTexts; + private int mSelectedIndex; + + BatteryChartViewModel( + @NonNull List levels, @NonNull List texts, int selectedIndex) { + Preconditions.checkArgument( + levels.size() == texts.size() + && levels.size() >= MIN_LEVELS_DATA_SIZE + && selectedIndex >= SELECTED_INDEX_ALL + && selectedIndex < levels.size(), + String.format(Locale.getDefault(), "Invalid BatteryChartViewModel" + + " levels.size: %d\ntexts.size: %d\nselectedIndex: %d.", + levels.size(), texts.size(), selectedIndex)); + mLevels = levels; + mTexts = texts; + mSelectedIndex = selectedIndex; + } + + public int size() { + return mLevels.size(); + } + + public List levels() { + return mLevels; + } + + public List texts() { + return mTexts; + } + + public int selectedIndex() { + return mSelectedIndex; + } + + public void setSelectedIndex(int index) { + mSelectedIndex = index; + } + + @Override + public int hashCode() { + return Objects.hash(mLevels, mTexts, mSelectedIndex); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } else if (!(other instanceof BatteryChartViewModel)) { + return false; + } + final BatteryChartViewModel batteryChartViewModel = (BatteryChartViewModel) other; + return Objects.equals(mLevels, batteryChartViewModel.mLevels) + && Objects.equals(mTexts, batteryChartViewModel.mTexts) + && mSelectedIndex == batteryChartViewModel.mSelectedIndex; + } + + @Override + public String toString() { + return String.format(Locale.getDefault(), "levels: %s\ntexts: %s\nselectedIndex: %d", + Objects.toString(mLevels), Objects.toString(mTexts), mSelectedIndex); + } +} diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2.java index 15a3ca6f69f..bbaa157e5b2 100644 --- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2.java +++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2.java @@ -20,7 +20,6 @@ import static com.android.settings.Utils.formatPercentage; import static java.lang.Math.round; import android.accessibilityservice.AccessibilityServiceInfo; -import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; @@ -38,6 +37,7 @@ import android.view.View; import android.view.accessibility.AccessibilityManager; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.appcompat.widget.AppCompatImageView; @@ -61,16 +61,14 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli private static final int DIVIDER_COLOR = Color.parseColor("#CDCCC5"); private static final long UPDATE_STATE_DELAYED_TIME = 500L; - /** Selects all trapezoid shapes. */ - public static final int SELECTED_INDEX_ALL = -1; - public static final int SELECTED_INDEX_INVALID = -2; - /** A callback listener for selected group index is updated. */ public interface OnSelectListener { /** The callback function for selected group index is updated. */ void onSelect(int trapezoidIndex); } + private BatteryChartViewModel mViewModel; + private int mDividerWidth; private int mDividerHeight; private float mTrapezoidVOffset; @@ -79,9 +77,7 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli private String[] mPercentages = getPercentages(); @VisibleForTesting - int mHoveredIndex = SELECTED_INDEX_INVALID; - @VisibleForTesting - int mSelectedIndex = SELECTED_INDEX_INVALID; + int mHoveredIndex = BatteryChartViewModel.SELECTED_INDEX_INVALID; @VisibleForTesting String[] mAxisLabels; @@ -103,7 +99,6 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli @VisibleForTesting final Runnable mUpdateClickableStateRun = () -> updateClickableState(); - private int[] mLevels; private Paint mTextPaint; private Paint mDividerPaint; private Paint mTrapezoidPaint; @@ -126,44 +121,26 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli initializeColors(context); // Registers the click event listener. setOnClickListener(this); - setSelectedIndex(SELECTED_INDEX_ALL); setClickable(false); + requestLayout(); } - /** Sets all levels value to draw the trapezoid shape */ - public void setLevels(int[] levels) { - Log.d(TAG, "setLevels() " + (levels == null ? "null" : levels.length)); - // At least 2 levels to draw a trapezoid. - if (levels == null || levels.length < 2) { - mLevels = null; + /** Sets the data model of this view. */ + public void setViewModel(BatteryChartViewModel viewModel) { + if (viewModel == null) { + mViewModel = null; invalidate(); return; } - mLevels = levels; - // Initialize trapezoid slots. - mTrapezoidSlots = new TrapezoidSlot[mLevels.length - 1]; - for (int index = 0; index < mTrapezoidSlots.length; index++) { - mTrapezoidSlots[index] = new TrapezoidSlot(); - } + Log.d(TAG, String.format("setViewModel(): size: %d, selectedIndex: %d.", + viewModel.size(), viewModel.selectedIndex())); + mViewModel = viewModel; - setClickable(false); - invalidate(); - // Sets the chart is clickable if there is at least one valid item in it. - for (int index = 0; index < mLevels.length - 1; index++) { - if (mLevels[index] != 0 && mLevels[index + 1] != 0) { - setClickable(true); - break; - } - } - } - - /** Sets the selected group index to draw highlight effect. */ - public void setSelectedIndex(int index) { - if (mSelectedIndex != index) { - mSelectedIndex = index; - invalidate(); - } + initializeTrapezoidSlots(viewModel.size() - 1); + initializeAxisLabels(viewModel.texts()); + setClickable(hasNonZeroTrapezoid(viewModel.levels())); + requestLayout(); } /** Sets the callback to monitor the selected group index. */ @@ -184,26 +161,6 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli requestLayout(); } - /** - * Sets the X-axis labels list for each level. This class will choose some labels among the - * input list to show. - * - * @param labels The length of this parameter should be the same as the length of - * {@code levels}. - */ - public void setAxisLabels(@NonNull String[] labels) { - if (mAxisLabels == null) { - mAxisLabels = new String[DEFAULT_AXIS_LABEL_COUNT]; - } - // Current logic is always showing {@code AXIS_LABEL_GAPS_COUNT} labels. - // TODO: Support different count of labels for different levels sizes. - final int step = (labels.length - 1) / AXIS_LABEL_GAPS_COUNT; - for (int index = 0; index < DEFAULT_AXIS_LABEL_COUNT; index++) { - mAxisLabels[index] = labels[index * step]; - } - requestLayout(); - } - @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); @@ -240,7 +197,7 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli // Before mLevels initialized, the count of trapezoids is unknown. Only draws the // horizontal percentages and dividers. drawHorizontalDividers(canvas); - if (mLevels == null) { + if (mViewModel == null) { return; } drawVerticalDividers(canvas); @@ -282,7 +239,7 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli public void onHoverChanged(boolean hovered) { super.onHoverChanged(hovered); if (!hovered) { - mHoveredIndex = SELECTED_INDEX_INVALID; // reset + mHoveredIndex = BatteryChartViewModel.SELECTED_INDEX_INVALID; // reset invalidate(); } } @@ -295,13 +252,15 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli } final int trapezoidIndex = getTrapezoidIndex(mTouchUpEventX); // Ignores the click event if the level is zero. - if (trapezoidIndex == SELECTED_INDEX_INVALID + if (trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_INVALID || !isValidToDraw(trapezoidIndex)) { return; } if (mOnSelectListener != null) { + // Selects all if users click the same trapezoid item two times. mOnSelectListener.onSelect( - trapezoidIndex == mSelectedIndex ? SELECTED_INDEX_ALL : trapezoidIndex); + trapezoidIndex == mViewModel.selectedIndex() + ? BatteryChartViewModel.SELECTED_INDEX_ALL : trapezoidIndex); } view.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK); } @@ -350,8 +309,8 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli mTrapezoidCurvePaint.setStrokeWidth(mDividerWidth * 2); } else if (mIsSlotsClickabled) { mTrapezoidCurvePaint = null; - // Sets levels again to force update the click state. - setLevels(mLevels); + // Sets view model again to force update the click state. + setViewModel(mViewModel); } invalidate(); } @@ -366,6 +325,28 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli super.setClickable(clickable); } + private void initializeTrapezoidSlots(int count) { + mTrapezoidSlots = new TrapezoidSlot[count]; + for (int index = 0; index < mTrapezoidSlots.length; index++) { + mTrapezoidSlots[index] = new TrapezoidSlot(); + } + } + + /** + * Initializes the displayed X-axis labels list selected from the model all texts list. + */ + private void initializeAxisLabels(@NonNull List allTexts) { + if (mAxisLabels == null) { + mAxisLabels = new String[DEFAULT_AXIS_LABEL_COUNT]; + } + // Current logic is always showing {@code AXIS_LABEL_GAPS_COUNT} labels. + // TODO: Support different count of labels for different levels sizes. + final int step = (allTexts.size() - 1) / AXIS_LABEL_GAPS_COUNT; + for (int index = 0; index < DEFAULT_AXIS_LABEL_COUNT; index++) { + mAxisLabels[index] = allTexts.get(index * step); + } + } + private void initializeColors(Context context) { setBackgroundColor(Color.TRANSPARENT); mTrapezoidSolidColor = Utils.getColorAccentDefaultColor(context); @@ -498,7 +479,7 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli private void drawTrapezoids(Canvas canvas) { // Ignores invalid trapezoid data. - if (mLevels == null) { + if (mViewModel == null) { return; } final float trapezoidBottom = @@ -519,17 +500,17 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli continue; } // Configures the trapezoid paint color. - final int trapezoidColor = - !mIsSlotsClickabled - ? mTrapezoidColor - : mSelectedIndex == index || mSelectedIndex == SELECTED_INDEX_ALL - ? mTrapezoidSolidColor : mTrapezoidColor; + final int trapezoidColor = mIsSlotsClickabled && (mViewModel.selectedIndex() == index + || mViewModel.selectedIndex() == BatteryChartViewModel.SELECTED_INDEX_ALL) + ? mTrapezoidSolidColor : mTrapezoidColor; final boolean isHoverState = mIsSlotsClickabled && mHoveredIndex == index && isValidToDraw(mHoveredIndex); mTrapezoidPaint.setColor(isHoverState ? mTrapezoidHoverColor : trapezoidColor); - final float leftTop = round(trapezoidBottom - mLevels[index] * unitHeight); - final float rightTop = round(trapezoidBottom - mLevels[index + 1] * unitHeight); + final float leftTop = round( + trapezoidBottom - mViewModel.levels().get(index) * unitHeight); + final float rightTop = round( + trapezoidBottom - mViewModel.levels().get(index + 1) * unitHeight); trapezoidPath.reset(); trapezoidPath.moveTo(mTrapezoidSlots[index].mLeft, trapezoidBottom); trapezoidPath.lineTo(mTrapezoidSlots[index].mLeft, leftTop); @@ -568,15 +549,25 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli return index; } } - return SELECTED_INDEX_INVALID; + return BatteryChartViewModel.SELECTED_INDEX_INVALID; } private boolean isValidToDraw(int trapezoidIndex) { - return mLevels != null + return mViewModel != null && trapezoidIndex >= 0 - && trapezoidIndex < mLevels.length - 1 - && mLevels[trapezoidIndex] != 0 - && mLevels[trapezoidIndex + 1] != 0; + && trapezoidIndex < mViewModel.size() - 1 + && mViewModel.levels().get(trapezoidIndex) != 0 + && mViewModel.levels().get(trapezoidIndex + 1) != 0; + } + + private static boolean hasNonZeroTrapezoid(List levels) { + // Sets the chart is clickable if there is at least one valid item in it. + for (int index = 0; index < levels.size() - 1; index++) { + if (levels.get(index) != 0 && levels.get(index + 1) != 0) { + return true; + } + } + return false; } private static String[] getPercentages() { 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 c40d359aa87..a25afed444b 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2Test.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2Test.java @@ -55,6 +55,7 @@ import org.robolectric.RuntimeEnvironment; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; @@ -173,11 +174,11 @@ public final class BatteryChartPreferenceControllerV2Test { for (int index = 0; index < DESIRED_HISTORY_SIZE; index++) { assertThat(mBatteryChartPreferenceController.mBatteryHistoryKeys[index]) // These values is are calculated by hand from createBatteryHistoryMap(). - .isEqualTo(index + 1); + .isEqualTo(generateTimestamp(index)); } // Verifies the created battery levels array. for (int index = 0; index < 13; index++) { - assertThat(mBatteryChartPreferenceController.mBatteryHistoryLevels[index]) + assertThat(mBatteryChartPreferenceController.mViewModel.levels().get(index)) // These values is are calculated by hand from createBatteryHistoryMap(). .isEqualTo(100 - index * 2); } @@ -193,79 +194,63 @@ public final class BatteryChartPreferenceControllerV2Test { for (int index = 0; index < DESIRED_HISTORY_SIZE; index++) { assertThat(mBatteryChartPreferenceController.mBatteryHistoryKeys[index]) // These values is are calculated by hand from createBatteryHistoryMap(). - .isEqualTo(index + 1); + .isEqualTo(generateTimestamp(index)); } // Verifies the created battery levels array. for (int index = 0; index < 13; index++) { - assertThat(mBatteryChartPreferenceController.mBatteryHistoryLevels[index]) + assertThat(mBatteryChartPreferenceController.mViewModel.levels().get(index)) // These values is are calculated by hand from createBatteryHistoryMap(). .isEqualTo(100 - index * 2); } assertThat(mBatteryChartPreferenceController.mBatteryIndexedMap).hasSize(13); } + @Test + public void testSetBatteryChartViewModel() { + verify(mBatteryChartPreferenceController.mBatteryChartView) + .setViewModel(new BatteryChartViewModel( + List.of(100, 98, 96, 94, 92, 90, 88, 86, 84, 82, 80, 78, 76), + List.of("7 am", "9 am", "11 am", "1 pm", "3 pm", "5 pm", "7 pm", + "9 pm", "11 pm", "1 am", "3 am", "5 am", "7 am"), + BatteryChartViewModel.SELECTED_INDEX_ALL)); + } + + @Test + public void testRefreshUi_refresh() { + assertThat(mBatteryChartPreferenceController.refreshUi()).isTrue(); + } + @Test public void testRefreshUi_batteryIndexedMapIsNull_ignoreRefresh() { mBatteryChartPreferenceController.setBatteryHistoryMap(null); - assertThat(mBatteryChartPreferenceController.refreshUi( - /*trapezoidIndex=*/ 1, /*isForce=*/ false)).isFalse(); + assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse(); } @Test public void testRefreshUi_batteryChartViewIsNull_ignoreRefresh() { mBatteryChartPreferenceController.mBatteryChartView = null; - assertThat(mBatteryChartPreferenceController.refreshUi( - /*trapezoidIndex=*/ 1, /*isForce=*/ false)).isFalse(); - } - - @Test - public void testRefreshUi_trapezoidIndexIsNotChanged_ignoreRefresh() { - final int trapezoidIndex = 1; - mBatteryChartPreferenceController.mTrapezoidIndex = trapezoidIndex; - assertThat(mBatteryChartPreferenceController.refreshUi( - trapezoidIndex, /*isForce=*/ false)).isFalse(); - } - - @Test - public void testRefreshUi_forceUpdate_refreshUi() { - final int trapezoidIndex = 1; - mBatteryChartPreferenceController.mTrapezoidIndex = trapezoidIndex; - assertThat(mBatteryChartPreferenceController.refreshUi( - trapezoidIndex, /*isForce=*/ true)).isTrue(); - } - - @Test - public void testForceRefreshUi_updateTrapezoidIndexIntoSelectAll() { - mBatteryChartPreferenceController.mTrapezoidIndex = - BatteryChartViewV2.SELECTED_INDEX_INVALID; - mBatteryChartPreferenceController.setBatteryHistoryMap( - createBatteryHistoryMap()); - - assertThat(mBatteryChartPreferenceController.mTrapezoidIndex) - .isEqualTo(BatteryChartViewV2.SELECTED_INDEX_ALL); + assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse(); } @Test public void testRemoveAndCacheAllPrefs_emptyContent_ignoreRemoveAll() { - final int trapezoidIndex = 1; + mBatteryChartPreferenceController.mTrapezoidIndex = 1; doReturn(0).when(mAppListGroup).getPreferenceCount(); - mBatteryChartPreferenceController.refreshUi( - trapezoidIndex, /*isForce=*/ true); + mBatteryChartPreferenceController.refreshUi(); verify(mAppListGroup, never()).removeAll(); } @Test public void testRemoveAndCacheAllPrefs_buildCacheAndRemoveAllPreference() { - final int trapezoidIndex = 1; + mBatteryChartPreferenceController.mTrapezoidIndex = 1; doReturn(1).when(mAppListGroup).getPreferenceCount(); doReturn(mPowerGaugePreference).when(mAppListGroup).getPreference(0); doReturn(PREF_KEY).when(mPowerGaugePreference).getKey(); // Ensures the testing data is correct. assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty(); - mBatteryChartPreferenceController.refreshUi( - trapezoidIndex, /*isForce=*/ true); + mBatteryChartPreferenceController.refreshUi(); assertThat(mBatteryChartPreferenceController.mPreferenceCache.get(PREF_KEY)) .isEqualTo(mPowerGaugePreference); @@ -522,7 +507,7 @@ public final class BatteryChartPreferenceControllerV2Test { @Test public void testOnSelect_selectAll_logMetric() { mBatteryChartPreferenceController.onSelect( - BatteryChartViewV2.SELECTED_INDEX_ALL /*slot index*/); + BatteryChartViewModel.SELECTED_INDEX_ALL /*slot index*/); verify(mMetricsFeatureProvider) .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL); @@ -562,7 +547,7 @@ public final class BatteryChartPreferenceControllerV2Test { spy(new ExpandDividerPreference(mContext)); // Simulates select all condition. mBatteryChartPreferenceController.mTrapezoidIndex = - BatteryChartViewV2.SELECTED_INDEX_ALL; + BatteryChartViewModel.SELECTED_INDEX_ALL; mBatteryChartPreferenceController.refreshCategoryTitle(); @@ -580,44 +565,6 @@ public final class BatteryChartPreferenceControllerV2Test { .isEqualTo("System usage for past 24 hr"); } - @Test - public void testSetTimestampLabel_nullBatteryHistoryKeys_ignore() { - mBatteryChartPreferenceController = createController(); - mBatteryChartPreferenceController.mBatteryHistoryKeys = null; - mBatteryChartPreferenceController.mBatteryChartView = - spy(new BatteryChartViewV2(mContext)); - mBatteryChartPreferenceController.setTimestampLabel(); - - verify(mBatteryChartPreferenceController.mBatteryChartView, never()) - .setAxisLabels(any()); - } - - @Test - public void testSetTimestampLabel_setExpectedTimestampData() { - mBatteryChartPreferenceController = createController(); - mBatteryChartPreferenceController.mBatteryChartView = - spy(new BatteryChartViewV2(mContext)); - setUpBatteryHistoryKeys(); - - mBatteryChartPreferenceController.setTimestampLabel(); - - verify(mBatteryChartPreferenceController.mBatteryChartView) - .setAxisLabels(new String[] {"4 pm", "12 am", "7 am"}); - } - - @Test - public void testSetTimestampLabel_withoutValidTimestamp_setExpectedTimestampData() { - mBatteryChartPreferenceController = createController(); - mBatteryChartPreferenceController.mBatteryChartView = - spy(new BatteryChartViewV2(mContext)); - mBatteryChartPreferenceController.mBatteryHistoryKeys = new long[]{0L}; - - mBatteryChartPreferenceController.setTimestampLabel(); - - verify(mBatteryChartPreferenceController.mBatteryChartView) - .setAxisLabels(new String[] {"12 am"}); - } - @Test public void testOnSaveInstanceState_restoreSelectedIndexAndExpandState() { final int expectedIndex = 1; @@ -663,6 +610,11 @@ public final class BatteryChartPreferenceControllerV2Test { .isFalse(); } + private static Long generateTimestamp(int index) { + // "2021-04-23 07:00:00 UTC" + index hours + return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS; + } + private static Map> createBatteryHistoryMap() { final Map> batteryHistoryMap = new HashMap<>(); for (int index = 0; index < DESIRED_HISTORY_SIZE; index++) { @@ -671,7 +623,7 @@ public final class BatteryChartPreferenceControllerV2Test { final BatteryHistEntry entry = new BatteryHistEntry(values); final Map entryMap = new HashMap<>(); entryMap.put("fake_entry_key" + index, entry); - batteryHistoryMap.put(Long.valueOf(index + 1), entryMap); + batteryHistoryMap.put(generateTimestamp(index), entryMap); } return batteryHistoryMap; } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2Test.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2Test.java index 34ba2ebeeb2..a8b8d10e07c 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2Test.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2Test.java @@ -42,6 +42,7 @@ import org.robolectric.RuntimeEnvironment; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Locale; @RunWith(RobolectricTestRunner.class) @@ -100,13 +101,15 @@ public final class BatteryChartViewV2Test { @Test public void onClick_invokesCallback() { - mBatteryChartView.setLevels(new int[] {90, 80, 70, 60}); + final int originalSelectedIndex = 2; + mBatteryChartView.setViewModel( + new BatteryChartViewModel(List.of(90, 80, 70, 60), List.of("", "", "", ""), + originalSelectedIndex)); for (int i = 0; i < mBatteryChartView.mTrapezoidSlots.length; i++) { mBatteryChartView.mTrapezoidSlots[i] = new BatteryChartViewV2.TrapezoidSlot(); mBatteryChartView.mTrapezoidSlots[i].mLeft = i; mBatteryChartView.mTrapezoidSlots[i].mRight = i + 0.5f; } - mBatteryChartView.mSelectedIndex = 2; final int[] selectedIndex = new int[1]; mBatteryChartView.setOnSelectListener( trapezoidIndex -> { @@ -123,7 +126,7 @@ public final class BatteryChartViewV2Test { mBatteryChartView.mTouchUpEventX = 2; selectedIndex[0] = Integer.MIN_VALUE; mBatteryChartView.onClick(mMockView); - assertThat(selectedIndex[0]).isEqualTo(BatteryChartViewV2.SELECTED_INDEX_ALL); + assertThat(selectedIndex[0]).isEqualTo(BatteryChartViewModel.SELECTED_INDEX_ALL); } @Test @@ -178,11 +181,14 @@ public final class BatteryChartViewV2Test { @Test public void clickable_restoreFromNonClickableState() { - final int[] levels = new int[13]; - for (int index = 0; index < levels.length; index++) { - levels[index] = index + 1; + final List levels = new ArrayList(); + final List texts = new ArrayList(); + for (int index = 0; index < 13; index++) { + levels.add(index + 1); + texts.add(""); } - mBatteryChartView.setLevels(levels); + mBatteryChartView.setViewModel(new BatteryChartViewModel( + levels, texts, BatteryChartViewModel.SELECTED_INDEX_ALL)); mBatteryChartView.setClickableForce(true); when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext)) .thenReturn(true);