diff --git a/res/layout/preference_expand_divider.xml b/res/layout/preference_expand_divider.xml index 685ec0ea2e6..164419a8c51 100644 --- a/res/layout/preference_expand_divider.xml +++ b/res/layout/preference_expand_divider.xml @@ -38,7 +38,6 @@ android:paddingEnd="4dp" android:singleLine="true" android:textAlignment="viewStart" - android:text="@string/battery_system_usage_for_past_24" style="@style/PreferenceCategoryTitleTextStyle"/> System usage for past 24 hr - System usage for + System usage for %s - App usage for + App usage for %s am diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java index 7131f28eb20..649b410c9e2 100644 --- a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java +++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java @@ -65,6 +65,8 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll @VisibleForTesting PreferenceGroup mAppListPrefGroup; @VisibleForTesting BatteryChartView mBatteryChartView; @VisibleForTesting ExpandDividerPreference mExpandDividerPreference; + @VisibleForTesting CategoryTitleType mCategoryTitleType = + CategoryTitleType.TYPE_UNKNOWN; @VisibleForTesting int[] mBatteryHistoryLevels; @VisibleForTesting long[] mBatteryHistoryKeys; @@ -84,6 +86,14 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll @VisibleForTesting final List mSystemEntries = new ArrayList<>(); + /** Which component data will be shown in the screen. */ + enum CategoryTitleType { + TYPE_UNKNOWN, + TYPE_APP_COMPONENT, + TYPE_SYSTEM_COMPONENT, + TYPE_ALL_COMPONENTS + } + public BatteryChartPreferenceController( Context context, String preferenceKey, Lifecycle lifecycle, SettingsActivity activity, @@ -263,11 +273,13 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll mHandler.post(() -> { removeAndCacheAllPrefs(); addAllPreferences(); + refreshCategoryTitle(); }); return true; } private void addAllPreferences() { + mCategoryTitleType = CategoryTitleType.TYPE_UNKNOWN; final List entries = mBatteryIndexedMap.get(Integer.valueOf(mTrapezoidIndex)); if (entries == null) { @@ -296,6 +308,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll // Adds app entries to the list if it is not empty. if (!appEntries.isEmpty()) { addPreferenceToScreen(appEntries); + mCategoryTitleType = CategoryTitleType.TYPE_APP_COMPONENT; } // Adds the expabable divider if we have two sections data. if (!appEntries.isEmpty() && !mSystemEntries.isEmpty()) { @@ -306,6 +319,9 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll mExpandDividerPreference.setOrder( mAppListPrefGroup.getPreferenceCount()); mAppListPrefGroup.addPreference(mExpandDividerPreference); + mCategoryTitleType = CategoryTitleType.TYPE_ALL_COMPONENTS; + } else if (appEntries.isEmpty() && !mSystemEntries.isEmpty()) { + mCategoryTitleType = CategoryTitleType.TYPE_SYSTEM_COMPONENT; } refreshExpandUi(); } @@ -385,6 +401,68 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll } } + @VisibleForTesting + void refreshCategoryTitle() { + final String slotInformation = getSlotInformation(); + Log.d(TAG, String.format("refreshCategoryTitle:%s slotInfo:%s", + mCategoryTitleType, slotInformation)); + refreshPreferenceCategoryTitle(slotInformation); + refreshExpandableDividerTitle(slotInformation); + } + + private void refreshExpandableDividerTitle(String slotInformation) { + if (mExpandDividerPreference == null) { + return; + } + mExpandDividerPreference.setTitle( + mCategoryTitleType == CategoryTitleType.TYPE_ALL_COMPONENTS + ? getSlotInformation(/*isApp=*/ false, slotInformation) + : null); + } + + private void refreshPreferenceCategoryTitle(String slotInformation) { + if (mAppListPrefGroup == null) { + return; + } + switch (mCategoryTitleType) { + case TYPE_APP_COMPONENT: + case TYPE_ALL_COMPONENTS: + mAppListPrefGroup.setTitle( + getSlotInformation(/*isApp=*/ true, slotInformation)); + break; + case TYPE_SYSTEM_COMPONENT: + mAppListPrefGroup.setTitle( + getSlotInformation(/*isApp=*/ false, slotInformation)); + break; + default: + mAppListPrefGroup.setTitle(R.string.battery_app_usage_for_past_24); + } + } + + private String getSlotInformation(boolean isApp, String slotInformation) { + // 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); + } else { + return isApp + ? mPrefContext.getString(R.string.battery_app_usage_for, slotInformation) + : mPrefContext.getString(R.string.battery_system_usage_for ,slotInformation); + } + } + + private String getSlotInformation() { + if (mTrapezoidIndex < 0) { + return null; + } + final String fromHour = ConvertUtils.utcToLocalTimeHour( + mBatteryHistoryKeys[mTrapezoidIndex * 2]); + final String toHour = ConvertUtils.utcToLocalTimeHour( + mBatteryHistoryKeys[(mTrapezoidIndex + 1) * 2]); + return String.format("%s-%s", fromHour, toHour); + } + @VisibleForTesting void setPreferenceSummary( PowerGaugePreference preference, BatteryDiffEntry entry) { diff --git a/src/com/android/settings/fuelgauge/ExpandDividerPreference.java b/src/com/android/settings/fuelgauge/ExpandDividerPreference.java index 06476df4564..40536eb37c7 100644 --- a/src/com/android/settings/fuelgauge/ExpandDividerPreference.java +++ b/src/com/android/settings/fuelgauge/ExpandDividerPreference.java @@ -71,9 +71,10 @@ public class ExpandDividerPreference extends Preference { } } - void setTitle(String titleContent) { + void setTitle(final String titleContent) { if (mTextView != null) { - mTextView.setText(titleContent); + mTextView.postDelayed( + () -> mTextView.setText(titleContent), 50); } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java index 9f0ffb01b10..9cf45ea9a1b 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java @@ -52,8 +52,10 @@ import org.robolectric.RuntimeEnvironment; import java.util.Arrays; import java.util.ArrayList; import java.util.HashMap; +import java.util.Locale; import java.util.List; import java.util.Map; +import java.util.TimeZone; @RunWith(RobolectricTestRunner.class) public final class BatteryChartPreferenceControllerTest { @@ -68,6 +70,7 @@ public final class BatteryChartPreferenceControllerTest { @Mock private BatteryHistEntry mBatteryHistEntry; @Mock private BatteryChartView mBatteryChartView; @Mock private PowerGaugePreference mPowerGaugePreference; + @Mock private ExpandDividerPreference mExpandDividerPreference; @Mock private BatteryUtils mBatteryUtils; private Context mContext; @@ -480,6 +483,94 @@ public final class BatteryChartPreferenceControllerTest { assertThat(mBatteryChartPreferenceController.mPreferenceCache).hasSize(1); } + @Test + public void testRefreshCategoryTitle_appComponent_setHourIntoPreferenceTitle() { + setUpBatteryHistoryKeys(); + mBatteryChartPreferenceController.mCategoryTitleType = + BatteryChartPreferenceController.CategoryTitleType.TYPE_APP_COMPONENT; + mBatteryChartPreferenceController.mExpandDividerPreference = + mExpandDividerPreference; + // Simulates select the first slot. + mBatteryChartPreferenceController.mTrapezoidIndex = 0; + + mBatteryChartPreferenceController.refreshCategoryTitle(); + + final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + // Verifies the title in the preference group. + verify(mAppListGroup).setTitle(captor.capture()); + assertThat(captor.getValue()) + .isEqualTo("App usage for 4 pm-7 am"); + verify(mExpandDividerPreference).setTitle(null); + } + + @Test + public void testRefreshCategoryTitle_systemComponent_setHourIntoPreferenceTitle() { + setUpBatteryHistoryKeys(); + mBatteryChartPreferenceController.mCategoryTitleType = + BatteryChartPreferenceController.CategoryTitleType.TYPE_SYSTEM_COMPONENT; + mBatteryChartPreferenceController.mExpandDividerPreference = + mExpandDividerPreference; + // Simulates select the first slot. + mBatteryChartPreferenceController.mTrapezoidIndex = 0; + + mBatteryChartPreferenceController.refreshCategoryTitle(); + + final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + // Verifies the title in the preference group. + verify(mAppListGroup).setTitle(captor.capture()); + assertThat(captor.getValue()) + .isEqualTo("System usage for 4 pm-7 am"); + verify(mExpandDividerPreference).setTitle(null); + } + + @Test + public void testRefreshCategoryTitle_allComponents_setHourIntoBothTitleTextView() { + setUpBatteryHistoryKeys(); + mBatteryChartPreferenceController.mCategoryTitleType = + BatteryChartPreferenceController.CategoryTitleType.TYPE_ALL_COMPONENTS; + mBatteryChartPreferenceController.mExpandDividerPreference = + mExpandDividerPreference; + // Simulates select the first slot. + mBatteryChartPreferenceController.mTrapezoidIndex = 0; + + mBatteryChartPreferenceController.refreshCategoryTitle(); + + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + // Verifies the title in the preference group. + verify(mAppListGroup).setTitle(captor.capture()); + assertThat(captor.getValue()) + .isEqualTo("App usage for 4 pm-7 am"); + // Verifies the title in the expandable divider. + captor = ArgumentCaptor.forClass(String.class); + verify(mExpandDividerPreference).setTitle(captor.capture()); + assertThat(captor.getValue()) + .isEqualTo("System usage for 4 pm-7 am"); + } + + @Test + public void testRefreshCategoryTitle_allComponents_setLast24HrIntoBothTitleTextView() { + mBatteryChartPreferenceController.mCategoryTitleType = + BatteryChartPreferenceController.CategoryTitleType.TYPE_ALL_COMPONENTS; + mBatteryChartPreferenceController.mExpandDividerPreference = + mExpandDividerPreference; + // Simulates select all condition. + mBatteryChartPreferenceController.mTrapezoidIndex = + BatteryChartView.SELECTED_INDEX_ALL; + + mBatteryChartPreferenceController.refreshCategoryTitle(); + + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + // Verifies the title in the preference group. + verify(mAppListGroup).setTitle(captor.capture()); + assertThat(captor.getValue()) + .isEqualTo("App usage for past 24 hr"); + // Verifies the title in the expandable divider. + captor = ArgumentCaptor.forClass(String.class); + verify(mExpandDividerPreference).setTitle(captor.capture()); + assertThat(captor.getValue()) + .isEqualTo("System usage for past 24 hr"); + } + private static Map> createBatteryHistoryMap(int size) { final Map> batteryHistoryMap = new HashMap<>(); for (int index = 0; index < size; index++) { @@ -497,4 +588,13 @@ public final class BatteryChartPreferenceControllerTest { mContext, foregroundUsageTimeInMs, backgroundUsageTimeInMs, /*consumePower=*/ 0, mBatteryHistEntry); } + + private void setUpBatteryHistoryKeys() { + mBatteryChartPreferenceController.mBatteryHistoryKeys = + new long[] {1619196786769L, 0L, 1619247636826L}; + ConvertUtils.utcToLocalTimeHour(/*timestamp=*/ 0); + // Simulates the locale in GMT. + ConvertUtils.sSimpleDateFormatForHour + .setTimeZone(TimeZone.getTimeZone("GMT")); + } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java index 12913a29dc8..c9c9f3b4a57 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java @@ -263,10 +263,10 @@ public final class ConvertUtilsTest { // Invokes the method first to create the SimpleDateFormat. ConvertUtils.utcToLocalTime(/*timestamp=*/ 0); ConvertUtils.sSimpleDateFormat - .setTimeZone(TimeZone.getTimeZone("GMT")); + .setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); assertThat(ConvertUtils.utcToLocalTime(timestamp)) - .isEqualTo("Apr 23,2021 16:53:06"); + .isEqualTo("Apr 23,2021 09:53:06"); } @Test @@ -276,10 +276,10 @@ public final class ConvertUtilsTest { // Invokes the method first to create the SimpleDateFormat. ConvertUtils.utcToLocalTimeHour(/*timestamp=*/ 0); ConvertUtils.sSimpleDateFormatForHour - .setTimeZone(TimeZone.getTimeZone("GMT")); + .setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); assertThat(ConvertUtils.utcToLocalTimeHour(timestamp)) - .isEqualTo("4 pm"); + .isEqualTo("9 am"); } private static BatteryHistEntry createBatteryHistEntry( diff --git a/tests/robotests/src/com/android/settings/fuelgauge/ExpandDividerPreferenceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/ExpandDividerPreferenceTest.java index f9009a145b8..97af2827e6f 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/ExpandDividerPreferenceTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/ExpandDividerPreferenceTest.java @@ -19,6 +19,7 @@ package com.android.settings.fuelgauge; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; @@ -35,7 +36,7 @@ import com.android.settings.R; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; +import org.mockito.ArgumentCaptor; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; @@ -46,13 +47,15 @@ public final class ExpandDividerPreferenceTest { private Context mContext; private ExpandDividerPreference mExpandDividerPreference; - @Mock private ImageView mImageView; - @Mock private TextView mTextView; + private ImageView mImageView; + private TextView mTextView; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); + mImageView = spy(new ImageView(mContext)); + mTextView = spy(new TextView(mContext)); mExpandDividerPreference = new ExpandDividerPreference(mContext); doReturn(R.id.expand_title).when(mTextView).getId(); doReturn(R.id.expand_icon).when(mImageView).getId(); @@ -72,6 +75,9 @@ public final class ExpandDividerPreferenceTest { mExpandDividerPreference.mTextView = mTextView; mExpandDividerPreference.setTitle(titleContent); + final ArgumentCaptor captor = ArgumentCaptor.forClass(Runnable.class); + verify(mTextView).postDelayed(captor.capture(), eq(50L)); + captor.getValue().run(); verify(mTextView).setText(titleContent); }