Merge "Fix crash when opening battery page" into oc-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4ebc07b..e4fa50e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7390,7 +7390,7 @@
         Allowing <xliff:g id="app_name" example="Settings">%1$s</xliff:g> to always run in the background may reduce battery life.
         \n\nYou can change this later from Settings > Apps &amp; notifications.</string>
     <!-- Summary of power usage for an app [CHAR LIMIT=NONE] -->
-    <string name="battery_summary"><xliff:g id="percentage" example="2">%1$d</xliff:g>%% use since last full charge</string>
+    <string name="battery_summary"><xliff:g id="percentage" example="2">%1$s</xliff:g> use since last full charge</string>
 
     <!-- Title of a group of settings that let you manage settings that affect battery life [CHAR LIMIT=60] -->
     <string name="battery_power_management">Power management</string>
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index c662c4a..9967918 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -89,6 +89,7 @@
 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;
@@ -183,10 +184,12 @@
     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;
@@ -194,6 +197,7 @@
     private InstantAppButtonsController mInstantAppButtonsController;
 
     private AppStorageStats mLastResult;
+    private String mBatteryPercent;
 
     private boolean handleDisableable(Button button) {
         boolean disableable = false;
@@ -686,7 +690,8 @@
                     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));
@@ -960,9 +965,9 @@
         } 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 f02f58c..a33a8c8 100644
--- a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
@@ -23,12 +23,16 @@
 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;
@@ -53,8 +57,10 @@
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 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;
 
@@ -64,23 +70,37 @@
 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",
@@ -157,6 +177,16 @@
         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() {
@@ -184,7 +214,7 @@
     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;