diff --git a/res/layout/battery_chart_graph.xml b/res/layout/battery_chart_graph.xml
index 024f37cbf70..8b05b5191e8 100644
--- a/res/layout/battery_chart_graph.xml
+++ b/res/layout/battery_chart_graph.xml
@@ -32,10 +32,20 @@
android:text="@string/battery_usage_chart_graph_hint_last_full_charge" />
+
+ 5dp
1dp
2dp
- 16dp
174dp
diff --git a/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java b/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java
index 0b0dbfdee62..732163b6a36 100644
--- a/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java
@@ -40,7 +40,7 @@ import com.android.settings.core.BasePreferenceController;
import com.android.settings.fuelgauge.AdvancedPowerUsageDetail;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
-import com.android.settings.fuelgauge.batteryusage.BatteryChartPreferenceControllerV2;
+import com.android.settings.fuelgauge.batteryusage.BatteryChartPreferenceController;
import com.android.settings.fuelgauge.batteryusage.BatteryDiffEntry;
import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
import com.android.settings.fuelgauge.batteryusage.BatteryUsageStatsLoader;
@@ -179,7 +179,7 @@ public class AppBatteryPreferenceController extends BasePreferenceController
return null;
}
final BatteryDiffEntry entry =
- BatteryChartPreferenceControllerV2.getAppBatteryUsageData(
+ BatteryChartPreferenceController.getAppBatteryUsageData(
mContext, mPackageName, mUserId);
Log.d(TAG, "loadBatteryDiffEntries():\n" + entry);
return entry;
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
index d363308740a..a399b7d4420 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
@@ -20,7 +20,6 @@ import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -28,7 +27,9 @@ import android.text.TextUtils;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.util.Log;
+import android.view.View;
+import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
@@ -53,8 +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;
import java.util.Map;
@@ -62,27 +61,23 @@ import java.util.Map;
/** Controls the update for chart graph and the list items. */
public class BatteryChartPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnCreate, OnDestroy,
- OnSaveInstanceState, BatteryChartView.OnSelectListener, OnResume,
- ExpandDividerPreference.OnExpandListener {
+ OnSaveInstanceState, OnResume, ExpandDividerPreference.OnExpandListener {
private static final String TAG = "BatteryChartPreferenceController";
private static final String KEY_FOOTER_PREF = "battery_graph_footer";
private static final String PACKAGE_NAME_NONE = "none";
- /** Desired battery history size for timestamp slots. */
- public static final int DESIRED_HISTORY_SIZE = 25;
- private static final int CHART_LEVEL_ARRAY_SIZE = 13;
- private static final int CHART_KEY_ARRAY_SIZE = DESIRED_HISTORY_SIZE;
private static final long VALID_USAGE_TIME_DURATION = DateUtils.HOUR_IN_MILLIS * 2;
private static final long VALID_DIFF_DURATION = DateUtils.MINUTE_IN_MILLIS * 3;
// Keys for bundle instance to restore configurations.
private static final String KEY_EXPAND_SYSTEM_INFO = "expand_system_info";
- private static final String KEY_CURRENT_TIME_SLOT = "current_time_slot";
+ private static final String KEY_DAILY_CHART_INDEX = "daily_chart_index";
+ private static final String KEY_HOURLY_CHART_INDEX = "hourly_chart_index";
private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
@VisibleForTesting
- Map> mBatteryIndexedMap;
+ Map> mBatteryUsageMap;
@VisibleForTesting
Context mPrefContext;
@@ -91,28 +86,34 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
@VisibleForTesting
PreferenceGroup mAppListPrefGroup;
@VisibleForTesting
- BatteryChartView mBatteryChartView;
- @VisibleForTesting
ExpandDividerPreference mExpandDividerPreference;
-
@VisibleForTesting
boolean mIsExpanded = false;
- @VisibleForTesting
- int[] mBatteryHistoryLevels;
- @VisibleForTesting
- long[] mBatteryHistoryKeys;
- @VisibleForTesting
- int mTrapezoidIndex = BatteryChartView.SELECTED_INDEX_INVALID;
- private boolean mIs24HourFormat = false;
+ @VisibleForTesting
+ BatteryChartView mDailyChartView;
+ @VisibleForTesting
+ BatteryChartView mHourlyChartView;
+
+ @VisibleForTesting
+ int mDailyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
+ @VisibleForTesting
+ int mHourlyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
+
+ private boolean mIs24HourFormat;
private boolean mIsFooterPrefAdded = false;
private PreferenceScreen mPreferenceScreen;
private FooterPreference mFooterPreference;
+ // Daily view model only saves abbreviated day of week texts (e.g. MON). This field saves the
+ // full day of week texts (e.g. Monday), which is used in category title and battery detail
+ // page.
+ private List mDailyTimestampFullTexts;
+ private BatteryChartViewModel mDailyViewModel;
+ private List mHourlyViewModels;
private final String mPreferenceKey;
private final SettingsActivity mActivity;
private final InstrumentedPreferenceFragment mFragment;
- private final CharSequence[] mNotAllowShowEntryPackages;
private final CharSequence[] mNotAllowShowSummaryPackages;
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -120,8 +121,6 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
// Preference cache to avoid create new instance each time.
@VisibleForTesting
final Map mPreferenceCache = new HashMap<>();
- @VisibleForTesting
- final List mSystemEntries = new ArrayList<>();
public BatteryChartPreferenceController(
Context context, String preferenceKey,
@@ -134,10 +133,6 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
mIs24HourFormat = DateFormat.is24HourFormat(context);
mMetricsFeatureProvider =
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
- mNotAllowShowEntryPackages =
- FeatureFactory.getFactory(context)
- .getPowerUsageFeatureProvider(context)
- .getHideApplicationEntries(context);
mNotAllowShowSummaryPackages =
FeatureFactory.getFactory(context)
.getPowerUsageFeatureProvider(context)
@@ -152,12 +147,14 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
if (savedInstanceState == null) {
return;
}
- mTrapezoidIndex =
- savedInstanceState.getInt(KEY_CURRENT_TIME_SLOT, mTrapezoidIndex);
+ mDailyChartIndex =
+ savedInstanceState.getInt(KEY_DAILY_CHART_INDEX, mDailyChartIndex);
+ mHourlyChartIndex =
+ savedInstanceState.getInt(KEY_HOURLY_CHART_INDEX, mHourlyChartIndex);
mIsExpanded =
savedInstanceState.getBoolean(KEY_EXPAND_SYSTEM_INFO, mIsExpanded);
- Log.d(TAG, String.format("onCreate() slotIndex=%d isExpanded=%b",
- mTrapezoidIndex, mIsExpanded));
+ Log.d(TAG, String.format("onCreate() dailyIndex=%d hourlyIndex=%d isExpanded=%b",
+ mDailyChartIndex, mHourlyChartIndex, mIsExpanded));
}
@Override
@@ -179,10 +176,11 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
if (savedInstance == null) {
return;
}
- savedInstance.putInt(KEY_CURRENT_TIME_SLOT, mTrapezoidIndex);
+ savedInstance.putInt(KEY_DAILY_CHART_INDEX, mDailyChartIndex);
+ savedInstance.putInt(KEY_HOURLY_CHART_INDEX, mHourlyChartIndex);
savedInstance.putBoolean(KEY_EXPAND_SYSTEM_INFO, mIsExpanded);
- Log.d(TAG, String.format("onSaveInstanceState() slotIndex=%d isExpanded=%b",
- mTrapezoidIndex, mIsExpanded));
+ Log.d(TAG, String.format("onSaveInstanceState() dailyIndex=%d hourlyIndex=%d isExpanded=%b",
+ mDailyChartIndex, mHourlyChartIndex, mIsExpanded));
}
@Override
@@ -204,8 +202,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
mPrefContext = screen.getContext();
mAppListPrefGroup = screen.findPreference(mPreferenceKey);
mAppListPrefGroup.setOrderingAsAdded(false);
- mAppListPrefGroup.setTitle(
- mPrefContext.getString(R.string.battery_app_usage_for_past_24));
+ mAppListPrefGroup.setTitle(mPrefContext.getString(R.string.battery_app_usage));
mFooterPreference = screen.findPreference(KEY_FOOTER_PREF);
// Removes footer first until usage data is loaded to avoid flashing.
if (mFooterPreference != null) {
@@ -249,17 +246,6 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
return true;
}
- @Override
- public void onSelect(int trapezoidIndex) {
- Log.d(TAG, "onChartSelect:" + trapezoidIndex);
- refreshUi(trapezoidIndex, /*isForce=*/ false);
- mMetricsFeatureProvider.action(
- mPrefContext,
- trapezoidIndex == BatteryChartView.SELECTED_INDEX_ALL
- ? SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL
- : SettingsEnums.ACTION_BATTERY_USAGE_TIME_SLOT);
- }
-
@Override
public void onExpand(boolean isExpanded) {
mIsExpanded = isExpanded;
@@ -272,81 +258,119 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
void setBatteryHistoryMap(
final Map> batteryHistoryMap) {
- // Resets all battery history data relative variables.
- if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) {
- mBatteryIndexedMap = null;
- mBatteryHistoryKeys = null;
- mBatteryHistoryLevels = null;
- addFooterPreferenceIfNeeded(false);
+ Log.d(TAG, "setBatteryHistoryMap() " + (batteryHistoryMap == null ? "null"
+ : ("size=" + batteryHistoryMap.size())));
+ final BatteryLevelData batteryLevelData =
+ DataProcessor.getBatteryLevelData(mContext, mHandler, batteryHistoryMap,
+ batteryUsageMap -> {
+ mBatteryUsageMap = batteryUsageMap;
+ refreshUi();
+ });
+ Log.d(TAG, "getBatteryLevelData: " + batteryLevelData);
+ if (batteryLevelData == null) {
+ mDailyTimestampFullTexts = null;
+ mDailyViewModel = null;
+ mHourlyViewModels = null;
+ refreshUi();
return;
}
- mBatteryHistoryKeys = getBatteryHistoryKeys(batteryHistoryMap);
- mBatteryHistoryLevels = new int[CHART_LEVEL_ARRAY_SIZE];
- 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));
- continue;
+ mDailyTimestampFullTexts = generateTimestampDayOfWeekTexts(
+ mContext, batteryLevelData.getDailyBatteryLevels().getTimestamps(),
+ /* isAbbreviation= */ false);
+ mDailyViewModel = new BatteryChartViewModel(
+ batteryLevelData.getDailyBatteryLevels().getLevels(),
+ generateTimestampDayOfWeekTexts(
+ mContext, batteryLevelData.getDailyBatteryLevels().getTimestamps(),
+ /* isAbbreviation= */ true),
+ BatteryChartViewModel.AxisLabelPosition.CENTER_OF_TRAPEZOIDS);
+ mHourlyViewModels = new ArrayList<>();
+ for (BatteryLevelData.PeriodBatteryLevelData hourlyBatteryLevelsPerDay :
+ batteryLevelData.getHourlyBatteryLevelsPerDay()) {
+ mHourlyViewModels.add(new BatteryChartViewModel(
+ hourlyBatteryLevelsPerDay.getLevels(),
+ generateTimestampHourTexts(
+ mContext, hourlyBatteryLevelsPerDay.getTimestamps()),
+ BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
+ }
+ refreshUi();
+ }
+
+ void setBatteryChartView(@NonNull final BatteryChartView dailyChartView,
+ @NonNull final BatteryChartView hourlyChartView) {
+ if (mDailyChartView != dailyChartView || mHourlyChartView != hourlyChartView) {
+ mHandler.post(() -> setBatteryChartViewInner(dailyChartView, hourlyChartView));
+ }
+ }
+
+ private void setBatteryChartViewInner(@NonNull final BatteryChartView dailyChartView,
+ @NonNull final BatteryChartView hourlyChartView) {
+ mDailyChartView = dailyChartView;
+ mDailyChartView.setOnSelectListener(trapezoidIndex -> {
+ if (mDailyChartIndex == trapezoidIndex) {
+ return;
}
- // Averages the battery level in each time slot to avoid corner conditions.
- float batteryLevelCounter = 0;
- for (BatteryHistEntry entry : entryMap.values()) {
- batteryLevelCounter += entry.mBatteryLevel;
+ Log.d(TAG, "onDailyChartSelect:" + trapezoidIndex);
+ mDailyChartIndex = trapezoidIndex;
+ mHourlyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
+ refreshUi();
+ // TODO: Change to log daily data.
+ });
+ mHourlyChartView = hourlyChartView;
+ mHourlyChartView.setOnSelectListener(trapezoidIndex -> {
+ if (mHourlyChartIndex == trapezoidIndex) {
+ return;
}
- mBatteryHistoryLevels[index] =
- Math.round(batteryLevelCounter / entryMap.size());
- }
- forceRefreshUi();
- Log.d(TAG, String.format(
- "setBatteryHistoryMap() size=%d key=%s\nlevels=%s",
- batteryHistoryMap.size(),
- ConvertUtils.utcToLocalTime(mPrefContext,
- mBatteryHistoryKeys[mBatteryHistoryKeys.length - 1]),
- Arrays.toString(mBatteryHistoryLevels)));
-
- // Loads item icon and label in the background.
- new LoadAllItemsInfoTask(batteryHistoryMap).execute();
- }
-
- void setBatteryChartView(final BatteryChartView batteryChartView) {
- if (mBatteryChartView != batteryChartView) {
- mHandler.post(() -> setBatteryChartViewInner(batteryChartView));
- }
- }
-
- private void setBatteryChartViewInner(final BatteryChartView batteryChartView) {
- mBatteryChartView = batteryChartView;
- mBatteryChartView.setOnSelectListener(this);
- forceRefreshUi();
- }
-
- private void forceRefreshUi() {
- final int refreshIndex =
- mTrapezoidIndex == BatteryChartView.SELECTED_INDEX_INVALID
- ? BatteryChartView.SELECTED_INDEX_ALL
- : mTrapezoidIndex;
- if (mBatteryChartView != null) {
- mBatteryChartView.setLevels(mBatteryHistoryLevels);
- mBatteryChartView.setSelectedIndex(refreshIndex);
- setTimestampLabel();
- }
- refreshUi(refreshIndex, /*isForce=*/ true);
+ Log.d(TAG, "onHourlyChartSelect:" + trapezoidIndex);
+ mHourlyChartIndex = trapezoidIndex;
+ refreshUi();
+ mMetricsFeatureProvider.action(
+ mPrefContext,
+ trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_ALL
+ ? SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL
+ : SettingsEnums.ACTION_BATTERY_USAGE_TIME_SLOT);
+ });
+ refreshUi();
}
@VisibleForTesting
- boolean refreshUi(int trapezoidIndex, boolean isForce) {
- // Invalid refresh condition.
- if (mBatteryIndexedMap == null
- || mBatteryChartView == null
- || (mTrapezoidIndex == trapezoidIndex && !isForce)) {
+ boolean refreshUi() {
+ if (mDailyChartView == null || mHourlyChartView == null) {
+ // Chart views are not initialized.
+ return false;
+ }
+ if (mDailyViewModel == null || mHourlyViewModels == null) {
+ // Fail to get battery level data, show an empty hourly chart view.
+ mDailyChartView.setVisibility(View.GONE);
+ mHourlyChartView.setVisibility(View.VISIBLE);
+ mHourlyChartView.setViewModel(null);
+ addFooterPreferenceIfNeeded(false);
+ return false;
+ }
+ if (mBatteryUsageMap == null) {
+ // Battery usage data is not ready, wait for data ready to refresh UI.
return false;
}
- Log.d(TAG, String.format("refreshUi: index=%d size=%d isForce:%b",
- trapezoidIndex, mBatteryIndexedMap.size(), isForce));
- mTrapezoidIndex = trapezoidIndex;
+ if (isBatteryLevelDataInOneDay()) {
+ // Only 1 day data, hide the daily chart view.
+ mDailyChartView.setVisibility(View.GONE);
+ mDailyChartIndex = 0;
+ } else {
+ mDailyChartView.setVisibility(View.VISIBLE);
+ mDailyViewModel.setSelectedIndex(mDailyChartIndex);
+ mDailyChartView.setViewModel(mDailyViewModel);
+ }
+
+ if (mDailyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL) {
+ // Multiple days are selected, hide the hourly chart view.
+ mHourlyChartView.setVisibility(View.GONE);
+ } else {
+ mHourlyChartView.setVisibility(View.VISIBLE);
+ final BatteryChartViewModel hourlyViewModel = mHourlyViewModels.get(mDailyChartIndex);
+ hourlyViewModel.setSelectedIndex(mHourlyChartIndex);
+ mHourlyChartView.setViewModel(hourlyViewModel);
+ }
+
mHandler.post(() -> {
final long start = System.currentTimeMillis();
removeAndCacheAllPrefs();
@@ -359,43 +383,22 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
}
private void addAllPreferences() {
- final List entries =
- mBatteryIndexedMap.get(Integer.valueOf(mTrapezoidIndex));
- addFooterPreferenceIfNeeded(entries != null && !entries.isEmpty());
- if (entries == null) {
- Log.w(TAG, "cannot find BatteryDiffEntry for:" + mTrapezoidIndex);
+ final BatteryDiffData batteryDiffData =
+ mBatteryUsageMap.get(mDailyChartIndex).get(mHourlyChartIndex);
+ addFooterPreferenceIfNeeded(batteryDiffData != null
+ && (!batteryDiffData.getAppDiffEntryList().isEmpty()
+ || !batteryDiffData.getSystemDiffEntryList().isEmpty()));
+ if (batteryDiffData == null) {
+ Log.w(TAG, "cannot find BatteryDiffEntry for daily_index: " + mDailyChartIndex
+ + " hourly_index: " + mHourlyChartIndex);
return;
}
- // Separates data into two groups and sort them individually.
- final List appEntries = new ArrayList<>();
- mSystemEntries.clear();
- entries.forEach(entry -> {
- final String packageName = entry.getPackageName();
- if (!isValidToShowEntry(packageName)) {
- Log.w(TAG, "ignore showing item:" + packageName);
- return;
- }
- if (entry.isSystemEntry()) {
- mSystemEntries.add(entry);
- } else {
- appEntries.add(entry);
- }
- // Validates the usage time if users click a specific slot.
- if (mTrapezoidIndex >= 0) {
- validateUsageTime(entry);
- }
- });
- Collections.sort(appEntries, BatteryDiffEntry.COMPARATOR);
- Collections.sort(mSystemEntries, BatteryDiffEntry.COMPARATOR);
- Log.d(TAG, String.format("addAllPreferences() app=%d system=%d",
- appEntries.size(), mSystemEntries.size()));
-
// Adds app entries to the list if it is not empty.
- if (!appEntries.isEmpty()) {
- addPreferenceToScreen(appEntries);
+ if (!batteryDiffData.getAppDiffEntryList().isEmpty()) {
+ addPreferenceToScreen(batteryDiffData.getAppDiffEntryList());
}
// Adds the expabable divider if we have system entries data.
- if (!mSystemEntries.isEmpty()) {
+ if (!batteryDiffData.getSystemDiffEntryList().isEmpty()) {
if (mExpandDividerPreference == null) {
mExpandDividerPreference = new ExpandDividerPreference(mPrefContext);
mExpandDividerPreference.setOnExpandListener(this);
@@ -469,11 +472,13 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
}
private void refreshExpandUi() {
+ final List systemEntries = mBatteryUsageMap.get(mDailyChartIndex).get(
+ mHourlyChartIndex).getSystemDiffEntryList();
if (mIsExpanded) {
- addPreferenceToScreen(mSystemEntries);
+ addPreferenceToScreen(systemEntries);
} else {
// Removes and recycles all system entries to hide all of them.
- for (BatteryDiffEntry entry : mSystemEntries) {
+ for (BatteryDiffEntry entry : systemEntries) {
final String prefKey = entry.mBatteryHistEntry.getKey();
final Preference pref = mAppListPrefGroup.findPreference(prefKey);
if (pref != null) {
@@ -499,11 +504,12 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
}
private String getSlotInformation(boolean isApp, String slotInformation) {
+ // TODO: Updates the right slot information from daily and hourly chart selection.
// Null means we show all information without a specific time slot.
if (slotInformation == null) {
return isApp
- ? mPrefContext.getString(R.string.battery_app_usage_for_past_24)
- : mPrefContext.getString(R.string.battery_system_usage_for_past_24);
+ ? mPrefContext.getString(R.string.battery_app_usage)
+ : mPrefContext.getString(R.string.battery_system_usage);
} else {
return isApp
? mPrefContext.getString(R.string.battery_app_usage_for, slotInformation)
@@ -511,17 +517,33 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
}
}
- private String getSlotInformation() {
- if (mTrapezoidIndex < 0) {
+ @VisibleForTesting
+ String getSlotInformation() {
+ if (mDailyTimestampFullTexts == null || mDailyViewModel == null
+ || mHourlyViewModels == null) {
+ // No data
return null;
}
- final String fromHour = ConvertUtils.utcToLocalTimeHour(mPrefContext,
- mBatteryHistoryKeys[mTrapezoidIndex * 2], mIs24HourFormat);
- final String toHour = ConvertUtils.utcToLocalTimeHour(mPrefContext,
- mBatteryHistoryKeys[(mTrapezoidIndex + 1) * 2], mIs24HourFormat);
- return mIs24HourFormat
- ? String.format("%sā%s", fromHour, toHour)
- : String.format("%s ā %s", fromHour, toHour);
+ if (isAllSelected()) {
+ return null;
+ }
+
+ final String selectedDayText = mDailyTimestampFullTexts.get(mDailyChartIndex);
+ if (mHourlyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL) {
+ return selectedDayText;
+ }
+
+ final String fromHourText = mHourlyViewModels.get(mDailyChartIndex).texts().get(
+ mHourlyChartIndex);
+ final String toHourText = mHourlyViewModels.get(mDailyChartIndex).texts().get(
+ mHourlyChartIndex + 1);
+ final String selectedHourText =
+ String.format("%s%s%s", fromHourText, mIs24HourFormat ? "-" : " - ", toHourText);
+ if (isBatteryLevelDataInOneDay()) {
+ return selectedHourText;
+ }
+
+ return String.format("%s %s", selectedDayText, selectedHourText);
}
@VisibleForTesting
@@ -575,22 +597,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
@VisibleForTesting
boolean isValidToShowSummary(String packageName) {
- return !contains(packageName, mNotAllowShowSummaryPackages);
- }
-
- @VisibleForTesting
- boolean isValidToShowEntry(String packageName) {
- return !contains(packageName, mNotAllowShowEntryPackages);
- }
-
- @VisibleForTesting
- void setTimestampLabel() {
- if (mBatteryChartView == null || mBatteryHistoryKeys == null) {
- return;
- }
- final long latestTimestamp =
- mBatteryHistoryKeys[mBatteryHistoryKeys.length - 1];
- mBatteryChartView.setLatestTimestamp(latestTimestamp);
+ return !DataProcessor.contains(packageName, mNotAllowShowSummaryPackages);
}
private void addFooterPreferenceIfNeeded(boolean containAppItems) {
@@ -605,60 +612,65 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
mHandler.post(() -> mPreferenceScreen.addPreference(mFooterPreference));
}
- private static boolean contains(String target, CharSequence[] packageNames) {
- if (target != null && packageNames != null) {
- for (CharSequence packageName : packageNames) {
- if (TextUtils.equals(target, packageName)) {
- return true;
- }
- }
- }
- return false;
+ private boolean isBatteryLevelDataInOneDay() {
+ return mHourlyViewModels != null && mHourlyViewModels.size() == 1;
}
- @VisibleForTesting
- static boolean validateUsageTime(BatteryDiffEntry entry) {
- final long foregroundUsageTimeInMs = entry.mForegroundUsageTimeInMs;
- final long backgroundUsageTimeInMs = entry.mBackgroundUsageTimeInMs;
- final long totalUsageTimeInMs = foregroundUsageTimeInMs + backgroundUsageTimeInMs;
- if (foregroundUsageTimeInMs > VALID_USAGE_TIME_DURATION
- || backgroundUsageTimeInMs > VALID_USAGE_TIME_DURATION
- || totalUsageTimeInMs > VALID_USAGE_TIME_DURATION) {
- Log.e(TAG, "validateUsageTime() fail for\n" + entry);
- return false;
+ private boolean isAllSelected() {
+ return (isBatteryLevelDataInOneDay()
+ || mDailyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL)
+ && mHourlyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL;
+ }
+
+ private static List generateTimestampDayOfWeekTexts(@NonNull final Context context,
+ @NonNull final List timestamps, final boolean isAbbreviation) {
+ final ArrayList texts = new ArrayList<>();
+ for (Long timestamp : timestamps) {
+ texts.add(ConvertUtils.utcToLocalTimeDayOfWeek(context, timestamp, isAbbreviation));
}
- return true;
+ return texts;
+ }
+
+ private static List generateTimestampHourTexts(
+ @NonNull final Context context, @NonNull final List timestamps) {
+ final boolean is24HourFormat = DateFormat.is24HourFormat(context);
+ final ArrayList texts = new ArrayList<>();
+ for (Long timestamp : timestamps) {
+ texts.add(ConvertUtils.utcToLocalTimeHour(context, timestamp, is24HourFormat));
+ }
+ return texts;
}
/** Used for {@link AppBatteryPreferenceController}. */
- public static List getBatteryLast24HrUsageData(Context context) {
+ public static List getAppBatteryUsageData(Context context) {
final long start = System.currentTimeMillis();
final Map> batteryHistoryMap =
FeatureFactory.getFactory(context)
.getPowerUsageFeatureProvider(context)
- .getBatteryHistory(context);
+ .getBatteryHistorySinceLastFullCharge(context);
if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) {
return null;
}
- Log.d(TAG, String.format("getBatteryLast24HrData() size=%d time=&d/ms",
+ Log.d(TAG, String.format("getBatterySinceLastFullChargeUsageData() size=%d time=%d/ms",
batteryHistoryMap.size(), (System.currentTimeMillis() - start)));
- final Map> batteryIndexedMap =
- ConvertUtils.getIndexedUsageMap(
- context,
- /*timeSlotSize=*/ CHART_LEVEL_ARRAY_SIZE - 1,
- getBatteryHistoryKeys(batteryHistoryMap),
- batteryHistoryMap,
- /*purgeLowPercentageAndFakeData=*/ true);
- return batteryIndexedMap.get(BatteryChartView.SELECTED_INDEX_ALL);
+
+ final Map> batteryUsageData =
+ DataProcessor.getBatteryUsageData(context, batteryHistoryMap);
+ return batteryUsageData == null
+ ? null
+ : batteryUsageData
+ .get(BatteryChartViewModel.SELECTED_INDEX_ALL)
+ .get(BatteryChartViewModel.SELECTED_INDEX_ALL)
+ .getAppDiffEntryList();
}
/** Used for {@link AppBatteryPreferenceController}. */
- public static BatteryDiffEntry getBatteryLast24HrUsageData(
+ public static BatteryDiffEntry getAppBatteryUsageData(
Context context, String packageName, int userId) {
if (packageName == null) {
return null;
}
- final List entries = getBatteryLast24HrUsageData(context);
+ final List entries = getAppBatteryUsageData(context);
if (entries == null) {
return null;
}
@@ -673,65 +685,4 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
}
return null;
}
-
- private static long[] getBatteryHistoryKeys(
- final Map> batteryHistoryMap) {
- final List batteryHistoryKeyList =
- new ArrayList<>(batteryHistoryMap.keySet());
- Collections.sort(batteryHistoryKeyList);
- final long[] batteryHistoryKeys = new long[CHART_KEY_ARRAY_SIZE];
- for (int index = 0; index < CHART_KEY_ARRAY_SIZE; index++) {
- batteryHistoryKeys[index] = batteryHistoryKeyList.get(index);
- }
- return batteryHistoryKeys;
- }
-
- // Loads all items icon and label in the background.
- private final class LoadAllItemsInfoTask
- extends AsyncTask>> {
-
- private long[] mBatteryHistoryKeysCache;
- private Map> mBatteryHistoryMap;
-
- private LoadAllItemsInfoTask(
- Map> batteryHistoryMap) {
- this.mBatteryHistoryMap = batteryHistoryMap;
- this.mBatteryHistoryKeysCache = mBatteryHistoryKeys;
- }
-
- @Override
- protected Map> doInBackground(Void... voids) {
- if (mPrefContext == null || mBatteryHistoryKeysCache == null) {
- return null;
- }
- final long startTime = System.currentTimeMillis();
- final Map> indexedUsageMap =
- ConvertUtils.getIndexedUsageMap(
- mPrefContext, /*timeSlotSize=*/ CHART_LEVEL_ARRAY_SIZE - 1,
- mBatteryHistoryKeysCache, mBatteryHistoryMap,
- /*purgeLowPercentageAndFakeData=*/ true);
- // Pre-loads each BatteryDiffEntry relative icon and label for all slots.
- for (List entries : indexedUsageMap.values()) {
- entries.forEach(entry -> entry.loadLabelAndIcon());
- }
- Log.d(TAG, String.format("execute LoadAllItemsInfoTask in %d/ms",
- (System.currentTimeMillis() - startTime)));
- return indexedUsageMap;
- }
-
- @Override
- protected void onPostExecute(
- Map> indexedUsageMap) {
- mBatteryHistoryMap = null;
- mBatteryHistoryKeysCache = null;
- if (indexedUsageMap == null) {
- return;
- }
- // Posts results back to main thread to refresh UI.
- mHandler.post(() -> {
- mBatteryIndexedMap = indexedUsageMap;
- forceRefreshUi();
- });
- }
- }
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java
deleted file mode 100644
index e743e22215a..00000000000
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2.java
+++ /dev/null
@@ -1,701 +0,0 @@
-/*
- * 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 android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.text.TextUtils;
-import android.text.format.DateFormat;
-import android.text.format.DateUtils;
-import android.util.Log;
-import android.view.View;
-import android.widget.LinearLayout;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.SettingsActivity;
-import com.android.settings.core.InstrumentedPreferenceFragment;
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settings.fuelgauge.AdvancedPowerUsageDetail;
-import com.android.settings.fuelgauge.BatteryUtils;
-import com.android.settings.overlay.FeatureFactory;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnCreate;
-import com.android.settingslib.core.lifecycle.events.OnDestroy;
-import com.android.settingslib.core.lifecycle.events.OnResume;
-import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
-import com.android.settingslib.utils.StringUtil;
-import com.android.settingslib.widget.FooterPreference;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/** Controls the update for chart graph and the list items. */
-public class BatteryChartPreferenceControllerV2 extends AbstractPreferenceController
- implements PreferenceControllerMixin, LifecycleObserver, OnCreate, OnDestroy,
- OnSaveInstanceState, OnResume, ExpandDividerPreference.OnExpandListener {
- private static final String TAG = "BatteryChartPreferenceControllerV2";
- private static final String KEY_FOOTER_PREF = "battery_graph_footer";
- private static final String PACKAGE_NAME_NONE = "none";
-
- private static final int TWENTY_FOUR_HOURS_TIME_SLOT_SIZE = 12;
- private static final long VALID_USAGE_TIME_DURATION = DateUtils.HOUR_IN_MILLIS * 2;
- private static final long VALID_DIFF_DURATION = DateUtils.MINUTE_IN_MILLIS * 3;
-
- // Keys for bundle instance to restore configurations.
- private static final String KEY_EXPAND_SYSTEM_INFO = "expand_system_info";
- private static final String KEY_DAILY_CHART_INDEX = "daily_chart_index";
- private static final String KEY_HOURLY_CHART_INDEX = "hourly_chart_index";
-
- private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
-
- @VisibleForTesting
- Map> mBatteryUsageMap;
-
- @VisibleForTesting
- Context mPrefContext;
- @VisibleForTesting
- BatteryUtils mBatteryUtils;
- @VisibleForTesting
- PreferenceGroup mAppListPrefGroup;
- @VisibleForTesting
- ExpandDividerPreference mExpandDividerPreference;
- @VisibleForTesting
- boolean mIsExpanded = false;
-
- @VisibleForTesting
- BatteryChartViewV2 mDailyChartView;
- @VisibleForTesting
- BatteryChartViewV2 mHourlyChartView;
-
- @VisibleForTesting
- int mDailyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
- @VisibleForTesting
- int mHourlyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
-
- private boolean mIs24HourFormat;
- private boolean mIsFooterPrefAdded = false;
- private PreferenceScreen mPreferenceScreen;
- private FooterPreference mFooterPreference;
- // Daily view model only saves abbreviated day of week texts (e.g. MON). This field saves the
- // full day of week texts (e.g. Monday), which is used in category title and battery detail
- // page.
- private List mDailyTimestampFullTexts;
- private BatteryChartViewModel mDailyViewModel;
- private List mHourlyViewModels;
-
- private final String mPreferenceKey;
- private final SettingsActivity mActivity;
- private final InstrumentedPreferenceFragment mFragment;
- private final CharSequence[] mNotAllowShowSummaryPackages;
- private final MetricsFeatureProvider mMetricsFeatureProvider;
- private final Handler mHandler = new Handler(Looper.getMainLooper());
-
- // Preference cache to avoid create new instance each time.
- @VisibleForTesting
- final Map mPreferenceCache = new HashMap<>();
-
- public BatteryChartPreferenceControllerV2(
- Context context, String preferenceKey,
- Lifecycle lifecycle, SettingsActivity activity,
- InstrumentedPreferenceFragment fragment) {
- super(context);
- mActivity = activity;
- mFragment = fragment;
- mPreferenceKey = preferenceKey;
- mIs24HourFormat = DateFormat.is24HourFormat(context);
- mMetricsFeatureProvider =
- FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
- mNotAllowShowSummaryPackages =
- FeatureFactory.getFactory(context)
- .getPowerUsageFeatureProvider(context)
- .getHideApplicationSummary(context);
- if (lifecycle != null) {
- lifecycle.addObserver(this);
- }
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- if (savedInstanceState == null) {
- return;
- }
- mDailyChartIndex =
- savedInstanceState.getInt(KEY_DAILY_CHART_INDEX, mDailyChartIndex);
- mHourlyChartIndex =
- savedInstanceState.getInt(KEY_HOURLY_CHART_INDEX, mHourlyChartIndex);
- mIsExpanded =
- savedInstanceState.getBoolean(KEY_EXPAND_SYSTEM_INFO, mIsExpanded);
- Log.d(TAG, String.format("onCreate() dailyIndex=%d hourlyIndex=%d isExpanded=%b",
- mDailyChartIndex, mHourlyChartIndex, mIsExpanded));
- }
-
- @Override
- public void onResume() {
- final int currentUiMode =
- mContext.getResources().getConfiguration().uiMode
- & Configuration.UI_MODE_NIGHT_MASK;
- if (sUiMode != currentUiMode) {
- sUiMode = currentUiMode;
- BatteryDiffEntry.clearCache();
- Log.d(TAG, "clear icon and label cache since uiMode is changed");
- }
- mIs24HourFormat = DateFormat.is24HourFormat(mContext);
- mMetricsFeatureProvider.action(mPrefContext, SettingsEnums.OPEN_BATTERY_USAGE);
- }
-
- @Override
- public void onSaveInstanceState(Bundle savedInstance) {
- if (savedInstance == null) {
- return;
- }
- savedInstance.putInt(KEY_DAILY_CHART_INDEX, mDailyChartIndex);
- savedInstance.putInt(KEY_HOURLY_CHART_INDEX, mHourlyChartIndex);
- savedInstance.putBoolean(KEY_EXPAND_SYSTEM_INFO, mIsExpanded);
- Log.d(TAG, String.format("onSaveInstanceState() dailyIndex=%d hourlyIndex=%d isExpanded=%b",
- mDailyChartIndex, mHourlyChartIndex, mIsExpanded));
- }
-
- @Override
- public void onDestroy() {
- if (mActivity.isChangingConfigurations()) {
- BatteryDiffEntry.clearCache();
- }
- mHandler.removeCallbacksAndMessages(/*token=*/ null);
- mPreferenceCache.clear();
- if (mAppListPrefGroup != null) {
- mAppListPrefGroup.removeAll();
- }
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- mPreferenceScreen = screen;
- mPrefContext = screen.getContext();
- mAppListPrefGroup = screen.findPreference(mPreferenceKey);
- mAppListPrefGroup.setOrderingAsAdded(false);
- mAppListPrefGroup.setTitle(mPrefContext.getString(R.string.battery_app_usage));
- mFooterPreference = screen.findPreference(KEY_FOOTER_PREF);
- // Removes footer first until usage data is loaded to avoid flashing.
- if (mFooterPreference != null) {
- screen.removePreference(mFooterPreference);
- }
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public String getPreferenceKey() {
- return mPreferenceKey;
- }
-
- @Override
- public boolean handlePreferenceTreeClick(Preference preference) {
- if (!(preference instanceof PowerGaugePreference)) {
- return false;
- }
- final PowerGaugePreference powerPref = (PowerGaugePreference) preference;
- final BatteryDiffEntry diffEntry = powerPref.getBatteryDiffEntry();
- final BatteryHistEntry histEntry = diffEntry.mBatteryHistEntry;
- final String packageName = histEntry.mPackageName;
- final boolean isAppEntry = histEntry.isAppEntry();
- mMetricsFeatureProvider.action(
- /* attribution */ SettingsEnums.OPEN_BATTERY_USAGE,
- /* action */ isAppEntry
- ? SettingsEnums.ACTION_BATTERY_USAGE_APP_ITEM
- : SettingsEnums.ACTION_BATTERY_USAGE_SYSTEM_ITEM,
- /* pageId */ SettingsEnums.OPEN_BATTERY_USAGE,
- TextUtils.isEmpty(packageName) ? PACKAGE_NAME_NONE : packageName,
- (int) Math.round(diffEntry.getPercentOfTotal()));
- Log.d(TAG, String.format("handleClick() label=%s key=%s package=%s",
- diffEntry.getAppLabel(), histEntry.getKey(), histEntry.mPackageName));
- AdvancedPowerUsageDetail.startBatteryDetailPage(
- mActivity, mFragment, diffEntry, powerPref.getPercent(),
- isValidToShowSummary(packageName), getSlotInformation());
- return true;
- }
-
- @Override
- public void onExpand(boolean isExpanded) {
- mIsExpanded = isExpanded;
- mMetricsFeatureProvider.action(
- mPrefContext,
- SettingsEnums.ACTION_BATTERY_USAGE_EXPAND_ITEM,
- isExpanded);
- refreshExpandUi();
- }
-
- void setBatteryHistoryMap(
- final Map> batteryHistoryMap) {
- Log.d(TAG, "setBatteryHistoryMap() " + (batteryHistoryMap == null ? "null"
- : ("size=" + batteryHistoryMap.size())));
- final BatteryLevelData batteryLevelData =
- DataProcessor.getBatteryLevelData(mContext, mHandler, batteryHistoryMap,
- batteryUsageMap -> {
- mBatteryUsageMap = batteryUsageMap;
- refreshUi();
- });
- Log.d(TAG, "getBatteryLevelData: " + batteryLevelData);
- if (batteryLevelData == null) {
- mDailyTimestampFullTexts = null;
- mDailyViewModel = null;
- mHourlyViewModels = null;
- refreshUi();
- return;
- }
- mDailyTimestampFullTexts = generateTimestampDayOfWeekTexts(
- mContext, batteryLevelData.getDailyBatteryLevels().getTimestamps(),
- /* isAbbreviation= */ false);
- mDailyViewModel = new BatteryChartViewModel(
- batteryLevelData.getDailyBatteryLevels().getLevels(),
- generateTimestampDayOfWeekTexts(
- mContext, batteryLevelData.getDailyBatteryLevels().getTimestamps(),
- /* isAbbreviation= */ true),
- BatteryChartViewModel.AxisLabelPosition.CENTER_OF_TRAPEZOIDS);
- mHourlyViewModels = new ArrayList<>();
- for (BatteryLevelData.PeriodBatteryLevelData hourlyBatteryLevelsPerDay :
- batteryLevelData.getHourlyBatteryLevelsPerDay()) {
- mHourlyViewModels.add(new BatteryChartViewModel(
- hourlyBatteryLevelsPerDay.getLevels(),
- generateTimestampHourTexts(
- mContext, hourlyBatteryLevelsPerDay.getTimestamps()),
- BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
- }
- refreshUi();
- }
-
- void setBatteryChartView(@NonNull final BatteryChartViewV2 dailyChartView,
- @NonNull final BatteryChartViewV2 hourlyChartView) {
- if (mDailyChartView != dailyChartView || mHourlyChartView != hourlyChartView) {
- mHandler.post(() -> setBatteryChartViewInner(dailyChartView, hourlyChartView));
- }
- }
-
- private void setBatteryChartViewInner(@NonNull final BatteryChartViewV2 dailyChartView,
- @NonNull final BatteryChartViewV2 hourlyChartView) {
- mDailyChartView = dailyChartView;
- mDailyChartView.setOnSelectListener(trapezoidIndex -> {
- if (mDailyChartIndex == trapezoidIndex) {
- return;
- }
- Log.d(TAG, "onDailyChartSelect:" + trapezoidIndex);
- mDailyChartIndex = trapezoidIndex;
- mHourlyChartIndex = BatteryChartView.SELECTED_INDEX_ALL;
- refreshUi();
- // TODO: Change to log daily data.
- });
- mHourlyChartView = hourlyChartView;
- mHourlyChartView.setOnSelectListener(trapezoidIndex -> {
- if (mHourlyChartIndex == trapezoidIndex) {
- return;
- }
- Log.d(TAG, "onHourlyChartSelect:" + trapezoidIndex);
- mHourlyChartIndex = trapezoidIndex;
- refreshUi();
- mMetricsFeatureProvider.action(
- mPrefContext,
- trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_ALL
- ? SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL
- : SettingsEnums.ACTION_BATTERY_USAGE_TIME_SLOT);
- });
- refreshUi();
- }
-
- @VisibleForTesting
- boolean refreshUi() {
- if (mDailyChartView == null || mHourlyChartView == null) {
- // Chart views are not initialized.
- return false;
- }
- if (mDailyViewModel == null || mHourlyViewModels == null) {
- // Fail to get battery level data, show an empty hourly chart view.
- mDailyChartView.setVisibility(View.GONE);
- mHourlyChartView.setVisibility(View.VISIBLE);
- mHourlyChartView.setViewModel(null);
- addFooterPreferenceIfNeeded(false);
- return false;
- }
- if (mBatteryUsageMap == null) {
- // Battery usage data is not ready, wait for data ready to refresh UI.
- return false;
- }
-
- if (isBatteryLevelDataInOneDay()) {
- // Only 1 day data, hide the daily chart view.
- mDailyChartView.setVisibility(View.GONE);
- mDailyChartIndex = 0;
- } else {
- mDailyChartView.setVisibility(View.VISIBLE);
- mDailyViewModel.setSelectedIndex(mDailyChartIndex);
- mDailyChartView.setViewModel(mDailyViewModel);
- }
-
- if (mDailyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL) {
- // Multiple days are selected, hide the hourly chart view.
- mHourlyChartView.setVisibility(View.GONE);
- updateMarginBetweenCharts(false);
- } else {
- mHourlyChartView.setVisibility(View.VISIBLE);
- final BatteryChartViewModel hourlyViewModel = mHourlyViewModels.get(mDailyChartIndex);
- hourlyViewModel.setSelectedIndex(mHourlyChartIndex);
- mHourlyChartView.setViewModel(hourlyViewModel);
-
- updateMarginBetweenCharts(true);
- }
-
- mHandler.post(() -> {
- final long start = System.currentTimeMillis();
- removeAndCacheAllPrefs();
- addAllPreferences();
- refreshCategoryTitle();
- Log.d(TAG, String.format("refreshUi is finished in %d/ms",
- (System.currentTimeMillis() - start)));
- });
- return true;
- }
-
- private void updateMarginBetweenCharts(boolean addMargin) {
- final LinearLayout.LayoutParams layoutParams =
- (LinearLayout.LayoutParams) mDailyChartView.getLayoutParams();
- layoutParams.bottomMargin = addMargin ? Math.round(
- mContext.getResources().getDimension(R.dimen.chartview_two_charts_margin)) : 0;
- mDailyChartView.setLayoutParams(layoutParams);
- }
-
- private void addAllPreferences() {
- final BatteryDiffData batteryDiffData =
- mBatteryUsageMap.get(mDailyChartIndex).get(mHourlyChartIndex);
- addFooterPreferenceIfNeeded(batteryDiffData != null
- && (!batteryDiffData.getAppDiffEntryList().isEmpty()
- || !batteryDiffData.getSystemDiffEntryList().isEmpty()));
- if (batteryDiffData == null) {
- Log.w(TAG, "cannot find BatteryDiffEntry for daily_index: " + mDailyChartIndex
- + " hourly_index: " + mHourlyChartIndex);
- return;
- }
- // Adds app entries to the list if it is not empty.
- if (!batteryDiffData.getAppDiffEntryList().isEmpty()) {
- addPreferenceToScreen(batteryDiffData.getAppDiffEntryList());
- }
- // Adds the expabable divider if we have system entries data.
- if (!batteryDiffData.getSystemDiffEntryList().isEmpty()) {
- if (mExpandDividerPreference == null) {
- mExpandDividerPreference = new ExpandDividerPreference(mPrefContext);
- mExpandDividerPreference.setOnExpandListener(this);
- mExpandDividerPreference.setIsExpanded(mIsExpanded);
- }
- mExpandDividerPreference.setOrder(
- mAppListPrefGroup.getPreferenceCount());
- mAppListPrefGroup.addPreference(mExpandDividerPreference);
- }
- refreshExpandUi();
- }
-
- @VisibleForTesting
- void addPreferenceToScreen(List entries) {
- if (mAppListPrefGroup == null || entries.isEmpty()) {
- return;
- }
- int prefIndex = mAppListPrefGroup.getPreferenceCount();
- for (BatteryDiffEntry entry : entries) {
- boolean isAdded = false;
- final String appLabel = entry.getAppLabel();
- final Drawable appIcon = entry.getAppIcon();
- if (TextUtils.isEmpty(appLabel) || appIcon == null) {
- Log.w(TAG, "cannot find app resource for:" + entry.getPackageName());
- continue;
- }
- final String prefKey = entry.mBatteryHistEntry.getKey();
- PowerGaugePreference pref = mAppListPrefGroup.findPreference(prefKey);
- if (pref != null) {
- isAdded = true;
- Log.w(TAG, "preference should be removed for:" + entry.getPackageName());
- } else {
- pref = (PowerGaugePreference) mPreferenceCache.get(prefKey);
- }
- // Creates new innstance if cached preference is not found.
- if (pref == null) {
- pref = new PowerGaugePreference(mPrefContext);
- pref.setKey(prefKey);
- mPreferenceCache.put(prefKey, pref);
- }
- pref.setIcon(appIcon);
- pref.setTitle(appLabel);
- pref.setOrder(prefIndex);
- pref.setPercent(entry.getPercentOfTotal());
- pref.setSingleLineTitle(true);
- // Sets the BatteryDiffEntry to preference for launching detailed page.
- pref.setBatteryDiffEntry(entry);
- pref.setEnabled(entry.validForRestriction());
- setPreferenceSummary(pref, entry);
- if (!isAdded) {
- mAppListPrefGroup.addPreference(pref);
- }
- prefIndex++;
- }
- }
-
- private void removeAndCacheAllPrefs() {
- if (mAppListPrefGroup == null
- || mAppListPrefGroup.getPreferenceCount() == 0) {
- return;
- }
- final int prefsCount = mAppListPrefGroup.getPreferenceCount();
- for (int index = 0; index < prefsCount; index++) {
- final Preference pref = mAppListPrefGroup.getPreference(index);
- if (TextUtils.isEmpty(pref.getKey())) {
- continue;
- }
- mPreferenceCache.put(pref.getKey(), pref);
- }
- mAppListPrefGroup.removeAll();
- }
-
- private void refreshExpandUi() {
- final List systemEntries = mBatteryUsageMap.get(mDailyChartIndex).get(
- mHourlyChartIndex).getSystemDiffEntryList();
- if (mIsExpanded) {
- addPreferenceToScreen(systemEntries);
- } else {
- // Removes and recycles all system entries to hide all of them.
- for (BatteryDiffEntry entry : systemEntries) {
- final String prefKey = entry.mBatteryHistEntry.getKey();
- final Preference pref = mAppListPrefGroup.findPreference(prefKey);
- if (pref != null) {
- mAppListPrefGroup.removePreference(pref);
- mPreferenceCache.put(pref.getKey(), pref);
- }
- }
- }
- }
-
- @VisibleForTesting
- void refreshCategoryTitle() {
- final String slotInformation = getSlotInformation();
- Log.d(TAG, String.format("refreshCategoryTitle:%s", slotInformation));
- if (mAppListPrefGroup != null) {
- mAppListPrefGroup.setTitle(
- getSlotInformation(/*isApp=*/ true, slotInformation));
- }
- if (mExpandDividerPreference != null) {
- mExpandDividerPreference.setTitle(
- getSlotInformation(/*isApp=*/ false, slotInformation));
- }
- }
-
- private String getSlotInformation(boolean isApp, String slotInformation) {
- // TODO: Updates the right slot information from daily and hourly chart selection.
- // Null means we show all information without a specific time slot.
- if (slotInformation == null) {
- return isApp
- ? mPrefContext.getString(R.string.battery_app_usage)
- : mPrefContext.getString(R.string.battery_system_usage);
- } else {
- return isApp
- ? mPrefContext.getString(R.string.battery_app_usage_for, slotInformation)
- : mPrefContext.getString(R.string.battery_system_usage_for, slotInformation);
- }
- }
-
- @VisibleForTesting
- String getSlotInformation() {
- if (mDailyTimestampFullTexts == null || mDailyViewModel == null
- || mHourlyViewModels == null) {
- // No data
- return null;
- }
- if (isAllSelected()) {
- return null;
- }
-
- final String selectedDayText = mDailyTimestampFullTexts.get(mDailyChartIndex);
- if (mHourlyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL) {
- return selectedDayText;
- }
-
- final String fromHourText = mHourlyViewModels.get(mDailyChartIndex).texts().get(
- mHourlyChartIndex);
- final String toHourText = mHourlyViewModels.get(mDailyChartIndex).texts().get(
- mHourlyChartIndex + 1);
- final String selectedHourText =
- String.format("%s%s%s", fromHourText, mIs24HourFormat ? "-" : " - ", toHourText);
- if (isBatteryLevelDataInOneDay()) {
- return selectedHourText;
- }
-
- return String.format("%s %s", selectedDayText, selectedHourText);
- }
-
- @VisibleForTesting
- void setPreferenceSummary(
- PowerGaugePreference preference, BatteryDiffEntry entry) {
- final long foregroundUsageTimeInMs = entry.mForegroundUsageTimeInMs;
- final long backgroundUsageTimeInMs = entry.mBackgroundUsageTimeInMs;
- final long totalUsageTimeInMs = foregroundUsageTimeInMs + backgroundUsageTimeInMs;
- // Checks whether the package is allowed to show summary or not.
- if (!isValidToShowSummary(entry.getPackageName())) {
- preference.setSummary(null);
- return;
- }
- String usageTimeSummary = null;
- // Not shows summary for some system components without usage time.
- if (totalUsageTimeInMs == 0) {
- preference.setSummary(null);
- // Shows background summary only if we don't have foreground usage time.
- } else if (foregroundUsageTimeInMs == 0 && backgroundUsageTimeInMs != 0) {
- usageTimeSummary = buildUsageTimeInfo(backgroundUsageTimeInMs, true);
- // Shows total usage summary only if total usage time is small.
- } else if (totalUsageTimeInMs < DateUtils.MINUTE_IN_MILLIS) {
- usageTimeSummary = buildUsageTimeInfo(totalUsageTimeInMs, false);
- } else {
- usageTimeSummary = buildUsageTimeInfo(totalUsageTimeInMs, false);
- // Shows background usage time if it is larger than a minute.
- if (backgroundUsageTimeInMs > 0) {
- usageTimeSummary +=
- "\n" + buildUsageTimeInfo(backgroundUsageTimeInMs, true);
- }
- }
- preference.setSummary(usageTimeSummary);
- }
-
- private String buildUsageTimeInfo(long usageTimeInMs, boolean isBackground) {
- if (usageTimeInMs < DateUtils.MINUTE_IN_MILLIS) {
- return mPrefContext.getString(
- isBackground
- ? R.string.battery_usage_background_less_than_one_minute
- : R.string.battery_usage_total_less_than_one_minute);
- }
- final CharSequence timeSequence =
- StringUtil.formatElapsedTime(mPrefContext, usageTimeInMs,
- /*withSeconds=*/ false, /*collapseTimeUnit=*/ false);
- final int resourceId =
- isBackground
- ? R.string.battery_usage_for_background_time
- : R.string.battery_usage_for_total_time;
- return mPrefContext.getString(resourceId, timeSequence);
- }
-
- @VisibleForTesting
- boolean isValidToShowSummary(String packageName) {
- return !DataProcessor.contains(packageName, mNotAllowShowSummaryPackages);
- }
-
- private void addFooterPreferenceIfNeeded(boolean containAppItems) {
- if (mIsFooterPrefAdded || mFooterPreference == null) {
- return;
- }
- mIsFooterPrefAdded = true;
- mFooterPreference.setTitle(mPrefContext.getString(
- containAppItems
- ? R.string.battery_usage_screen_footer
- : R.string.battery_usage_screen_footer_empty));
- mHandler.post(() -> mPreferenceScreen.addPreference(mFooterPreference));
- }
-
- private boolean isBatteryLevelDataInOneDay() {
- return mHourlyViewModels != null && mHourlyViewModels.size() == 1;
- }
-
- private boolean isAllSelected() {
- return (isBatteryLevelDataInOneDay()
- || mDailyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL)
- && mHourlyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL;
- }
-
- private static List generateTimestampDayOfWeekTexts(@NonNull final Context context,
- @NonNull final List timestamps, final boolean isAbbreviation) {
- final ArrayList texts = new ArrayList<>();
- for (Long timestamp : timestamps) {
- texts.add(ConvertUtils.utcToLocalTimeDayOfWeek(context, timestamp, isAbbreviation));
- }
- return texts;
- }
-
- private static List generateTimestampHourTexts(
- @NonNull final Context context, @NonNull final List timestamps) {
- final boolean is24HourFormat = DateFormat.is24HourFormat(context);
- final ArrayList texts = new ArrayList<>();
- for (Long timestamp : timestamps) {
- texts.add(ConvertUtils.utcToLocalTimeHour(context, timestamp, is24HourFormat));
- }
- return texts;
- }
-
- /** Used for {@link AppBatteryPreferenceController}. */
- public static List getAppBatteryUsageData(Context context) {
- final long start = System.currentTimeMillis();
- final Map> batteryHistoryMap =
- FeatureFactory.getFactory(context)
- .getPowerUsageFeatureProvider(context)
- .getBatteryHistorySinceLastFullCharge(context);
- if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) {
- return null;
- }
- Log.d(TAG, String.format("getBatterySinceLastFullChargeUsageData() size=%d time=%d/ms",
- batteryHistoryMap.size(), (System.currentTimeMillis() - start)));
-
- final Map> batteryUsageData =
- DataProcessor.getBatteryUsageData(context, batteryHistoryMap);
- return batteryUsageData == null
- ? null
- : batteryUsageData
- .get(BatteryChartViewModel.SELECTED_INDEX_ALL)
- .get(BatteryChartViewModel.SELECTED_INDEX_ALL)
- .getAppDiffEntryList();
- }
-
- /** Used for {@link AppBatteryPreferenceController}. */
- public static BatteryDiffEntry getAppBatteryUsageData(
- Context context, String packageName, int userId) {
- if (packageName == null) {
- return null;
- }
- final List entries = getAppBatteryUsageData(context);
- if (entries == null) {
- return null;
- }
- for (BatteryDiffEntry entry : entries) {
- final BatteryHistEntry batteryHistEntry = entry.mBatteryHistEntry;
- if (batteryHistEntry != null
- && batteryHistEntry.mConsumerType == ConvertUtils.CONSUMER_TYPE_UID_BATTERY
- && batteryHistEntry.mUserId == userId
- && packageName.equals(entry.getPackageName())) {
- return entry;
- }
- }
- return null;
- }
-}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartView.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartView.java
index 427388befcd..ddfbbc200dd 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartView.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartView.java
@@ -18,6 +18,7 @@ package com.android.settings.fuelgauge.batteryusage;
import static com.android.settings.Utils.formatPercentage;
import static java.lang.Math.round;
+import static java.util.Objects.requireNonNull;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
@@ -29,8 +30,6 @@ import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.os.Handler;
-import android.text.format.DateFormat;
-import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.HapticFeedbackConstants;
@@ -39,6 +38,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;
@@ -46,7 +46,7 @@ import com.android.settings.R;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.Utils;
-import java.time.Clock;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
@@ -58,36 +58,26 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
private static final List ACCESSIBILITY_SERVICE_NAMES =
Arrays.asList("SwitchAccessService", "TalkBackService", "JustSpeakService");
- private static final int DEFAULT_TRAPEZOID_COUNT = 12;
- private static final int DEFAULT_TIMESTAMP_COUNT = 4;
- private static final int TIMESTAMP_GAPS_COUNT = DEFAULT_TIMESTAMP_COUNT - 1;
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 int mTrapezoidCount;
private float mTrapezoidVOffset;
private float mTrapezoidHOffset;
private boolean mIsSlotsClickabled;
private String[] mPercentages = getPercentages();
@VisibleForTesting
- int mHoveredIndex = SELECTED_INDEX_INVALID;
- @VisibleForTesting
- int mSelectedIndex = SELECTED_INDEX_INVALID;
- @VisibleForTesting
- String[] mTimestamps;
+ int mHoveredIndex = BatteryChartViewModel.SELECTED_INDEX_INVALID;
// Colors for drawing the trapezoid shape and dividers.
private int mTrapezoidColor;
@@ -98,25 +88,26 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
private final Rect mIndent = new Rect();
private final Rect[] mPercentageBounds =
new Rect[]{new Rect(), new Rect(), new Rect()};
- // For drawing the timestamp information.
- private final Rect[] mTimestampsBounds =
- new Rect[]{new Rect(), new Rect(), new Rect(), new Rect()};
+ // For drawing the axis label information.
+ private final List mAxisLabelsBounds = new ArrayList<>();
+
@VisibleForTesting
Handler mHandler = new Handler();
@VisibleForTesting
final Runnable mUpdateClickableStateRun = () -> updateClickableState();
- private int[] mLevels;
private Paint mTextPaint;
private Paint mDividerPaint;
private Paint mTrapezoidPaint;
@VisibleForTesting
Paint mTrapezoidCurvePaint = null;
- private TrapezoidSlot[] mTrapezoidSlots;
+ @VisibleForTesting
+ TrapezoidSlot[] mTrapezoidSlots;
// Records the location to calculate selected index.
- private float mTouchUpEventX = Float.MIN_VALUE;
+ @VisibleForTesting
+ float mTouchUpEventX = Float.MIN_VALUE;
private BatteryChartView.OnSelectListener mOnSelectListener;
public BatteryChartView(Context context) {
@@ -128,57 +119,25 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
initializeColors(context);
// Registers the click event listener.
setOnClickListener(this);
- setSelectedIndex(SELECTED_INDEX_ALL);
- setTrapezoidCount(DEFAULT_TRAPEZOID_COUNT);
setClickable(false);
- setLatestTimestamp(0);
+ requestLayout();
}
- /** Sets the total trapezoid count for drawing. */
- public void setTrapezoidCount(int trapezoidCount) {
- Log.i(TAG, "trapezoidCount:" + trapezoidCount);
- mTrapezoidCount = trapezoidCount;
- mTrapezoidSlots = new TrapezoidSlot[trapezoidCount];
- // Allocates the trapezoid slot array.
- for (int index = 0; index < trapezoidCount; index++) {
- mTrapezoidSlots[index] = new TrapezoidSlot();
- }
- invalidate();
- }
-
- /** Sets all levels value to draw the trapezoid shape */
- public void setLevels(int[] levels) {
- Log.d(TAG, "setLevels() " + (levels == null ? "null" : levels.length));
- if (levels == null) {
- mLevels = null;
- return;
- }
- // We should provide trapezoid count + 1 data to draw all trapezoids.
- mLevels = levels.length == mTrapezoidCount + 1 ? levels : null;
- setClickable(false);
- invalidate();
- if (mLevels == null) {
- return;
- }
- // 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;
+ /** Sets the data model of this view. */
+ public void setViewModel(BatteryChartViewModel viewModel) {
+ if (viewModel == null) {
+ mViewModel = null;
invalidate();
- // Callbacks to the listener if we have.
- if (mOnSelectListener != null) {
- mOnSelectListener.onSelect(mSelectedIndex);
- }
+ return;
}
+
+ Log.d(TAG, String.format("setViewModel(): size: %d, selectedIndex: %d.",
+ viewModel.size(), viewModel.selectedIndex()));
+ mViewModel = viewModel;
+ initializeAxisLabelsBounds();
+ initializeTrapezoidSlots(viewModel.size() - 1);
+ setClickable(hasAnyValidTrapezoid(viewModel));
+ requestLayout();
}
/** Sets the callback to monitor the selected group index. */
@@ -195,29 +154,6 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
} else {
mTextPaint = null;
}
- setVisibility(View.VISIBLE);
- requestLayout();
- }
-
- /** Sets the latest timestamp for drawing into x-axis information. */
- public void setLatestTimestamp(long latestTimestamp) {
- if (latestTimestamp == 0) {
- latestTimestamp = Clock.systemUTC().millis();
- }
- if (mTimestamps == null) {
- mTimestamps = new String[DEFAULT_TIMESTAMP_COUNT];
- }
- final long timeSlotOffset =
- DateUtils.HOUR_IN_MILLIS * (/*total 24 hours*/ 24 / TIMESTAMP_GAPS_COUNT);
- final boolean is24HourFormat = DateFormat.is24HourFormat(getContext());
- for (int index = 0; index < DEFAULT_TIMESTAMP_COUNT; index++) {
- mTimestamps[index] =
- ConvertUtils.utcToLocalTimeHour(
- getContext(),
- latestTimestamp - (TIMESTAMP_GAPS_COUNT - index)
- * timeSlotOffset,
- is24HourFormat);
- }
requestLayout();
}
@@ -226,6 +162,7 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Measures text bounds and updates indent configuration.
if (mTextPaint != null) {
+ mTextPaint.setTextAlign(Paint.Align.LEFT);
for (int index = 0; index < mPercentages.length; index++) {
mTextPaint.getTextBounds(
mPercentages[index], 0, mPercentages[index].length(),
@@ -235,15 +172,14 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
mIndent.top = mPercentageBounds[0].height();
mIndent.right = mPercentageBounds[0].width() + mTextPadding;
- if (mTimestamps != null) {
- int maxHeight = 0;
- for (int index = 0; index < DEFAULT_TIMESTAMP_COUNT; index++) {
- mTextPaint.getTextBounds(
- mTimestamps[index], 0, mTimestamps[index].length(),
- mTimestampsBounds[index]);
- maxHeight = Math.max(maxHeight, mTimestampsBounds[index].height());
+ if (mViewModel != null) {
+ int maxTop = 0;
+ for (int index = 0; index < mViewModel.size(); index++) {
+ final String text = mViewModel.texts().get(index);
+ mTextPaint.getTextBounds(text, 0, text.length(), mAxisLabelsBounds.get(index));
+ maxTop = Math.max(maxTop, -mAxisLabelsBounds.get(index).top);
}
- mIndent.bottom = maxHeight + round(mTextPadding * 1.5f);
+ mIndent.bottom = maxTop + round(mTextPadding * 2f);
}
Log.d(TAG, "setIndent:" + mPercentageBounds[0]);
} else {
@@ -254,7 +190,12 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
+ // Before mLevels initialized, the count of trapezoids is unknown. Only draws the
+ // horizontal percentages and dividers.
drawHorizontalDividers(canvas);
+ if (mViewModel == null) {
+ return;
+ }
drawVerticalDividers(canvas);
drawTrapezoids(canvas);
}
@@ -294,7 +235,7 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
public void onHoverChanged(boolean hovered) {
super.onHoverChanged(hovered);
if (!hovered) {
- mHoveredIndex = SELECTED_INDEX_INVALID; // reset
+ mHoveredIndex = BatteryChartViewModel.SELECTED_INDEX_INVALID; // reset
invalidate();
}
}
@@ -307,15 +248,15 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
}
final int trapezoidIndex = getTrapezoidIndex(mTouchUpEventX);
// Ignores the click event if the level is zero.
- if (trapezoidIndex == SELECTED_INDEX_INVALID
- || !isValidToDraw(trapezoidIndex)) {
+ if (trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_INVALID
+ || !isValidToDraw(mViewModel, trapezoidIndex)) {
return;
}
- // Selects all if users click the same trapezoid item two times.
- if (trapezoidIndex == mSelectedIndex) {
- setSelectedIndex(SELECTED_INDEX_ALL);
- } else {
- setSelectedIndex(trapezoidIndex);
+ if (mOnSelectListener != null) {
+ // Selects all if users click the same trapezoid item two times.
+ mOnSelectListener.onSelect(
+ trapezoidIndex == mViewModel.selectedIndex()
+ ? BatteryChartViewModel.SELECTED_INDEX_ALL : trapezoidIndex);
}
view.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
}
@@ -364,8 +305,8 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
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();
}
@@ -380,6 +321,13 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
super.setClickable(clickable);
}
+ private void initializeTrapezoidSlots(int count) {
+ mTrapezoidSlots = new TrapezoidSlot[count];
+ for (int index = 0; index < mTrapezoidSlots.length; index++) {
+ mTrapezoidSlots[index] = new TrapezoidSlot();
+ }
+ }
+
private void initializeColors(Context context) {
setBackgroundColor(Color.TRANSPARENT);
mTrapezoidSolidColor = Utils.getColorAccentDefaultColor(context);
@@ -434,10 +382,10 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
private void drawPercentage(Canvas canvas, int index, float offsetY) {
if (mTextPaint != null) {
+ mTextPaint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText(
mPercentages[index],
- getWidth() - mPercentageBounds[index].width()
- - mPercentageBounds[index].left,
+ getWidth(),
offsetY + mPercentageBounds[index].height() * .5f,
mTextPaint);
}
@@ -445,9 +393,9 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
private void drawVerticalDividers(Canvas canvas) {
final int width = getWidth() - mIndent.right;
- final int dividerCount = mTrapezoidCount + 1;
+ final int dividerCount = mTrapezoidSlots.length + 1;
final float dividerSpace = dividerCount * mDividerWidth;
- final float unitWidth = (width - dividerSpace) / (float) mTrapezoidCount;
+ final float unitWidth = (width - dividerSpace) / (float) mTrapezoidSlots.length;
final float bottomY = getHeight() - mIndent.bottom;
final float startY = bottomY - mDividerHeight;
final float trapezoidSlotOffset = mTrapezoidHOffset + mDividerWidth * .5f;
@@ -463,53 +411,119 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
}
startX = nextX;
}
- // Draws the timestamp slot information.
- if (mTimestamps != null) {
- final float[] xOffsets = new float[DEFAULT_TIMESTAMP_COUNT];
- final float baselineX = mDividerWidth * .5f;
- final float offsetX = mDividerWidth + unitWidth;
- final int slotBarOffset = (/*total 12 bars*/ 12) / TIMESTAMP_GAPS_COUNT;
- for (int index = 0; index < DEFAULT_TIMESTAMP_COUNT; index++) {
- xOffsets[index] = baselineX + index * offsetX * slotBarOffset;
+ // Draws the axis label slot information.
+ if (mViewModel != null) {
+ final float baselineY = getHeight() - mTextPadding * 1.5f;
+ Rect[] axisLabelDisplayAreas;
+ switch (mViewModel.axisLabelPosition()) {
+ case CENTER_OF_TRAPEZOIDS:
+ axisLabelDisplayAreas = getAxisLabelDisplayAreas(
+ /* size= */ mViewModel.size() - 1,
+ /* baselineX= */ mDividerWidth + unitWidth * .5f,
+ /* offsetX= */ mDividerWidth + unitWidth,
+ baselineY,
+ /* shiftFirstAndLast= */ false);
+ break;
+ case BETWEEN_TRAPEZOIDS:
+ default:
+ axisLabelDisplayAreas = getAxisLabelDisplayAreas(
+ /* size= */ mViewModel.size(),
+ /* baselineX= */ mDividerWidth * .5f,
+ /* offsetX= */ mDividerWidth + unitWidth,
+ baselineY,
+ /* shiftFirstAndLast= */ true);
+ break;
}
- drawTimestamp(canvas, xOffsets);
+ drawAxisLabels(canvas, axisLabelDisplayAreas, baselineY);
}
}
- private void drawTimestamp(Canvas canvas, float[] xOffsets) {
- // Draws the 1st timestamp info.
- canvas.drawText(
- mTimestamps[0],
- xOffsets[0] - mTimestampsBounds[0].left,
- getTimestampY(0), mTextPaint);
- final int latestIndex = DEFAULT_TIMESTAMP_COUNT - 1;
- // Draws the last timestamp info.
- canvas.drawText(
- mTimestamps[latestIndex],
- xOffsets[latestIndex] - mTimestampsBounds[latestIndex].width()
- - mTimestampsBounds[latestIndex].left,
- getTimestampY(latestIndex), mTextPaint);
- // Draws the rest of timestamp info since it is located in the center.
- for (int index = 1; index <= DEFAULT_TIMESTAMP_COUNT - 2; index++) {
- canvas.drawText(
- mTimestamps[index],
- xOffsets[index]
- - (mTimestampsBounds[index].width() - mTimestampsBounds[index].left)
- * .5f,
- getTimestampY(index), mTextPaint);
+ /** Gets all the axis label texts displaying area positions if they are shown. */
+ private Rect[] getAxisLabelDisplayAreas(final int size, final float baselineX,
+ final float offsetX, final float baselineY, final boolean shiftFirstAndLast) {
+ final Rect[] result = new Rect[size];
+ for (int index = 0; index < result.length; index++) {
+ final float width = mAxisLabelsBounds.get(index).width();
+ float middle = baselineX + index * offsetX;
+ if (shiftFirstAndLast) {
+ if (index == 0) {
+ middle += width * .5f;
+ }
+ if (index == size - 1) {
+ middle -= width * .5f;
+ }
+ }
+ final float left = middle - width * .5f;
+ final float right = left + width;
+ final float top = baselineY + mAxisLabelsBounds.get(index).top;
+ final float bottom = top + mAxisLabelsBounds.get(index).height();
+ result[index] = new Rect(round(left), round(top), round(right), round(bottom));
+ }
+ return result;
+ }
+ /**
+ * Pairly draws axis labels from left and right side to middle. If the pair of labels have
+ * any overlap, skips that pair of labels.
+ */
+ private void drawAxisLabels(Canvas canvas, final Rect[] displayAreas, final float baselineY) {
+ int forwardCheckLine = Integer.MIN_VALUE;
+ int backwardCheckLine = Integer.MAX_VALUE;
+ Rect middleDisplayArea = null;
+ for (int forwardIndex = 0, backwordIndex = displayAreas.length - 1;
+ forwardIndex <= backwordIndex; forwardIndex++, backwordIndex--) {
+ final Rect forwardDisplayArea = displayAreas[forwardIndex];
+ final Rect backwardDisplayArea = displayAreas[backwordIndex];
+ if (forwardDisplayArea.left < forwardCheckLine
+ || backwardDisplayArea.right > backwardCheckLine) {
+ // Overlapped at left or right, skip the pair of labels
+ continue;
+ }
+ if (middleDisplayArea != null && (
+ forwardDisplayArea.right + mTextPadding > middleDisplayArea.left
+ || backwardDisplayArea.left - mTextPadding < middleDisplayArea.right)) {
+ // Overlapped with the middle label.
+ continue;
+ }
+ if (forwardIndex != backwordIndex
+ && forwardDisplayArea.right + mTextPadding > backwardDisplayArea.left) {
+ // Overlapped in the middle, skip the pair of labels
+ continue;
+ }
+
+ drawAxisLabelText(canvas, forwardIndex, forwardDisplayArea, baselineY);
+ drawAxisLabelText(canvas, backwordIndex, backwardDisplayArea, baselineY);
+
+ forwardCheckLine = forwardDisplayArea.right + mTextPadding;
+ backwardCheckLine = backwardDisplayArea.left - mTextPadding;
+
+ // If the number of labels is odd, draw the middle label first
+ if (forwardIndex == 0 && backwordIndex % 2 == 0) {
+ final int middleIndex = backwordIndex / 2;
+ middleDisplayArea = displayAreas[middleIndex];
+ if (middleDisplayArea.left < forwardCheckLine
+ || middleDisplayArea.right > backwardCheckLine) {
+ // Overlapped at left or right, skip the pair of labels
+ continue;
+ }
+ drawAxisLabelText(canvas, middleIndex, middleDisplayArea, baselineY);
+ }
}
}
- private int getTimestampY(int index) {
- return getHeight() - mTimestampsBounds[index].height()
- + (mTimestampsBounds[index].height() + mTimestampsBounds[index].top)
- + round(mTextPadding * 1.5f);
+ private void drawAxisLabelText(
+ Canvas canvas, final int index, final Rect displayArea, final float baselineY) {
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+ canvas.drawText(
+ mViewModel.texts().get(index),
+ displayArea.centerX(),
+ baselineY,
+ mTextPaint);
}
private void drawTrapezoids(Canvas canvas) {
// Ignores invalid trapezoid data.
- if (mLevels == null) {
+ if (mViewModel == null) {
return;
}
final float trapezoidBottom =
@@ -520,9 +534,9 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
// Draws all trapezoid shapes into the canvas.
final Path trapezoidPath = new Path();
Path trapezoidCurvePath = null;
- for (int index = 0; index < mTrapezoidCount; index++) {
+ for (int index = 0; index < mTrapezoidSlots.length; index++) {
// Not draws the trapezoid for corner or not initialization cases.
- if (!isValidToDraw(index)) {
+ if (!isValidToDraw(mViewModel, index)) {
if (mTrapezoidCurvePaint != null && trapezoidCurvePath != null) {
canvas.drawPath(trapezoidCurvePath, mTrapezoidCurvePaint);
trapezoidCurvePath = null;
@@ -530,17 +544,18 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
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);
+ mIsSlotsClickabled && mHoveredIndex == index
+ && isValidToDraw(mViewModel, 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 - requireNonNull(mViewModel.levels().get(index)) * unitHeight);
+ final float rightTop = round(trapezoidBottom
+ - requireNonNull(mViewModel.levels().get(index + 1)) * unitHeight);
trapezoidPath.reset();
trapezoidPath.moveTo(mTrapezoidSlots[index].mLeft, trapezoidBottom);
trapezoidPath.lineTo(mTrapezoidSlots[index].mLeft, leftTop);
@@ -579,15 +594,37 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
return index;
}
}
- return SELECTED_INDEX_INVALID;
+ return BatteryChartViewModel.SELECTED_INDEX_INVALID;
}
- private boolean isValidToDraw(int trapezoidIndex) {
- return mLevels != null
+ private void initializeAxisLabelsBounds() {
+ mAxisLabelsBounds.clear();
+ for (int i = 0; i < mViewModel.size(); i++) {
+ mAxisLabelsBounds.add(new Rect());
+ }
+ }
+
+ private static boolean isTrapezoidValid(
+ @NonNull BatteryChartViewModel viewModel, int trapezoidIndex) {
+ return viewModel.levels().get(trapezoidIndex) != null
+ && viewModel.levels().get(trapezoidIndex + 1) != null;
+ }
+
+ private static boolean isValidToDraw(BatteryChartViewModel viewModel, int trapezoidIndex) {
+ return viewModel != null
&& trapezoidIndex >= 0
- && trapezoidIndex < mLevels.length - 1
- && mLevels[trapezoidIndex] != 0
- && mLevels[trapezoidIndex + 1] != 0;
+ && trapezoidIndex < viewModel.size() - 1
+ && isTrapezoidValid(viewModel, trapezoidIndex);
+ }
+
+ private static boolean hasAnyValidTrapezoid(@NonNull BatteryChartViewModel viewModel) {
+ // Sets the chart is clickable if there is at least one valid item in it.
+ for (int trapezoidIndex = 0; trapezoidIndex < viewModel.size() - 1; trapezoidIndex++) {
+ if (isTrapezoidValid(viewModel, trapezoidIndex)) {
+ return true;
+ }
+ }
+ return false;
}
private static String[] getPercentages() {
@@ -621,7 +658,8 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
}
// A container class for each trapezoid left and right location.
- private static final class TrapezoidSlot {
+ @VisibleForTesting
+ static final class TrapezoidSlot {
public float mLeft;
public float mRight;
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewModel.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewModel.java
index 82a41c4a26e..ac01bfd645b 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewModel.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewModel.java
@@ -23,7 +23,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Objects;
-/** The view model of {@code BatteryChartViewV2} */
+/** The view model of {@code BatteryChartView} */
class BatteryChartViewModel {
private static final String TAG = "BatteryChartViewModel";
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2.java
deleted file mode 100644
index 64f650603e8..00000000000
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2.java
+++ /dev/null
@@ -1,671 +0,0 @@
-/*
- * 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 static com.android.settings.Utils.formatPercentage;
-
-import static java.lang.Math.round;
-import static java.util.Objects.requireNonNull;
-
-import android.accessibilityservice.AccessibilityServiceInfo;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.CornerPathEffect;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.HapticFeedbackConstants;
-import android.view.MotionEvent;
-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;
-
-import com.android.settings.R;
-import com.android.settings.overlay.FeatureFactory;
-import com.android.settingslib.Utils;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
-
-/** A widget component to draw chart graph. */
-public class BatteryChartViewV2 extends AppCompatImageView implements View.OnClickListener,
- AccessibilityManager.AccessibilityStateChangeListener {
- private static final String TAG = "BatteryChartViewV2";
- private static final List ACCESSIBILITY_SERVICE_NAMES =
- Arrays.asList("SwitchAccessService", "TalkBackService", "JustSpeakService");
-
- private static final int DIVIDER_COLOR = Color.parseColor("#CDCCC5");
- private static final long UPDATE_STATE_DELAYED_TIME = 500L;
-
- /** 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;
- private float mTrapezoidHOffset;
- private boolean mIsSlotsClickabled;
- private String[] mPercentages = getPercentages();
-
- @VisibleForTesting
- int mHoveredIndex = BatteryChartViewModel.SELECTED_INDEX_INVALID;
-
- // Colors for drawing the trapezoid shape and dividers.
- private int mTrapezoidColor;
- private int mTrapezoidSolidColor;
- private int mTrapezoidHoverColor;
- // For drawing the percentage information.
- private int mTextPadding;
- private final Rect mIndent = new Rect();
- private final Rect[] mPercentageBounds =
- new Rect[]{new Rect(), new Rect(), new Rect()};
- // For drawing the axis label information.
- private final List mAxisLabelsBounds = new ArrayList<>();
-
-
- @VisibleForTesting
- Handler mHandler = new Handler();
- @VisibleForTesting
- final Runnable mUpdateClickableStateRun = () -> updateClickableState();
-
- private Paint mTextPaint;
- private Paint mDividerPaint;
- private Paint mTrapezoidPaint;
-
- @VisibleForTesting
- Paint mTrapezoidCurvePaint = null;
- @VisibleForTesting
- TrapezoidSlot[] mTrapezoidSlots;
- // Records the location to calculate selected index.
- @VisibleForTesting
- float mTouchUpEventX = Float.MIN_VALUE;
- private BatteryChartViewV2.OnSelectListener mOnSelectListener;
-
- public BatteryChartViewV2(Context context) {
- super(context, null);
- }
-
- public BatteryChartViewV2(Context context, AttributeSet attrs) {
- super(context, attrs);
- initializeColors(context);
- // Registers the click event listener.
- setOnClickListener(this);
- setClickable(false);
- requestLayout();
- }
-
- /** Sets the data model of this view. */
- public void setViewModel(BatteryChartViewModel viewModel) {
- if (viewModel == null) {
- mViewModel = null;
- invalidate();
- return;
- }
-
- Log.d(TAG, String.format("setViewModel(): size: %d, selectedIndex: %d.",
- viewModel.size(), viewModel.selectedIndex()));
- mViewModel = viewModel;
- initializeAxisLabelsBounds();
- initializeTrapezoidSlots(viewModel.size() - 1);
- setClickable(hasAnyValidTrapezoid(viewModel));
- requestLayout();
- }
-
- /** Sets the callback to monitor the selected group index. */
- public void setOnSelectListener(BatteryChartViewV2.OnSelectListener listener) {
- mOnSelectListener = listener;
- }
-
- /** Sets the companion {@link TextView} for percentage information. */
- public void setCompanionTextView(TextView textView) {
- if (textView != null) {
- // Pre-draws the view first to load style atttributions into paint.
- textView.draw(new Canvas());
- mTextPaint = textView.getPaint();
- } else {
- mTextPaint = null;
- }
- requestLayout();
- }
-
- @Override
- public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- // Measures text bounds and updates indent configuration.
- if (mTextPaint != null) {
- mTextPaint.setTextAlign(Paint.Align.LEFT);
- for (int index = 0; index < mPercentages.length; index++) {
- mTextPaint.getTextBounds(
- mPercentages[index], 0, mPercentages[index].length(),
- mPercentageBounds[index]);
- }
- // Updates the indent configurations.
- mIndent.top = mPercentageBounds[0].height();
- mIndent.right = mPercentageBounds[0].width() + mTextPadding;
-
- if (mViewModel != null) {
- int maxTop = 0;
- for (int index = 0; index < mViewModel.size(); index++) {
- final String text = mViewModel.texts().get(index);
- mTextPaint.getTextBounds(text, 0, text.length(), mAxisLabelsBounds.get(index));
- maxTop = Math.max(maxTop, -mAxisLabelsBounds.get(index).top);
- }
- mIndent.bottom = maxTop + round(mTextPadding * 2f);
- }
- Log.d(TAG, "setIndent:" + mPercentageBounds[0]);
- } else {
- mIndent.set(0, 0, 0, 0);
- }
- }
-
- @Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
- // Before mLevels initialized, the count of trapezoids is unknown. Only draws the
- // horizontal percentages and dividers.
- drawHorizontalDividers(canvas);
- if (mViewModel == null) {
- return;
- }
- drawVerticalDividers(canvas);
- drawTrapezoids(canvas);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- // Caches the location to calculate selected trapezoid index.
- final int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_UP:
- mTouchUpEventX = event.getX();
- break;
- case MotionEvent.ACTION_CANCEL:
- mTouchUpEventX = Float.MIN_VALUE; // reset
- break;
- }
- return super.onTouchEvent(event);
- }
-
- @Override
- public boolean onHoverEvent(MotionEvent event) {
- final int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_HOVER_ENTER:
- case MotionEvent.ACTION_HOVER_MOVE:
- final int trapezoidIndex = getTrapezoidIndex(event.getX());
- if (mHoveredIndex != trapezoidIndex) {
- mHoveredIndex = trapezoidIndex;
- invalidate();
- }
- break;
- }
- return super.onHoverEvent(event);
- }
-
- @Override
- public void onHoverChanged(boolean hovered) {
- super.onHoverChanged(hovered);
- if (!hovered) {
- mHoveredIndex = BatteryChartViewModel.SELECTED_INDEX_INVALID; // reset
- invalidate();
- }
- }
-
- @Override
- public void onClick(View view) {
- if (mTouchUpEventX == Float.MIN_VALUE) {
- Log.w(TAG, "invalid motion event for onClick() callback");
- return;
- }
- final int trapezoidIndex = getTrapezoidIndex(mTouchUpEventX);
- // Ignores the click event if the level is zero.
- if (trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_INVALID
- || !isValidToDraw(mViewModel, trapezoidIndex)) {
- return;
- }
- if (mOnSelectListener != null) {
- // Selects all if users click the same trapezoid item two times.
- mOnSelectListener.onSelect(
- trapezoidIndex == mViewModel.selectedIndex()
- ? BatteryChartViewModel.SELECTED_INDEX_ALL : trapezoidIndex);
- }
- view.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
- }
-
- @Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- updateClickableState();
- mContext.getSystemService(AccessibilityManager.class)
- .addAccessibilityStateChangeListener(/*listener=*/ this);
- }
-
- @Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- mContext.getSystemService(AccessibilityManager.class)
- .removeAccessibilityStateChangeListener(/*listener=*/ this);
- mHandler.removeCallbacks(mUpdateClickableStateRun);
- }
-
- @Override
- public void onAccessibilityStateChanged(boolean enabled) {
- Log.d(TAG, "onAccessibilityStateChanged:" + enabled);
- mHandler.removeCallbacks(mUpdateClickableStateRun);
- // We should delay it a while since accessibility manager will spend
- // some times to bind with new enabled accessibility services.
- mHandler.postDelayed(
- mUpdateClickableStateRun, UPDATE_STATE_DELAYED_TIME);
- }
-
- private void updateClickableState() {
- final Context context = mContext;
- mIsSlotsClickabled =
- FeatureFactory.getFactory(context)
- .getPowerUsageFeatureProvider(context)
- .isChartGraphSlotsEnabled(context)
- && !isAccessibilityEnabled(context);
- Log.d(TAG, "isChartGraphSlotsEnabled:" + mIsSlotsClickabled);
- setClickable(isClickable());
- // Initializes the trapezoid curve paint for non-clickable case.
- if (!mIsSlotsClickabled && mTrapezoidCurvePaint == null) {
- mTrapezoidCurvePaint = new Paint();
- mTrapezoidCurvePaint.setAntiAlias(true);
- mTrapezoidCurvePaint.setColor(mTrapezoidSolidColor);
- mTrapezoidCurvePaint.setStyle(Paint.Style.STROKE);
- mTrapezoidCurvePaint.setStrokeWidth(mDividerWidth * 2);
- } else if (mIsSlotsClickabled) {
- mTrapezoidCurvePaint = null;
- // Sets view model again to force update the click state.
- setViewModel(mViewModel);
- }
- invalidate();
- }
-
- @Override
- public void setClickable(boolean clickable) {
- super.setClickable(mIsSlotsClickabled && clickable);
- }
-
- @VisibleForTesting
- void setClickableForce(boolean 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();
- }
- }
-
- private void initializeColors(Context context) {
- setBackgroundColor(Color.TRANSPARENT);
- mTrapezoidSolidColor = Utils.getColorAccentDefaultColor(context);
- mTrapezoidColor = Utils.getDisabled(context, mTrapezoidSolidColor);
- mTrapezoidHoverColor = Utils.getColorAttrDefaultColor(context,
- com.android.internal.R.attr.colorAccentSecondaryVariant);
- // Initializes the divider line paint.
- final Resources resources = getContext().getResources();
- mDividerWidth = resources.getDimensionPixelSize(R.dimen.chartview_divider_width);
- mDividerHeight = resources.getDimensionPixelSize(R.dimen.chartview_divider_height);
- mDividerPaint = new Paint();
- mDividerPaint.setAntiAlias(true);
- mDividerPaint.setColor(DIVIDER_COLOR);
- mDividerPaint.setStyle(Paint.Style.STROKE);
- mDividerPaint.setStrokeWidth(mDividerWidth);
- Log.i(TAG, "mDividerWidth:" + mDividerWidth);
- Log.i(TAG, "mDividerHeight:" + mDividerHeight);
- // Initializes the trapezoid paint.
- mTrapezoidHOffset = resources.getDimension(R.dimen.chartview_trapezoid_margin_start);
- mTrapezoidVOffset = resources.getDimension(R.dimen.chartview_trapezoid_margin_bottom);
- mTrapezoidPaint = new Paint();
- mTrapezoidPaint.setAntiAlias(true);
- mTrapezoidPaint.setColor(mTrapezoidSolidColor);
- mTrapezoidPaint.setStyle(Paint.Style.FILL);
- mTrapezoidPaint.setPathEffect(
- new CornerPathEffect(
- resources.getDimensionPixelSize(R.dimen.chartview_trapezoid_radius)));
- // Initializes for drawing text information.
- mTextPadding = resources.getDimensionPixelSize(R.dimen.chartview_text_padding);
- }
-
- private void drawHorizontalDividers(Canvas canvas) {
- final int width = getWidth() - mIndent.right;
- final int height = getHeight() - mIndent.top - mIndent.bottom;
- // Draws the top divider line for 100% curve.
- float offsetY = mIndent.top + mDividerWidth * .5f;
- canvas.drawLine(0, offsetY, width, offsetY, mDividerPaint);
- drawPercentage(canvas, /*index=*/ 0, offsetY);
-
- // Draws the center divider line for 50% curve.
- final float availableSpace =
- height - mDividerWidth * 2 - mTrapezoidVOffset - mDividerHeight;
- offsetY = mIndent.top + mDividerWidth + availableSpace * .5f;
- canvas.drawLine(0, offsetY, width, offsetY, mDividerPaint);
- drawPercentage(canvas, /*index=*/ 1, offsetY);
-
- // Draws the bottom divider line for 0% curve.
- offsetY = mIndent.top + (height - mDividerHeight - mDividerWidth * .5f);
- canvas.drawLine(0, offsetY, width, offsetY, mDividerPaint);
- drawPercentage(canvas, /*index=*/ 2, offsetY);
- }
-
- private void drawPercentage(Canvas canvas, int index, float offsetY) {
- if (mTextPaint != null) {
- mTextPaint.setTextAlign(Paint.Align.RIGHT);
- canvas.drawText(
- mPercentages[index],
- getWidth(),
- offsetY + mPercentageBounds[index].height() * .5f,
- mTextPaint);
- }
- }
-
- private void drawVerticalDividers(Canvas canvas) {
- final int width = getWidth() - mIndent.right;
- final int dividerCount = mTrapezoidSlots.length + 1;
- final float dividerSpace = dividerCount * mDividerWidth;
- final float unitWidth = (width - dividerSpace) / (float) mTrapezoidSlots.length;
- final float bottomY = getHeight() - mIndent.bottom;
- final float startY = bottomY - mDividerHeight;
- final float trapezoidSlotOffset = mTrapezoidHOffset + mDividerWidth * .5f;
- // Draws each vertical dividers.
- float startX = mDividerWidth * .5f;
- for (int index = 0; index < dividerCount; index++) {
- canvas.drawLine(startX, startY, startX, bottomY, mDividerPaint);
- final float nextX = startX + mDividerWidth + unitWidth;
- // Updates the trapezoid slots for drawing.
- if (index < mTrapezoidSlots.length) {
- mTrapezoidSlots[index].mLeft = round(startX + trapezoidSlotOffset);
- mTrapezoidSlots[index].mRight = round(nextX - trapezoidSlotOffset);
- }
- startX = nextX;
- }
- // Draws the axis label slot information.
- if (mViewModel != null) {
- final float baselineY = getHeight() - mTextPadding * 1.5f;
- Rect[] axisLabelDisplayAreas;
- switch (mViewModel.axisLabelPosition()) {
- case CENTER_OF_TRAPEZOIDS:
- axisLabelDisplayAreas = getAxisLabelDisplayAreas(
- /* size= */ mViewModel.size() - 1,
- /* baselineX= */ mDividerWidth + unitWidth * .5f,
- /* offsetX= */ mDividerWidth + unitWidth,
- baselineY,
- /* shiftFirstAndLast= */ false);
- break;
- case BETWEEN_TRAPEZOIDS:
- default:
- axisLabelDisplayAreas = getAxisLabelDisplayAreas(
- /* size= */ mViewModel.size(),
- /* baselineX= */ mDividerWidth * .5f,
- /* offsetX= */ mDividerWidth + unitWidth,
- baselineY,
- /* shiftFirstAndLast= */ true);
- break;
- }
- drawAxisLabels(canvas, axisLabelDisplayAreas, baselineY);
- }
- }
-
- /** Gets all the axis label texts displaying area positions if they are shown. */
- private Rect[] getAxisLabelDisplayAreas(final int size, final float baselineX,
- final float offsetX, final float baselineY, final boolean shiftFirstAndLast) {
- final Rect[] result = new Rect[size];
- for (int index = 0; index < result.length; index++) {
- final float width = mAxisLabelsBounds.get(index).width();
- float middle = baselineX + index * offsetX;
- if (shiftFirstAndLast) {
- if (index == 0) {
- middle += width * .5f;
- }
- if (index == size - 1) {
- middle -= width * .5f;
- }
- }
- final float left = middle - width * .5f;
- final float right = left + width;
- final float top = baselineY + mAxisLabelsBounds.get(index).top;
- final float bottom = top + mAxisLabelsBounds.get(index).height();
- result[index] = new Rect(round(left), round(top), round(right), round(bottom));
- }
- return result;
- }
-
- /**
- * Pairly draws axis labels from left and right side to middle. If the pair of labels have
- * any overlap, skips that pair of labels.
- */
- private void drawAxisLabels(Canvas canvas, final Rect[] displayAreas, final float baselineY) {
- int forwardCheckLine = Integer.MIN_VALUE;
- int backwardCheckLine = Integer.MAX_VALUE;
- Rect middleDisplayArea = null;
- for (int forwardIndex = 0, backwordIndex = displayAreas.length - 1;
- forwardIndex <= backwordIndex; forwardIndex++, backwordIndex--) {
- final Rect forwardDisplayArea = displayAreas[forwardIndex];
- final Rect backwardDisplayArea = displayAreas[backwordIndex];
- if (forwardDisplayArea.left < forwardCheckLine
- || backwardDisplayArea.right > backwardCheckLine) {
- // Overlapped at left or right, skip the pair of labels
- continue;
- }
- if (middleDisplayArea != null && (
- forwardDisplayArea.right + mTextPadding > middleDisplayArea.left
- || backwardDisplayArea.left - mTextPadding < middleDisplayArea.right)) {
- // Overlapped with the middle label.
- continue;
- }
- if (forwardIndex != backwordIndex
- && forwardDisplayArea.right + mTextPadding > backwardDisplayArea.left) {
- // Overlapped in the middle, skip the pair of labels
- continue;
- }
-
- drawAxisLabelText(canvas, forwardIndex, forwardDisplayArea, baselineY);
- drawAxisLabelText(canvas, backwordIndex, backwardDisplayArea, baselineY);
-
- forwardCheckLine = forwardDisplayArea.right + mTextPadding;
- backwardCheckLine = backwardDisplayArea.left - mTextPadding;
-
- // If the number of labels is odd, draw the middle label first
- if (forwardIndex == 0 && backwordIndex % 2 == 0) {
- final int middleIndex = backwordIndex / 2;
- middleDisplayArea = displayAreas[middleIndex];
- if (middleDisplayArea.left < forwardCheckLine
- || middleDisplayArea.right > backwardCheckLine) {
- // Overlapped at left or right, skip the pair of labels
- continue;
- }
- drawAxisLabelText(canvas, middleIndex, middleDisplayArea, baselineY);
- }
- }
- }
-
- private void drawAxisLabelText(
- Canvas canvas, final int index, final Rect displayArea, final float baselineY) {
- mTextPaint.setTextAlign(Paint.Align.CENTER);
- canvas.drawText(
- mViewModel.texts().get(index),
- displayArea.centerX(),
- baselineY,
- mTextPaint);
- }
-
- private void drawTrapezoids(Canvas canvas) {
- // Ignores invalid trapezoid data.
- if (mViewModel == null) {
- return;
- }
- final float trapezoidBottom =
- getHeight() - mIndent.bottom - mDividerHeight - mDividerWidth
- - mTrapezoidVOffset;
- final float availableSpace = trapezoidBottom - mDividerWidth * .5f - mIndent.top;
- final float unitHeight = availableSpace / 100f;
- // Draws all trapezoid shapes into the canvas.
- final Path trapezoidPath = new Path();
- Path trapezoidCurvePath = null;
- for (int index = 0; index < mTrapezoidSlots.length; index++) {
- // Not draws the trapezoid for corner or not initialization cases.
- if (!isValidToDraw(mViewModel, index)) {
- if (mTrapezoidCurvePaint != null && trapezoidCurvePath != null) {
- canvas.drawPath(trapezoidCurvePath, mTrapezoidCurvePaint);
- trapezoidCurvePath = null;
- }
- continue;
- }
- // Configures the trapezoid paint color.
- final int trapezoidColor = mIsSlotsClickabled && (mViewModel.selectedIndex() == index
- || mViewModel.selectedIndex() == BatteryChartViewModel.SELECTED_INDEX_ALL)
- ? mTrapezoidSolidColor : mTrapezoidColor;
- final boolean isHoverState =
- mIsSlotsClickabled && mHoveredIndex == index
- && isValidToDraw(mViewModel, mHoveredIndex);
- mTrapezoidPaint.setColor(isHoverState ? mTrapezoidHoverColor : trapezoidColor);
-
- final float leftTop = round(
- trapezoidBottom - requireNonNull(mViewModel.levels().get(index)) * unitHeight);
- final float rightTop = round(trapezoidBottom
- - requireNonNull(mViewModel.levels().get(index + 1)) * unitHeight);
- trapezoidPath.reset();
- trapezoidPath.moveTo(mTrapezoidSlots[index].mLeft, trapezoidBottom);
- trapezoidPath.lineTo(mTrapezoidSlots[index].mLeft, leftTop);
- trapezoidPath.lineTo(mTrapezoidSlots[index].mRight, rightTop);
- trapezoidPath.lineTo(mTrapezoidSlots[index].mRight, trapezoidBottom);
- // A tricky way to make the trapezoid shape drawing the rounded corner.
- trapezoidPath.lineTo(mTrapezoidSlots[index].mLeft, trapezoidBottom);
- trapezoidPath.lineTo(mTrapezoidSlots[index].mLeft, leftTop);
- // Draws the trapezoid shape into canvas.
- canvas.drawPath(trapezoidPath, mTrapezoidPaint);
-
- // Generates path for non-clickable trapezoid curve.
- if (mTrapezoidCurvePaint != null) {
- if (trapezoidCurvePath == null) {
- trapezoidCurvePath = new Path();
- trapezoidCurvePath.moveTo(mTrapezoidSlots[index].mLeft, leftTop);
- } else {
- trapezoidCurvePath.lineTo(mTrapezoidSlots[index].mLeft, leftTop);
- }
- trapezoidCurvePath.lineTo(mTrapezoidSlots[index].mRight, rightTop);
- }
- }
- // Draws the trapezoid curve for non-clickable case.
- if (mTrapezoidCurvePaint != null && trapezoidCurvePath != null) {
- canvas.drawPath(trapezoidCurvePath, mTrapezoidCurvePaint);
- trapezoidCurvePath = null;
- }
- }
-
- // Searches the corresponding trapezoid index from x location.
- private int getTrapezoidIndex(float x) {
- for (int index = 0; index < mTrapezoidSlots.length; index++) {
- final TrapezoidSlot slot = mTrapezoidSlots[index];
- if (x >= slot.mLeft - mTrapezoidHOffset
- && x <= slot.mRight + mTrapezoidHOffset) {
- return index;
- }
- }
- return BatteryChartViewModel.SELECTED_INDEX_INVALID;
- }
-
- private void initializeAxisLabelsBounds() {
- mAxisLabelsBounds.clear();
- for (int i = 0; i < mViewModel.size(); i++) {
- mAxisLabelsBounds.add(new Rect());
- }
- }
-
- private static boolean isTrapezoidValid(
- @NonNull BatteryChartViewModel viewModel, int trapezoidIndex) {
- return viewModel.levels().get(trapezoidIndex) != null
- && viewModel.levels().get(trapezoidIndex + 1) != null;
- }
-
- private static boolean isValidToDraw(BatteryChartViewModel viewModel, int trapezoidIndex) {
- return viewModel != null
- && trapezoidIndex >= 0
- && trapezoidIndex < viewModel.size() - 1
- && isTrapezoidValid(viewModel, trapezoidIndex);
- }
-
- private static boolean hasAnyValidTrapezoid(@NonNull BatteryChartViewModel viewModel) {
- // Sets the chart is clickable if there is at least one valid item in it.
- for (int trapezoidIndex = 0; trapezoidIndex < viewModel.size() - 1; trapezoidIndex++) {
- if (isTrapezoidValid(viewModel, trapezoidIndex)) {
- return true;
- }
- }
- return false;
- }
-
- private static String[] getPercentages() {
- return new String[]{
- formatPercentage(/*percentage=*/ 100, /*round=*/ true),
- formatPercentage(/*percentage=*/ 50, /*round=*/ true),
- formatPercentage(/*percentage=*/ 0, /*round=*/ true)};
- }
-
- @VisibleForTesting
- static boolean isAccessibilityEnabled(Context context) {
- final AccessibilityManager accessibilityManager =
- context.getSystemService(AccessibilityManager.class);
- if (!accessibilityManager.isEnabled()) {
- return false;
- }
- final List serviceInfoList =
- accessibilityManager.getEnabledAccessibilityServiceList(
- AccessibilityServiceInfo.FEEDBACK_SPOKEN
- | AccessibilityServiceInfo.FEEDBACK_GENERIC);
- for (AccessibilityServiceInfo info : serviceInfoList) {
- for (String serviceName : ACCESSIBILITY_SERVICE_NAMES) {
- final String serviceId = info.getId();
- if (serviceId != null && serviceId.contains(serviceName)) {
- Log.d(TAG, "acccessibilityEnabled:" + serviceId);
- return true;
- }
- }
- }
- return false;
- }
-
- // A container class for each trapezoid left and right location.
- @VisibleForTesting
- static final class TrapezoidSlot {
- public float mLeft;
- public float mRight;
-
- @Override
- public String toString() {
- return String.format(Locale.US, "TrapezoidSlot[%f,%f]", mLeft, mRight);
- }
- }
-}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryLoader.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryLoader.java
index 34606a5a583..83b26150d39 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryLoader.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryLoader.java
@@ -43,6 +43,6 @@ public class BatteryHistoryLoader
public Map> loadInBackground() {
final PowerUsageFeatureProvider powerUsageFeatureProvider =
FeatureFactory.getFactory(mContext).getPowerUsageFeatureProvider(mContext);
- return powerUsageFeatureProvider.getBatteryHistory(mContext);
+ return powerUsageFeatureProvider.getBatteryHistorySinceLastFullCharge(mContext);
}
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryPreference.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryPreference.java
index e125d17d6a3..71fd26ce95c 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryPreference.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryPreference.java
@@ -49,7 +49,8 @@ public class BatteryHistoryPreference extends Preference {
private TextView mSummaryView;
private CharSequence mSummaryContent;
- private BatteryChartView mBatteryChartView;
+ private BatteryChartView mDailyChartView;
+ private BatteryChartView mHourlyChartView;
private BatteryChartPreferenceController mChartPreferenceController;
public BatteryHistoryPreference(Context context, AttributeSet attrs) {
@@ -92,8 +93,8 @@ public class BatteryHistoryPreference extends Preference {
void setChartPreferenceController(BatteryChartPreferenceController controller) {
mChartPreferenceController = controller;
- if (mBatteryChartView != null) {
- mChartPreferenceController.setBatteryChartView(mBatteryChartView);
+ if (mDailyChartView != null && mHourlyChartView != null) {
+ mChartPreferenceController.setBatteryChartView(mDailyChartView, mHourlyChartView);
}
}
@@ -105,11 +106,14 @@ public class BatteryHistoryPreference extends Preference {
return;
}
if (mIsChartGraphEnabled) {
- mBatteryChartView = (BatteryChartView) view.findViewById(R.id.battery_chart);
- mBatteryChartView.setCompanionTextView(
+ mDailyChartView = (BatteryChartView) view.findViewById(R.id.daily_battery_chart);
+ mDailyChartView.setCompanionTextView(
+ (TextView) view.findViewById(R.id.companion_text));
+ mHourlyChartView = (BatteryChartView) view.findViewById(R.id.hourly_battery_chart);
+ mHourlyChartView.setCompanionTextView(
(TextView) view.findViewById(R.id.companion_text));
if (mChartPreferenceController != null) {
- mChartPreferenceController.setBatteryChartView(mBatteryChartView);
+ mChartPreferenceController.setBatteryChartView(mDailyChartView, mHourlyChartView);
}
} else {
final TextView chargeView = (TextView) view.findViewById(R.id.charge);
diff --git a/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java b/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
index 8d2013ce793..f04658d83a4 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
@@ -276,7 +276,7 @@ public final class ConvertUtils {
diffEntry.setTotalConsumePower(totalConsumePower);
}
}
- insert24HoursData(BatteryChartView.SELECTED_INDEX_ALL, resultMap);
+ insert24HoursData(BatteryChartViewModel.SELECTED_INDEX_ALL, resultMap);
resolveMultiUsersData(context, resultMap);
if (purgeLowPercentageAndFakeData) {
purgeLowPercentageAndFakeData(context, resultMap);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
index 4a28e64693e..016287e2f87 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
@@ -19,9 +19,10 @@ package com.android.settings.fuelgauge.batteryusage;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -33,6 +34,8 @@ import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.LocaleList;
import android.text.format.DateUtils;
+import android.view.View;
+import android.widget.LinearLayout;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
@@ -56,15 +59,15 @@ 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;
@RunWith(RobolectricTestRunner.class)
public final class BatteryChartPreferenceControllerTest {
private static final String PREF_KEY = "pref_key";
private static final String PREF_SUMMARY = "fake preference summary";
- private static final int DESIRED_HISTORY_SIZE =
- BatteryChartPreferenceController.DESIRED_HISTORY_SIZE;
@Mock
private InstrumentedPreferenceFragment mFragment;
@@ -77,11 +80,15 @@ public final class BatteryChartPreferenceControllerTest {
@Mock
private BatteryHistEntry mBatteryHistEntry;
@Mock
- private BatteryChartView mBatteryChartView;
+ private BatteryChartView mDailyChartView;
+ @Mock
+ private BatteryChartView mHourlyChartView;
@Mock
private PowerGaugePreference mPowerGaugePreference;
@Mock
private BatteryUtils mBatteryUtils;
+ @Mock
+ private LinearLayout.LayoutParams mLayoutParams;
private Context mContext;
private FakeFeatureFactory mFeatureFactory;
@@ -94,6 +101,7 @@ public final class BatteryChartPreferenceControllerTest {
MockitoAnnotations.initMocks(this);
Locale.setDefault(new Locale("en_US"));
org.robolectric.shadows.ShadowSettings.set24HourTimeFormat(false);
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
mFeatureFactory = FakeFeatureFactory.setupForTest();
mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
mContext = spy(RuntimeEnvironment.application);
@@ -106,10 +114,12 @@ public final class BatteryChartPreferenceControllerTest {
doReturn(new String[]{"com.android.gms.persistent"})
.when(mFeatureFactory.powerUsageFeatureProvider)
.getHideApplicationEntries(mContext);
+ doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
mBatteryChartPreferenceController = createController();
mBatteryChartPreferenceController.mPrefContext = mContext;
mBatteryChartPreferenceController.mAppListPrefGroup = mAppListGroup;
- mBatteryChartPreferenceController.mBatteryChartView = mBatteryChartView;
+ mBatteryChartPreferenceController.mDailyChartView = mDailyChartView;
+ mBatteryChartPreferenceController.mHourlyChartView = mHourlyChartView;
mBatteryDiffEntry = new BatteryDiffEntry(
mContext,
/*foregroundUsageTimeInMs=*/ 1,
@@ -121,12 +131,10 @@ public final class BatteryChartPreferenceControllerTest {
BatteryDiffEntry.sResourceCache.put(
"fakeBatteryDiffEntryKey",
new BatteryEntry.NameAndIcon("fakeName", /*icon=*/ null, /*iconId=*/ 1));
- mBatteryChartPreferenceController.setBatteryHistoryMap(
- createBatteryHistoryMap());
}
@Test
- public void testOnDestroy_activityIsChanging_clearBatteryEntryCache() {
+ public void onDestroy_activityIsChanging_clearBatteryEntryCache() {
doReturn(true).when(mSettingsActivity).isChangingConfigurations();
// Ensures the testing environment is correct.
assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
@@ -136,7 +144,7 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testOnDestroy_activityIsNotChanging_notClearBatteryEntryCache() {
+ public void onDestroy_activityIsNotChanging_notClearBatteryEntryCache() {
doReturn(false).when(mSettingsActivity).isChangingConfigurations();
// Ensures the testing environment is correct.
assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
@@ -146,7 +154,7 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testOnDestroy_clearPreferenceCache() {
+ public void onDestroy_clearPreferenceCache() {
// Ensures the testing environment is correct.
mBatteryChartPreferenceController.mPreferenceCache.put(
PREF_KEY, mPowerGaugePreference);
@@ -158,113 +166,135 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testOnDestroy_removeAllPreferenceFromPreferenceGroup() {
+ public void onDestroy_removeAllPreferenceFromPreferenceGroup() {
mBatteryChartPreferenceController.onDestroy();
verify(mAppListGroup).removeAll();
}
@Test
- public void testSetBatteryHistoryMap_createExpectedKeysAndLevels() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(
- createBatteryHistoryMap());
+ public void setBatteryChartViewModel_6Hours() {
+ mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
- // Verifies the created battery keys array.
- 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);
- }
- // Verifies the created battery levels array.
- for (int index = 0; index < 13; index++) {
- assertThat(mBatteryChartPreferenceController.mBatteryHistoryLevels[index])
- // These values is are calculated by hand from createBatteryHistoryMap().
- .isEqualTo(100 - index * 2);
- }
- assertThat(mBatteryChartPreferenceController.mBatteryIndexedMap).hasSize(13);
+ verify(mDailyChartView, atLeastOnce()).setVisibility(View.GONE);
+ verify(mHourlyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
+ verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
+ List.of(100, 97, 95),
+ List.of("8 am", "10 am", "12 pm"),
+ BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
}
@Test
- public void testSetBatteryHistoryMap_largeSize_createExpectedKeysAndLevels() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(
- createBatteryHistoryMap());
+ public void setBatteryChartViewModel_60Hours() {
+ BatteryChartViewModel expectedDailyViewModel = new BatteryChartViewModel(
+ List.of(100, 83, 59, 41),
+ List.of("Sat", "Sun", "Mon", "Mon"),
+ BatteryChartViewModel.AxisLabelPosition.CENTER_OF_TRAPEZOIDS);
- // Verifies the created battery keys array.
- 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);
- }
- // Verifies the created battery levels array.
- for (int index = 0; index < 13; index++) {
- assertThat(mBatteryChartPreferenceController.mBatteryHistoryLevels[index])
- // These values is are calculated by hand from createBatteryHistoryMap().
- .isEqualTo(100 - index * 2);
- }
- assertThat(mBatteryChartPreferenceController.mBatteryIndexedMap).hasSize(13);
+ mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
+
+ verify(mDailyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
+ verify(mHourlyChartView, atLeastOnce()).setVisibility(View.GONE);
+ verify(mDailyChartView).setViewModel(expectedDailyViewModel);
+
+ reset(mDailyChartView);
+ reset(mHourlyChartView);
+ doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
+ mBatteryChartPreferenceController.mDailyChartIndex = 0;
+ mBatteryChartPreferenceController.refreshUi();
+ verify(mDailyChartView).setVisibility(View.VISIBLE);
+ verify(mHourlyChartView).setVisibility(View.VISIBLE);
+
+ expectedDailyViewModel.setSelectedIndex(0);
+ verify(mDailyChartView).setViewModel(expectedDailyViewModel);
+ verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
+ List.of(100, 97, 95, 93, 91, 89, 87, 85, 83),
+ List.of("8 am", "10 am", "12 pm", "2 pm", "4 pm", "6 pm", "8 pm", "10 pm",
+ "12 am"),
+ BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
+
+ reset(mDailyChartView);
+ reset(mHourlyChartView);
+ doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
+ mBatteryChartPreferenceController.mDailyChartIndex = 1;
+ mBatteryChartPreferenceController.mHourlyChartIndex = 6;
+ mBatteryChartPreferenceController.refreshUi();
+ verify(mDailyChartView).setVisibility(View.VISIBLE);
+ verify(mHourlyChartView).setVisibility(View.VISIBLE);
+ expectedDailyViewModel.setSelectedIndex(1);
+ verify(mDailyChartView).setViewModel(expectedDailyViewModel);
+ BatteryChartViewModel expectedHourlyViewModel = new BatteryChartViewModel(
+ List.of(83, 81, 79, 77, 75, 73, 71, 69, 67, 65, 63, 61, 59),
+ List.of("12 am", "2 am", "4 am", "6 am", "8 am", "10 am", "12 pm", "2 pm",
+ "4 pm", "6 pm", "8 pm", "10 pm", "12 am"),
+ BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS);
+ expectedHourlyViewModel.setSelectedIndex(6);
+ verify(mHourlyChartView).setViewModel(expectedHourlyViewModel);
+
+ reset(mDailyChartView);
+ reset(mHourlyChartView);
+ doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
+ mBatteryChartPreferenceController.mDailyChartIndex = 2;
+ mBatteryChartPreferenceController.mHourlyChartIndex =
+ BatteryChartViewModel.SELECTED_INDEX_ALL;
+ mBatteryChartPreferenceController.refreshUi();
+ verify(mDailyChartView).setVisibility(View.VISIBLE);
+ verify(mHourlyChartView).setVisibility(View.VISIBLE);
+ expectedDailyViewModel.setSelectedIndex(2);
+ verify(mDailyChartView).setViewModel(expectedDailyViewModel);
+ verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
+ List.of(59, 57, 55, 53, 51, 49, 47, 45, 43, 41),
+ List.of("12 am", "2 am", "4 am", "6 am", "8 am", "10 am", "12 pm", "2 pm",
+ "4 pm", "6 pm"),
+ BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
}
@Test
- public void testRefreshUi_batteryIndexedMapIsNull_ignoreRefresh() {
+ public void refreshUi_normalCase_returnTrue() {
+ mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
+ assertThat(mBatteryChartPreferenceController.refreshUi()).isTrue();
+ }
+
+ @Test
+ public void refreshUi_batteryIndexedMapIsNull_ignoreRefresh() {
mBatteryChartPreferenceController.setBatteryHistoryMap(null);
- assertThat(mBatteryChartPreferenceController.refreshUi(
- /*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();
+ public void refreshUi_dailyChartViewIsNull_ignoreRefresh() {
+ mBatteryChartPreferenceController.mDailyChartView = null;
+ assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse();
}
@Test
- public void testRefreshUi_trapezoidIndexIsNotChanged_ignoreRefresh() {
- final int trapezoidIndex = 1;
- mBatteryChartPreferenceController.mTrapezoidIndex = trapezoidIndex;
- assertThat(mBatteryChartPreferenceController.refreshUi(
- trapezoidIndex, /*isForce=*/ false)).isFalse();
+ public void refreshUi_hourlyChartViewIsNull_ignoreRefresh() {
+ mBatteryChartPreferenceController.mHourlyChartView = null;
+ assertThat(mBatteryChartPreferenceController.refreshUi()).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 =
- BatteryChartView.SELECTED_INDEX_INVALID;
- mBatteryChartPreferenceController.setBatteryHistoryMap(
- createBatteryHistoryMap());
-
- assertThat(mBatteryChartPreferenceController.mTrapezoidIndex)
- .isEqualTo(BatteryChartView.SELECTED_INDEX_ALL);
- }
-
- @Test
- public void testRemoveAndCacheAllPrefs_emptyContent_ignoreRemoveAll() {
- final int trapezoidIndex = 1;
+ public void removeAndCacheAllPrefs_emptyContent_ignoreRemoveAll() {
+ mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
+ mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
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;
+ public void removeAndCacheAllPrefs_buildCacheAndRemoveAllPreference() {
+ mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
+ mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
doReturn(1).when(mAppListGroup).getPreferenceCount();
doReturn(mPowerGaugePreference).when(mAppListGroup).getPreference(0);
+ doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
+ doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
// Ensures the testing data is correct.
assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
- mBatteryChartPreferenceController.refreshUi(
- trapezoidIndex, /*isForce=*/ true);
+ mBatteryChartPreferenceController.refreshUi();
assertThat(mBatteryChartPreferenceController.mPreferenceCache.get(PREF_KEY))
.isEqualTo(mPowerGaugePreference);
@@ -272,14 +302,14 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testAddPreferenceToScreen_emptyContent_ignoreAddPreference() {
+ public void addPreferenceToScreen_emptyContent_ignoreAddPreference() {
mBatteryChartPreferenceController.addPreferenceToScreen(
new ArrayList());
verify(mAppListGroup, never()).addPreference(any());
}
@Test
- public void testAddPreferenceToScreen_addPreferenceIntoScreen() {
+ public void addPreferenceToScreen_addPreferenceIntoScreen() {
final String appLabel = "fake app label";
doReturn(1).when(mAppListGroup).getPreferenceCount();
doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
@@ -308,7 +338,7 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testAddPreferenceToScreen_alreadyInScreen_notAddPreferenceAgain() {
+ public void addPreferenceToScreen_alreadyInScreen_notAddPreferenceAgain() {
final String appLabel = "fake app label";
doReturn(1).when(mAppListGroup).getPreferenceCount();
doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
@@ -323,7 +353,7 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testHandlePreferenceTreeiClick_notPowerGaugePreference_returnFalse() {
+ public void handlePreferenceTreeClick_notPowerGaugePreference_returnFalse() {
assertThat(mBatteryChartPreferenceController.handlePreferenceTreeClick(mAppListGroup))
.isFalse();
@@ -334,7 +364,7 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testHandlePreferenceTreeClick_forAppEntry_returnTrue() {
+ public void handlePreferenceTreeClick_forAppEntry_returnTrue() {
doReturn(false).when(mBatteryHistEntry).isAppEntry();
doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
@@ -350,7 +380,7 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testHandlePreferenceTreeClick_forSystemEntry_returnTrue() {
+ public void handlePreferenceTreeClick_forSystemEntry_returnTrue() {
mBatteryChartPreferenceController.mBatteryUtils = mBatteryUtils;
doReturn(true).when(mBatteryHistEntry).isAppEntry();
doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
@@ -367,7 +397,7 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testSetPreferenceSummary_setNullContentIfTotalUsageTimeIsZero() {
+ public void setPreferenceSummary_setNullContentIfTotalUsageTimeIsZero() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
pref.setSummary(PREF_SUMMARY);
@@ -379,7 +409,7 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testSetPreferenceSummary_setBackgroundUsageTimeOnly() {
+ public void setPreferenceSummary_setBackgroundUsageTimeOnly() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
pref.setSummary(PREF_SUMMARY);
@@ -391,7 +421,7 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testSetPreferenceSummary_setTotalUsageTimeLessThanAMinute() {
+ public void setPreferenceSummary_setTotalUsageTimeLessThanAMinute() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
pref.setSummary(PREF_SUMMARY);
@@ -403,7 +433,7 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testSetPreferenceSummary_setTotalTimeIfBackgroundTimeLessThanAMinute() {
+ public void setPreferenceSummary_setTotalTimeIfBackgroundTimeLessThanAMinute() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
pref.setSummary(PREF_SUMMARY);
@@ -416,7 +446,7 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testSetPreferenceSummary_setTotalAndBackgroundUsageTime() {
+ public void setPreferenceSummary_setTotalAndBackgroundUsageTime() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
pref.setSummary(PREF_SUMMARY);
@@ -428,7 +458,7 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testSetPreferenceSummary_notAllowShownPackage_setSummayAsNull() {
+ public void setPreferenceSummary_notAllowShownPackage_setSummayAsNull() {
final PowerGaugePreference pref = new PowerGaugePreference(mContext);
pref.setSummary(PREF_SUMMARY);
final BatteryDiffEntry batteryDiffEntry =
@@ -443,36 +473,9 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testValidateUsageTime_returnTrueIfBatteryDiffEntryIsValid() {
- assertThat(BatteryChartPreferenceController.validateUsageTime(
- createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
- /*backgroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS)))
- .isTrue();
- }
-
- @Test
- public void testValidateUsageTime_foregroundTimeExceedThreshold_returnFalse() {
- assertThat(BatteryChartPreferenceController.validateUsageTime(
- createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ DateUtils.HOUR_IN_MILLIS * 3,
- /*backgroundUsageTimeInMs=*/ 0)))
- .isFalse();
- }
-
- @Test
- public void testValidateUsageTime_backgroundTimeExceedThreshold_returnFalse() {
- assertThat(BatteryChartPreferenceController.validateUsageTime(
- createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ 0,
- /*backgroundUsageTimeInMs=*/ DateUtils.HOUR_IN_MILLIS * 3)))
- .isFalse();
- }
-
- @Test
- public void testOnExpand_expandedIsTrue_addSystemEntriesToPreferenceGroup() {
+ public void onExpand_expandedIsTrue_addSystemEntriesToPreferenceGroup() {
doReturn(1).when(mAppListGroup).getPreferenceCount();
- mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
+ mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
doReturn("label").when(mBatteryDiffEntry).getAppLabel();
doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
@@ -491,10 +494,10 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testOnExpand_expandedIsFalse_removeSystemEntriesFromPreferenceGroup() {
+ public void onExpand_expandedIsFalse_removeSystemEntriesFromPreferenceGroup() {
doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
- mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
+ mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
// Verifies the cache is empty first.
assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
@@ -511,57 +514,17 @@ public final class BatteryChartPreferenceControllerTest {
}
@Test
- public void testOnSelect_selectSpecificTimeSlot_logMetric() {
- mBatteryChartPreferenceController.onSelect(1 /*slot index*/);
-
- verify(mMetricsFeatureProvider)
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_TIME_SLOT);
- }
-
- @Test
- public void testOnSelect_selectAll_logMetric() {
- mBatteryChartPreferenceController.onSelect(
- BatteryChartView.SELECTED_INDEX_ALL /*slot index*/);
-
- verify(mMetricsFeatureProvider)
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL);
- }
-
- @Test
- public void testRefreshCategoryTitle_setHourIntoBothTitleTextView() {
- mBatteryChartPreferenceController = createController();
- setUpBatteryHistoryKeys();
- mBatteryChartPreferenceController.mAppListPrefGroup =
- spy(new PreferenceCategory(mContext));
- mBatteryChartPreferenceController.mExpandDividerPreference =
- spy(new ExpandDividerPreference(mContext));
- // Simulates select the first slot.
- mBatteryChartPreferenceController.mTrapezoidIndex = 0;
-
- mBatteryChartPreferenceController.refreshCategoryTitle();
-
- ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
- // Verifies the title in the preference group.
- verify(mBatteryChartPreferenceController.mAppListPrefGroup)
- .setTitle(captor.capture());
- assertThat(captor.getValue()).isNotEqualTo("App usage for past 24 hr");
- // Verifies the title in the expandable divider.
- captor = ArgumentCaptor.forClass(String.class);
- verify(mBatteryChartPreferenceController.mExpandDividerPreference)
- .setTitle(captor.capture());
- assertThat(captor.getValue()).isNotEqualTo("System usage for past 24 hr");
- }
-
- @Test
- public void testRefreshCategoryTitle_setLast24HrIntoBothTitleTextView() {
+ public void refreshCategoryTitle_setLastFullChargeIntoBothTitleTextView() {
mBatteryChartPreferenceController = createController();
mBatteryChartPreferenceController.mAppListPrefGroup =
spy(new PreferenceCategory(mContext));
mBatteryChartPreferenceController.mExpandDividerPreference =
spy(new ExpandDividerPreference(mContext));
// Simulates select all condition.
- mBatteryChartPreferenceController.mTrapezoidIndex =
- BatteryChartView.SELECTED_INDEX_ALL;
+ mBatteryChartPreferenceController.mDailyChartIndex =
+ BatteryChartViewModel.SELECTED_INDEX_ALL;
+ mBatteryChartPreferenceController.mHourlyChartIndex =
+ BatteryChartViewModel.SELECTED_INDEX_ALL;
mBatteryChartPreferenceController.refreshCategoryTitle();
@@ -570,76 +533,93 @@ public final class BatteryChartPreferenceControllerTest {
verify(mBatteryChartPreferenceController.mAppListPrefGroup)
.setTitle(captor.capture());
assertThat(captor.getValue())
- .isEqualTo("App usage for past 24 hr");
+ .isEqualTo("App usage since last full charge");
// Verifies the title in the expandable divider.
captor = ArgumentCaptor.forClass(String.class);
verify(mBatteryChartPreferenceController.mExpandDividerPreference)
.setTitle(captor.capture());
assertThat(captor.getValue())
- .isEqualTo("System usage for past 24 hr");
+ .isEqualTo("System usage since last full charge");
}
@Test
- public void testSetTimestampLabel_nullBatteryHistoryKeys_ignore() {
- mBatteryChartPreferenceController = createController();
- mBatteryChartPreferenceController.mBatteryHistoryKeys = null;
- mBatteryChartPreferenceController.mBatteryChartView =
- spy(new BatteryChartView(mContext));
- mBatteryChartPreferenceController.setTimestampLabel();
+ public void selectedSlotText_selectAllDaysAllHours_returnNull() {
+ mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
+ mBatteryChartPreferenceController.mDailyChartIndex =
+ BatteryChartViewModel.SELECTED_INDEX_ALL;
+ mBatteryChartPreferenceController.mHourlyChartIndex =
+ BatteryChartViewModel.SELECTED_INDEX_ALL;
- verify(mBatteryChartPreferenceController.mBatteryChartView, never())
- .setLatestTimestamp(anyLong());
+ assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(null);
}
@Test
- public void testSetTimestampLabel_setExpectedTimestampData() {
- mBatteryChartPreferenceController = createController();
- mBatteryChartPreferenceController.mBatteryChartView =
- spy(new BatteryChartView(mContext));
- setUpBatteryHistoryKeys();
+ public void selectedSlotText_onlyOneDayDataSelectAllHours_returnNull() {
+ mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
+ mBatteryChartPreferenceController.mDailyChartIndex = 0;
+ mBatteryChartPreferenceController.mHourlyChartIndex =
+ BatteryChartViewModel.SELECTED_INDEX_ALL;
- mBatteryChartPreferenceController.setTimestampLabel();
-
- verify(mBatteryChartPreferenceController.mBatteryChartView)
- .setLatestTimestamp(1619247636826L);
+ assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(null);
}
@Test
- public void testSetTimestampLabel_withoutValidTimestamp_setExpectedTimestampData() {
- mBatteryChartPreferenceController = createController();
- mBatteryChartPreferenceController.mBatteryChartView =
- spy(new BatteryChartView(mContext));
- mBatteryChartPreferenceController.mBatteryHistoryKeys = new long[]{0L};
+ public void selectedSlotText_selectADayAllHours_onlyDayText() {
+ mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
+ mBatteryChartPreferenceController.mDailyChartIndex = 1;
+ mBatteryChartPreferenceController.mHourlyChartIndex =
+ BatteryChartViewModel.SELECTED_INDEX_ALL;
- mBatteryChartPreferenceController.setTimestampLabel();
-
- verify(mBatteryChartPreferenceController.mBatteryChartView)
- .setLatestTimestamp(anyLong());
+ assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo("Sunday");
}
@Test
- public void testOnSaveInstanceState_restoreSelectedIndexAndExpandState() {
- final int expectedIndex = 1;
+ public void selectedSlotText_onlyOneDayDataSelectAnHour_onlyHourText() {
+ mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
+ mBatteryChartPreferenceController.mDailyChartIndex = 0;
+ mBatteryChartPreferenceController.mHourlyChartIndex = 1;
+
+ assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(
+ "10 am - 12 pm");
+ }
+
+ @Test
+ public void selectedSlotText_SelectADayAnHour_dayAndHourText() {
+ mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
+ mBatteryChartPreferenceController.mDailyChartIndex = 1;
+ mBatteryChartPreferenceController.mHourlyChartIndex = 8;
+
+ assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(
+ "Sunday 4 pm - 6 pm");
+ }
+
+ @Test
+ public void onSaveInstanceState_restoreSelectedIndexAndExpandState() {
+ final int expectedDailyIndex = 1;
+ final int expectedHourlyIndex = 2;
final boolean isExpanded = true;
final Bundle bundle = new Bundle();
- mBatteryChartPreferenceController.mTrapezoidIndex = expectedIndex;
+ mBatteryChartPreferenceController.mDailyChartIndex = expectedDailyIndex;
+ mBatteryChartPreferenceController.mHourlyChartIndex = expectedHourlyIndex;
mBatteryChartPreferenceController.mIsExpanded = isExpanded;
mBatteryChartPreferenceController.onSaveInstanceState(bundle);
// Replaces the original controller with other values.
- mBatteryChartPreferenceController.mTrapezoidIndex = -1;
+ mBatteryChartPreferenceController.mDailyChartIndex = -1;
+ mBatteryChartPreferenceController.mHourlyChartIndex = -1;
mBatteryChartPreferenceController.mIsExpanded = false;
mBatteryChartPreferenceController.onCreate(bundle);
- mBatteryChartPreferenceController.setBatteryHistoryMap(
- createBatteryHistoryMap());
+ mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(25));
- assertThat(mBatteryChartPreferenceController.mTrapezoidIndex)
- .isEqualTo(expectedIndex);
+ assertThat(mBatteryChartPreferenceController.mDailyChartIndex)
+ .isEqualTo(expectedDailyIndex);
+ assertThat(mBatteryChartPreferenceController.mHourlyChartIndex)
+ .isEqualTo(expectedHourlyIndex);
assertThat(mBatteryChartPreferenceController.mIsExpanded).isTrue();
}
@Test
- public void testIsValidToShowSummary_returnExpectedResult() {
+ public void isValidToShowSummary_returnExpectedResult() {
assertThat(mBatteryChartPreferenceController
.isValidToShowSummary("com.google.android.apps.scone"))
.isTrue();
@@ -650,31 +630,42 @@ public final class BatteryChartPreferenceControllerTest {
.isFalse();
}
- @Test
- public void testIsValidToShowEntry_returnExpectedResult() {
- assertThat(mBatteryChartPreferenceController
- .isValidToShowEntry("com.google.android.apps.scone"))
- .isTrue();
-
- // Verifies the items which are defined in the array list.
- assertThat(mBatteryChartPreferenceController
- .isValidToShowEntry("com.android.gms.persistent"))
- .isFalse();
+ private static Long generateTimestamp(int index) {
+ // "2021-04-23 07:00:00 UTC" + index hours
+ return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS;
}
- private static Map> createBatteryHistoryMap() {
+ private static Map> createBatteryHistoryMap(
+ int numOfHours) {
final Map> batteryHistoryMap = new HashMap<>();
- for (int index = 0; index < DESIRED_HISTORY_SIZE; index++) {
+ for (int index = 0; index < numOfHours; index++) {
final ContentValues values = new ContentValues();
values.put("batteryLevel", Integer.valueOf(100 - index));
+ values.put("consumePower", Integer.valueOf(100 - index));
final BatteryHistEntry entry = new BatteryHistEntry(values);
final Map entryMap = new HashMap<>();
entryMap.put("fake_entry_key" + index, entry);
- batteryHistoryMap.put(Long.valueOf(index + 1), entryMap);
+ batteryHistoryMap.put(generateTimestamp(index), entryMap);
}
return batteryHistoryMap;
}
+ private Map> createBatteryUsageMap() {
+ final int selectedAll = BatteryChartViewModel.SELECTED_INDEX_ALL;
+ return Map.of(
+ selectedAll, Map.of(
+ selectedAll, new BatteryDiffData(
+ Arrays.asList(mBatteryDiffEntry),
+ Arrays.asList(mBatteryDiffEntry))),
+ 0, Map.of(
+ selectedAll, new BatteryDiffData(
+ Arrays.asList(mBatteryDiffEntry),
+ Arrays.asList(mBatteryDiffEntry)),
+ 0, new BatteryDiffData(
+ Arrays.asList(mBatteryDiffEntry),
+ Arrays.asList(mBatteryDiffEntry))));
+ }
+
private BatteryDiffEntry createBatteryDiffEntry(
long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) {
return new BatteryDiffEntry(
@@ -682,13 +673,6 @@ public final class BatteryChartPreferenceControllerTest {
/*consumePower=*/ 0, mBatteryHistEntry);
}
- private void setUpBatteryHistoryKeys() {
- mBatteryChartPreferenceController.mBatteryHistoryKeys =
- new long[]{1619196786769L, 0L, 1619247636826L};
- ConvertUtils.utcToLocalTimeHour(
- mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false);
- }
-
private BatteryChartPreferenceController createController() {
final BatteryChartPreferenceController controller =
new BatteryChartPreferenceController(
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2Test.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2Test.java
deleted file mode 100644
index e738e6534f6..00000000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerV2Test.java
+++ /dev/null
@@ -1,684 +0,0 @@
-/*
- * 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 static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-import android.app.settings.SettingsEnums;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.LocaleList;
-import android.text.format.DateUtils;
-import android.view.View;
-import android.widget.LinearLayout;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceGroup;
-
-import com.android.settings.SettingsActivity;
-import com.android.settings.core.InstrumentedPreferenceFragment;
-import com.android.settings.fuelgauge.BatteryUtils;
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-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;
-
-@RunWith(RobolectricTestRunner.class)
-public final class BatteryChartPreferenceControllerV2Test {
- private static final String PREF_KEY = "pref_key";
- private static final String PREF_SUMMARY = "fake preference summary";
-
- @Mock
- private InstrumentedPreferenceFragment mFragment;
- @Mock
- private SettingsActivity mSettingsActivity;
- @Mock
- private PreferenceGroup mAppListGroup;
- @Mock
- private Drawable mDrawable;
- @Mock
- private BatteryHistEntry mBatteryHistEntry;
- @Mock
- private BatteryChartViewV2 mDailyChartView;
- @Mock
- private BatteryChartViewV2 mHourlyChartView;
- @Mock
- private PowerGaugePreference mPowerGaugePreference;
- @Mock
- private BatteryUtils mBatteryUtils;
- @Mock
- private LinearLayout.LayoutParams mLayoutParams;
-
- private Context mContext;
- private FakeFeatureFactory mFeatureFactory;
- private BatteryDiffEntry mBatteryDiffEntry;
- private MetricsFeatureProvider mMetricsFeatureProvider;
- private BatteryChartPreferenceControllerV2 mBatteryChartPreferenceController;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- Locale.setDefault(new Locale("en_US"));
- org.robolectric.shadows.ShadowSettings.set24HourTimeFormat(false);
- TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
- mFeatureFactory = FakeFeatureFactory.setupForTest();
- mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
- mContext = spy(RuntimeEnvironment.application);
- final Resources resources = spy(mContext.getResources());
- resources.getConfiguration().setLocales(new LocaleList(new Locale("en_US")));
- doReturn(resources).when(mContext).getResources();
- doReturn(new String[]{"com.android.googlequicksearchbox"})
- .when(mFeatureFactory.powerUsageFeatureProvider)
- .getHideApplicationSummary(mContext);
- doReturn(new String[]{"com.android.gms.persistent"})
- .when(mFeatureFactory.powerUsageFeatureProvider)
- .getHideApplicationEntries(mContext);
- doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
- mBatteryChartPreferenceController = createController();
- mBatteryChartPreferenceController.mPrefContext = mContext;
- mBatteryChartPreferenceController.mAppListPrefGroup = mAppListGroup;
- mBatteryChartPreferenceController.mDailyChartView = mDailyChartView;
- mBatteryChartPreferenceController.mHourlyChartView = mHourlyChartView;
- mBatteryDiffEntry = new BatteryDiffEntry(
- mContext,
- /*foregroundUsageTimeInMs=*/ 1,
- /*backgroundUsageTimeInMs=*/ 2,
- /*consumePower=*/ 3,
- mBatteryHistEntry);
- mBatteryDiffEntry = spy(mBatteryDiffEntry);
- // Adds fake testing data.
- BatteryDiffEntry.sResourceCache.put(
- "fakeBatteryDiffEntryKey",
- new BatteryEntry.NameAndIcon("fakeName", /*icon=*/ null, /*iconId=*/ 1));
- }
-
- @Test
- public void onDestroy_activityIsChanging_clearBatteryEntryCache() {
- doReturn(true).when(mSettingsActivity).isChangingConfigurations();
- // Ensures the testing environment is correct.
- assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
-
- mBatteryChartPreferenceController.onDestroy();
- assertThat(BatteryDiffEntry.sResourceCache).isEmpty();
- }
-
- @Test
- public void onDestroy_activityIsNotChanging_notClearBatteryEntryCache() {
- doReturn(false).when(mSettingsActivity).isChangingConfigurations();
- // Ensures the testing environment is correct.
- assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
-
- mBatteryChartPreferenceController.onDestroy();
- assertThat(BatteryDiffEntry.sResourceCache).isNotEmpty();
- }
-
- @Test
- public void onDestroy_clearPreferenceCache() {
- // Ensures the testing environment is correct.
- mBatteryChartPreferenceController.mPreferenceCache.put(
- PREF_KEY, mPowerGaugePreference);
- assertThat(mBatteryChartPreferenceController.mPreferenceCache).hasSize(1);
-
- mBatteryChartPreferenceController.onDestroy();
- // Verifies the result after onDestroy.
- assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
- }
-
- @Test
- public void onDestroy_removeAllPreferenceFromPreferenceGroup() {
- mBatteryChartPreferenceController.onDestroy();
- verify(mAppListGroup).removeAll();
- }
-
- @Test
- public void setBatteryChartViewModel_6Hours() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
-
- verify(mDailyChartView, atLeastOnce()).setVisibility(View.GONE);
- verify(mHourlyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
- verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
- List.of(100, 97, 95),
- List.of("8 am", "10 am", "12 pm"),
- BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
- }
-
- @Test
- public void setBatteryChartViewModel_60Hours() {
- BatteryChartViewModel expectedDailyViewModel = new BatteryChartViewModel(
- List.of(100, 83, 59, 41),
- List.of("Sat", "Sun", "Mon", "Mon"),
- BatteryChartViewModel.AxisLabelPosition.CENTER_OF_TRAPEZOIDS);
-
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
-
- verify(mDailyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
- verify(mHourlyChartView, atLeastOnce()).setVisibility(View.GONE);
- verify(mDailyChartView).setViewModel(expectedDailyViewModel);
-
- reset(mDailyChartView);
- reset(mHourlyChartView);
- doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
- mBatteryChartPreferenceController.mDailyChartIndex = 0;
- mBatteryChartPreferenceController.refreshUi();
- verify(mDailyChartView).setVisibility(View.VISIBLE);
- verify(mHourlyChartView).setVisibility(View.VISIBLE);
-
- expectedDailyViewModel.setSelectedIndex(0);
- verify(mDailyChartView).setViewModel(expectedDailyViewModel);
- verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
- List.of(100, 97, 95, 93, 91, 89, 87, 85, 83),
- List.of("8 am", "10 am", "12 pm", "2 pm", "4 pm", "6 pm", "8 pm", "10 pm",
- "12 am"),
- BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
-
- reset(mDailyChartView);
- reset(mHourlyChartView);
- doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
- mBatteryChartPreferenceController.mDailyChartIndex = 1;
- mBatteryChartPreferenceController.mHourlyChartIndex = 6;
- mBatteryChartPreferenceController.refreshUi();
- verify(mDailyChartView).setVisibility(View.VISIBLE);
- verify(mHourlyChartView).setVisibility(View.VISIBLE);
- expectedDailyViewModel.setSelectedIndex(1);
- verify(mDailyChartView).setViewModel(expectedDailyViewModel);
- BatteryChartViewModel expectedHourlyViewModel = new BatteryChartViewModel(
- List.of(83, 81, 79, 77, 75, 73, 71, 69, 67, 65, 63, 61, 59),
- List.of("12 am", "2 am", "4 am", "6 am", "8 am", "10 am", "12 pm", "2 pm",
- "4 pm", "6 pm", "8 pm", "10 pm", "12 am"),
- BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS);
- expectedHourlyViewModel.setSelectedIndex(6);
- verify(mHourlyChartView).setViewModel(expectedHourlyViewModel);
-
- reset(mDailyChartView);
- reset(mHourlyChartView);
- doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
- mBatteryChartPreferenceController.mDailyChartIndex = 2;
- mBatteryChartPreferenceController.mHourlyChartIndex =
- BatteryChartViewModel.SELECTED_INDEX_ALL;
- mBatteryChartPreferenceController.refreshUi();
- verify(mDailyChartView).setVisibility(View.VISIBLE);
- verify(mHourlyChartView).setVisibility(View.VISIBLE);
- expectedDailyViewModel.setSelectedIndex(2);
- verify(mDailyChartView).setViewModel(expectedDailyViewModel);
- verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
- List.of(59, 57, 55, 53, 51, 49, 47, 45, 43, 41),
- List.of("12 am", "2 am", "4 am", "6 am", "8 am", "10 am", "12 pm", "2 pm",
- "4 pm", "6 pm"),
- BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
- }
-
- @Test
- public void refreshUi_normalCase_returnTrue() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
- assertThat(mBatteryChartPreferenceController.refreshUi()).isTrue();
- }
-
- @Test
- public void refreshUi_batteryIndexedMapIsNull_ignoreRefresh() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(null);
- assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse();
- }
-
- @Test
- public void refreshUi_dailyChartViewIsNull_ignoreRefresh() {
- mBatteryChartPreferenceController.mDailyChartView = null;
- assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse();
- }
-
- @Test
- public void refreshUi_hourlyChartViewIsNull_ignoreRefresh() {
- mBatteryChartPreferenceController.mHourlyChartView = null;
- assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse();
- }
-
- @Test
- public void removeAndCacheAllPrefs_emptyContent_ignoreRemoveAll() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
- mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
- doReturn(0).when(mAppListGroup).getPreferenceCount();
-
- mBatteryChartPreferenceController.refreshUi();
- verify(mAppListGroup, never()).removeAll();
- }
-
- @Test
- public void removeAndCacheAllPrefs_buildCacheAndRemoveAllPreference() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
- mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
- doReturn(1).when(mAppListGroup).getPreferenceCount();
- doReturn(mPowerGaugePreference).when(mAppListGroup).getPreference(0);
- doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
- doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
- doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
- // Ensures the testing data is correct.
- assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
-
- mBatteryChartPreferenceController.refreshUi();
-
- assertThat(mBatteryChartPreferenceController.mPreferenceCache.get(PREF_KEY))
- .isEqualTo(mPowerGaugePreference);
- verify(mAppListGroup).removeAll();
- }
-
- @Test
- public void addPreferenceToScreen_emptyContent_ignoreAddPreference() {
- mBatteryChartPreferenceController.addPreferenceToScreen(
- new ArrayList());
- verify(mAppListGroup, never()).addPreference(any());
- }
-
- @Test
- public void addPreferenceToScreen_addPreferenceIntoScreen() {
- final String appLabel = "fake app label";
- doReturn(1).when(mAppListGroup).getPreferenceCount();
- doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
- doReturn(appLabel).when(mBatteryDiffEntry).getAppLabel();
- doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
- doReturn(null).when(mAppListGroup).findPreference(PREF_KEY);
- doReturn(false).when(mBatteryDiffEntry).validForRestriction();
-
- mBatteryChartPreferenceController.addPreferenceToScreen(
- Arrays.asList(mBatteryDiffEntry));
-
- // Verifies the preference cache.
- final PowerGaugePreference pref =
- (PowerGaugePreference) mBatteryChartPreferenceController.mPreferenceCache
- .get(PREF_KEY);
- assertThat(pref).isNotNull();
- // Verifies the added preference configuration.
- verify(mAppListGroup).addPreference(pref);
- assertThat(pref.getKey()).isEqualTo(PREF_KEY);
- assertThat(pref.getTitle()).isEqualTo(appLabel);
- assertThat(pref.getIcon()).isEqualTo(mDrawable);
- assertThat(pref.getOrder()).isEqualTo(1);
- assertThat(pref.getBatteryDiffEntry()).isSameInstanceAs(mBatteryDiffEntry);
- assertThat(pref.isSingleLineTitle()).isTrue();
- assertThat(pref.isEnabled()).isFalse();
- }
-
- @Test
- public void addPreferenceToScreen_alreadyInScreen_notAddPreferenceAgain() {
- final String appLabel = "fake app label";
- doReturn(1).when(mAppListGroup).getPreferenceCount();
- doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
- doReturn(appLabel).when(mBatteryDiffEntry).getAppLabel();
- doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
- doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
-
- mBatteryChartPreferenceController.addPreferenceToScreen(
- Arrays.asList(mBatteryDiffEntry));
-
- verify(mAppListGroup, never()).addPreference(any());
- }
-
- @Test
- public void handlePreferenceTreeClick_notPowerGaugePreference_returnFalse() {
- assertThat(mBatteryChartPreferenceController.handlePreferenceTreeClick(mAppListGroup))
- .isFalse();
-
- verify(mMetricsFeatureProvider, never())
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_APP_ITEM);
- verify(mMetricsFeatureProvider, never())
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SYSTEM_ITEM);
- }
-
- @Test
- public void handlePreferenceTreeClick_forAppEntry_returnTrue() {
- doReturn(false).when(mBatteryHistEntry).isAppEntry();
- doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
-
- assertThat(mBatteryChartPreferenceController.handlePreferenceTreeClick(
- mPowerGaugePreference)).isTrue();
- verify(mMetricsFeatureProvider)
- .action(
- SettingsEnums.OPEN_BATTERY_USAGE,
- SettingsEnums.ACTION_BATTERY_USAGE_SYSTEM_ITEM,
- SettingsEnums.OPEN_BATTERY_USAGE,
- /* package name */ "none",
- /* percentage of total */ 0);
- }
-
- @Test
- public void handlePreferenceTreeClick_forSystemEntry_returnTrue() {
- mBatteryChartPreferenceController.mBatteryUtils = mBatteryUtils;
- doReturn(true).when(mBatteryHistEntry).isAppEntry();
- doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
-
- assertThat(mBatteryChartPreferenceController.handlePreferenceTreeClick(
- mPowerGaugePreference)).isTrue();
- verify(mMetricsFeatureProvider)
- .action(
- SettingsEnums.OPEN_BATTERY_USAGE,
- SettingsEnums.ACTION_BATTERY_USAGE_APP_ITEM,
- SettingsEnums.OPEN_BATTERY_USAGE,
- /* package name */ "none",
- /* percentage of total */ 0);
- }
-
- @Test
- public void setPreferenceSummary_setNullContentIfTotalUsageTimeIsZero() {
- final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary(PREF_SUMMARY);
-
- mBatteryChartPreferenceController.setPreferenceSummary(
- pref, createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ 0,
- /*backgroundUsageTimeInMs=*/ 0));
- assertThat(pref.getSummary()).isNull();
- }
-
- @Test
- public void setPreferenceSummary_setBackgroundUsageTimeOnly() {
- final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary(PREF_SUMMARY);
-
- mBatteryChartPreferenceController.setPreferenceSummary(
- pref, createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ 0,
- /*backgroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS));
- assertThat(pref.getSummary()).isEqualTo("Background: 1 min");
- }
-
- @Test
- public void setPreferenceSummary_setTotalUsageTimeLessThanAMinute() {
- final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary(PREF_SUMMARY);
-
- mBatteryChartPreferenceController.setPreferenceSummary(
- pref, createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ 100,
- /*backgroundUsageTimeInMs=*/ 200));
- assertThat(pref.getSummary()).isEqualTo("Total: less than a min");
- }
-
- @Test
- public void setPreferenceSummary_setTotalTimeIfBackgroundTimeLessThanAMinute() {
- final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary(PREF_SUMMARY);
-
- mBatteryChartPreferenceController.setPreferenceSummary(
- pref, createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
- /*backgroundUsageTimeInMs=*/ 200));
- assertThat(pref.getSummary())
- .isEqualTo("Total: 1 min\nBackground: less than a min");
- }
-
- @Test
- public void setPreferenceSummary_setTotalAndBackgroundUsageTime() {
- final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary(PREF_SUMMARY);
-
- mBatteryChartPreferenceController.setPreferenceSummary(
- pref, createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
- /*backgroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS));
- assertThat(pref.getSummary()).isEqualTo("Total: 2 min\nBackground: 1 min");
- }
-
- @Test
- public void setPreferenceSummary_notAllowShownPackage_setSummayAsNull() {
- final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary(PREF_SUMMARY);
- final BatteryDiffEntry batteryDiffEntry =
- spy(createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
- /*backgroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS));
- doReturn("com.android.googlequicksearchbox").when(batteryDiffEntry)
- .getPackageName();
-
- mBatteryChartPreferenceController.setPreferenceSummary(pref, batteryDiffEntry);
- assertThat(pref.getSummary()).isNull();
- }
-
- @Test
- public void onExpand_expandedIsTrue_addSystemEntriesToPreferenceGroup() {
- doReturn(1).when(mAppListGroup).getPreferenceCount();
- mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
- doReturn("label").when(mBatteryDiffEntry).getAppLabel();
- doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
- doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
-
- mBatteryChartPreferenceController.onExpand(/*isExpanded=*/ true);
-
- final ArgumentCaptor captor = ArgumentCaptor.forClass(Preference.class);
- verify(mAppListGroup).addPreference(captor.capture());
- // Verifies the added preference.
- assertThat(captor.getValue().getKey()).isEqualTo(PREF_KEY);
- verify(mMetricsFeatureProvider)
- .action(
- mContext,
- SettingsEnums.ACTION_BATTERY_USAGE_EXPAND_ITEM,
- true /*isExpanded*/);
- }
-
- @Test
- public void onExpand_expandedIsFalse_removeSystemEntriesFromPreferenceGroup() {
- doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
- doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
- mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
- // Verifies the cache is empty first.
- assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
-
- mBatteryChartPreferenceController.onExpand(/*isExpanded=*/ false);
-
- verify(mAppListGroup).findPreference(PREF_KEY);
- verify(mAppListGroup).removePreference(mPowerGaugePreference);
- assertThat(mBatteryChartPreferenceController.mPreferenceCache).hasSize(1);
- verify(mMetricsFeatureProvider)
- .action(
- mContext,
- SettingsEnums.ACTION_BATTERY_USAGE_EXPAND_ITEM,
- false /*isExpanded*/);
- }
-
- @Test
- public void refreshCategoryTitle_setLastFullChargeIntoBothTitleTextView() {
- mBatteryChartPreferenceController = createController();
- mBatteryChartPreferenceController.mAppListPrefGroup =
- spy(new PreferenceCategory(mContext));
- mBatteryChartPreferenceController.mExpandDividerPreference =
- spy(new ExpandDividerPreference(mContext));
- // Simulates select all condition.
- mBatteryChartPreferenceController.mDailyChartIndex =
- BatteryChartViewModel.SELECTED_INDEX_ALL;
- mBatteryChartPreferenceController.mHourlyChartIndex =
- BatteryChartViewModel.SELECTED_INDEX_ALL;
-
- mBatteryChartPreferenceController.refreshCategoryTitle();
-
- ArgumentCaptor captor = ArgumentCaptor.forClass(String.class);
- // Verifies the title in the preference group.
- verify(mBatteryChartPreferenceController.mAppListPrefGroup)
- .setTitle(captor.capture());
- assertThat(captor.getValue())
- .isEqualTo("App usage since last full charge");
- // Verifies the title in the expandable divider.
- captor = ArgumentCaptor.forClass(String.class);
- verify(mBatteryChartPreferenceController.mExpandDividerPreference)
- .setTitle(captor.capture());
- assertThat(captor.getValue())
- .isEqualTo("System usage since last full charge");
- }
-
- @Test
- public void selectedSlotText_selectAllDaysAllHours_returnNull() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
- mBatteryChartPreferenceController.mDailyChartIndex =
- BatteryChartViewModel.SELECTED_INDEX_ALL;
- mBatteryChartPreferenceController.mHourlyChartIndex =
- BatteryChartViewModel.SELECTED_INDEX_ALL;
-
- assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(null);
- }
-
- @Test
- public void selectedSlotText_onlyOneDayDataSelectAllHours_returnNull() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
- mBatteryChartPreferenceController.mDailyChartIndex = 0;
- mBatteryChartPreferenceController.mHourlyChartIndex =
- BatteryChartViewModel.SELECTED_INDEX_ALL;
-
- assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(null);
- }
-
- @Test
- public void selectedSlotText_selectADayAllHours_onlyDayText() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
- mBatteryChartPreferenceController.mDailyChartIndex = 1;
- mBatteryChartPreferenceController.mHourlyChartIndex =
- BatteryChartViewModel.SELECTED_INDEX_ALL;
-
- assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo("Sunday");
- }
-
- @Test
- public void selectedSlotText_onlyOneDayDataSelectAnHour_onlyHourText() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
- mBatteryChartPreferenceController.mDailyChartIndex = 0;
- mBatteryChartPreferenceController.mHourlyChartIndex = 1;
-
- assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(
- "10 am - 12 pm");
- }
-
- @Test
- public void selectedSlotText_SelectADayAnHour_dayAndHourText() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
- mBatteryChartPreferenceController.mDailyChartIndex = 1;
- mBatteryChartPreferenceController.mHourlyChartIndex = 8;
-
- assertThat(mBatteryChartPreferenceController.getSlotInformation()).isEqualTo(
- "Sunday 4 pm - 6 pm");
- }
-
- @Test
- public void onSaveInstanceState_restoreSelectedIndexAndExpandState() {
- final int expectedDailyIndex = 1;
- final int expectedHourlyIndex = 2;
- final boolean isExpanded = true;
- final Bundle bundle = new Bundle();
- mBatteryChartPreferenceController.mDailyChartIndex = expectedDailyIndex;
- mBatteryChartPreferenceController.mHourlyChartIndex = expectedHourlyIndex;
- mBatteryChartPreferenceController.mIsExpanded = isExpanded;
- mBatteryChartPreferenceController.onSaveInstanceState(bundle);
- // Replaces the original controller with other values.
- mBatteryChartPreferenceController.mDailyChartIndex = -1;
- mBatteryChartPreferenceController.mHourlyChartIndex = -1;
- mBatteryChartPreferenceController.mIsExpanded = false;
-
- mBatteryChartPreferenceController.onCreate(bundle);
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(25));
-
- assertThat(mBatteryChartPreferenceController.mDailyChartIndex)
- .isEqualTo(expectedDailyIndex);
- assertThat(mBatteryChartPreferenceController.mHourlyChartIndex)
- .isEqualTo(expectedHourlyIndex);
- assertThat(mBatteryChartPreferenceController.mIsExpanded).isTrue();
- }
-
- @Test
- public void isValidToShowSummary_returnExpectedResult() {
- assertThat(mBatteryChartPreferenceController
- .isValidToShowSummary("com.google.android.apps.scone"))
- .isTrue();
-
- // Verifies the item which is defined in the array list.
- assertThat(mBatteryChartPreferenceController
- .isValidToShowSummary("com.android.googlequicksearchbox"))
- .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(
- int numOfHours) {
- final Map> batteryHistoryMap = new HashMap<>();
- for (int index = 0; index < numOfHours; index++) {
- final ContentValues values = new ContentValues();
- values.put("batteryLevel", Integer.valueOf(100 - index));
- values.put("consumePower", Integer.valueOf(100 - index));
- final BatteryHistEntry entry = new BatteryHistEntry(values);
- final Map entryMap = new HashMap<>();
- entryMap.put("fake_entry_key" + index, entry);
- batteryHistoryMap.put(generateTimestamp(index), entryMap);
- }
- return batteryHistoryMap;
- }
-
- private Map> createBatteryUsageMap() {
- final int selectedAll = BatteryChartViewModel.SELECTED_INDEX_ALL;
- return Map.of(
- selectedAll, Map.of(
- selectedAll, new BatteryDiffData(
- Arrays.asList(mBatteryDiffEntry),
- Arrays.asList(mBatteryDiffEntry))),
- 0, Map.of(
- selectedAll, new BatteryDiffData(
- Arrays.asList(mBatteryDiffEntry),
- Arrays.asList(mBatteryDiffEntry)),
- 0, new BatteryDiffData(
- Arrays.asList(mBatteryDiffEntry),
- Arrays.asList(mBatteryDiffEntry))));
- }
-
- private BatteryDiffEntry createBatteryDiffEntry(
- long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) {
- return new BatteryDiffEntry(
- mContext, foregroundUsageTimeInMs, backgroundUsageTimeInMs,
- /*consumePower=*/ 0, mBatteryHistEntry);
- }
-
- private BatteryChartPreferenceControllerV2 createController() {
- final BatteryChartPreferenceControllerV2 controller =
- new BatteryChartPreferenceControllerV2(
- mContext, "app_list", /*lifecycle=*/ null,
- mSettingsActivity, mFragment);
- controller.mPrefContext = mContext;
- return controller;
- }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewTest.java
index a2d8ca95c07..8a430875614 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewTest.java
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.when;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
import android.os.LocaleList;
+import android.view.View;
import android.view.accessibility.AccessibilityManager;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
@@ -41,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)
@@ -55,6 +57,8 @@ public final class BatteryChartViewTest {
private AccessibilityServiceInfo mMockAccessibilityServiceInfo;
@Mock
private AccessibilityManager mMockAccessibilityManager;
+ @Mock
+ private View mMockView;
@Before
public void setUp() {
@@ -74,13 +78,13 @@ public final class BatteryChartViewTest {
}
@Test
- public void testIsAccessibilityEnabled_disable_returnFalse() {
+ public void isAccessibilityEnabled_disable_returnFalse() {
doReturn(false).when(mMockAccessibilityManager).isEnabled();
assertThat(BatteryChartView.isAccessibilityEnabled(mContext)).isFalse();
}
@Test
- public void testIsAccessibilityEnabled_emptyInfo_returnFalse() {
+ public void isAccessibilityEnabled_emptyInfo_returnFalse() {
doReturn(true).when(mMockAccessibilityManager).isEnabled();
doReturn(new ArrayList())
.when(mMockAccessibilityManager)
@@ -90,68 +94,70 @@ public final class BatteryChartViewTest {
}
@Test
- public void testIsAccessibilityEnabled_validServiceId_returnTrue() {
+ public void isAccessibilityEnabled_validServiceId_returnTrue() {
doReturn(true).when(mMockAccessibilityManager).isEnabled();
assertThat(BatteryChartView.isAccessibilityEnabled(mContext)).isTrue();
}
@Test
- public void testSetSelectedIndex_invokesCallback() {
+ public void onClick_invokesCallback() {
+ final int originalSelectedIndex = 2;
+ BatteryChartViewModel batteryChartViewModel = new BatteryChartViewModel(
+ List.of(90, 80, 70, 60), List.of("", "", "", ""),
+ BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS);
+ batteryChartViewModel.setSelectedIndex(originalSelectedIndex);
+ mBatteryChartView.setViewModel(batteryChartViewModel);
+ for (int i = 0; i < mBatteryChartView.mTrapezoidSlots.length; i++) {
+ mBatteryChartView.mTrapezoidSlots[i] = new BatteryChartView.TrapezoidSlot();
+ mBatteryChartView.mTrapezoidSlots[i].mLeft = i;
+ mBatteryChartView.mTrapezoidSlots[i].mRight = i + 0.5f;
+ }
final int[] selectedIndex = new int[1];
- final int expectedIndex = 2;
- mBatteryChartView.mSelectedIndex = 1;
mBatteryChartView.setOnSelectListener(
trapezoidIndex -> {
selectedIndex[0] = trapezoidIndex;
});
- mBatteryChartView.setSelectedIndex(expectedIndex);
+ // Verify onClick() a different index 1.
+ mBatteryChartView.mTouchUpEventX = 1;
+ selectedIndex[0] = Integer.MIN_VALUE;
+ mBatteryChartView.onClick(mMockView);
+ assertThat(selectedIndex[0]).isEqualTo(1);
- assertThat(mBatteryChartView.mSelectedIndex)
- .isEqualTo(expectedIndex);
- assertThat(selectedIndex[0]).isEqualTo(expectedIndex);
+ // Verify onClick() the same index 2.
+ mBatteryChartView.mTouchUpEventX = 2;
+ selectedIndex[0] = Integer.MIN_VALUE;
+ mBatteryChartView.onClick(mMockView);
+ assertThat(selectedIndex[0]).isEqualTo(BatteryChartViewModel.SELECTED_INDEX_ALL);
}
@Test
- public void testSetSelectedIndex_sameIndex_notInvokesCallback() {
- final int[] selectedIndex = new int[1];
- final int expectedIndex = 1;
- mBatteryChartView.mSelectedIndex = expectedIndex;
- mBatteryChartView.setOnSelectListener(
- trapezoidIndex -> {
- selectedIndex[0] = trapezoidIndex;
- });
-
- mBatteryChartView.setSelectedIndex(expectedIndex);
-
- assertThat(selectedIndex[0]).isNotEqualTo(expectedIndex);
- }
-
- @Test
- public void testClickable_isChartGraphSlotsEnabledIsFalse_notClickable() {
+ public void clickable_isChartGraphSlotsEnabledIsFalse_notClickable() {
mBatteryChartView.setClickableForce(true);
when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
.thenReturn(false);
mBatteryChartView.onAttachedToWindow();
+
assertThat(mBatteryChartView.isClickable()).isFalse();
assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNotNull();
}
@Test
- public void testClickable_accessibilityIsDisabled_clickable() {
+ public void clickable_accessibilityIsDisabled_clickable() {
mBatteryChartView.setClickableForce(true);
when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
.thenReturn(true);
doReturn(false).when(mMockAccessibilityManager).isEnabled();
mBatteryChartView.onAttachedToWindow();
+
assertThat(mBatteryChartView.isClickable()).isTrue();
assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNull();
}
@Test
- public void testClickable_accessibilityIsEnabledWithoutValidId_clickable() {
+ public void clickable_accessibilityIsEnabledWithoutValidId_clickable() {
mBatteryChartView.setClickableForce(true);
when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
.thenReturn(true);
@@ -161,30 +167,34 @@ public final class BatteryChartViewTest {
.getEnabledAccessibilityServiceList(anyInt());
mBatteryChartView.onAttachedToWindow();
+
assertThat(mBatteryChartView.isClickable()).isTrue();
assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNull();
}
@Test
- public void testClickable_accessibilityIsEnabledWithValidId_notClickable() {
+ public void clickable_accessibilityIsEnabledWithValidId_notClickable() {
mBatteryChartView.setClickableForce(true);
when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
.thenReturn(true);
doReturn(true).when(mMockAccessibilityManager).isEnabled();
mBatteryChartView.onAttachedToWindow();
+
assertThat(mBatteryChartView.isClickable()).isFalse();
assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNotNull();
}
@Test
- public void testClickable_restoreFromNonClickableState() {
- final int[] levels = new int[13];
- for (int index = 0; index < levels.length; index++) {
- levels[index] = index + 1;
+ public void clickable_restoreFromNonClickableState() {
+ final List levels = new ArrayList();
+ final List texts = new ArrayList();
+ for (int index = 0; index < 13; index++) {
+ levels.add(index + 1);
+ texts.add("");
}
- mBatteryChartView.setTrapezoidCount(12);
- mBatteryChartView.setLevels(levels);
+ mBatteryChartView.setViewModel(new BatteryChartViewModel(levels, texts,
+ BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
mBatteryChartView.setClickableForce(true);
when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
.thenReturn(true);
@@ -201,14 +211,14 @@ public final class BatteryChartViewTest {
}
@Test
- public void testOnAttachedToWindow_addAccessibilityStateChangeListener() {
+ public void onAttachedToWindow_addAccessibilityStateChangeListener() {
mBatteryChartView.onAttachedToWindow();
verify(mMockAccessibilityManager)
.addAccessibilityStateChangeListener(mBatteryChartView);
}
@Test
- public void testOnDetachedFromWindow_removeAccessibilityStateChangeListener() {
+ public void onDetachedFromWindow_removeAccessibilityStateChangeListener() {
mBatteryChartView.onAttachedToWindow();
mBatteryChartView.mHandler.postDelayed(
mBatteryChartView.mUpdateClickableStateRun, 1000);
@@ -223,7 +233,7 @@ public final class BatteryChartViewTest {
}
@Test
- public void testOnAccessibilityStateChanged_postUpdateStateRunnable() {
+ public void onAccessibilityStateChanged_postUpdateStateRunnable() {
mBatteryChartView.mHandler = spy(mBatteryChartView.mHandler);
mBatteryChartView.onAccessibilityStateChanged(/*enabled=*/ true);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2Test.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2Test.java
deleted file mode 100644
index 10e62d69dfb..00000000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartViewV2Test.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * 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 static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.accessibilityservice.AccessibilityServiceInfo;
-import android.content.Context;
-import android.os.LocaleList;
-import android.view.View;
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
-import com.android.settings.testutils.FakeFeatureFactory;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
-
-@RunWith(RobolectricTestRunner.class)
-public final class BatteryChartViewV2Test {
-
- private Context mContext;
- private BatteryChartViewV2 mBatteryChartView;
- private FakeFeatureFactory mFeatureFactory;
- private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
-
- @Mock
- private AccessibilityServiceInfo mMockAccessibilityServiceInfo;
- @Mock
- private AccessibilityManager mMockAccessibilityManager;
- @Mock
- private View mMockView;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mFeatureFactory = FakeFeatureFactory.setupForTest();
- mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
- mContext = spy(RuntimeEnvironment.application);
- mContext.getResources().getConfiguration().setLocales(
- new LocaleList(new Locale("en_US")));
- mBatteryChartView = new BatteryChartViewV2(mContext);
- doReturn(mMockAccessibilityManager).when(mContext)
- .getSystemService(AccessibilityManager.class);
- doReturn("TalkBackService").when(mMockAccessibilityServiceInfo).getId();
- doReturn(Arrays.asList(mMockAccessibilityServiceInfo))
- .when(mMockAccessibilityManager)
- .getEnabledAccessibilityServiceList(anyInt());
- }
-
- @Test
- public void isAccessibilityEnabled_disable_returnFalse() {
- doReturn(false).when(mMockAccessibilityManager).isEnabled();
- assertThat(BatteryChartViewV2.isAccessibilityEnabled(mContext)).isFalse();
- }
-
- @Test
- public void isAccessibilityEnabled_emptyInfo_returnFalse() {
- doReturn(true).when(mMockAccessibilityManager).isEnabled();
- doReturn(new ArrayList())
- .when(mMockAccessibilityManager)
- .getEnabledAccessibilityServiceList(anyInt());
-
- assertThat(BatteryChartViewV2.isAccessibilityEnabled(mContext)).isFalse();
- }
-
- @Test
- public void isAccessibilityEnabled_validServiceId_returnTrue() {
- doReturn(true).when(mMockAccessibilityManager).isEnabled();
- assertThat(BatteryChartViewV2.isAccessibilityEnabled(mContext)).isTrue();
- }
-
- @Test
- public void onClick_invokesCallback() {
- final int originalSelectedIndex = 2;
- BatteryChartViewModel batteryChartViewModel = new BatteryChartViewModel(
- List.of(90, 80, 70, 60), List.of("", "", "", ""),
- BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS);
- batteryChartViewModel.setSelectedIndex(originalSelectedIndex);
- mBatteryChartView.setViewModel(batteryChartViewModel);
- 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;
- }
- final int[] selectedIndex = new int[1];
- mBatteryChartView.setOnSelectListener(
- trapezoidIndex -> {
- selectedIndex[0] = trapezoidIndex;
- });
-
- // Verify onClick() a different index 1.
- mBatteryChartView.mTouchUpEventX = 1;
- selectedIndex[0] = Integer.MIN_VALUE;
- mBatteryChartView.onClick(mMockView);
- assertThat(selectedIndex[0]).isEqualTo(1);
-
- // Verify onClick() the same index 2.
- mBatteryChartView.mTouchUpEventX = 2;
- selectedIndex[0] = Integer.MIN_VALUE;
- mBatteryChartView.onClick(mMockView);
- assertThat(selectedIndex[0]).isEqualTo(BatteryChartViewModel.SELECTED_INDEX_ALL);
- }
-
- @Test
- public void clickable_isChartGraphSlotsEnabledIsFalse_notClickable() {
- mBatteryChartView.setClickableForce(true);
- when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
- .thenReturn(false);
-
- mBatteryChartView.onAttachedToWindow();
-
- assertThat(mBatteryChartView.isClickable()).isFalse();
- assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNotNull();
- }
-
- @Test
- public void clickable_accessibilityIsDisabled_clickable() {
- mBatteryChartView.setClickableForce(true);
- when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
- .thenReturn(true);
- doReturn(false).when(mMockAccessibilityManager).isEnabled();
-
- mBatteryChartView.onAttachedToWindow();
-
- assertThat(mBatteryChartView.isClickable()).isTrue();
- assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNull();
- }
-
- @Test
- public void clickable_accessibilityIsEnabledWithoutValidId_clickable() {
- mBatteryChartView.setClickableForce(true);
- when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
- .thenReturn(true);
- doReturn(true).when(mMockAccessibilityManager).isEnabled();
- doReturn(new ArrayList())
- .when(mMockAccessibilityManager)
- .getEnabledAccessibilityServiceList(anyInt());
-
- mBatteryChartView.onAttachedToWindow();
-
- assertThat(mBatteryChartView.isClickable()).isTrue();
- assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNull();
- }
-
- @Test
- public void clickable_accessibilityIsEnabledWithValidId_notClickable() {
- mBatteryChartView.setClickableForce(true);
- when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
- .thenReturn(true);
- doReturn(true).when(mMockAccessibilityManager).isEnabled();
-
- mBatteryChartView.onAttachedToWindow();
-
- assertThat(mBatteryChartView.isClickable()).isFalse();
- assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNotNull();
- }
-
- @Test
- public void clickable_restoreFromNonClickableState() {
- final List levels = new ArrayList();
- final List texts = new ArrayList();
- for (int index = 0; index < 13; index++) {
- levels.add(index + 1);
- texts.add("");
- }
- mBatteryChartView.setViewModel(new BatteryChartViewModel(levels, texts,
- BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS));
- mBatteryChartView.setClickableForce(true);
- when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
- .thenReturn(true);
- doReturn(true).when(mMockAccessibilityManager).isEnabled();
- mBatteryChartView.onAttachedToWindow();
- // Ensures the testing environment is correct.
- assertThat(mBatteryChartView.isClickable()).isFalse();
- // Turns off accessibility service.
- doReturn(false).when(mMockAccessibilityManager).isEnabled();
-
- mBatteryChartView.onAttachedToWindow();
-
- assertThat(mBatteryChartView.isClickable()).isTrue();
- }
-
- @Test
- public void onAttachedToWindow_addAccessibilityStateChangeListener() {
- mBatteryChartView.onAttachedToWindow();
- verify(mMockAccessibilityManager)
- .addAccessibilityStateChangeListener(mBatteryChartView);
- }
-
- @Test
- public void onDetachedFromWindow_removeAccessibilityStateChangeListener() {
- mBatteryChartView.onAttachedToWindow();
- mBatteryChartView.mHandler.postDelayed(
- mBatteryChartView.mUpdateClickableStateRun, 1000);
-
- mBatteryChartView.onDetachedFromWindow();
-
- verify(mMockAccessibilityManager)
- .removeAccessibilityStateChangeListener(mBatteryChartView);
- assertThat(mBatteryChartView.mHandler.hasCallbacks(
- mBatteryChartView.mUpdateClickableStateRun))
- .isFalse();
- }
-
- @Test
- public void onAccessibilityStateChanged_postUpdateStateRunnable() {
- mBatteryChartView.mHandler = spy(mBatteryChartView.mHandler);
- mBatteryChartView.onAccessibilityStateChanged(/*enabled=*/ true);
-
- verify(mBatteryChartView.mHandler)
- .removeCallbacks(mBatteryChartView.mUpdateClickableStateRun);
- verify(mBatteryChartView.mHandler)
- .postDelayed(mBatteryChartView.mUpdateClickableStateRun, 500L);
- }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryLoaderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryLoaderTest.java
index 98a44de81b8..57178578169 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryLoaderTest.java
@@ -53,7 +53,7 @@ public final class BatteryHistoryLoaderTest {
public void testLoadIBackground_returnsMapFromPowerFeatureProvider() {
final Map> batteryHistoryMap = new HashMap<>();
doReturn(batteryHistoryMap).when(mFeatureFactory.powerUsageFeatureProvider)
- .getBatteryHistory(mContext);
+ .getBatteryHistorySinceLastFullCharge(mContext);
assertThat(mBatteryHistoryLoader.loadInBackground())
.isSameInstanceAs(batteryHistoryMap);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
index c1f981539c1..c9bac030ac8 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
@@ -26,6 +26,7 @@ import android.os.BatteryManager;
import android.os.BatteryUsageStats;
import android.os.LocaleList;
import android.os.UserHandle;
+import android.text.format.DateUtils;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
@@ -39,8 +40,8 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -173,7 +174,8 @@ public final class ConvertUtilsTest {
public void getIndexedUsageMap_returnsExpectedResult() {
// Creates the fake testing data.
final int timeSlotSize = 2;
- final long[] batteryHistoryKeys = new long[]{101L, 102L, 103L, 104L, 105L};
+ final long[] batteryHistoryKeys = new long[]{generateTimestamp(0), generateTimestamp(1),
+ generateTimestamp(2), generateTimestamp(3), generateTimestamp(4)};
final Map> batteryHistoryMap =
new HashMap<>();
final BatteryHistEntry fakeEntry = createBatteryHistEntry(
@@ -270,11 +272,11 @@ public final class ConvertUtilsTest {
for (int index = 0; index < remainingSize; index++) {
batteryHistoryMap.put(105L + index + 1, new HashMap<>());
}
- when(mPowerUsageFeatureProvider.getBatteryHistory(mContext))
+ when(mPowerUsageFeatureProvider.getBatteryHistorySinceLastFullCharge(mContext))
.thenReturn(batteryHistoryMap);
final List batteryDiffEntryList =
- BatteryChartPreferenceController.getBatteryLast24HrUsageData(mContext);
+ BatteryChartPreferenceController.getAppBatteryUsageData(mContext);
assertThat(batteryDiffEntryList).isNotEmpty();
final BatteryDiffEntry resultEntry = batteryDiffEntryList.get(0);
@@ -472,4 +474,9 @@ public final class ConvertUtilsTest {
assertThat(entry.mForegroundUsageTimeInMs).isEqualTo(foregroundUsageTimeInMs);
assertThat(entry.mBackgroundUsageTimeInMs).isEqualTo(backgroundUsageTimeInMs);
}
+
+ private static Long generateTimestamp(int index) {
+ // "2021-04-23 07:00:00 UTC" + index hours
+ return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS;
+ }
}