Refresh category title by different time slot condition

Bug: 177406865
Bug: 185187729
Test: make SettingsRoboTests
Test: make SettingsGoogleRoboTests
Change-Id: Ib124e1cfb9549f838540ff547bc616049f65180d
This commit is contained in:
ykhung
2021-04-24 14:29:25 +08:00
committed by YUKAI HUNG
parent 219dabcabf
commit 41fd8a7494
7 changed files with 196 additions and 12 deletions

View File

@@ -38,7 +38,6 @@
android:paddingEnd="4dp" android:paddingEnd="4dp"
android:singleLine="true" android:singleLine="true"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:text="@string/battery_system_usage_for_past_24"
style="@style/PreferenceCategoryTitleTextStyle"/> style="@style/PreferenceCategoryTitleTextStyle"/>
<ImageView <ImageView

View File

@@ -6442,9 +6442,9 @@
<!-- [CHAR_LIMIT=NONE] Battery system usage section header for past 24 hour --> <!-- [CHAR_LIMIT=NONE] Battery system usage section header for past 24 hour -->
<string name="battery_system_usage_for_past_24">System usage for past 24 hr</string> <string name="battery_system_usage_for_past_24">System usage for past 24 hr</string>
<!-- [CHAR_LIMIT=NONE] Battery system usage section header --> <!-- [CHAR_LIMIT=NONE] Battery system usage section header -->
<string name="battery_system_usage_for">System usage for</string> <string name="battery_system_usage_for">System usage for <xliff:g id="slot">%s</xliff:g></string>
<!-- [CHAR_LIMIT=NONE] Battery app usage section header --> <!-- [CHAR_LIMIT=NONE] Battery app usage section header -->
<string name="battery_app_usage_for">App usage for</string> <string name="battery_app_usage_for">App usage for <xliff:g id="slot">%s</xliff:g></string>
<!-- [CHAR_LIMIT=NONE] Battery usage section header for a specific time slot --> <!-- [CHAR_LIMIT=NONE] Battery usage section header for a specific time slot -->
<string name="battery_usage_time_am">am</string> <string name="battery_usage_time_am">am</string>
<!-- [CHAR_LIMIT=NONE] Battery usage section header for a specific time slot --> <!-- [CHAR_LIMIT=NONE] Battery usage section header for a specific time slot -->

View File

