Add battery chart view model.
Test: manual Bug: 239491373 Bug: 236101166 Change-Id: I1ae0e5fcc006855ac552fbbdfb4cd73f3dec52e7
This commit is contained in:
@@ -29,6 +29,7 @@ import android.text.format.DateFormat;
|
|||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceGroup;
|
import androidx.preference.PreferenceGroup;
|
||||||
@@ -53,7 +54,6 @@ import com.android.settingslib.utils.StringUtil;
|
|||||||
import com.android.settingslib.widget.FooterPreference;
|
import com.android.settingslib.widget.FooterPreference;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -98,13 +98,13 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
boolean mIsExpanded = false;
|
boolean mIsExpanded = false;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
int[] mBatteryHistoryLevels;
|
|
||||||
@VisibleForTesting
|
|
||||||
long[] mBatteryHistoryKeys;
|
long[] mBatteryHistoryKeys;
|
||||||
@VisibleForTesting
|
@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 boolean mIsFooterPrefAdded = false;
|
||||||
private PreferenceScreen mPreferenceScreen;
|
private PreferenceScreen mPreferenceScreen;
|
||||||
private FooterPreference mFooterPreference;
|
private FooterPreference mFooterPreference;
|
||||||
@@ -252,10 +252,11 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
|
|||||||
@Override
|
@Override
|
||||||
public void onSelect(int trapezoidIndex) {
|
public void onSelect(int trapezoidIndex) {
|
||||||
Log.d(TAG, "onChartSelect:" + trapezoidIndex);
|
Log.d(TAG, "onChartSelect:" + trapezoidIndex);
|
||||||
refreshUi(trapezoidIndex, /*isForce=*/ false);
|
mTrapezoidIndex = trapezoidIndex;
|
||||||
|
refreshUi();
|
||||||
mMetricsFeatureProvider.action(
|
mMetricsFeatureProvider.action(
|
||||||
mPrefContext,
|
mPrefContext,
|
||||||
trapezoidIndex == BatteryChartViewV2.SELECTED_INDEX_ALL
|
trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_ALL
|
||||||
? SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL
|
? SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL
|
||||||
: SettingsEnums.ACTION_BATTERY_USAGE_TIME_SLOT);
|
: SettingsEnums.ACTION_BATTERY_USAGE_TIME_SLOT);
|
||||||
}
|
}
|
||||||
@@ -276,18 +277,19 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
|
|||||||
if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) {
|
if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) {
|
||||||
mBatteryIndexedMap = null;
|
mBatteryIndexedMap = null;
|
||||||
mBatteryHistoryKeys = null;
|
mBatteryHistoryKeys = null;
|
||||||
mBatteryHistoryLevels = null;
|
mViewModel = null;
|
||||||
addFooterPreferenceIfNeeded(false);
|
addFooterPreferenceIfNeeded(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mBatteryHistoryKeys = getBatteryHistoryKeys(batteryHistoryMap);
|
mBatteryHistoryKeys = getBatteryHistoryKeys(batteryHistoryMap);
|
||||||
mBatteryHistoryLevels = new int[CHART_LEVEL_ARRAY_SIZE];
|
List<Integer> levels = new ArrayList<Integer>();
|
||||||
for (int index = 0; index < CHART_LEVEL_ARRAY_SIZE; index++) {
|
for (int index = 0; index < CHART_LEVEL_ARRAY_SIZE; index++) {
|
||||||
final long timestamp = mBatteryHistoryKeys[index * 2];
|
final long timestamp = mBatteryHistoryKeys[index * 2];
|
||||||
final Map<String, BatteryHistEntry> entryMap = batteryHistoryMap.get(timestamp);
|
final Map<String, BatteryHistEntry> entryMap = batteryHistoryMap.get(timestamp);
|
||||||
if (entryMap == null || entryMap.isEmpty()) {
|
if (entryMap == null || entryMap.isEmpty()) {
|
||||||
Log.e(TAG, "abnormal entry list in the timestamp:"
|
Log.e(TAG, "abnormal entry list in the timestamp:"
|
||||||
+ ConvertUtils.utcToLocalTime(mPrefContext, timestamp));
|
+ ConvertUtils.utcToLocalTime(mPrefContext, timestamp));
|
||||||
|
levels.add(0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Averages the battery level in each time slot to avoid corner conditions.
|
// 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()) {
|
for (BatteryHistEntry entry : entryMap.values()) {
|
||||||
batteryLevelCounter += entry.mBatteryLevel;
|
batteryLevelCounter += entry.mBatteryLevel;
|
||||||
}
|
}
|
||||||
mBatteryHistoryLevels[index] =
|
levels.add(Math.round(batteryLevelCounter / entryMap.size()));
|
||||||
Math.round(batteryLevelCounter / entryMap.size());
|
|
||||||
}
|
}
|
||||||
forceRefreshUi();
|
final List<String> texts = generateTimestampTexts(mBatteryHistoryKeys, mContext);
|
||||||
|
mViewModel = new BatteryChartViewModel(levels, texts, mTrapezoidIndex);
|
||||||
|
refreshUi();
|
||||||
Log.d(TAG, String.format(
|
Log.d(TAG, String.format(
|
||||||
"setBatteryHistoryMap() size=%d key=%s\nlevels=%s",
|
"setBatteryHistoryMap() size=%d key=%s\nview model=%s",
|
||||||
batteryHistoryMap.size(),
|
batteryHistoryMap.size(),
|
||||||
ConvertUtils.utcToLocalTime(mPrefContext,
|
ConvertUtils.utcToLocalTime(mPrefContext,
|
||||||
mBatteryHistoryKeys[mBatteryHistoryKeys.length - 1]),
|
mBatteryHistoryKeys[mBatteryHistoryKeys.length - 1]),
|
||||||
Arrays.toString(mBatteryHistoryLevels)));
|
mViewModel));
|
||||||
|
|
||||||
// Loads item icon and label in the background.
|
// Loads item icon and label in the background.
|
||||||
new LoadAllItemsInfoTask(batteryHistoryMap).execute();
|
new LoadAllItemsInfoTask(batteryHistoryMap).execute();
|
||||||
@@ -319,35 +322,20 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
|
|||||||
private void setBatteryChartViewInner(final BatteryChartViewV2 batteryChartView) {
|
private void setBatteryChartViewInner(final BatteryChartViewV2 batteryChartView) {
|
||||||
mBatteryChartView = batteryChartView;
|
mBatteryChartView = batteryChartView;
|
||||||
mBatteryChartView.setOnSelectListener(this);
|
mBatteryChartView.setOnSelectListener(this);
|
||||||
forceRefreshUi();
|
refreshUi();
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
boolean refreshUi(int trapezoidIndex, boolean isForce) {
|
boolean refreshUi() {
|
||||||
// Invalid refresh condition.
|
// Invalid refresh condition.
|
||||||
if (mBatteryIndexedMap == null
|
if (mBatteryIndexedMap == null || mBatteryChartView == null) {
|
||||||
|| mBatteryChartView == null
|
|
||||||
|| (mTrapezoidIndex == trapezoidIndex && !isForce)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Log.d(TAG, String.format("refreshUi: index=%d size=%d isForce:%b",
|
if (mViewModel != null) {
|
||||||
trapezoidIndex, mBatteryIndexedMap.size(), isForce));
|
mViewModel.setSelectedIndex(mTrapezoidIndex);
|
||||||
|
}
|
||||||
|
mBatteryChartView.setViewModel(mViewModel);
|
||||||
|
|
||||||
mTrapezoidIndex = trapezoidIndex;
|
|
||||||
mBatteryChartView.setSelectedIndex(mTrapezoidIndex);
|
|
||||||
mHandler.post(() -> {
|
mHandler.post(() -> {
|
||||||
final long start = System.currentTimeMillis();
|
final long start = System.currentTimeMillis();
|
||||||
removeAndCacheAllPrefs();
|
removeAndCacheAllPrefs();
|
||||||
@@ -584,20 +572,6 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
|
|||||||
return !contains(packageName, mNotAllowShowEntryPackages);
|
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) {
|
private void addFooterPreferenceIfNeeded(boolean containAppItems) {
|
||||||
if (mIsFooterPrefAdded || mFooterPreference == null) {
|
if (mIsFooterPrefAdded || mFooterPreference == null) {
|
||||||
return;
|
return;
|
||||||
@@ -610,6 +584,17 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
|
|||||||
mHandler.post(() -> mPreferenceScreen.addPreference(mFooterPreference));
|
mHandler.post(() -> mPreferenceScreen.addPreference(mFooterPreference));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<String> generateTimestampTexts(
|
||||||
|
@NonNull long[] timestamps, Context context) {
|
||||||
|
final boolean is24HourFormat = DateFormat.is24HourFormat(context);
|
||||||
|
final List<String> texts = new ArrayList<String>();
|
||||||
|
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) {
|
private static boolean contains(String target, CharSequence[] packageNames) {
|
||||||
if (target != null && packageNames != null) {
|
if (target != null && packageNames != null) {
|
||||||
for (CharSequence packageName : packageNames) {
|
for (CharSequence packageName : packageNames) {
|
||||||
@@ -654,7 +639,7 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
|
|||||||
getBatteryHistoryKeys(batteryHistoryMap),
|
getBatteryHistoryKeys(batteryHistoryMap),
|
||||||
batteryHistoryMap,
|
batteryHistoryMap,
|
||||||
/*purgeLowPercentageAndFakeData=*/ true);
|
/*purgeLowPercentageAndFakeData=*/ true);
|
||||||
return batteryIndexedMap.get(BatteryChartViewV2.SELECTED_INDEX_ALL);
|
return batteryIndexedMap.get(BatteryChartViewModel.SELECTED_INDEX_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Used for {@link AppBatteryPreferenceController}. */
|
/** Used for {@link AppBatteryPreferenceController}. */
|
||||||
@@ -735,7 +720,7 @@ public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceContro
|
|||||||
// Posts results back to main thread to refresh UI.
|
// Posts results back to main thread to refresh UI.
|
||||||
mHandler.post(() -> {
|
mHandler.post(() -> {
|
||||||
mBatteryIndexedMap = indexedUsageMap;
|
mBatteryIndexedMap = indexedUsageMap;
|
||||||
forceRefreshUi();
|
refreshUi();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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<Integer> mLevels;
|
||||||
|
private final List<String> mTexts;
|
||||||
|
private int mSelectedIndex;
|
||||||
|
|
||||||
|
BatteryChartViewModel(
|
||||||
|
@NonNull List<Integer> levels, @NonNull List<String> 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<Integer> levels() {
|
||||||
|
return mLevels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> 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);
|
||||||
|
}
|
||||||
|
}
|
@@ -20,7 +20,6 @@ import static com.android.settings.Utils.formatPercentage;
|
|||||||
import static java.lang.Math.round;
|
import static java.lang.Math.round;
|
||||||
|
|
||||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||||
import android.annotation.NonNull;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
@@ -38,6 +37,7 @@ import android.view.View;
|
|||||||
import android.view.accessibility.AccessibilityManager;
|
import android.view.accessibility.AccessibilityManager;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.appcompat.widget.AppCompatImageView;
|
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 int DIVIDER_COLOR = Color.parseColor("#CDCCC5");
|
||||||
private static final long UPDATE_STATE_DELAYED_TIME = 500L;
|
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. */
|
/** A callback listener for selected group index is updated. */
|
||||||
public interface OnSelectListener {
|
public interface OnSelectListener {
|
||||||
/** The callback function for selected group index is updated. */
|
/** The callback function for selected group index is updated. */
|
||||||
void onSelect(int trapezoidIndex);
|
void onSelect(int trapezoidIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BatteryChartViewModel mViewModel;
|
||||||
|
|
||||||
private int mDividerWidth;
|
private int mDividerWidth;
|
||||||
private int mDividerHeight;
|
private int mDividerHeight;
|
||||||
private float mTrapezoidVOffset;
|
private float mTrapezoidVOffset;
|
||||||
@@ -79,9 +77,7 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli
|
|||||||
private String[] mPercentages = getPercentages();
|
private String[] mPercentages = getPercentages();
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
int mHoveredIndex = SELECTED_INDEX_INVALID;
|
int mHoveredIndex = BatteryChartViewModel.SELECTED_INDEX_INVALID;
|
||||||
@VisibleForTesting
|
|
||||||
int mSelectedIndex = SELECTED_INDEX_INVALID;
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
String[] mAxisLabels;
|
String[] mAxisLabels;
|
||||||
|
|
||||||
@@ -103,7 +99,6 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final Runnable mUpdateClickableStateRun = () -> updateClickableState();
|
final Runnable mUpdateClickableStateRun = () -> updateClickableState();
|
||||||
|
|
||||||
private int[] mLevels;
|
|
||||||
private Paint mTextPaint;
|
private Paint mTextPaint;
|
||||||
private Paint mDividerPaint;
|
private Paint mDividerPaint;
|
||||||
private Paint mTrapezoidPaint;
|
private Paint mTrapezoidPaint;
|
||||||
@@ -126,44 +121,26 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli
|
|||||||
initializeColors(context);
|
initializeColors(context);
|
||||||
// Registers the click event listener.
|
// Registers the click event listener.
|
||||||
setOnClickListener(this);
|
setOnClickListener(this);
|
||||||
setSelectedIndex(SELECTED_INDEX_ALL);
|
|
||||||
setClickable(false);
|
setClickable(false);
|
||||||
|
requestLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets all levels value to draw the trapezoid shape */
|
/** Sets the data model of this view. */
|
||||||
public void setLevels(int[] levels) {
|
public void setViewModel(BatteryChartViewModel viewModel) {
|
||||||
Log.d(TAG, "setLevels() " + (levels == null ? "null" : levels.length));
|
if (viewModel == null) {
|
||||||
// At least 2 levels to draw a trapezoid.
|
mViewModel = null;
|
||||||
if (levels == null || levels.length < 2) {
|
|
||||||
mLevels = null;
|
|
||||||
invalidate();
|
invalidate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mLevels = levels;
|
|
||||||
|
|
||||||
// Initialize trapezoid slots.
|
Log.d(TAG, String.format("setViewModel(): size: %d, selectedIndex: %d.",
|
||||||
mTrapezoidSlots = new TrapezoidSlot[mLevels.length - 1];
|
viewModel.size(), viewModel.selectedIndex()));
|
||||||
for (int index = 0; index < mTrapezoidSlots.length; index++) {
|
mViewModel = viewModel;
|
||||||
mTrapezoidSlots[index] = new TrapezoidSlot();
|
|
||||||
}
|
|
||||||
|
|
||||||
setClickable(false);
|
initializeTrapezoidSlots(viewModel.size() - 1);
|
||||||
invalidate();
|
initializeAxisLabels(viewModel.texts());
|
||||||
// Sets the chart is clickable if there is at least one valid item in it.
|
setClickable(hasNonZeroTrapezoid(viewModel.levels()));
|
||||||
for (int index = 0; index < mLevels.length - 1; index++) {
|
requestLayout();
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the callback to monitor the selected group index. */
|
/** Sets the callback to monitor the selected group index. */
|
||||||
@@ -184,26 +161,6 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli
|
|||||||
requestLayout();
|
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
|
@Override
|
||||||
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
super.onMeasure(widthMeasureSpec, 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
|
// Before mLevels initialized, the count of trapezoids is unknown. Only draws the
|
||||||
// horizontal percentages and dividers.
|
// horizontal percentages and dividers.
|
||||||
drawHorizontalDividers(canvas);
|
drawHorizontalDividers(canvas);
|
||||||
if (mLevels == null) {
|
if (mViewModel == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
drawVerticalDividers(canvas);
|
drawVerticalDividers(canvas);
|
||||||
@@ -282,7 +239,7 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli
|
|||||||
public void onHoverChanged(boolean hovered) {
|
public void onHoverChanged(boolean hovered) {
|
||||||
super.onHoverChanged(hovered);
|
super.onHoverChanged(hovered);
|
||||||
if (!hovered) {
|
if (!hovered) {
|
||||||
mHoveredIndex = SELECTED_INDEX_INVALID; // reset
|
mHoveredIndex = BatteryChartViewModel.SELECTED_INDEX_INVALID; // reset
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,13 +252,15 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli
|
|||||||
}
|
}
|
||||||
final int trapezoidIndex = getTrapezoidIndex(mTouchUpEventX);
|
final int trapezoidIndex = getTrapezoidIndex(mTouchUpEventX);
|
||||||
// Ignores the click event if the level is zero.
|
// Ignores the click event if the level is zero.
|
||||||
if (trapezoidIndex == SELECTED_INDEX_INVALID
|
if (trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_INVALID
|
||||||
|| !isValidToDraw(trapezoidIndex)) {
|
|| !isValidToDraw(trapezoidIndex)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mOnSelectListener != null) {
|
if (mOnSelectListener != null) {
|
||||||
|
// Selects all if users click the same trapezoid item two times.
|
||||||
mOnSelectListener.onSelect(
|
mOnSelectListener.onSelect(
|
||||||
trapezoidIndex == mSelectedIndex ? SELECTED_INDEX_ALL : trapezoidIndex);
|
trapezoidIndex == mViewModel.selectedIndex()
|
||||||
|
? BatteryChartViewModel.SELECTED_INDEX_ALL : trapezoidIndex);
|
||||||
}
|
}
|
||||||
view.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
|
view.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
|
||||||
}
|
}
|
||||||
@@ -350,8 +309,8 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli
|
|||||||
mTrapezoidCurvePaint.setStrokeWidth(mDividerWidth * 2);
|
mTrapezoidCurvePaint.setStrokeWidth(mDividerWidth * 2);
|
||||||
} else if (mIsSlotsClickabled) {
|
} else if (mIsSlotsClickabled) {
|
||||||
mTrapezoidCurvePaint = null;
|
mTrapezoidCurvePaint = null;
|
||||||
// Sets levels again to force update the click state.
|
// Sets view model again to force update the click state.
|
||||||
setLevels(mLevels);
|
setViewModel(mViewModel);
|
||||||
}
|
}
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
@@ -366,6 +325,28 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli
|
|||||||
super.setClickable(clickable);
|
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<String> 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) {
|
private void initializeColors(Context context) {
|
||||||
setBackgroundColor(Color.TRANSPARENT);
|
setBackgroundColor(Color.TRANSPARENT);
|
||||||
mTrapezoidSolidColor = Utils.getColorAccentDefaultColor(context);
|
mTrapezoidSolidColor = Utils.getColorAccentDefaultColor(context);
|
||||||
@@ -498,7 +479,7 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli
|
|||||||
|
|
||||||
private void drawTrapezoids(Canvas canvas) {
|
private void drawTrapezoids(Canvas canvas) {
|
||||||
// Ignores invalid trapezoid data.
|
// Ignores invalid trapezoid data.
|
||||||
if (mLevels == null) {
|
if (mViewModel == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final float trapezoidBottom =
|
final float trapezoidBottom =
|
||||||
@@ -519,17 +500,17 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Configures the trapezoid paint color.
|
// Configures the trapezoid paint color.
|
||||||
final int trapezoidColor =
|
final int trapezoidColor = mIsSlotsClickabled && (mViewModel.selectedIndex() == index
|
||||||
!mIsSlotsClickabled
|
|| mViewModel.selectedIndex() == BatteryChartViewModel.SELECTED_INDEX_ALL)
|
||||||
? mTrapezoidColor
|
? mTrapezoidSolidColor : mTrapezoidColor;
|
||||||
: mSelectedIndex == index || mSelectedIndex == SELECTED_INDEX_ALL
|
|
||||||
? mTrapezoidSolidColor : mTrapezoidColor;
|
|
||||||
final boolean isHoverState =
|
final boolean isHoverState =
|
||||||
mIsSlotsClickabled && mHoveredIndex == index && isValidToDraw(mHoveredIndex);
|
mIsSlotsClickabled && mHoveredIndex == index && isValidToDraw(mHoveredIndex);
|
||||||
mTrapezoidPaint.setColor(isHoverState ? mTrapezoidHoverColor : trapezoidColor);
|
mTrapezoidPaint.setColor(isHoverState ? mTrapezoidHoverColor : trapezoidColor);
|
||||||
|
|
||||||
final float leftTop = round(trapezoidBottom - mLevels[index] * unitHeight);
|
final float leftTop = round(
|
||||||
final float rightTop = round(trapezoidBottom - mLevels[index + 1] * unitHeight);
|
trapezoidBottom - mViewModel.levels().get(index) * unitHeight);
|
||||||
|
final float rightTop = round(
|
||||||
|
trapezoidBottom - mViewModel.levels().get(index + 1) * unitHeight);
|
||||||
trapezoidPath.reset();
|
trapezoidPath.reset();
|
||||||
trapezoidPath.moveTo(mTrapezoidSlots[index].mLeft, trapezoidBottom);
|
trapezoidPath.moveTo(mTrapezoidSlots[index].mLeft, trapezoidBottom);
|
||||||
trapezoidPath.lineTo(mTrapezoidSlots[index].mLeft, leftTop);
|
trapezoidPath.lineTo(mTrapezoidSlots[index].mLeft, leftTop);
|
||||||
@@ -568,15 +549,25 @@ public class BatteryChartViewV2 extends AppCompatImageView implements View.OnCli
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SELECTED_INDEX_INVALID;
|
return BatteryChartViewModel.SELECTED_INDEX_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidToDraw(int trapezoidIndex) {
|
private boolean isValidToDraw(int trapezoidIndex) {
|
||||||
return mLevels != null
|
return mViewModel != null
|
||||||
&& trapezoidIndex >= 0
|
&& trapezoidIndex >= 0
|
||||||
&& trapezoidIndex < mLevels.length - 1
|
&& trapezoidIndex < mViewModel.size() - 1
|
||||||
&& mLevels[trapezoidIndex] != 0
|
&& mViewModel.levels().get(trapezoidIndex) != 0
|
||||||
&& mLevels[trapezoidIndex + 1] != 0;
|
&& mViewModel.levels().get(trapezoidIndex + 1) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasNonZeroTrapezoid(List<Integer> 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() {
|
private static String[] getPercentages() {
|
||||||
|
@@ -55,6 +55,7 @@ import org.robolectric.RuntimeEnvironment;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
@@ -173,11 +174,11 @@ public final class BatteryChartPreferenceControllerV2Test {
|
|||||||
for (int index = 0; index < DESIRED_HISTORY_SIZE; index++) {
|
for (int index = 0; index < DESIRED_HISTORY_SIZE; index++) {
|
||||||
assertThat(mBatteryChartPreferenceController.mBatteryHistoryKeys[index])
|
assertThat(mBatteryChartPreferenceController.mBatteryHistoryKeys[index])
|
||||||
// These values is are calculated by hand from createBatteryHistoryMap().
|
// These values is are calculated by hand from createBatteryHistoryMap().
|
||||||
.isEqualTo(index + 1);
|
.isEqualTo(generateTimestamp(index));
|
||||||
}
|
}
|
||||||
// Verifies the created battery levels array.
|
// Verifies the created battery levels array.
|
||||||
for (int index = 0; index < 13; index++) {
|
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().
|
// These values is are calculated by hand from createBatteryHistoryMap().
|
||||||
.isEqualTo(100 - index * 2);
|
.isEqualTo(100 - index * 2);
|
||||||
}
|
}
|
||||||
@@ -193,79 +194,63 @@ public final class BatteryChartPreferenceControllerV2Test {
|
|||||||
for (int index = 0; index < DESIRED_HISTORY_SIZE; index++) {
|
for (int index = 0; index < DESIRED_HISTORY_SIZE; index++) {
|
||||||
assertThat(mBatteryChartPreferenceController.mBatteryHistoryKeys[index])
|
assertThat(mBatteryChartPreferenceController.mBatteryHistoryKeys[index])
|
||||||
// These values is are calculated by hand from createBatteryHistoryMap().
|
// These values is are calculated by hand from createBatteryHistoryMap().
|
||||||
.isEqualTo(index + 1);
|
.isEqualTo(generateTimestamp(index));
|
||||||
}
|
}
|
||||||
// Verifies the created battery levels array.
|
// Verifies the created battery levels array.
|
||||||
for (int index = 0; index < 13; index++) {
|
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().
|
// These values is are calculated by hand from createBatteryHistoryMap().
|
||||||
.isEqualTo(100 - index * 2);
|
.isEqualTo(100 - index * 2);
|
||||||
}
|
}
|
||||||
assertThat(mBatteryChartPreferenceController.mBatteryIndexedMap).hasSize(13);
|
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
|
@Test
|
||||||
public void testRefreshUi_batteryIndexedMapIsNull_ignoreRefresh() {
|
public void testRefreshUi_batteryIndexedMapIsNull_ignoreRefresh() {
|
||||||
mBatteryChartPreferenceController.setBatteryHistoryMap(null);
|
mBatteryChartPreferenceController.setBatteryHistoryMap(null);
|
||||||
assertThat(mBatteryChartPreferenceController.refreshUi(
|
assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse();
|
||||||
/*trapezoidIndex=*/ 1, /*isForce=*/ false)).isFalse();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRefreshUi_batteryChartViewIsNull_ignoreRefresh() {
|
public void testRefreshUi_batteryChartViewIsNull_ignoreRefresh() {
|
||||||
mBatteryChartPreferenceController.mBatteryChartView = null;
|
mBatteryChartPreferenceController.mBatteryChartView = null;
|
||||||
assertThat(mBatteryChartPreferenceController.refreshUi(
|
assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse();
|
||||||
/*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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveAndCacheAllPrefs_emptyContent_ignoreRemoveAll() {
|
public void testRemoveAndCacheAllPrefs_emptyContent_ignoreRemoveAll() {
|
||||||
final int trapezoidIndex = 1;
|
mBatteryChartPreferenceController.mTrapezoidIndex = 1;
|
||||||
doReturn(0).when(mAppListGroup).getPreferenceCount();
|
doReturn(0).when(mAppListGroup).getPreferenceCount();
|
||||||
|
|
||||||
mBatteryChartPreferenceController.refreshUi(
|
mBatteryChartPreferenceController.refreshUi();
|
||||||
trapezoidIndex, /*isForce=*/ true);
|
|
||||||
verify(mAppListGroup, never()).removeAll();
|
verify(mAppListGroup, never()).removeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveAndCacheAllPrefs_buildCacheAndRemoveAllPreference() {
|
public void testRemoveAndCacheAllPrefs_buildCacheAndRemoveAllPreference() {
|
||||||
final int trapezoidIndex = 1;
|
mBatteryChartPreferenceController.mTrapezoidIndex = 1;
|
||||||
doReturn(1).when(mAppListGroup).getPreferenceCount();
|
doReturn(1).when(mAppListGroup).getPreferenceCount();
|
||||||
doReturn(mPowerGaugePreference).when(mAppListGroup).getPreference(0);
|
doReturn(mPowerGaugePreference).when(mAppListGroup).getPreference(0);
|
||||||
doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
|
doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
|
||||||
// Ensures the testing data is correct.
|
// Ensures the testing data is correct.
|
||||||
assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
|
assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
|
||||||
|
|
||||||
mBatteryChartPreferenceController.refreshUi(
|
mBatteryChartPreferenceController.refreshUi();
|
||||||
trapezoidIndex, /*isForce=*/ true);
|
|
||||||
|
|
||||||
assertThat(mBatteryChartPreferenceController.mPreferenceCache.get(PREF_KEY))
|
assertThat(mBatteryChartPreferenceController.mPreferenceCache.get(PREF_KEY))
|
||||||
.isEqualTo(mPowerGaugePreference);
|
.isEqualTo(mPowerGaugePreference);
|
||||||
@@ -522,7 +507,7 @@ public final class BatteryChartPreferenceControllerV2Test {
|
|||||||
@Test
|
@Test
|
||||||
public void testOnSelect_selectAll_logMetric() {
|
public void testOnSelect_selectAll_logMetric() {
|
||||||
mBatteryChartPreferenceController.onSelect(
|
mBatteryChartPreferenceController.onSelect(
|
||||||
BatteryChartViewV2.SELECTED_INDEX_ALL /*slot index*/);
|
BatteryChartViewModel.SELECTED_INDEX_ALL /*slot index*/);
|
||||||
|
|
||||||
verify(mMetricsFeatureProvider)
|
verify(mMetricsFeatureProvider)
|
||||||
.action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL);
|
.action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL);
|
||||||
@@ -562,7 +547,7 @@ public final class BatteryChartPreferenceControllerV2Test {
|
|||||||
spy(new ExpandDividerPreference(mContext));
|
spy(new ExpandDividerPreference(mContext));
|
||||||
// Simulates select all condition.
|
// Simulates select all condition.
|
||||||
mBatteryChartPreferenceController.mTrapezoidIndex =
|
mBatteryChartPreferenceController.mTrapezoidIndex =
|
||||||
BatteryChartViewV2.SELECTED_INDEX_ALL;
|
BatteryChartViewModel.SELECTED_INDEX_ALL;
|
||||||
|
|
||||||
mBatteryChartPreferenceController.refreshCategoryTitle();
|
mBatteryChartPreferenceController.refreshCategoryTitle();
|
||||||
|
|
||||||
@@ -580,44 +565,6 @@ public final class BatteryChartPreferenceControllerV2Test {
|
|||||||
.isEqualTo("System usage for past 24 hr");
|
.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
|
@Test
|
||||||
public void testOnSaveInstanceState_restoreSelectedIndexAndExpandState() {
|
public void testOnSaveInstanceState_restoreSelectedIndexAndExpandState() {
|
||||||
final int expectedIndex = 1;
|
final int expectedIndex = 1;
|
||||||
@@ -663,6 +610,11 @@ public final class BatteryChartPreferenceControllerV2Test {
|
|||||||
.isFalse();
|
.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<Long, Map<String, BatteryHistEntry>> createBatteryHistoryMap() {
|
private static Map<Long, Map<String, BatteryHistEntry>> createBatteryHistoryMap() {
|
||||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
|
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
|
||||||
for (int index = 0; index < DESIRED_HISTORY_SIZE; index++) {
|
for (int index = 0; index < DESIRED_HISTORY_SIZE; index++) {
|
||||||
@@ -671,7 +623,7 @@ public final class BatteryChartPreferenceControllerV2Test {
|
|||||||
final BatteryHistEntry entry = new BatteryHistEntry(values);
|
final BatteryHistEntry entry = new BatteryHistEntry(values);
|
||||||
final Map<String, BatteryHistEntry> entryMap = new HashMap<>();
|
final Map<String, BatteryHistEntry> entryMap = new HashMap<>();
|
||||||
entryMap.put("fake_entry_key" + index, entry);
|
entryMap.put("fake_entry_key" + index, entry);
|
||||||
batteryHistoryMap.put(Long.valueOf(index + 1), entryMap);
|
batteryHistoryMap.put(generateTimestamp(index), entryMap);
|
||||||
}
|
}
|
||||||
return batteryHistoryMap;
|
return batteryHistoryMap;
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,7 @@ import org.robolectric.RuntimeEnvironment;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@@ -100,13 +101,15 @@ public final class BatteryChartViewV2Test {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onClick_invokesCallback() {
|
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++) {
|
for (int i = 0; i < mBatteryChartView.mTrapezoidSlots.length; i++) {
|
||||||
mBatteryChartView.mTrapezoidSlots[i] = new BatteryChartViewV2.TrapezoidSlot();
|
mBatteryChartView.mTrapezoidSlots[i] = new BatteryChartViewV2.TrapezoidSlot();
|
||||||
mBatteryChartView.mTrapezoidSlots[i].mLeft = i;
|
mBatteryChartView.mTrapezoidSlots[i].mLeft = i;
|
||||||
mBatteryChartView.mTrapezoidSlots[i].mRight = i + 0.5f;
|
mBatteryChartView.mTrapezoidSlots[i].mRight = i + 0.5f;
|
||||||
}
|
}
|
||||||
mBatteryChartView.mSelectedIndex = 2;
|
|
||||||
final int[] selectedIndex = new int[1];
|
final int[] selectedIndex = new int[1];
|
||||||
mBatteryChartView.setOnSelectListener(
|
mBatteryChartView.setOnSelectListener(
|
||||||
trapezoidIndex -> {
|
trapezoidIndex -> {
|
||||||
@@ -123,7 +126,7 @@ public final class BatteryChartViewV2Test {
|
|||||||
mBatteryChartView.mTouchUpEventX = 2;
|
mBatteryChartView.mTouchUpEventX = 2;
|
||||||
selectedIndex[0] = Integer.MIN_VALUE;
|
selectedIndex[0] = Integer.MIN_VALUE;
|
||||||
mBatteryChartView.onClick(mMockView);
|
mBatteryChartView.onClick(mMockView);
|
||||||
assertThat(selectedIndex[0]).isEqualTo(BatteryChartViewV2.SELECTED_INDEX_ALL);
|
assertThat(selectedIndex[0]).isEqualTo(BatteryChartViewModel.SELECTED_INDEX_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -178,11 +181,14 @@ public final class BatteryChartViewV2Test {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void clickable_restoreFromNonClickableState() {
|
public void clickable_restoreFromNonClickableState() {
|
||||||
final int[] levels = new int[13];
|
final List<Integer> levels = new ArrayList<Integer>();
|
||||||
for (int index = 0; index < levels.length; index++) {
|
final List<String> texts = new ArrayList<String>();
|
||||||
levels[index] = index + 1;
|
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);
|
mBatteryChartView.setClickableForce(true);
|
||||||
when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
|
when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
|
||||||
.thenReturn(true);
|
.thenReturn(true);
|
||||||
|
Reference in New Issue
Block a user