From cdbc114376499c22bc43c078d58cf3331dd40ade Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Fri, 31 Mar 2017 14:26:38 -0700 Subject: [PATCH] Fix crash when opening battery page The settings crashes when opening battery usage detail page from installed app page. Main reason is that it trying to open obsolete page. This cl directs it to open AdvancedPowerUsageDetail instead. Following cl will make InstalledAppDetail show calibrated percentage, which is trakced in b/36816681 Bug: 36792973 Test: RunSettingsRoboTests Change-Id: Ie63e64e543ed3b28974ffdda8b42c97e7749a0f7 (cherry picked from commit fac713318c8834ded349bc6d187499f61d399748) --- res/values/strings.xml | 2 +- .../applications/InstalledAppDetails.java | 21 ++++++---- .../applications/InstalledAppDetailsTest.java | 41 ++++++++++++++++--- 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 3173e85e73d..cab276e2d87 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7400,7 +7400,7 @@ Allowing %1$s to always run in the background may reduce battery life. \n\nYou can change this later from Settings > Apps & notifications. - %1$d%% use since last full charge + %1$s use since last full charge Power management diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java index 1fc5515e60c..5dc73a992bb 100755 --- a/src/com/android/settings/applications/InstalledAppDetails.java +++ b/src/com/android/settings/applications/InstalledAppDetails.java @@ -88,6 +88,7 @@ import com.android.settings.applications.defaultapps.DefaultSmsPreferenceControl import com.android.settings.datausage.AppDataUsage; import com.android.settings.datausage.DataUsageList; import com.android.settings.datausage.DataUsageSummary; +import com.android.settings.fuelgauge.AdvancedPowerUsageDetail; import com.android.settings.fuelgauge.BatteryEntry; import com.android.settings.fuelgauge.PowerUsageDetail; import com.android.settings.notification.AppNotificationSettings; @@ -182,15 +183,18 @@ public class InstalledAppDetails extends AppInfoBase private ChartData mChartData; private INetworkStatsSession mStatsSession; - private Preference mBatteryPreference; - - private BatteryStatsHelper mBatteryHelper; - private BatterySipper mSipper; + @VisibleForTesting + Preference mBatteryPreference; + @VisibleForTesting + BatterySipper mSipper; + @VisibleForTesting + BatteryStatsHelper mBatteryHelper; protected ProcStatsData mStatsManager; protected ProcStatsPackageEntry mStats; private AppStorageStats mLastResult; + private String mBatteryPercent; private boolean handleDisableable(Button button) { boolean disableable = false; @@ -683,7 +687,8 @@ public class InstalledAppDetails extends AppInfoBase BatteryStats.STATS_SINCE_CHARGED); final int percentOfMax = (int) ((mSipper.totalPowerMah) / mBatteryHelper.getTotalPower() * dischargeAmount + .5f); - mBatteryPreference.setSummary(getString(R.string.battery_summary, percentOfMax)); + mBatteryPercent = Utils.formatPercentage(percentOfMax); + mBatteryPreference.setSummary(getString(R.string.battery_summary, mBatteryPercent)); } else { mBatteryPreference.setEnabled(false); mBatteryPreference.setSummary(getString(R.string.no_battery_summary)); @@ -954,9 +959,9 @@ public class InstalledAppDetails extends AppInfoBase } else if (preference == mDataPreference) { startAppInfoFragment(AppDataUsage.class, getString(R.string.app_data_usage)); } else if (preference == mBatteryPreference) { - BatteryEntry entry = new BatteryEntry(getActivity(), null, mUserManager, mSipper); - PowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(), this, - mBatteryHelper, BatteryStats.STATS_SINCE_CHARGED, entry, true, false); + BatteryEntry entry = new BatteryEntry(getContext(), null, mUserManager, mSipper); + AdvancedPowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(), this, + mBatteryHelper, BatteryStats.STATS_SINCE_CHARGED, entry, mBatteryPercent); } else { return false; } diff --git a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java index 209cdeb59a9..dba25bb963f 100644 --- a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java +++ b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java @@ -22,12 +22,16 @@ import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; +import android.os.BatteryStats; import android.os.UserManager; import android.support.v7.preference.Preference; import android.view.View; import android.widget.Button; +import com.android.internal.os.BatterySipper; +import com.android.internal.os.BatteryStatsHelper; import com.android.settings.R; +import com.android.settings.SettingsActivity; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import com.android.settings.applications.instantapps.InstantAppButtonsController; @@ -48,10 +52,13 @@ import org.robolectric.annotation.Config; import org.robolectric.util.ReflectionHelpers; import static com.google.common.truth.Truth.assertThat; + import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -61,23 +68,37 @@ import static org.mockito.Mockito.when; public final class InstalledAppDetailsTest { @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext; - @Mock ApplicationFeatureProvider mApplicationFeatureProvider; - @Mock(answer = Answers.RETURNS_DEEP_STUBS) private UserManager mUserManager; @Mock - private Activity mActivity; + private SettingsActivity mActivity; @Mock private DevicePolicyManager mDevicePolicyManager; + @Mock + private Preference mBatteryPreference; + @Mock + private BatterySipper mBatterySipper; + @Mock + private BatteryStatsHelper mBatteryStatsHelper; + @Mock + private BatteryStats.Uid mUid; private InstalledAppDetails mAppDetail; + private Context mShadowContext; @Before public void setUp() { MockitoAnnotations.initMocks(this); - mAppDetail = new InstalledAppDetails(); + 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(); // Default to not considering any apps to be instant (individual tests can override this). ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", @@ -154,6 +175,16 @@ public final class InstalledAppDetailsTest { verify(mActivity, never()).finishAndRemoveTask(); } + @Test + public void launchPowerUsageDetailFragment_shouldNotCrash() { + mAppDetail.mBatteryPreference = mBatteryPreference; + mAppDetail.mSipper = mBatterySipper; + mAppDetail.mBatteryHelper = mBatteryStatsHelper; + + // Should not crash + mAppDetail.onPreferenceClick(mBatteryPreference); + } + // Tests that we don't show the "uninstall for all users" button for instant apps. @Test public void instantApps_noUninstallForAllButton() { @@ -181,7 +212,7 @@ public final class InstalledAppDetailsTest { public void instantApps_noUninstallButton() { // Make this app appear to be instant. ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", - (InstantAppDataProvider) (i -> true)); + (InstantAppDataProvider) (i -> true)); final ApplicationInfo info = new ApplicationInfo(); info.flags = ApplicationInfo.FLAG_INSTALLED; info.enabled = true;