@@ -65,6 +65,8 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
@VisibleForTesting PreferenceGroup mAppListPrefGroup; @VisibleForTesting PreferenceGroup mAppListPrefGroup;
@VisibleForTesting BatteryChartView mBatteryChartView; @VisibleForTesting BatteryChartView mBatteryChartView;
@VisibleForTesting ExpandDividerPreference mExpandDividerPreference; @VisibleForTesting ExpandDividerPreference mExpandDividerPreference;
@VisibleForTesting CategoryTitleType mCategoryTitleType =
CategoryTitleType.TYPE_UNKNOWN;
@VisibleForTesting int[] mBatteryHistoryLevels; @VisibleForTesting int[] mBatteryHistoryLevels;
@VisibleForTesting long[] mBatteryHistoryKeys; @VisibleForTesting long[] mBatteryHistoryKeys;
@@ -84,6 +86,14 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
@VisibleForTesting @VisibleForTesting
final List<BatteryDiffEntry> mSystemEntries = new ArrayList<>(); final List<BatteryDiffEntry> 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( public BatteryChartPreferenceController(
Context context, String preferenceKey, Context context, String preferenceKey,
Lifecycle lifecycle, SettingsActivity activity, Lifecycle lifecycle, SettingsActivity activity,
@@ -263,11 +273,13 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
mHandler.post(() -> { mHandler.post(() -> {
removeAndCacheAllPrefs(); removeAndCacheAllPrefs();
addAllPreferences(); addAllPreferences();
refreshCategoryTitle();
}); });
return true; return true;
} }
private void addAllPreferences() { private void addAllPreferences() {
mCategoryTitleType = CategoryTitleType.TYPE_UNKNOWN;
final List<BatteryDiffEntry> entries = final List<BatteryDiffEntry> entries =
mBatteryIndexedMap.get(Integer.valueOf(mTrapezoidIndex)); mBatteryIndexedMap.get(Integer.valueOf(mTrapezoidIndex));
if (entries == null) { if (entries == null) {
@@ -296,6 +308,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
// Adds app entries to the list if it is not empty. // Adds app entries to the list if it is not empty.
if (!appEntries.isEmpty()) { if (!appEntries.isEmpty()) {
addPreferenceToScreen(appEntries); addPreferenceToScreen(appEntries);
mCategoryTitleType = CategoryTitleType.TYPE_APP_COMPONENT;
} }
// Adds the expabable divider if we have two sections data. // Adds the expabable divider if we have two sections data.
if (!appEntries.isEmpty() && !mSystemEntries.isEmpty()) { if (!appEntries.isEmpty() && !mSystemEntries.isEmpty()) {
@@ -306,6 +319,9 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
mExpandDividerPreference.setOrder( mExpandDividerPreference.setOrder(
mAppListPrefGroup.getPreferenceCount()); mAppListPrefGroup.getPreferenceCount());
mAppListPrefGroup.addPreference(mExpandDividerPreference); mAppListPrefGroup.addPreference(mExpandDividerPreference);
mCategoryTitleType = CategoryTitleType.TYPE_ALL_COMPONENTS;
} else if (appEntries.isEmpty() && !mSystemEntries.isEmpty()) {
mCategoryTitleType = CategoryTitleType.TYPE_SYSTEM_COMPONENT;
} }
refreshExpandUi(); 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 @VisibleForTesting
void setPreferenceSummary( void setPreferenceSummary(
PowerGaugePreference preference, BatteryDiffEntry entry) { PowerGaugePreference preference, BatteryDiffEntry entry) {

View File

@@ -71,9 +71,10 @@ public class ExpandDividerPreference extends Preference {
} }
} }
void setTitle(String titleContent) { void setTitle(final String titleContent) {
if (mTextView != null) { if (mTextView != null) {
mTextView.setText(titleContent); mTextView.postDelayed(
() -> mTextView.setText(titleContent), 50);
} }
} }

View File

@@ -52,8 +52,10 @@ import org.robolectric.RuntimeEnvironment;
import java.util.Arrays; import java.util.Arrays;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TimeZone;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public final class BatteryChartPreferenceControllerTest { public final class BatteryChartPreferenceControllerTest {
@@ -68,6 +70,7 @@ public final class BatteryChartPreferenceControllerTest {
@Mock private BatteryHistEntry mBatteryHistEntry; @Mock private BatteryHistEntry mBatteryHistEntry;
@Mock private BatteryChartView mBatteryChartView; @Mock private BatteryChartView mBatteryChartView;
@Mock private PowerGaugePreference mPowerGaugePreference; @Mock private PowerGaugePreference mPowerGaugePreference;
@Mock private ExpandDividerPreference mExpandDividerPreference;
@Mock private BatteryUtils mBatteryUtils; @Mock private BatteryUtils mBatteryUtils;
private Context mContext; private Context mContext;
@@ -480,6 +483,94 @@ public final class BatteryChartPreferenceControllerTest {
assertThat(mBatteryChartPreferenceController.mPreferenceCache).hasSize(1); 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<String> 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<String> 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<String> 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<String> 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<Long, List<BatteryHistEntry>> createBatteryHistoryMap(int size) { private static Map<Long, List<BatteryHistEntry>> createBatteryHistoryMap(int size) {
final Map<Long, List<BatteryHistEntry>> batteryHistoryMap = new HashMap<>(); final Map<Long, List<BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
for (int index = 0; index < size; index++) { for (int index = 0; index < size; index++) {
@@ -497,4 +588,13 @@ public final class BatteryChartPreferenceControllerTest {
mContext, foregroundUsageTimeInMs, backgroundUsageTimeInMs, mContext, foregroundUsageTimeInMs, backgroundUsageTimeInMs,
/*consumePower=*/ 0, mBatteryHistEntry); /*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"));
}
} }

View File

@@ -263,10 +263,10 @@ public final class ConvertUtilsTest {
// Invokes the method first to create the SimpleDateFormat. // Invokes the method first to create the SimpleDateFormat.
ConvertUtils.utcToLocalTime(/*timestamp=*/ 0); ConvertUtils.utcToLocalTime(/*timestamp=*/ 0);
ConvertUtils.sSimpleDateFormat ConvertUtils.sSimpleDateFormat
.setTimeZone(TimeZone.getTimeZone("GMT")); .setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
assertThat(ConvertUtils.utcToLocalTime(timestamp)) assertThat(ConvertUtils.utcToLocalTime(timestamp))
.isEqualTo("Apr 23,2021 16:53:06"); .isEqualTo("Apr 23,2021 09:53:06");
} }
@Test @Test
@@ -276,10 +276,10 @@ public final class ConvertUtilsTest {
// Invokes the method first to create the SimpleDateFormat. // Invokes the method first to create the SimpleDateFormat.
ConvertUtils.utcToLocalTimeHour(/*timestamp=*/ 0); ConvertUtils.utcToLocalTimeHour(/*timestamp=*/ 0);
ConvertUtils.sSimpleDateFormatForHour ConvertUtils.sSimpleDateFormatForHour
.setTimeZone(TimeZone.getTimeZone("GMT")); .setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
assertThat(ConvertUtils.utcToLocalTimeHour(timestamp)) assertThat(ConvertUtils.utcToLocalTimeHour(timestamp))
.isEqualTo("4 pm"); .isEqualTo("9 am");
} }
private static BatteryHistEntry createBatteryHistEntry( private static BatteryHistEntry createBatteryHistEntry(

View File

@@ -19,6 +19,7 @@ package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
@@ -35,7 +36,7 @@ import com.android.settings.R;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.ArgumentCaptor;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
@@ -46,13 +47,15 @@ public final class ExpandDividerPreferenceTest {
private Context mContext; private Context mContext;
private ExpandDividerPreference mExpandDividerPreference; private ExpandDividerPreference mExpandDividerPreference;
@Mock private ImageView mImageView; private ImageView mImageView;
@Mock private TextView mTextView; private TextView mTextView;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application); mContext = spy(RuntimeEnvironment.application);
mImageView = spy(new ImageView(mContext));
mTextView = spy(new TextView(mContext));
mExpandDividerPreference = new ExpandDividerPreference(mContext); mExpandDividerPreference = new ExpandDividerPreference(mContext);
doReturn(R.id.expand_title).when(mTextView).getId(); doReturn(R.id.expand_title).when(mTextView).getId();
doReturn(R.id.expand_icon).when(mImageView).getId(); doReturn(R.id.expand_icon).when(mImageView).getId();
@@ -72,6 +75,9 @@ public final class ExpandDividerPreferenceTest {
mExpandDividerPreference.mTextView = mTextView; mExpandDividerPreference.mTextView = mTextView;
mExpandDividerPreference.setTitle(titleContent); mExpandDividerPreference.setTitle(titleContent);
final ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
verify(mTextView).postDelayed(captor.capture(), eq(50L));
captor.getValue().run();
verify(mTextView).setText(titleContent); verify(mTextView).setText(titleContent);
} }