From f4c1cef322f2c747b606ba0d78563bbb0e887c51 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Fri, 31 Mar 2017 12:57:10 -0700 Subject: [PATCH] Add TtsSpan for formatted time. Talk back will read "Used for 3m" as "Used for 3 meters", but it will read "Used for 3h 3m" correctly. This cl add specific Ttsspan if the time only contains "minute" Bug: 36379530 Test: Run SettingsRoboTests Change-Id: I033575938cce24221980dddd9d66be4e18804541 --- res/values/strings.xml | 12 ++--- src/com/android/settings/Utils.java | 16 ++++-- .../fuelgauge/AdvancedPowerUsageDetail.java | 4 ++ .../settings/fuelgauge/BatteryUtils.java | 6 +-- .../fuelgauge/PowerGaugePreference.java | 6 ++- .../fuelgauge/PowerUsageAdvanced.java | 13 +++-- .../settings/fuelgauge/PowerUsageSummary.java | 26 ++++++---- .../src/com/android/settings/UtilsTest.java | 45 ++++++++++++---- .../applications/InstalledAppDetailsTest.java | 5 +- .../AdvancedPowerUsageDetailTest.java | 3 ++ .../settings/fuelgauge/BatteryUtilsTest.java | 9 ++-- .../fuelgauge/PowerUsageAdvancedTest.java | 8 ++- .../fuelgauge/PowerUsageSummaryTest.java | 52 ++++++++++++------- 13 files changed, 142 insertions(+), 63 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 102de7eddd7..c023c7d0390 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4474,10 +4474,10 @@ Mobile network scanning - - %1$s ago - - App usage since full charge (%1$s ago) + + ^1 ago + + App usage since full charge (^1 ago) Amount of time screen has been on since full charge @@ -4676,8 +4676,8 @@ %d mAh - - Used for %1$s + + Used for ^1 %1$s used by %2$s diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index d04ae8d0de9..f6f980aa28c 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -81,6 +81,8 @@ import android.support.v7.preference.PreferenceScreen; import android.telephony.TelephonyManager; import android.text.Spannable; import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.TextUtils; import android.text.format.DateUtils; import android.text.style.TtsSpan; @@ -770,8 +772,9 @@ public final class Utils extends com.android.settingslib.Utils { * @param withSeconds include seconds? * @return the formatted elapsed time */ - public static String formatElapsedTime(Context context, double millis, boolean withSeconds) { - StringBuilder sb = new StringBuilder(); + public static CharSequence formatElapsedTime(Context context, double millis, + boolean withSeconds) { + SpannableStringBuilder sb = new SpannableStringBuilder(); int seconds = (int) Math.floor(millis / 1000); if (!withSeconds) { // Round up. @@ -812,9 +815,15 @@ public final class Utils extends com.android.settingslib.Utils { hours, minutes)); } else { sb.append(context.getString(R.string.battery_history_minutes_no_seconds, minutes)); + + // Add ttsSpan if it only have minute value, because it will be read as "meters" + TtsSpan ttsSpan = new TtsSpan.MeasureBuilder().setNumber(minutes) + .setUnit("minute").build(); + sb.setSpan(ttsSpan, 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } - return sb.toString(); + + return sb; } /** @@ -1256,4 +1265,5 @@ public final class Utils extends com.android.settingslib.Utils { return (volume != null) && (volume.getType() == VolumeInfo.TYPE_PRIVATE) && volume.isMountedReadable(); } + } diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java index 0c798a64baa..e4f7e227838 100644 --- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java +++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java @@ -28,6 +28,7 @@ import android.os.UserManager; import android.support.annotation.VisibleForTesting; import android.support.v14.preference.PreferenceFragment; import android.support.v7.preference.Preference; +import android.text.TextUtils; import android.view.View; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -82,6 +83,8 @@ public class AdvancedPowerUsageDetail extends PowerUsageBase implements ApplicationsState mState; @VisibleForTesting ApplicationsState.AppEntry mAppEntry; + @VisibleForTesting + BatteryUtils mBatteryUtils; private Preference mForegroundPreference; private Preference mBackgroundPreference; @@ -136,6 +139,7 @@ public class AdvancedPowerUsageDetail extends PowerUsageBase implements (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE)); mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE); mPackageManager = activity.getPackageManager(); + mBatteryUtils = BatteryUtils.getInstance(getContext()); } @Override diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java index 48e2421264a..c8af4a0435e 100644 --- a/src/com/android/settings/fuelgauge/BatteryUtils.java +++ b/src/com/android/settings/fuelgauge/BatteryUtils.java @@ -15,14 +15,13 @@ */ package com.android.settings.fuelgauge; -import android.annotation.IntDef; import android.content.Context; import android.content.pm.PackageManager; import android.os.BatteryStats; import android.os.SystemClock; +import android.support.annotation.IntDef; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; -import android.text.format.DateUtils; import android.util.Log; import com.android.internal.os.BatterySipper; @@ -64,7 +63,8 @@ public class BatteryUtils { return sInstance; } - private BatteryUtils(Context context) { + @VisibleForTesting + BatteryUtils(Context context) { mPackageManager = context.getPackageManager(); mPowerUsageFeatureProvider = FeatureFactory.getFactory( context).getPowerUsageFeatureProvider(context); diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java index bdadf4c7a85..b124c8150b0 100644 --- a/src/com/android/settings/fuelgauge/PowerGaugePreference.java +++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java @@ -79,11 +79,15 @@ public class PowerGaugePreference extends TintablePreference { return mProgress.toString(); } - public void setSubtitle(String subtitle) { + public void setSubtitle(CharSequence subtitle) { mProgress = subtitle; notifyChanged(); } + public CharSequence getSubtitle() { + return mProgress; + } + BatteryEntry getInfo() { return mInfo; } diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java index b718f8f1c41..28dfe1d5a9c 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java +++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java @@ -29,6 +29,7 @@ import android.support.annotation.StringRes; import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceGroup; +import android.text.TextUtils; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.os.BatterySipper; @@ -67,13 +68,15 @@ public class PowerUsageAdvanced extends PowerUsageBase { UsageType.APP, UsageType.UNACCOUNTED, UsageType.OVERCOUNTED}; + + @VisibleForTesting + BatteryUtils mBatteryUtils; private BatteryHistoryPreference mHistPref; private PreferenceGroup mUsageListGroup; private PowerUsageFeatureProvider mPowerUsageFeatureProvider; private PackageManager mPackageManager; private UserManager mUserManager; private Map mBatteryDataMap; - private BatteryUtils mBatteryUtils; Handler mHandler = new Handler() { @@ -270,8 +273,10 @@ public class PowerUsageAdvanced extends PowerUsageBase { return; } if (usageData.usageList.size() <= 1) { - usageData.summary = getString(R.string.battery_used_for, - Utils.formatElapsedTime(getContext(), usageData.totalUsageTimeMs, false)); + CharSequence timeSequence = Utils.formatElapsedTime(getContext(), + usageData.totalUsageTimeMs, false); + usageData.summary = TextUtils.expandTemplate(getText(R.string.battery_used_for), + timeSequence); } else { BatterySipper sipper = findBatterySipperWithMaxBatteryUsage(usageData.usageList); BatteryEntry batteryEntry = new BatteryEntry(getContext(), mHandler, mUserManager, @@ -346,7 +351,7 @@ public class PowerUsageAdvanced extends PowerUsageBase { @StringRes public int titleResId; - public String summary; + public CharSequence summary; public double percentage; public double totalPowerMah; public long totalUsageTimeMs; diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index 5f12d7c30ed..b0dacb06d63 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -415,15 +415,16 @@ public class PowerUsageSummary extends PowerUsageBase { final TypedValue value = new TypedValue(); context.getTheme().resolveAttribute(android.R.attr.colorControlNormal, value, true); final int colorControl = context.getColor(value.resourceId); - final String usedTime = context.getString(R.string.battery_used_for); final int dischargeAmount = USE_FAKE_DATA ? 5000 : stats != null ? stats.getDischargeAmount(mStatsType) : 0; final long runningTime = calculateRunningTimeBasedOnStatsType(); updateScreenPreference(); updateLastFullChargePreference(runningTime); - mAppListGroup.setTitle(getString(R.string.power_usage_list_summary, - Utils.formatElapsedTime(context, runningTime, false))); + + final CharSequence timeSequence = Utils.formatElapsedTime(context, runningTime, false); + mAppListGroup.setTitle( + TextUtils.expandTemplate(getText(R.string.power_usage_list_summary), timeSequence)); if (averagePower >= MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP || USE_FAKE_DATA) { final List usageList = getCoalescedUsageList( @@ -494,7 +495,7 @@ public class PowerUsageSummary extends PowerUsageBase { sipper.usageTimeMs = mBatteryUtils.getProcessTimeMs( BatteryUtils.StatusType.FOREGROUND, sipper.uidObj, mStatsType); } - setUsageSummary(pref, usedTime, sipper.usageTimeMs); + setUsageSummary(pref, sipper.usageTimeMs); if ((sipper.drainType != DrainType.APP || sipper.uidObj.getUid() == Process.ROOT_UID) && sipper.drainType != DrainType.USER) { @@ -531,16 +532,17 @@ public class PowerUsageSummary extends PowerUsageBase { void updateScreenPreference() { final BatterySipper sipper = findBatterySipperByType( mStatsHelper.getUsageList(), DrainType.SCREEN); - final Context context = getContext(); final long usageTimeMs = sipper != null ? sipper.usageTimeMs : 0; - mScreenUsagePref.setSubtitle(Utils.formatElapsedTime(context, usageTimeMs, false)); + mScreenUsagePref.setSubtitle(Utils.formatElapsedTime(getContext(), usageTimeMs, false)); } @VisibleForTesting void updateLastFullChargePreference(long timeMs) { - mLastFullChargePref.setSubtitle(getString(R.string.power_last_full_charge_summary, - Utils.formatElapsedTime(getContext(), timeMs, false))); + final CharSequence timeSequence = Utils.formatElapsedTime(getContext(), timeMs, false); + mLastFullChargePref.setSubtitle( + TextUtils.expandTemplate(getText(R.string.power_last_full_charge_summary), + timeSequence)); } @VisibleForTesting @@ -580,11 +582,13 @@ public class PowerUsageSummary extends PowerUsageBase { } @VisibleForTesting - void setUsageSummary(Preference preference, String usedTimePrefix, long usageTimeMs) { + void setUsageSummary(Preference preference, long usageTimeMs) { // Only show summary when usage time is longer than one minute if (usageTimeMs >= DateUtils.MINUTE_IN_MILLIS) { - preference.setSummary(String.format(usedTimePrefix, - Utils.formatElapsedTime(getContext(), usageTimeMs, false))); + final CharSequence timeSequence = Utils.formatElapsedTime(getContext(), usageTimeMs, + false); + preference.setSummary( + TextUtils.expandTemplate(getText(R.string.battery_used_for), timeSequence)); } } diff --git a/tests/robotests/src/com/android/settings/UtilsTest.java b/tests/robotests/src/com/android/settings/UtilsTest.java index 8b7605c2384..8dfd32a4d1d 100644 --- a/tests/robotests/src/com/android/settings/UtilsTest.java +++ b/tests/robotests/src/com/android/settings/UtilsTest.java @@ -19,7 +19,10 @@ import android.os.Bundle; import android.os.storage.DiskInfo; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; import android.text.format.DateUtils; +import android.text.style.TtsSpan; import org.junit.Before; import org.junit.Test; @@ -35,10 +38,14 @@ import java.net.InetAddress; @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class UtilsTest { + private static final String TIME_DESCRIPTION = "1 day 20 hours 30 minutes"; private Context mContext; - @Mock private WifiManager wifiManager; - @Mock private Network network; - @Mock private ConnectivityManager connectivityManager; + @Mock + private WifiManager wifiManager; + @Mock + private Network network; + @Mock + private ConnectivityManager connectivityManager; @Before public void setUp() { @@ -47,7 +54,7 @@ public class UtilsTest { mContext = spy(RuntimeEnvironment.application); when(mContext.getSystemService(WifiManager.class)).thenReturn(wifiManager); when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)) - .thenReturn(connectivityManager); + .thenReturn(connectivityManager); } @Test @@ -89,7 +96,8 @@ public class UtilsTest { final double testMillis = 5 * DateUtils.MINUTE_IN_MILLIS; final String expectedTime = "5m 0s"; - assertThat(Utils.formatElapsedTime(mContext, testMillis, true)).isEqualTo(expectedTime); + assertThat(Utils.formatElapsedTime(mContext, testMillis, true).toString()).isEqualTo( + expectedTime); } @Test @@ -97,7 +105,8 @@ public class UtilsTest { final double testMillis = 5 * DateUtils.MINUTE_IN_MILLIS; final String expectedTime = "5m"; - assertThat(Utils.formatElapsedTime(mContext, testMillis, false)).isEqualTo(expectedTime); + assertThat(Utils.formatElapsedTime(mContext, testMillis, false).toString()).isEqualTo( + expectedTime); } @Test @@ -106,7 +115,23 @@ public class UtilsTest { + 4 * DateUtils.HOUR_IN_MILLIS + 15 * DateUtils.MINUTE_IN_MILLIS; final String expectedTime = "2d 4h 15m"; - assertThat(Utils.formatElapsedTime(mContext, testMillis, false)).isEqualTo(expectedTime); + assertThat(Utils.formatElapsedTime(mContext, testMillis, false).toString()).isEqualTo( + expectedTime); + } + + @Test + public void testFormatElapsedTime_onlyContainsMinute_hasTtsSpan() { + final double testMillis = 15 * DateUtils.MINUTE_IN_MILLIS; + + final CharSequence charSequence = Utils.formatElapsedTime(mContext, testMillis, false); + assertThat(charSequence).isInstanceOf(SpannableStringBuilder.class); + + final SpannableStringBuilder expectedString = (SpannableStringBuilder) charSequence; + final TtsSpan[] ttsSpans = expectedString.getSpans(0, expectedString.length(), + TtsSpan.class); + + assertThat(ttsSpans).asList().hasSize(1); + assertThat(ttsSpans[0].getType()).isEqualTo(TtsSpan.TYPE_MEASURE); } @Test @@ -119,13 +144,13 @@ public class UtilsTest { } @Test - public void getInstallationStatus_notInstalled_shouldReturnUninstalled() { + public void testGetInstallationStatus_notInstalled_shouldReturnUninstalled() { assertThat(Utils.getInstallationStatus(new ApplicationInfo())) .isEqualTo(R.string.not_installed); } @Test - public void getInstallationStatus_enabled_shouldReturnInstalled() { + public void testGetInstallationStatus_enabled_shouldReturnInstalled() { final ApplicationInfo info = new ApplicationInfo(); info.flags = ApplicationInfo.FLAG_INSTALLED; info.enabled = true; @@ -134,7 +159,7 @@ public class UtilsTest { } @Test - public void getInstallationStatus_disabled_shouldReturnDisabled() { + public void testGetInstallationStatus_disabled_shouldReturnDisabled() { final ApplicationInfo info = new ApplicationInfo(); info.flags = ApplicationInfo.FLAG_INSTALLED; info.enabled = false; diff --git a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java index f3728365abd..9c91ccfcb05 100644 --- a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java +++ b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java @@ -87,6 +87,8 @@ public final class InstalledAppDetailsTest { private BatteryStatsHelper mBatteryStatsHelper; @Mock private BatteryStats.Uid mUid; + @Mock + private PackageManager mPackageManager; private InstalledAppDetails mAppDetail; private Context mShadowContext; @@ -94,14 +96,15 @@ public final class InstalledAppDetailsTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - mShadowContext = RuntimeEnvironment.application; + mShadowContext = RuntimeEnvironment.application; mAppDetail = spy(new InstalledAppDetails()); mBatterySipper.drainType = BatterySipper.DrainType.IDLE; mBatterySipper.uidObj = mUid; doReturn(mActivity).when(mAppDetail).getActivity(); doReturn(mShadowContext).when(mAppDetail).getContext(); + doReturn(mPackageManager).when(mActivity).getPackageManager(); // Default to not considering any apps to be instant (individual tests can override this). ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java index 801034c76e4..2ed45145614 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java @@ -57,6 +57,8 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import org.robolectric.RuntimeEnvironment; + import org.robolectric.annotation.Config; import org.robolectric.util.ReflectionHelpers; @@ -140,6 +142,7 @@ public class AdvancedPowerUsageDetailTest { mFragment.mHeaderPreference = mHeaderPreference; mFragment.mState = mState; + mFragment.mBatteryUtils = new BatteryUtils(RuntimeEnvironment.application); mAppEntry.info = mock(ApplicationInfo.class); mTestActivity = spy(new SettingsActivity()); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java index e5383c87ad5..52cfe4cf826 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java @@ -33,6 +33,9 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; +import java.util.ArrayList; +import java.util.List; + import static android.os.BatteryStats.Uid.PROCESS_STATE_BACKGROUND; import static android.os.BatteryStats.Uid.PROCESS_STATE_FOREGROUND; import static android.os.BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE; @@ -47,9 +50,7 @@ import static org.mockito.Matchers.anyLong; import static org.mockito.Mockito.doReturn; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.when; - -import java.util.ArrayList; -import java.util.List; +import static org.mockito.Mockito.spy; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @@ -127,6 +128,8 @@ public class BatteryUtilsTest { mBatteryUtils = BatteryUtils.getInstance(RuntimeEnvironment.application); mBatteryUtils.mPowerUsageFeatureProvider = mProvider; + + mBatteryUtils = spy(new BatteryUtils(RuntimeEnvironment.application)); } @Test diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java index 41b1c96f577..7a1284a2ddd 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java @@ -18,6 +18,7 @@ package com.android.settings.fuelgauge; import android.content.Context; import android.content.pm.PackageManager; import android.os.UserManager; +import android.text.TextUtils; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatterySipper.DrainType; @@ -105,9 +106,12 @@ public class PowerUsageAdvancedTest { when(mPowerUsageAdvanced.getContext()).thenReturn(mShadowContext); doReturn(STUB_STRING).when(mPowerUsageAdvanced).getString(anyInt(), any(), any()); doReturn(STUB_STRING).when(mPowerUsageAdvanced).getString(anyInt(), any()); + doReturn(mShadowContext.getText(R.string.battery_used_for)).when( + mPowerUsageAdvanced).getText(R.string.battery_used_for); mPowerUsageAdvanced.setPackageManager(mPackageManager); mPowerUsageAdvanced.setPowerUsageFeatureProvider(mPowerUsageFeatureProvider); mPowerUsageAdvanced.setUserManager(mUserManager); + mPowerUsageAdvanced.mBatteryUtils = spy(new BatteryUtils(mShadowContext)); mPowerUsageData = new PowerUsageData(UsageType.APP); mMaxBatterySipper.totalPowerMah = TYPE_BLUETOOTH_USAGE; @@ -176,10 +180,12 @@ public class PowerUsageAdvancedTest { @Test public void testUpdateUsageDataSummary_onlyOneApp_showUsageTime() { + final String expectedSummary = "Used for 0m"; mPowerUsageData.usageList.add(mNormalBatterySipper); + mPowerUsageAdvanced.updateUsageDataSummary(mPowerUsageData, TOTAL_POWER, DISCHARGE_AMOUNT); - verify(mPowerUsageAdvanced).getString(eq(R.string.battery_used_for), any()); + assertThat(mPowerUsageData.summary.toString()).isEqualTo(expectedSummary); } @Test diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java index 39c386b290a..170d517d1b8 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java @@ -86,15 +86,16 @@ import static org.mockito.Mockito.when; public class PowerUsageSummaryTest { private static final String[] PACKAGE_NAMES = {"com.app1", "com.app2"}; private static final String TIME_LEFT = "2h30min"; + private static final String STUB_STRING = "stub_string"; private static final int BATTERY_LEVEL = 55; private static final int UID = 123; private static final int POWER_MAH = 100; private static final long REMAINING_TIME_US = 100000; - private static final long TIME_SINCE_LAST_FULL_CHARGE_MS = 25000; + private static final long TIME_SINCE_LAST_FULL_CHARGE_MS = 120 * 60 * 1000; private static final long TIME_SINCE_LAST_FULL_CHARGE_US = TIME_SINCE_LAST_FULL_CHARGE_MS * 1000; private static final int DISCHARGE_AMOUNT = 100; - private static final long USAGE_TIME_MS = 10000; + private static final long USAGE_TIME_MS = 65 * 60 * 1000; private static final double TOTAL_POWER = 200; private static final double BATTERY_SCREEN_USAGE = 300; private static final double BATTERY_SYSTEM_USAGE = 600; @@ -123,8 +124,6 @@ public class PowerUsageSummaryTest { @Mock private BatterySipper mCellBatterySipper; @Mock - private PowerGaugePreference mPreference; - @Mock private LayoutPreference mBatteryLayoutPref; @Mock private TextView mBatteryPercentText; @@ -132,10 +131,6 @@ public class PowerUsageSummaryTest { private TextView mSummary1; @Mock private BatteryInfo mBatteryInfo; - @Mock - private PowerGaugePreference mScreenUsagePref; - @Mock - private PowerGaugePreference mLastFullChargePref; @Mock(answer = Answers.RETURNS_DEEP_STUBS) private BatteryStatsHelper mBatteryHelper; @Mock @@ -148,6 +143,9 @@ public class PowerUsageSummaryTest { private TestFragment mFragment; private FakeFeatureFactory mFeatureFactory; private BatteryMeterView mBatteryMeterView; + private PowerGaugePreference mPreference; + private PowerGaugePreference mScreenUsagePref; + private PowerGaugePreference mLastFullChargePref; @Before public void setUp() { @@ -158,6 +156,9 @@ public class PowerUsageSummaryTest { mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext); when(mContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mPowerManager); + mPreference = new PowerGaugePreference(mRealContext); + mScreenUsagePref = new PowerGaugePreference(mRealContext); + mLastFullChargePref = new PowerGaugePreference(mRealContext); mFragment = spy(new TestFragment(mContext)); mFragment.initFeatureProvider(); mBatteryMeterView = new BatteryMeterView(mRealContext); @@ -200,6 +201,7 @@ public class PowerUsageSummaryTest { when(mBatteryHelper.getUsageList()).thenReturn(mUsageList); mFragment.mScreenUsagePref = mScreenUsagePref; mFragment.mLastFullChargePref = mLastFullChargePref; + mFragment.mBatteryUtils = spy(new BatteryUtils(mRealContext)); mBatteryInfo.batteryLevel = BATTERY_LEVEL; } @@ -304,16 +306,21 @@ public class PowerUsageSummaryTest { public void testSetUsageSummary_timeLessThanOneMinute_DoNotSetSummary() { final long usageTimeMs = 59 * DateUtils.SECOND_IN_MILLIS; - mFragment.setUsageSummary(mPreference, "", usageTimeMs); - verify(mPreference, never()).setSummary(anyString()); + mFragment.setUsageSummary(mPreference, usageTimeMs); + assertThat(mPreference.getSummary()).isNull(); } @Test public void testSetUsageSummary_timeMoreThanOneMinute_setSummary() { final long usageTimeMs = 2 * DateUtils.MINUTE_IN_MILLIS; + doReturn(mRealContext.getText(R.string.battery_used_for)).when(mFragment).getText( + R.string.battery_used_for); + doReturn(mRealContext).when(mFragment).getContext(); + final String expectedSummary = "Used for 2m"; - mFragment.setUsageSummary(mPreference, "", usageTimeMs); - verify(mPreference).setSummary(anyString()); + mFragment.setUsageSummary(mPreference, usageTimeMs); + + assertThat(mPreference.getSummary().toString()).isEqualTo(expectedSummary); } @Test @@ -380,32 +387,37 @@ public class PowerUsageSummaryTest { @Test public void testUpdateScreenPreference_showCorrectSummary() { - final String expectedUsedTime = Utils.formatElapsedTime(mRealContext, USAGE_TIME_MS, false); doReturn(mScreenBatterySipper).when(mFragment).findBatterySipperByType(any(), any()); doReturn(mRealContext).when(mFragment).getContext(); + final CharSequence expectedSummary = Utils.formatElapsedTime(mRealContext, USAGE_TIME_MS, + false); mFragment.updateScreenPreference(); - verify(mScreenUsagePref).setSubtitle(expectedUsedTime); + assertThat(mScreenUsagePref.getSubtitle()).isEqualTo(expectedSummary); } @Test public void testUpdateLastFullChargePreference_showCorrectSummary() { + final CharSequence formattedString = mRealContext.getText( + R.string.power_last_full_charge_summary); + final CharSequence timeSequence = Utils.formatElapsedTime(mRealContext, + TIME_SINCE_LAST_FULL_CHARGE_MS, false); + final CharSequence expectedSummary = TextUtils.expandTemplate( + formattedString, timeSequence); + doReturn(formattedString).when(mFragment).getText(R.string.power_last_full_charge_summary); doReturn(mRealContext).when(mFragment).getContext(); - final String expected = mRealContext.getString(R.string.power_last_full_charge_summary, - Utils.formatElapsedTime(mRealContext, TIME_SINCE_LAST_FULL_CHARGE_MS, false)); - doReturn(expected).when(mFragment).getString(eq(R.string.power_last_full_charge_summary), - any()); mFragment.updateLastFullChargePreference(TIME_SINCE_LAST_FULL_CHARGE_MS); - verify(mLastFullChargePref).setSubtitle(expected); + assertThat(mLastFullChargePref.getSubtitle()).isEqualTo(expectedSummary); } @Test public void testUpdatePreference_usageListEmpty_shouldNotCrash() { when(mBatteryHelper.getUsageList()).thenReturn(new ArrayList()); - doReturn("").when(mFragment).getString(anyInt(), any()); + doReturn(STUB_STRING).when(mFragment).getString(anyInt(), any()); + doReturn(mRealContext).when(mFragment).getContext(); // Should not crash when update mFragment.updateScreenPreference();