Add high power whitelist for apps

 - Strings not final!
 - New UX for power usage details (more preferency)
 - Add high power apps list shows on/off and screen to
   change (when possible)
 - Link from power usage summary to high power list
 - Link from advanced apps to high power list

Bug: 19991702
Change-Id: I97c927ed82d3b89041e4429b427508545763d66c
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f01110a..6c04af2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -923,6 +923,15 @@
                 android:value="true" />
         </activity>
 
+        <activity android:name="Settings$HighPowerApplicationsActivity"
+                android:label="@string/high_power_apps"
+                android:taskAffinity="">
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.applications.ManageApplications" />
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                android:value="true" />
+        </activity>
+
         <!-- Keep compatibility with old shortcuts. -->
         <activity-alias android:name=".applications.ManageApplications"
                 android:label="@string/applications_settings"
diff --git a/res/layout/horizontal_preference.xml b/res/layout/horizontal_preference.xml
new file mode 100644
index 0000000..540b7e3
--- /dev/null
+++ b/res/layout/horizontal_preference.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:paddingTop="3dp"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+
+    <TextView
+        android:id="@android:id/title"
+        android:textAppearance="?android:attr/textAppearanceListItem"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_weight="1" />
+
+    <TextView
+        android:id="@android:id/summary"
+        android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+        android:textColor="?android:attr/textColorSecondary"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_weight="1"
+        android:gravity="end" />
+
+</LinearLayout>
diff --git a/res/layout/power_usage_action_item.xml b/res/layout/power_usage_action_item.xml
deleted file mode 100644
index 9e8551e..0000000
--- a/res/layout/power_usage_action_item.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:minHeight="?android:attr/listPreferredItemHeight"
-    android:gravity="center_vertical"
-    android:paddingStart="4dip"
-    android:focusable="true"
-    android:orientation="vertical"
-    android:paddingEnd="?android:attr/scrollbarSize">
-
-    <TextView android:id="@+id/summary"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="2dip"
-            android:paddingBottom="4dip"
-            android:ellipsize="marquee"
-            android:textAppearance="?android:attr/textAppearanceMedium"/>
-
-    <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal">
-        <!-- Spacer -->
-        <View
-                android:id="@+id/buttons_spacer_left"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_weight="0.7"
-                android:visibility="invisible" />
-
-        <Button
-                android:id="@+id/action_button"
-                android:layout_width="150dip"
-                android:paddingEnd="6dip"
-                android:layout_weight="0.3"
-                android:layout_height="wrap_content"/>
-    </LinearLayout>
-</LinearLayout>
diff --git a/res/layout/power_usage_detail_item_text.xml b/res/layout/power_usage_detail_item_text.xml
deleted file mode 100644
index 04b48b8..0000000
--- a/res/layout/power_usage_detail_item_text.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content">
-
-    <!--Label for the item-->
-    <TextView
-        android:id="@+id/label"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textStyle="bold"
-        android:singleLine="true"
-        android:ellipsize="middle"
-        android:layout_alignParentStart="true"
-        android:layout_toStartOf="@+id/value"
-        android:layout_marginBottom="4dip"
-        android:layout_marginTop="4dip"
-        android:layout_marginEnd="4dip"/>
-
-    <TextView
-        android:id="@+id/value"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentEnd="true"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textStyle="normal"
-        android:singleLine="true"
-        android:layout_marginBottom="4dip"
-        android:layout_marginTop="4dip" />
-
-</RelativeLayout>
diff --git a/res/layout/power_usage_details.xml b/res/layout/power_usage_details.xml
deleted file mode 100644
index f711d9a..0000000
--- a/res/layout/power_usage_details.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<ScrollView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:clipToPadding="false"
-    android:scrollbarStyle="@integer/preference_scrollbar_style">
-
-    <LinearLayout
-        android:id="@+id/all_details"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-        android:paddingTop="5dip"
-        android:paddingBottom="5dip"
-        android:orientation="vertical">
-
-        <include layout="@layout/app_percentage_item" />
-
-        <!-- Force stop and report buttons -->
-        <LinearLayout
-                android:id="@+id/two_buttons_panel"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingBottom="6dip"
-                android:orientation="vertical">
-            <include
-                    layout="@layout/two_buttons_panel"/>
-        </LinearLayout>
-
-        <TextView
-                style="?android:attr/listSeparatorTextViewStyle"
-                android:text="@string/details_subtitle" />
-
-        <LinearLayout
-                android:id="@+id/details"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingStart="6dip"
-                android:orientation="vertical">
-
-            <!-- Insert detail items here -->
-
-        </LinearLayout>
-
-        <LinearLayout
-                android:id="@+id/controls"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical">
-
-            <TextView
-                    android:id="@+id/controls_title"
-                    style="?android:attr/listSeparatorTextViewStyle"
-                    android:layout_marginTop="6dip"
-                    android:text="@string/controls_subtitle" />
-
-            <!-- Controls go here ... -->
-
-        </LinearLayout>
-
-        <LinearLayout
-                android:id="@+id/messages"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical">
-
-            <TextView
-                    android:id="@+id/messages_title"
-                    style="?android:attr/listSeparatorTextViewStyle"
-                    android:layout_marginTop="6dip" />
-
-            <!-- Messages go here ... -->
-
-        </LinearLayout>
-
-        <TextView
-                android:id="@+id/packages_section_title"
-                style="?android:attr/listSeparatorTextViewStyle"
-                android:layout_marginTop="6dip"
-                android:text="@string/packages_subtitle" />
-
-        <LinearLayout
-                android:id="@+id/packages_section"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingStart="6dip"
-                android:orientation="vertical">
-
-            <!-- Insert detail items here -->
-
-        </LinearLayout>
-
-    </LinearLayout>
-</ScrollView>
diff --git a/res/layout/power_usage_message_item.xml b/res/layout/power_usage_message_item.xml
deleted file mode 100644
index 6f9e619..0000000
--- a/res/layout/power_usage_message_item.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/message"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="2dip"
-        android:minHeight="?android:attr/listPreferredItemHeight"
-        android:paddingStart="4dip"
-        android:paddingEnd="?android:attr/scrollbarSize"
-        android:paddingBottom="4dip"
-        android:ellipsize="marquee"
-        android:textAppearance="?android:attr/textAppearanceMedium" />
diff --git a/res/layout/power_usage_package_item.xml b/res/layout/power_usage_package_item.xml
deleted file mode 100644
index 6c31792..0000000
--- a/res/layout/power_usage_package_item.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/label"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:textAppearance="?android:attr/textAppearanceMedium"
-    android:singleLine="true"
-    android:layout_alignParentStart="true"
-    android:layout_marginBottom="2dip"
-    android:layout_marginTop="2dip" />
diff --git a/res/layout/preference_batteryhistory.xml b/res/layout/preference_batteryhistory.xml
deleted file mode 100644
index 8697059..0000000
--- a/res/layout/preference_batteryhistory.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:minHeight="@dimen/battery_history_chart_height">
-
-    <include layout="@layout/battery_history_chart" />
-
-    <TextView android:id="@+id/labelsHeader"
-              android:layout_width="match_parent"
-              android:layout_height="48dp"
-              android:textAppearance="?android:attr/textAppearanceMedium"
-              android:textSize="14sp"
-              android:textColor="?android:attr/colorControlActivated"
-              android:gravity="start|center_vertical"
-              android:text="@string/power_usage_list_summary"
-              android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-              android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
-
-</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3da13e7..7e52036 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6642,4 +6642,31 @@
     <!-- Label for process [CHAR LIMIT=25] -->
     <string name="process_format">Process <xliff:g id="count" example="3">%1$d</xliff:g></string>
 
+    <!-- Label for whether app is allowed to use a lot ef power [CHAR LIMIT=25]-->
+    <string name="high_power" translatable="false">High power</string>
+
+    <!-- List of apps that are allowed to use a lot of power [CHAR LIMIT=25]-->
+    <string name="high_power_apps" translatable="false">High power apps</string>
+
+    <!-- Summary of app allowed to use a lot of power [CHAR LIMIT=25] -->
+    <string name="high_power_on">On</string>
+
+    <!-- Summary of app not allowed to use a lot of power [CHAR LIMIT=25] -->
+    <string name="high_power_off">Off</string>
+
+    <!-- Description of high power switch [CHAR LIMIT=NONE] -->
+    <string name="high_power_desc" translatable="false">High powered apps description text goes here.  This is a placeholder.</string>
+
+    <!-- Description of number of apps with high power turned on [CHAR LIMIT=NONE] -->
+    <plurals name="high_power_count" translatable="false">
+        <item quantity="one">1 app is allowed to ignore restrictions like battery saver mode, sync etc.</item>
+        <item quantity="other"><xliff:g id="count" example="10">%d</xliff:g> apps is allowed to ignore restrictions like battery saver mode, sync etc.</item>
+    </plurals>
+
+    <!-- Summary of power usage for an app [CHAR LIMIT=NONE] -->
+    <string name="battery_summary" translatable="false"><xliff:g id="percentage" example="2">%1$d</xliff:g>%% use since last full charge</string>
+
+    <!-- Summary for app with no battery usage [CHAR LIMIT=NONE] -->
+    <string name="no_battery_summary" translatable="false">No battery use since last full charge</string>
+
 </resources>
diff --git a/res/xml/advanced_apps.xml b/res/xml/advanced_apps.xml
index e808210..62431c3 100644
--- a/res/xml/advanced_apps.xml
+++ b/res/xml/advanced_apps.xml
@@ -26,12 +26,6 @@
         settings:keywords="@string/keywords_default_apps" />
 
     <PreferenceScreen
-        android:key="manage_perms"
-        android:fragment="com.android.settings.applications.ManagePermissions"
-        android:title="@string/app_permissions"
-        settings:keywords="@string/keywords_app_permissions" />
-
-    <PreferenceScreen
             android:key="domain_urls"
             android:title="@string/domain_urls_title"
             android:fragment="com.android.settings.applications.ManageApplications">
@@ -40,4 +34,19 @@
                 android:value="com.android.settings.Settings$DomainsURLsAppListActivity" />
     </PreferenceScreen>
 
+    <PreferenceScreen
+        android:key="manage_perms"
+        android:fragment="com.android.settings.applications.ManagePermissions"
+        android:title="@string/app_permissions"
+        settings:keywords="@string/keywords_app_permissions" />
+
+    <PreferenceScreen
+        android:key="high_power_apps"
+        android:title="@string/high_power_apps"
+        android:fragment="com.android.settings.applications.ManageApplications">
+        <extra
+            android:name="classname"
+            android:value="com.android.settings.Settings$HighPowerApplicationsActivity" />
+    </PreferenceScreen>
+
 </PreferenceScreen>
diff --git a/res/xml/high_power_details.xml b/res/xml/high_power_details.xml
new file mode 100644
index 0000000..81f7806
--- /dev/null
+++ b/res/xml/high_power_details.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+    android:title="@string/high_power">
+
+    <SwitchPreference
+        android:key="high_power_switch"
+        android:title="@string/high_power" />
+
+    <Preference
+        android:summary="@string/high_power_desc"
+        android:selectable="false" />
+
+</PreferenceScreen>
diff --git a/res/xml/installed_app_details.xml b/res/xml/installed_app_details.xml
index 233331d..deab13b 100644
--- a/res/xml/installed_app_details.xml
+++ b/res/xml/installed_app_details.xml
@@ -18,7 +18,8 @@
                   android:title="@string/application_info_label">
     <com.android.settings.applications.LayoutPreference
         android:key="header_view"
-        android:layout="@layout/installed_app_details" />
+        android:layout="@layout/installed_app_details"
+        android:selectable="false" />
 
     <Preference
         android:key="storage_settings"
@@ -44,4 +45,10 @@
         android:key="preferred_settings"
         android:title="@string/launch_by_default"
         android:selectable="true" />
+
+    <Preference
+        android:key="battery"
+        android:title="@string/power_usage_summary_title"
+        android:selectable="true" />
+
 </PreferenceScreen>
diff --git a/res/xml/power_usage_details.xml b/res/xml/power_usage_details.xml
new file mode 100644
index 0000000..ca84e89
--- /dev/null
+++ b/res/xml/power_usage_details.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
+
+        <com.android.settings.fuelgauge.BatteryHistoryPreference
+            android:key="battery_history" />
+
+        <com.android.settings.applications.LayoutPreference
+            android:key="two_buttons"
+            android:layout="@layout/two_buttons_panel"
+            android:selectable="false" />
+
+        <Preference
+            android:key="high_power"
+            android:title="@string/high_power" />
+
+        <PreferenceCategory
+            android:key="details_parent"
+            android:title="@string/details_subtitle" />
+
+        <PreferenceCategory
+            android:key="controls_parent"
+            android:title="@string/controls_subtitle" />
+
+        <PreferenceCategory
+            android:key="messages_parent" />
+
+        <PreferenceCategory
+            android:key="packages_parent"
+            android:title="@string/packages_subtitle" />
+
+</PreferenceScreen>
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index 0622513..3f39d47 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -17,6 +17,13 @@
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
                   xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
         android:title="@string/power_usage_summary_title"
-        settings:keywords="@string/keywords_battery"
-        android:key="app_list">
+        settings:keywords="@string/keywords_battery">
+
+        <com.android.settings.fuelgauge.BatteryHistoryPreference
+            android:key="battery_history" />
+
+        <PreferenceCategory
+            android:key="app_list"
+            android:title="@string/power_usage_list_summary" />
+
 </PreferenceScreen>
diff --git a/src/com/android/settings/AppHeader.java b/src/com/android/settings/AppHeader.java
index cd76e80..2f3678b 100644
--- a/src/com/android/settings/AppHeader.java
+++ b/src/com/android/settings/AppHeader.java
@@ -18,6 +18,7 @@
 
 import android.app.Activity;
 import android.content.Intent;
+import android.content.res.ColorStateList;
 import android.graphics.drawable.Drawable;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -29,6 +30,11 @@
 
     public static void createAppHeader(final Activity activity, Drawable icon, CharSequence label,
             final Intent settingsIntent) {
+        createAppHeader(activity, icon, label, settingsIntent, 0);
+    }
+
+    public static void createAppHeader(final Activity activity, Drawable icon, CharSequence label,
+            final Intent settingsIntent, int tintColorRes) {
         final View content = activity.findViewById(R.id.main_content);
         final ViewGroup contentParent = (ViewGroup) content.getParent();
         final View bar = activity.getLayoutInflater().inflate(R.layout.app_header,
@@ -36,6 +42,9 @@
 
         final ImageView appIcon = (ImageView) bar.findViewById(R.id.app_icon);
         appIcon.setImageDrawable(icon);
+        if (tintColorRes != 0) {
+            appIcon.setImageTintList(ColorStateList.valueOf(activity.getColor(tintColorRes)));
+        }
 
         final TextView appName = (TextView) bar.findViewById(R.id.app_name);
         appName.setText(label);
diff --git a/src/com/android/settings/InstrumentedFragment.java b/src/com/android/settings/InstrumentedFragment.java
index d239d4e..1ee7e73 100644
--- a/src/com/android/settings/InstrumentedFragment.java
+++ b/src/com/android/settings/InstrumentedFragment.java
@@ -29,6 +29,8 @@
     public static final int VIEW_CATEGORY_DEFAULT_APPS = VIEW_CATEGORY_UNDECLARED + 1;
     public static final int VIEW_CATEGORY_STORAGE_APPS = VIEW_CATEGORY_UNDECLARED + 2;
     public static final int VIEW_CATEGORY_USAGE_ACCESS_DETAIL = VIEW_CATEGORY_UNDECLARED + 3;
+    public static final int VIEW_CATEGORY_HIGH_POWER_DETAILS = VIEW_CATEGORY_UNDECLARED + 4;
+    public static final int VIEW_CATEGORY_HIGH_POWER_APPS = VIEW_CATEGORY_UNDECLARED + 5;
 
     /**
      * Declare the view of this category.
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 6723839..b91275a 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -51,6 +51,7 @@
     public static class ApplicationSettingsActivity extends SettingsActivity { /* empty */ }
     public static class ManageApplicationsActivity extends SettingsActivity { /* empty */ }
     public static class AllApplicationsActivity extends SettingsActivity { /* empty */ }
+    public static class HighPowerApplicationsActivity extends SettingsActivity { /* empty */ }
     public static class AppOpsSummaryActivity extends SettingsActivity {
         @Override
         public boolean isValidFragment(String className) {
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index fcbb512..89dbc99 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -89,6 +89,7 @@
 import com.android.settings.deviceinfo.StorageSettings;
 import com.android.settings.deviceinfo.UsbSettings;
 import com.android.settings.fuelgauge.BatterySaverSettings;
+import com.android.settings.fuelgauge.PowerUsageDetail;
 import com.android.settings.fuelgauge.PowerUsageSummary;
 import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
 import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
@@ -347,6 +348,7 @@
             ZenModeEventRuleSettings.class.getName(),
             ZenModeExternalRuleSettings.class.getName(),
             ProcessStatsUi.class.getName(),
+            PowerUsageDetail.class.getName(),
     };
 
 
diff --git a/src/com/android/settings/applications/AdvancedAppSettings.java b/src/com/android/settings/applications/AdvancedAppSettings.java
index 52a8b85..5e8d2f4 100644
--- a/src/com/android/settings/applications/AdvancedAppSettings.java
+++ b/src/com/android/settings/applications/AdvancedAppSettings.java
@@ -26,6 +26,7 @@
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.applications.ApplicationsState.AppEntry;
 import com.android.settings.applications.ApplicationsState.Session;
+import com.android.settings.fuelgauge.PowerWhitelistBackend;
 import com.android.settingslib.applications.PermissionsInfo;
 
 import java.util.ArrayList;
@@ -38,11 +39,13 @@
 
     private static final String KEY_APP_PERM = "manage_perms";
     private static final String KEY_APP_DOMAIN_URLS = "domain_urls";
+    private static final String KEY_HIGH_POWER_APPS = "high_power_apps";
 
     private ApplicationsState mApplicationsState;
     private Session mSession;
     private Preference mAppPermsPreference;
     private Preference mAppDomainURLsPreference;
+    private Preference mHighPowerPreference;
     private PermissionsInfo mPermissionsInfo;
 
     @Override
@@ -55,6 +58,7 @@
 
         mAppPermsPreference = findPreference(KEY_APP_PERM);
         mAppDomainURLsPreference = findPreference(KEY_APP_DOMAIN_URLS);
+        mHighPowerPreference = findPreference(KEY_HIGH_POWER_APPS);
         updateUI();
     }
 
@@ -70,6 +74,10 @@
         String summary = getResources().getQuantityString(
                 R.plurals.domain_urls_apps_summary, countAppWithDomainURLs, countAppWithDomainURLs);
         mAppDomainURLsPreference.setSummary(summary);
+
+        int highPowerCount = PowerWhitelistBackend.getInstance().getWhitelistSize();
+        mHighPowerPreference.setSummary(getResources().getQuantityString(R.plurals.high_power_count,
+                highPowerCount, highPowerCount));
     }
 
     @Override
diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java
index 56fe885..2d402e5 100644
--- a/src/com/android/settings/applications/AppInfoBase.java
+++ b/src/com/android/settings/applications/AppInfoBase.java
@@ -20,6 +20,7 @@
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
+import android.app.Fragment;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.Intent;
@@ -36,6 +37,7 @@
 
 import com.android.settings.InstrumentedPreferenceFragment;
 import com.android.settings.SettingsActivity;
+import com.android.settings.Utils;
 import com.android.settings.applications.ApplicationsState.AppEntry;
 
 import java.util.ArrayList;
@@ -194,6 +196,17 @@
         refreshUi();
     }
 
+    public static void startAppInfoFragment(Class<? extends AppInfoBase> fragment, int titleRes,
+            String pkg, int uid, Fragment source, int request) {
+        Bundle args = new Bundle();
+        args.putString(AppInfoBase.ARG_PACKAGE_NAME, pkg);
+
+        Intent intent = Utils.onBuildStartFragmentIntent(source.getActivity(), fragment.getName(),
+                args, null, titleRes, null, false);
+        source.getActivity().startActivityForResultAsUser(intent, request,
+                new UserHandle(UserHandle.getUserId(uid)));
+    }
+
     public class MyAlertDialogFragment extends DialogFragment {
         public MyAlertDialogFragment(int id, int errorCode) {
             Bundle args = new Bundle();
diff --git a/src/com/android/settings/applications/AppStatePowerBridge.java b/src/com/android/settings/applications/AppStatePowerBridge.java
new file mode 100644
index 0000000..40163cb
--- /dev/null
+++ b/src/com/android/settings/applications/AppStatePowerBridge.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.applications;
+
+import com.android.settings.applications.ApplicationsState.AppEntry;
+import com.android.settings.applications.ApplicationsState.AppFilter;
+import com.android.settings.fuelgauge.PowerWhitelistBackend;
+
+import java.util.ArrayList;
+
+/**
+ * Connects data from the PowerWhitelistBackend to ApplicationsState.
+ */
+public class AppStatePowerBridge extends AppStateBaseBridge {
+
+    private final PowerWhitelistBackend mBackend = PowerWhitelistBackend.getInstance();
+
+    public AppStatePowerBridge(ApplicationsState appState, Callback callback) {
+        super(appState, callback);
+    }
+
+    @Override
+    protected void loadAllExtraInfo() {
+        ArrayList<AppEntry> apps = mAppSession.getAllApps();
+        final int N = apps.size();
+        for (int i = 0; i < N; i++) {
+            AppEntry app = apps.get(i);
+            app.extraInfo = mBackend.isWhitelisted(app.info.packageName)
+                    ? Boolean.TRUE : Boolean.FALSE;
+        }
+    }
+
+    @Override
+    protected void updateExtraInfo(AppEntry app, String pkg, int uid) {
+        app.extraInfo = mBackend.isWhitelisted(pkg) ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    public static class HighPowerState {
+        public boolean isHighPower;
+        public boolean isSystemHighPower;
+    }
+
+    public static final AppFilter FILTER_POWER_WHITELISTED = new AppFilter() {
+        @Override
+        public void init() {
+        }
+
+        @Override
+        public boolean filterApp(AppEntry info) {
+            return info.extraInfo == Boolean.TRUE;
+        }
+    };
+
+    public static final AppFilter FILTER_POWER_NOT_WHITELISTED = new AppFilter() {
+        @Override
+        public void init() {
+        }
+
+        @Override
+        public boolean filterApp(AppEntry info) {
+            return info.extraInfo == Boolean.FALSE;
+        }
+    };
+
+}
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index ffd4959..a6fee90 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -38,6 +38,7 @@
 import android.net.TrafficStats;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.BatteryStats;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -57,12 +58,16 @@
 import android.widget.TextView;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatteryStatsHelper;
 import com.android.settings.DataUsageSummary;
 import com.android.settings.DataUsageSummary.AppItem;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.Utils;
 import com.android.settings.applications.ApplicationsState.AppEntry;
+import com.android.settings.fuelgauge.BatteryEntry;
+import com.android.settings.fuelgauge.PowerUsageDetail;
 import com.android.settings.net.ChartData;
 import com.android.settings.net.ChartDataLoader;
 import com.android.settings.notification.NotificationBackend;
@@ -108,6 +113,7 @@
     private static final String KEY_PERMISSION = "permission_settings";
     private static final String KEY_DATA = "data_settings";
     private static final String KEY_LAUNCH = "preferred_settings";
+    private static final String KEY_BATTERY = "battery";
 
     private final HashSet<String> mHomePackages = new HashSet<String>();
 
@@ -131,6 +137,11 @@
     private ChartData mChartData;
     private INetworkStatsSession mStatsSession;
 
+    private Preference mBatteryPreference;
+
+    private BatteryStatsHelper mBatteryHelper;
+    private BatterySipper mSipper;
+
     private boolean handleDisableable(Button button) {
         boolean disableable = false;
         // Try to prevent the user from bricking their phone
@@ -221,6 +232,7 @@
         } catch (RemoteException e) {
             throw new RuntimeException(e);
         }
+        mBatteryHelper = new BatteryStatsHelper(getActivity(), true);
     }
 
     @Override
@@ -236,6 +248,7 @@
         getLoaderManager().restartLoader(LOADER_CHART_DATA,
                 ChartDataLoader.buildArgs(NetworkTemplate.buildTemplateMobileWildcard(), app),
                 mDataCallbacks);
+        new BatteryUpdater().execute();
     }
 
     @Override
@@ -263,6 +276,9 @@
         mPermissionsPreference.setOnPreferenceClickListener(this);
         mDataPreference = findPreference(KEY_DATA);
         mDataPreference.setOnPreferenceClickListener(this);
+        mBatteryPreference = findPreference(KEY_BATTERY);
+        mBatteryPreference.setEnabled(false);
+        mBatteryPreference.setOnPreferenceClickListener(this);
 
         mLaunchPreference = findPreference(KEY_LAUNCH);
         if ((mAppEntry.info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
@@ -434,6 +450,8 @@
                 mBackend));
         mDataPreference.setSummary(getDataSummary());
 
+        updateBattery();
+
         if (!mInitialized) {
             // First time init: are we displaying an uninstalled app?
             mInitialized = true;
@@ -459,6 +477,20 @@
         return true;
     }
 
+    private void updateBattery() {
+        if (mSipper != null) {
+            mBatteryPreference.setEnabled(true);
+            int dischargeAmount = mBatteryHelper.getStats().getDischargeAmount(
+                    BatteryStats.STATS_SINCE_CHARGED);
+            final int percentOfMax = (int) ((mSipper.totalPowerMah)
+                    / mBatteryHelper.getTotalPower() * dischargeAmount + .5f);
+            mBatteryPreference.setSummary(getString(R.string.battery_summary, percentOfMax));
+        } else {
+            mBatteryPreference.setEnabled(false);
+            mBatteryPreference.setSummary(getString(R.string.no_battery_summary));
+        }
+    }
+
     private CharSequence getDataSummary() {
         if (mChartData != null) {
             long totalBytes = mChartData.detail.getTotalBytes();
@@ -656,6 +688,10 @@
             SettingsActivity sa = (SettingsActivity) getActivity();
             sa.startPreferencePanel(DataUsageSummary.class.getName(), args, -1,
                     getString(R.string.app_data_usage), this, SUB_INFO_FRAGMENT);
+        } else if (preference == mBatteryPreference) {
+            BatteryEntry entry = new BatteryEntry(getActivity(), null, mUserManager, mSipper);
+            PowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(),
+                    mBatteryHelper, BatteryStats.STATS_SINCE_CHARGED, entry, true);
         } else {
             return false;
         }
@@ -700,7 +736,31 @@
         }
     }
 
-    static class DisableChanger extends AsyncTask<Object, Object, Object> {
+    private class BatteryUpdater extends AsyncTask<Void, Void, Void> {
+        @Override
+        protected Void doInBackground(Void... params) {
+            mBatteryHelper.create((Bundle) null);
+            mBatteryHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED,
+                    mUserManager.getUserProfiles());
+            List<BatterySipper> usageList = mBatteryHelper.getUsageList();
+            final int N = usageList.size();
+            for (int i = 0; i < N; i++) {
+                BatterySipper sipper = usageList.get(i);
+                if (sipper.getUid() == mPackageInfo.applicationInfo.uid) {
+                    mSipper = sipper;
+                    break;
+                }
+            }
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(Void result) {
+            refreshUi();
+        }
+    }
+
+    private static class DisableChanger extends AsyncTask<Object, Object, Object> {
         final PackageManager mPm;
         final WeakReference<InstalledAppDetails> mActivity;
         final ApplicationInfo mInfo;
diff --git a/src/com/android/settings/applications/LayoutPreference.java b/src/com/android/settings/applications/LayoutPreference.java
index c74ad16..8a4e533 100644
--- a/src/com/android/settings/applications/LayoutPreference.java
+++ b/src/com/android/settings/applications/LayoutPreference.java
@@ -45,7 +45,9 @@
                 .inflate(layoutResource, null, false);
 
         final ViewGroup allDetails = (ViewGroup) view.findViewById(R.id.all_details);
-        Utils.forceCustomPadding(allDetails, true /* additive padding */);
+        if (allDetails != null) {
+            Utils.forceCustomPadding(allDetails, true /* additive padding */);
+        }
         mRootView = view;
         setShouldDisableView(false);
     }
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index b9f49d1..b55cc44 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -55,6 +55,7 @@
 import com.android.settings.R;
 import com.android.settings.Settings.AllApplicationsActivity;
 import com.android.settings.Settings.DomainsURLsAppListActivity;
+import com.android.settings.Settings.HighPowerApplicationsActivity;
 import com.android.settings.Settings.NotificationAppListActivity;
 import com.android.settings.Settings.StorageUseActivity;
 import com.android.settings.Settings.UsageAccessSettingsActivity;
@@ -65,6 +66,7 @@
 import com.android.settings.applications.ApplicationsState.AppFilter;
 import com.android.settings.applications.ApplicationsState.CompoundFilter;
 import com.android.settings.applications.ApplicationsState.VolumeFilter;
+import com.android.settings.fuelgauge.HighPowerDetail;
 import com.android.settings.notification.NotificationBackend;
 import com.android.settings.notification.NotificationBackend.AppRow;
 
@@ -117,6 +119,8 @@
     public static final int FILTER_APPS_WORK                    = 8;
     public static final int FILTER_APPS_WITH_DOMAIN_URLS        = 9;
     public static final int FILTER_APPS_USAGE_ACCESS            = 10;
+    public static final int FILTER_APPS_POWER_WHITELIST         = 11;
+    public static final int FILTER_APPS_POWER_NO_WHITELIST      = 12;
 
     // This is the string labels for the filter modes above, the order must be kept in sync.
     public static final int[] FILTER_LABELS = new int[] {
@@ -131,6 +135,8 @@
         R.string.filter_work_apps,     // Work
         R.string.filter_with_domain_urls_apps,     // Domain URLs
         R.string.filter_all_apps,      // Usage access screen, never displayed
+        R.string.high_power_on,        // High power whitelist, on
+        R.string.high_power_off,       // High power whitelist, off
     };
     // This is the actual mapping to filters from FILTER_ constants above, the order must
     // be kept in sync.
@@ -146,6 +152,8 @@
         ApplicationsState.FILTER_WORK,        // Work
         ApplicationsState.FILTER_WITH_DOMAIN_URLS,   // Apps with Domain URLs
         AppStateUsageBridge.FILTER_APP_USAGE, // Apps with Domain URLs
+        AppStatePowerBridge.FILTER_POWER_WHITELISTED,     // High power whitelist, on
+        AppStatePowerBridge.FILTER_POWER_NOT_WHITELISTED, // High power whitelist, off
     };
 
     // sort order
@@ -180,11 +188,12 @@
 
     private Menu mOptionsMenu;
 
-    public static final int LIST_TYPE_MAIN = 0;
+    public static final int LIST_TYPE_MAIN         = 0;
     public static final int LIST_TYPE_NOTIFICATION = 1;
     public static final int LIST_TYPE_DOMAINS_URLS = 2;
-    public static final int LIST_TYPE_STORAGE = 3;
+    public static final int LIST_TYPE_STORAGE      = 3;
     public static final int LIST_TYPE_USAGE_ACCESS = 4;
+    public static final int LIST_TYPE_HIGH_POWER   = 5;
 
     private View mRootView;
 
@@ -228,6 +237,8 @@
         } else if (className.equals(UsageAccessSettingsActivity.class.getName())) {
             mListType = LIST_TYPE_USAGE_ACCESS;
             getActivity().getActionBar().setTitle(R.string.usage_access_title);
+        } else if (className.equals(HighPowerApplicationsActivity.class.getName())) {
+            mListType = LIST_TYPE_HIGH_POWER;
         } else {
             mListType = LIST_TYPE_MAIN;
         }
@@ -310,6 +321,9 @@
             mFilterAdapter.enableFilter(FILTER_APPS_SENSITIVE);
             mFilterAdapter.enableFilter(FILTER_APPS_NO_PEEKING);
         }
+        if (mListType == LIST_TYPE_HIGH_POWER) {
+            mFilterAdapter.enableFilter(FILTER_APPS_POWER_NO_WHITELIST);
+        }
         if (mListType == LIST_TYPE_STORAGE) {
             mApplications.setOverrideFilter(new VolumeFilter(mVolumeUuid));
         }
@@ -325,12 +339,12 @@
 
     private int getDefaultFilter() {
         switch (mListType) {
-            case LIST_TYPE_MAIN:
-                return FILTER_APPS_ALL;
             case LIST_TYPE_DOMAINS_URLS:
                 return FILTER_APPS_WITH_DOMAIN_URLS;
             case LIST_TYPE_USAGE_ACCESS:
                 return FILTER_APPS_USAGE_ACCESS;
+            case LIST_TYPE_HIGH_POWER:
+                return FILTER_APPS_POWER_WHITELIST;
             default:
                 return FILTER_APPS_ALL;
         }
@@ -349,6 +363,8 @@
                 return InstrumentedFragment.VIEW_CATEGORY_STORAGE_APPS;
             case LIST_TYPE_USAGE_ACCESS:
                 return MetricsLogger.USAGE_ACCESS;
+            case LIST_TYPE_HIGH_POWER:
+                return InstrumentedFragment.VIEW_CATEGORY_HIGH_POWER_APPS;
             default:
                 return MetricsLogger.VIEW_UNKNOWN;
         }
@@ -426,6 +442,9 @@
             case LIST_TYPE_STORAGE:
                 startAppInfoFragment(AppStorageSettings.class, R.string.storage_settings);
                 break;
+            case LIST_TYPE_HIGH_POWER:
+                startAppInfoFragment(HighPowerDetail.class, R.string.high_power);
+                break;
             // TODO: Figure out if there is a way where we can spin up the profile's settings
             // process ahead of time, to avoid a long load of data when user clicks on a managed app.
             // Maybe when they load the list of apps that contains managed profile apps.
@@ -436,13 +455,8 @@
     }
 
     private void startAppInfoFragment(Class<? extends AppInfoBase> fragment, int titleRes) {
-        Bundle args = new Bundle();
-        args.putString(AppInfoBase.ARG_PACKAGE_NAME, mCurrentPkgName);
-
-        Intent intent = Utils.onBuildStartFragmentIntent(getActivity(), fragment.getName(), args,
-                null, titleRes, null, false);
-        getActivity().startActivityForResultAsUser(intent, INSTALLED_APP_DETAILS,
-                new UserHandle(UserHandle.getUserId(mCurrentUid)));
+        AppInfoBase.startAppInfoFragment(fragment, titleRes, mCurrentPkgName, mCurrentUid, this,
+                INSTALLED_APP_DETAILS);
     }
 
     @Override
@@ -685,6 +699,8 @@
                         mState, this, manageApplications.mNotifBackend);
             } else if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
                 mExtraInfoBridge = new AppStateUsageBridge(mContext, mState, this);
+            } else if (mManageApplications.mListType == LIST_TYPE_HIGH_POWER) {
+                mExtraInfoBridge = new AppStatePowerBridge(mState, this);
             } else {
                 mExtraInfoBridge = null;
             }
@@ -994,6 +1010,10 @@
                     }
                     break;
 
+                case LIST_TYPE_HIGH_POWER:
+                    holder.summary.setText(HighPowerDetail.getSummary(mContext, holder.entry));
+                    break;
+
                 default:
                     holder.updateSizeText(mManageApplications.mInvalidSizeStr, mWhichSize);
                     break;
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
index b615ffd..0bf85b5 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
@@ -19,10 +19,16 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.BatteryStats;
+import android.os.Bundle;
 import android.preference.Preference;
+import android.preference.PreferenceScreen;
+import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
+
+import com.android.internal.os.BatteryStatsHelper;
 import com.android.settings.R;
+import com.android.settings.SettingsActivity;
 
 /**
  * Custom preference for displaying power consumption as a bar and an icon on the left for the
@@ -31,38 +37,60 @@
  */
 public class BatteryHistoryPreference extends Preference {
 
-    final private BatteryStats mStats;
-    final private Intent mBatteryBroadcast;
+    protected static final String BATTERY_HISTORY_FILE = "tmp_bat_history.bin";
 
-    private boolean mHideLabels;
-    private View mLabelHeader;
+    private BatteryStats mStats;
+    private Intent mBatteryBroadcast;
+
     private BatteryHistoryChart mChart;
+    private BatteryStatsHelper mHelper;
 
-    public BatteryHistoryPreference(Context context, BatteryStats stats, Intent batteryBroadcast) {
-        super(context);
-        setLayoutResource(R.layout.preference_batteryhistory);
-        mStats = stats;
-        mBatteryBroadcast = batteryBroadcast;
+    public BatteryHistoryPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void performClick(PreferenceScreen preferenceScreen) {
+        if (!isEnabled()) {
+            return;
+        }
+        mHelper.storeStatsHistoryInFile(BATTERY_HISTORY_FILE);
+        Bundle args = new Bundle();
+        args.putString(BatteryHistoryDetail.EXTRA_STATS, BATTERY_HISTORY_FILE);
+        args.putParcelable(BatteryHistoryDetail.EXTRA_BROADCAST,
+                mHelper.getBatteryBroadcast());
+        if (getContext() instanceof SettingsActivity) {
+            SettingsActivity sa = (SettingsActivity) getContext();
+            sa.startPreferencePanel(BatteryHistoryDetail.class.getName(), args,
+                    R.string.history_details_title, null, null, 0);
+        }
+    }
+
+    public void setStats(BatteryStatsHelper batteryStats) {
+        // Clear out the chart to receive new data.
+        mChart = null;
+        mHelper = batteryStats;
+        mStats = batteryStats.getStats();
+        mBatteryBroadcast = batteryStats.getBatteryBroadcast();
+        if (getLayoutResource() != R.layout.battery_history_chart) {
+            // Now we should have some data, set the layout we want.
+            setLayoutResource(R.layout.battery_history_chart);
+        }
+        notifyChanged();
     }
 
     BatteryStats getStats() {
         return mStats;
     }
 
-    public void setHideLabels(boolean hide) {
-        if (mHideLabels != hide) {
-            mHideLabels = hide;
-            if (mLabelHeader != null) {
-                mLabelHeader.setVisibility(hide ? View.GONE : View.VISIBLE);
-            }
-        }
-    }
-
     @Override
     protected void onBindView(View view) {
         super.onBindView(view);
 
-        BatteryHistoryChart chart = (BatteryHistoryChart)view.findViewById(
+        if (mStats == null) {
+            return;
+        }
+        BatteryHistoryChart chart = (BatteryHistoryChart) view.findViewById(
                 R.id.battery_history_chart);
         if (mChart == null) {
             // First time: use and initialize this chart.
@@ -71,15 +99,13 @@
         } else {
             // All future times: forget the newly inflated chart, re-use the
             // already initialized chart from last time.
-            ViewGroup parent = (ViewGroup)chart.getParent();
+            ViewGroup parent = (ViewGroup) chart.getParent();
             int index = parent.indexOfChild(chart);
             parent.removeViewAt(index);
             if (mChart.getParent() != null) {
-                ((ViewGroup)mChart.getParent()).removeView(mChart);
+                ((ViewGroup) mChart.getParent()).removeView(mChart);
             }
             parent.addView(mChart, index);
         }
-        mLabelHeader = view.findViewById(R.id.labelsHeader);
-        mLabelHeader.setVisibility(mHideLabels ? View.GONE : View.VISIBLE);
     }
 }
diff --git a/src/com/android/settings/fuelgauge/HighPowerDetail.java b/src/com/android/settings/fuelgauge/HighPowerDetail.java
new file mode 100644
index 0000000..d82cb6f
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/HighPowerDetail.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.SwitchPreference;
+
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.R;
+import com.android.settings.applications.AppInfoWithHeader;
+import com.android.settings.applications.ApplicationsState.AppEntry;
+
+public class HighPowerDetail extends AppInfoWithHeader implements OnPreferenceChangeListener {
+
+    private static final String KEY_HIGH_POWER_SWITCH = "high_power_switch";
+
+    private final PowerWhitelistBackend mBackend = PowerWhitelistBackend.getInstance();
+
+    private SwitchPreference mUsageSwitch;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        addPreferencesFromResource(R.xml.high_power_details);
+        mUsageSwitch = (SwitchPreference) findPreference(KEY_HIGH_POWER_SWITCH);
+        mUsageSwitch.setOnPreferenceChangeListener(this);
+    }
+
+    @Override
+    protected boolean refreshUi() {
+        mUsageSwitch.setEnabled(!mBackend.isSysWhitelisted(mPackageName));
+        mUsageSwitch.setChecked(mBackend.isWhitelisted(mPackageName));
+        return true;
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        if (newValue == Boolean.TRUE) {
+            mBackend.addApp(mPackageName);
+        } else {
+            mBackend.removeApp(mPackageName);
+        }
+        return true;
+    }
+
+    @Override
+    protected AlertDialog createDialog(int id, int errorCode) {
+        return null;
+    }
+
+    @Override
+    protected int getMetricsCategory() {
+        return InstrumentedFragment.VIEW_CATEGORY_HIGH_POWER_DETAILS;
+    }
+
+    public static CharSequence getSummary(Context context, AppEntry entry) {
+        return getSummary(context, entry.info.packageName);
+    }
+
+    public static CharSequence getSummary(Context context, String pkg) {
+        return context.getString(PowerWhitelistBackend.getInstance().isWhitelisted(pkg)
+                ? R.string.high_power_on : R.string.high_power_off);
+    }
+
+}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageBase.java b/src/com/android/settings/fuelgauge/PowerUsageBase.java
new file mode 100644
index 0000000..269249a
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/PowerUsageBase.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.fuelgauge;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryStats;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.UserManager;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+
+import com.android.internal.os.BatteryStatsHelper;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+
+/**
+ * Common base class for things that need to show the battery usage graph.
+ */
+public abstract class PowerUsageBase extends SettingsPreferenceFragment {
+
+    // +1 to allow ordering for PowerUsageSummary.
+    private static final int MENU_STATS_REFRESH = Menu.FIRST + 1;
+
+    protected BatteryStatsHelper mStatsHelper;
+    protected UserManager mUm;
+
+    private String mBatteryLevel;
+    private String mBatteryStatus;
+
+    @Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+        mUm = (UserManager) activity.getSystemService(Context.USER_SERVICE);
+        mStatsHelper = new BatteryStatsHelper(activity, true);
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        mStatsHelper.create(icicle);
+        setHasOptionsMenu(true);
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        mStatsHelper.clearStats();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        BatteryStatsHelper.dropFile(getActivity(), BatteryHistoryPreference.BATTERY_HISTORY_FILE);
+        updateBatteryStatus(getActivity().registerReceiver(mBatteryInfoReceiver,
+                new IntentFilter(Intent.ACTION_BATTERY_CHANGED)));
+        if (mHandler.hasMessages(MSG_REFRESH_STATS)) {
+            mHandler.removeMessages(MSG_REFRESH_STATS);
+            mStatsHelper.clearStats();
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        getActivity().unregisterReceiver(mBatteryInfoReceiver);
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        mHandler.removeMessages(MSG_REFRESH_STATS);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (getActivity().isChangingConfigurations()) {
+            mStatsHelper.storeState();
+        }
+    }
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        super.onCreateOptionsMenu(menu, inflater);
+        MenuItem refresh = menu.add(0, MENU_STATS_REFRESH, 0, R.string.menu_stats_refresh)
+                .setIcon(com.android.internal.R.drawable.ic_menu_refresh)
+                .setAlphabeticShortcut('r');
+        refresh.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM |
+                MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+    }
+
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case MENU_STATS_REFRESH:
+                mStatsHelper.clearStats();
+                refreshStats();
+                mHandler.removeMessages(MSG_REFRESH_STATS);
+                return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    protected void refreshStats() {
+        mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, mUm.getUserProfiles());
+    }
+
+    protected void updatePreference(BatteryHistoryPreference historyPref) {
+        historyPref.setStats(mStatsHelper);
+    }
+
+    private boolean updateBatteryStatus(Intent intent) {
+        if (intent != null) {
+            String batteryLevel = com.android.settings.Utils.getBatteryPercentage(intent);
+            String batteryStatus = com.android.settings.Utils.getBatteryStatus(getResources(),
+                    intent);
+            if (!batteryLevel.equals(mBatteryLevel) || !batteryStatus.equals(mBatteryStatus)) {
+                mBatteryLevel = batteryLevel;
+                mBatteryStatus = batteryStatus;
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static final int MSG_REFRESH_STATS = 100;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_REFRESH_STATS:
+                    mStatsHelper.clearStats();
+                    refreshStats();
+                    break;
+            }
+        }
+    };
+
+    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (Intent.ACTION_BATTERY_CHANGED.equals(action)
+                    && updateBatteryStatus(intent)) {
+                if (!mHandler.hasMessages(MSG_REFRESH_STATS)) {
+                    mHandler.sendEmptyMessageDelayed(MSG_REFRESH_STATS, 500);
+                }
+            }
+        }
+    };
+
+}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageDetail.java b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
index 1f13e8e..4aa935a 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.fuelgauge;
 
-import static com.android.settings.Utils.prepareCustomPreferencesList;
-
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ApplicationErrorReport;
@@ -30,33 +28,34 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.BatteryStats;
 import android.os.Bundle;
 import android.os.Process;
 import android.os.UserHandle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceCategory;
 import android.text.TextUtils;
-import android.view.LayoutInflater;
+import android.util.Log;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatterySipper.DrainType;
 import com.android.internal.os.BatteryStatsHelper;
 import com.android.internal.util.FastPrintWriter;
+import com.android.settings.AppHeader;
 import com.android.settings.DisplaySettings;
-import com.android.settings.InstrumentedFragment;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.Utils;
 import com.android.settings.WirelessSettings;
+import com.android.settings.applications.AppInfoBase;
 import com.android.settings.applications.InstalledAppDetails;
+import com.android.settings.applications.LayoutPreference;
 import com.android.settings.bluetooth.BluetoothSettings;
 import com.android.settings.location.LocationSettings;
 import com.android.settings.wifi.WifiSettings;
@@ -65,7 +64,7 @@
 import java.io.StringWriter;
 import java.io.Writer;
 
-public class PowerUsageDetail extends InstrumentedFragment implements Button.OnClickListener {
+public class PowerUsageDetail extends PowerUsageBase implements Button.OnClickListener {
 
     // Note: Must match the sequence of the DrainType
     private static int[] sDrainTypeDesciptions = new int[] {
@@ -292,51 +291,57 @@
     public static final String EXTRA_ICON_ID = "iconId"; // Int
     public static final String EXTRA_SHOW_LOCATION_BUTTON = "showLocationButton";  // Boolean
 
+    private static final String TAG = "PowerUsageDetail";
+
+    private static final String KEY_DETAILS_PARENT = "details_parent";
+    private static final String KEY_CONTROLS_PARENT = "controls_parent";
+    private static final String KEY_MESSAGES_PARENT = "messages_parent";
+    private static final String KEY_PACKAGES_PARENT = "packages_parent";
+    private static final String KEY_BATTERY_HISTORY = "battery_history";
+    private static final String KEY_TWO_BUTTONS = "two_buttons";
+    private static final String KEY_HIGH_POWER = "high_power";
+
     private PackageManager mPm;
     private DevicePolicyManager mDpm;
-    private String mTitle;
     private int mUsageSince;
     private int[] mTypes;
     private int mUid;
     private double[] mValues;
-    private View mRootView;
-    private TextView mTitleView;
-    private ViewGroup mTwoButtonsPanel;
     private Button mForceStopButton;
     private Button mReportButton;
-    private ViewGroup mDetailsParent;
-    private ViewGroup mControlsParent;
-    private ViewGroup mMessagesParent;
     private long mStartTime;
     private BatterySipper.DrainType mDrainType;
-    private Drawable mAppIcon;
     private double mNoCoverage; // Percentage of time that there was no coverage
 
+    private BatteryHistoryPreference mHistPref;
+    private PreferenceCategory mDetailsParent;
+    private PreferenceCategory mControlsParent;
+    private PreferenceCategory mMessagesParent;
+    private PreferenceCategory mPackagesParent;
+
     private boolean mUsesGps;
     private boolean mShowLocationButton;
 
-    private static final String TAG = "PowerUsageDetail";
     private String[] mPackages;
 
     ApplicationInfo mApp;
     ComponentName mInstaller;
+    private Preference mHighPower;
 
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         mPm = getActivity().getPackageManager();
         mDpm = (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
-    }
 
-    @Override
-    public View onCreateView(
-            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-        final View view = inflater.inflate(R.layout.power_usage_details, container, false);
-        prepareCustomPreferencesList(container, view, view, false);
+        addPreferencesFromResource(R.xml.power_usage_details);
+        mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_HISTORY);
+        mDetailsParent = (PreferenceCategory) findPreference(KEY_DETAILS_PARENT);
+        mControlsParent = (PreferenceCategory) findPreference(KEY_CONTROLS_PARENT);
+        mMessagesParent = (PreferenceCategory) findPreference(KEY_MESSAGES_PARENT);
+        mPackagesParent = (PreferenceCategory) findPreference(KEY_PACKAGES_PARENT);
 
-        mRootView = view;
         createDetails();
-        return view;
     }
 
     @Override
@@ -349,76 +354,31 @@
         super.onResume();
         mStartTime = android.os.Process.getElapsedCpuTime();
         checkForceStop();
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
+        if (mHighPower != null) {
+            mHighPower.setSummary(HighPowerDetail.getSummary(getActivity(), mApp.packageName));
+        }
     }
 
     private void createDetails() {
         final Bundle args = getArguments();
-        mTitle = args.getString(EXTRA_TITLE);
-        final int percentage = args.getInt(EXTRA_PERCENT, 1);
-        final int gaugeValue = args.getInt(EXTRA_GAUGE, 1);
+        Context context = getActivity();
         mUsageSince = args.getInt(EXTRA_USAGE_SINCE, USAGE_SINCE_UNPLUGGED);
         mUid = args.getInt(EXTRA_UID, 0);
+        mPackages = context.getPackageManager().getPackagesForUid(mUid);
         mDrainType = (BatterySipper.DrainType) args.getSerializable(EXTRA_DRAIN_TYPE);
         mNoCoverage = args.getDouble(EXTRA_NO_COVERAGE, 0);
-        String iconPackage = args.getString(EXTRA_ICON_PACKAGE);
-        int iconId = args.getInt(EXTRA_ICON_ID, 0);
         mShowLocationButton = args.getBoolean(EXTRA_SHOW_LOCATION_BUTTON);
-        if (!TextUtils.isEmpty(iconPackage)) {
-            try {
-                final PackageManager pm = getActivity().getPackageManager();
-                ApplicationInfo ai = pm.getPackageInfo(iconPackage, 0).applicationInfo;
-                if (ai != null) {
-                    mAppIcon = ai.loadIcon(pm);
-                }
-            } catch (NameNotFoundException nnfe) {
-                // Use default icon
-            }
-        } else if (iconId != 0) {
-            mAppIcon = getActivity().getDrawable(iconId);
-        }
-        if (mAppIcon == null) {
-            mAppIcon = getActivity().getPackageManager().getDefaultActivityIcon();
-        }
 
-        // Set the description
-        final TextView summary = (TextView) mRootView.findViewById(android.R.id.summary);
-        summary.setText(getDescriptionForDrainType());
-        summary.setVisibility(View.VISIBLE);
+        setupHeader();
 
         mTypes = args.getIntArray(EXTRA_DETAIL_TYPES);
         mValues = args.getDoubleArray(EXTRA_DETAIL_VALUES);
 
-        mTitleView = (TextView) mRootView.findViewById(android.R.id.title);
-        mTitleView.setText(mTitle);
-
-        final TextView text1 = (TextView)mRootView.findViewById(android.R.id.text1);
-        text1.setText(Utils.formatPercentage(percentage));
-
-        mTwoButtonsPanel = (ViewGroup)mRootView.findViewById(R.id.two_buttons_panel);
-        mForceStopButton = (Button)mRootView.findViewById(R.id.left_button);
-        mReportButton = (Button)mRootView.findViewById(R.id.right_button);
+        LayoutPreference twoButtons = (LayoutPreference) findPreference(KEY_TWO_BUTTONS);
+        mForceStopButton = (Button) twoButtons.findViewById(R.id.left_button);
+        mReportButton = (Button) twoButtons.findViewById(R.id.right_button);
         mForceStopButton.setEnabled(false);
 
-        final ProgressBar progress = (ProgressBar) mRootView.findViewById(android.R.id.progress);
-        progress.setProgress(gaugeValue);
-
-        final ImageView icon = (ImageView) mRootView.findViewById(android.R.id.icon);
-        icon.setImageDrawable(mAppIcon);
-
-        mDetailsParent = (ViewGroup)mRootView.findViewById(R.id.details);
-        mControlsParent = (ViewGroup)mRootView.findViewById(R.id.controls);
-        mMessagesParent = (ViewGroup)mRootView.findViewById(R.id.messages);
-
-        fillDetailsSection();
-        fillPackagesSection(mUid);
-        fillControlsSection(mUid);
-        fillMessagesSection(mUid);
-        
         if (mUid >= Process.FIRST_APPLICATION_UID) {
             mForceStopButton.setText(R.string.force_stop);
             mForceStopButton.setTag(ACTION_FORCE_STOP);
@@ -426,27 +386,86 @@
             mReportButton.setText(com.android.internal.R.string.report);
             mReportButton.setTag(ACTION_REPORT);
             mReportButton.setOnClickListener(this);
-            
+
+            if (mPackages != null && mPackages.length > 0) {
+                try {
+                    mApp = context.getPackageManager().getApplicationInfo(
+                            mPackages[0], 0);
+                } catch (NameNotFoundException e) {
+                }
+            } else {
+                Log.d(TAG, "No packages!!");
+            }
             // check if error reporting is enabled in secure settings
-            int enabled = android.provider.Settings.Global.getInt(getActivity().getContentResolver(),
+            int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
                     android.provider.Settings.Global.SEND_ACTION_APP_ERROR, 0);
             if (enabled != 0) {
-                if (mPackages != null && mPackages.length > 0) {
-                    try {
-                        mApp = getActivity().getPackageManager().getApplicationInfo(
-                                mPackages[0], 0);
-                        mInstaller = ApplicationErrorReport.getErrorReportReceiver(
-                                getActivity(), mPackages[0], mApp.flags);
-                    } catch (NameNotFoundException e) {
-                    }
+                if (mApp != null) {
+                    mInstaller = ApplicationErrorReport.getErrorReportReceiver(
+                            context, mPackages[0], mApp.flags);
                 }
                 mReportButton.setEnabled(mInstaller != null);
             } else {
-                mTwoButtonsPanel.setVisibility(View.GONE);
+                removePreference(KEY_TWO_BUTTONS);
+            }
+            if (mApp != null) {
+                mHighPower = findPreference(KEY_HIGH_POWER);
+                mHighPower.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+                    @Override
+                    public boolean onPreferenceClick(Preference preference) {
+                        AppInfoBase.startAppInfoFragment(HighPowerDetail.class, R.string.high_power,
+                                mApp.packageName, mApp.uid, PowerUsageDetail.this, 0);
+                        return true;
+                    }
+                });
+            } else {
+                removePreference(KEY_HIGH_POWER);
             }
         } else {
-            mTwoButtonsPanel.setVisibility(View.GONE);
+            removePreference(KEY_TWO_BUTTONS);
+            removePreference(KEY_HIGH_POWER);
         }
+
+        refreshStats();
+
+        fillDetailsSection();
+        fillPackagesSection(mUid);
+        fillControlsSection(mUid);
+        fillMessagesSection(mUid);
+    }
+    
+    @Override
+    protected void refreshStats() {
+        super.refreshStats();
+        updatePreference(mHistPref);
+    }
+
+    private void setupHeader() {
+        final Bundle args = getArguments();
+        String title = args.getString(EXTRA_TITLE);
+        String iconPackage = args.getString(EXTRA_ICON_PACKAGE);
+        int iconId = args.getInt(EXTRA_ICON_ID, 0);
+        Drawable appIcon = null;
+
+        if (!TextUtils.isEmpty(iconPackage)) {
+            try {
+                final PackageManager pm = getActivity().getPackageManager();
+                ApplicationInfo ai = pm.getPackageInfo(iconPackage, 0).applicationInfo;
+                if (ai != null) {
+                    appIcon = ai.loadIcon(pm);
+                }
+            } catch (NameNotFoundException nnfe) {
+                // Use default icon
+            }
+        } else if (iconId != 0) {
+            appIcon = getActivity().getDrawable(iconId);
+        }
+        if (appIcon == null) {
+            appIcon = getActivity().getPackageManager().getDefaultActivityIcon();
+        }
+
+        AppHeader.createAppHeader(getActivity(), appIcon, title, null,
+                mDrainType != DrainType.APP ? android.R.color.white : 0);
     }
 
     public void onClick(View v) {
@@ -500,7 +519,6 @@
     }
 
     private void fillDetailsSection() {
-        LayoutInflater inflater = getActivity().getLayoutInflater();
         if (mTypes != null && mValues != null) {
             for (int i = 0; i < mTypes.length; i++) {
                 // Only add an item if the time is greater than zero
@@ -530,17 +548,21 @@
                     default:
                         value = Utils.formatElapsedTime(getActivity(), mValues[i], true);
                 }
-                ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_detail_item_text,
-                        null);
-                mDetailsParent.addView(item);
-                TextView labelView = (TextView) item.findViewById(R.id.label);
-                TextView valueView = (TextView) item.findViewById(R.id.value);
-                labelView.setText(label);
-                valueView.setText(value);
+                addHorizontalPreference(mDetailsParent, label, value);
             }
         }
     }
 
+    private void addHorizontalPreference(PreferenceCategory parent, CharSequence title,
+            CharSequence summary) {
+        Preference pref = new Preference(getActivity());
+        pref.setLayoutResource(R.layout.horizontal_preference);
+        pref.setTitle(title);
+        pref.setSummary(summary);
+        pref.setSelectable(false);
+        parent.addPreference(pref);
+    }
+
     private void fillControlsSection(int uid) {
         PackageManager pm = getActivity().getPackageManager();
         String[] packages = pm.getPackagesForUid(uid);
@@ -597,21 +619,22 @@
                 break;
         }
         if (removeHeader) {
-            mControlsParent.setVisibility(View.GONE);
+            mControlsParent.setTitle(null);
         }
     }
 
-    private void addControl(int title, int summary, int action) {
-        final Resources res = getResources();
-        LayoutInflater inflater = getActivity().getLayoutInflater();
-        ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_action_item,null);
-        mControlsParent.addView(item);
-        Button actionButton = (Button) item.findViewById(R.id.action_button);
-        TextView summaryView = (TextView) item.findViewById(R.id.summary);
-        actionButton.setText(res.getString(title));
-        summaryView.setText(res.getString(summary));
-        actionButton.setOnClickListener(this);
-        actionButton.setTag(new Integer(action));
+    private void addControl(int pageSummary, int actionTitle, final int action) {
+        Preference pref = new Preference(getActivity());
+        pref.setTitle(actionTitle);
+        pref.setSummary(pageSummary);
+        pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+            @Override
+            public boolean onPreferenceClick(Preference preference) {
+                doAction(action);
+                return true;
+            }
+        });
+        mControlsParent.addPreference(pref);
     }
 
     private void fillMessagesSection(int uid) {
@@ -623,27 +646,16 @@
                 break;
         }
         if (removeHeader) {
-            mMessagesParent.setVisibility(View.GONE);
+            mMessagesParent.setTitle(null);
         }
     }
 
     private void addMessage(int message) {
-        final Resources res = getResources();
-        LayoutInflater inflater = getActivity().getLayoutInflater();
-        View item = inflater.inflate(R.layout.power_usage_message_item, null);
-        mMessagesParent.addView(item);
-        TextView messageView = (TextView) item.findViewById(R.id.message);
-        messageView.setText(res.getText(message));
+        addHorizontalPreference(mMessagesParent, getString(message), null);
     }
 
     private void removePackagesSection() {
-        View view;
-        if ((view = mRootView.findViewById(R.id.packages_section_title)) != null) {
-            view.setVisibility(View.GONE);
-        }
-        if ((view = mRootView.findViewById(R.id.packages_section)) != null) {
-            view.setVisibility(View.GONE);
-        }
+        getPreferenceScreen().removePreference(mPackagesParent);
     }
 
     private void killProcesses() {
@@ -663,7 +675,7 @@
             mForceStopButton.setEnabled(getResultCode() != Activity.RESULT_CANCELED);
         }
     };
-    
+
     private void checkForceStop() {
         if (mPackages == null || mUid < Process.FIRST_APPLICATION_UID) {
             mForceStopButton.setEnabled(false);
@@ -693,10 +705,10 @@
         getActivity().sendOrderedBroadcast(intent, null, mCheckKillProcessesReceiver, null,
                 Activity.RESULT_CANCELED, null, null);
     }
-    
+
     private void reportBatteryUse() {
         if (mPackages == null) return;
-        
+
         ApplicationErrorReport report = new ApplicationErrorReport();
         report.type = ApplicationErrorReport.TYPE_BATTERY;
         report.packageName = mPackages[0];
@@ -719,46 +731,29 @@
         result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         startActivity(result);
     }
-    
+
     private void fillPackagesSection(int uid) {
         if (uid < 1) {
             removePackagesSection();
             return;
         }
-        ViewGroup packagesParent = (ViewGroup)mRootView.findViewById(R.id.packages_section);
-        if (packagesParent == null) return;
-        LayoutInflater inflater = getActivity().getLayoutInflater();
-        
-        PackageManager pm = getActivity().getPackageManager();
-        //final Drawable defaultActivityIcon = pm.getDefaultActivityIcon();
-        mPackages = pm.getPackagesForUid(uid);
         if (mPackages == null || mPackages.length < 2) {
             removePackagesSection();
             return;
         }
 
+        PackageManager pm = getPackageManager();
         // Convert package names to user-facing labels where possible
         for (int i = 0; i < mPackages.length; i++) {
             try {
                 ApplicationInfo ai = pm.getApplicationInfo(mPackages[i], 0);
                 CharSequence label = ai.loadLabel(pm);
-                //Drawable icon = defaultActivityIcon;
                 if (label != null) {
                     mPackages[i] = label.toString();
                 }
-                //if (ai.icon != 0) {
-                //    icon = ai.loadIcon(pm);
-                //}
-                View item = inflater.inflate(R.layout.power_usage_package_item, null);
-                packagesParent.addView(item);
-                TextView labelView = (TextView) item.findViewById(R.id.label);
-                labelView.setText(mPackages[i]);
+                addHorizontalPreference(mPackagesParent, mPackages[i], null);
             } catch (NameNotFoundException e) {
             }
         }
     }
-    
-    private String getDescriptionForDrainType() {
-        return getResources().getString(sDrainTypeDesciptions[mDrainType.ordinal()]);
-    }
 }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 297fe1a..89a3325 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -17,10 +17,6 @@
 package com.android.settings.fuelgauge;
 
 import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.graphics.drawable.Drawable;
 import android.os.BatteryStats;
 import android.os.Build;
@@ -28,7 +24,6 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.preference.Preference;
 import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
@@ -39,12 +34,12 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.os.BatterySipper;
-import com.android.internal.os.BatteryStatsHelper;
 import com.android.internal.os.PowerProfile;
 import com.android.settings.HelpUtils;
-import com.android.settings.InstrumentedPreferenceFragment;
 import com.android.settings.R;
+import com.android.settings.Settings.HighPowerApplicationsActivity;
 import com.android.settings.SettingsActivity;
+import com.android.settings.applications.ManageApplications;
 
 import java.util.List;
 
@@ -52,27 +47,22 @@
  * Displays a list of apps and subsystems that consume power, ordered by how much power was
  * consumed since the last time it was unplugged.
  */
-public class PowerUsageSummary extends InstrumentedPreferenceFragment {
+public class PowerUsageSummary extends PowerUsageBase {
 
     private static final boolean DEBUG = false;
 
     static final String TAG = "PowerUsageSummary";
 
     private static final String KEY_APP_LIST = "app_list";
-
-    private static final String BATTERY_HISTORY_FILE = "tmp_bat_history.bin";
+    private static final String KEY_BATTERY_HISTORY = "battery_history";
 
     private static final int MENU_STATS_TYPE = Menu.FIRST;
-    private static final int MENU_STATS_REFRESH = Menu.FIRST + 1;
     private static final int MENU_BATTERY_SAVER = Menu.FIRST + 2;
-    private static final int MENU_HELP = Menu.FIRST + 3;
-
-    private UserManager mUm;
+    private static final int MENU_HIGH_POWER_APPS = Menu.FIRST + 3;
+    private static final int MENU_HELP = Menu.FIRST + 4;
 
     private BatteryHistoryPreference mHistPref;
     private PreferenceGroup mAppListGroup;
-    private String mBatteryLevel;
-    private String mBatteryStatus;
 
     private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
 
@@ -81,43 +71,13 @@
     private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
     private static final int SECONDS_IN_HOUR = 60 * 60;
 
-    private BatteryStatsHelper mStatsHelper;
-
-    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (Intent.ACTION_BATTERY_CHANGED.equals(action)
-                    && updateBatteryStatus(intent)) {
-                if (!mHandler.hasMessages(MSG_REFRESH_STATS)) {
-                    mHandler.sendEmptyMessageDelayed(MSG_REFRESH_STATS, 500);
-                }
-            }
-        }
-    };
-
-    @Override
-    public void onAttach(Activity activity) {
-        super.onAttach(activity);
-        mUm = (UserManager) activity.getSystemService(Context.USER_SERVICE);
-        mStatsHelper = new BatteryStatsHelper(activity, true);
-    }
-
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        mStatsHelper.create(icicle);
 
         addPreferencesFromResource(R.xml.power_usage_summary);
+        mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_HISTORY);
         mAppListGroup = (PreferenceGroup) findPreference(KEY_APP_LIST);
-        setHasOptionsMenu(true);
-    }
-
-    @Override
-    public void onStart() {
-        super.onStart();
-        mStatsHelper.clearStats();
     }
 
     @Override
@@ -128,13 +88,6 @@
     @Override
     public void onResume() {
         super.onResume();
-        BatteryStatsHelper.dropFile(getActivity(), BATTERY_HISTORY_FILE);
-        updateBatteryStatus(getActivity().registerReceiver(mBatteryInfoReceiver,
-                new IntentFilter(Intent.ACTION_BATTERY_CHANGED)));
-        if (mHandler.hasMessages(MSG_REFRESH_STATS)) {
-            mHandler.removeMessages(MSG_REFRESH_STATS);
-            mStatsHelper.clearStats();
-        }
         refreshStats();
     }
 
@@ -142,38 +95,19 @@
     public void onPause() {
         BatteryEntry.stopRequestQueue();
         mHandler.removeMessages(BatteryEntry.MSG_UPDATE_NAME_ICON);
-        getActivity().unregisterReceiver(mBatteryInfoReceiver);
         super.onPause();
     }
 
     @Override
-    public void onStop() {
-        super.onStop();
-        mHandler.removeMessages(MSG_REFRESH_STATS);
-    }
-
-    @Override
     public void onDestroy() {
         super.onDestroy();
         if (getActivity().isChangingConfigurations()) {
-            mStatsHelper.storeState();
             BatteryEntry.clearUidCache();
         }
     }
 
     @Override
     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
-        if (preference instanceof BatteryHistoryPreference) {
-            mStatsHelper.storeStatsHistoryInFile(BATTERY_HISTORY_FILE);
-            Bundle args = new Bundle();
-            args.putString(BatteryHistoryDetail.EXTRA_STATS, BATTERY_HISTORY_FILE);
-            args.putParcelable(BatteryHistoryDetail.EXTRA_BROADCAST,
-                    mStatsHelper.getBatteryBroadcast());
-            SettingsActivity sa = (SettingsActivity) getActivity();
-            sa.startPreferencePanel(BatteryHistoryDetail.class.getName(), args,
-                    R.string.history_details_title, null, null, 0);
-            return super.onPreferenceTreeClick(preferenceScreen, preference);
-        }
         if (!(preference instanceof PowerGaugePreference)) {
             return false;
         }
@@ -186,20 +120,18 @@
 
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        super.onCreateOptionsMenu(menu, inflater);
         if (DEBUG) {
             menu.add(0, MENU_STATS_TYPE, 0, R.string.menu_stats_total)
                     .setIcon(com.android.internal.R.drawable.ic_menu_info_details)
                     .setAlphabeticShortcut('t');
         }
-        MenuItem refresh = menu.add(0, MENU_STATS_REFRESH, 0, R.string.menu_stats_refresh)
-                .setIcon(com.android.internal.R.drawable.ic_menu_refresh)
-                .setAlphabeticShortcut('r');
-        refresh.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM |
-                MenuItem.SHOW_AS_ACTION_WITH_TEXT);
 
         MenuItem batterySaver = menu.add(0, MENU_BATTERY_SAVER, 0, R.string.battery_saver);
         batterySaver.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
 
+        menu.add(0, MENU_HIGH_POWER_APPS, 0, R.string.high_power_apps);
+
         String helpUrl;
         if (!TextUtils.isEmpty(helpUrl = getResources().getString(R.string.help_url_battery))) {
             final MenuItem help = menu.add(0, MENU_HELP, 0, R.string.help_label);
@@ -209,6 +141,7 @@
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
+        final SettingsActivity sa = (SettingsActivity) getActivity();
         switch (item.getItemId()) {
             case MENU_STATS_TYPE:
                 if (mStatsType == BatteryStats.STATS_SINCE_CHARGED) {
@@ -218,59 +151,40 @@
                 }
                 refreshStats();
                 return true;
-            case MENU_STATS_REFRESH:
-                mStatsHelper.clearStats();
-                refreshStats();
-                mHandler.removeMessages(MSG_REFRESH_STATS);
-                return true;
             case MENU_BATTERY_SAVER:
-                final SettingsActivity sa = (SettingsActivity) getActivity();
                 sa.startPreferencePanel(BatterySaverSettings.class.getName(), null,
                         R.string.battery_saver, null, null, 0);
                 return true;
+            case MENU_HIGH_POWER_APPS:
+                Bundle args = new Bundle();
+                args.putString(ManageApplications.EXTRA_CLASSNAME,
+                        HighPowerApplicationsActivity.class.getName());
+                sa.startPreferencePanel(ManageApplications.class.getName(), args,
+                        R.string.high_power_apps, null, null, 0);
+                return true;
             default:
-                return false;
+                return super.onOptionsItemSelected(item);
         }
     }
 
     private void addNotAvailableMessage() {
         Preference notAvailable = new Preference(getActivity());
         notAvailable.setTitle(R.string.power_usage_not_available);
-        mHistPref.setHideLabels(true);
         mAppListGroup.addPreference(notAvailable);
     }
 
-    private boolean updateBatteryStatus(Intent intent) {
-        if (intent != null) {
-            String batteryLevel = com.android.settings.Utils.getBatteryPercentage(intent);
-            String batteryStatus = com.android.settings.Utils.getBatteryStatus(getResources(),
-                    intent);
-            if (!batteryLevel.equals(mBatteryLevel) || !batteryStatus.equals(mBatteryStatus)) {
-                mBatteryLevel = batteryLevel;
-                mBatteryStatus = batteryStatus;
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private void refreshStats() {
+    protected void refreshStats() {
+        super.refreshStats();
+        updatePreference(mHistPref);
         mAppListGroup.removeAll();
         mAppListGroup.setOrderingAsAdded(false);
-        mHistPref = new BatteryHistoryPreference(getActivity(), mStatsHelper.getStats(),
-                mStatsHelper.getBatteryBroadcast());
-        mHistPref.setOrder(-1);
-        mAppListGroup.addPreference(mHistPref);
         boolean addedSome = false;
 
         final PowerProfile powerProfile = mStatsHelper.getPowerProfile();
         final BatteryStats stats = mStatsHelper.getStats();
         final double averagePower = powerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
+
         if (averagePower >= MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP) {
-            final List<UserHandle> profiles = mUm.getUserProfiles();
-
-            mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, profiles);
-
             final List<BatterySipper> usageList = mStatsHelper.getUsageList();
 
             final int dischargeAmount = stats != null ? stats.getDischargeAmount(mStatsType) : 0;
@@ -320,7 +234,8 @@
                 final PowerGaugePreference pref = new PowerGaugePreference(getActivity(),
                         badgedIcon, contentDescription, entry);
 
-                final double percentOfMax = (sipper.totalPowerMah * 100) / mStatsHelper.getMaxPower();
+                final double percentOfMax = (sipper.totalPowerMah * 100)
+                        / mStatsHelper.getMaxPower();
                 sipper.percent = percentOfTotal;
                 pref.setTitle(entry.getLabel());
                 pref.setOrder(i + 1);
@@ -342,8 +257,6 @@
         BatteryEntry.startRequestQueue();
     }
 
-    static final int MSG_REFRESH_STATS = 100;
-
     Handler mHandler = new Handler() {
 
         @Override
@@ -367,9 +280,6 @@
                         activity.reportFullyDrawn();
                     }
                     break;
-                case MSG_REFRESH_STATS:
-                    mStatsHelper.clearStats();
-                    refreshStats();
             }
             super.handleMessage(msg);
         }
diff --git a/src/com/android/settings/fuelgauge/PowerWhitelistBackend.java b/src/com/android/settings/fuelgauge/PowerWhitelistBackend.java
new file mode 100644
index 0000000..7199af8
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/PowerWhitelistBackend.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.fuelgauge;
+
+import android.os.IDeviceIdleController;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.ArraySet;
+import android.util.Log;
+
+
+/**
+ * Handles getting/changing the whitelist for the exceptions to battery saving features.
+ */
+public class PowerWhitelistBackend {
+
+    private static final String TAG = "PowerWhitelistBackend";
+
+    private static final String DEVICE_IDLE_SERVICE = "deviceidle";
+
+    private static final PowerWhitelistBackend INSTANCE = new PowerWhitelistBackend();
+
+    private final IDeviceIdleController mDeviceIdleService;
+    private final ArraySet<String> mWhitelistedApps = new ArraySet<>();
+    private final ArraySet<String> mSysWhitelistedApps = new ArraySet<>();
+
+    public PowerWhitelistBackend() {
+        mDeviceIdleService = IDeviceIdleController.Stub.asInterface(
+                ServiceManager.getService(DEVICE_IDLE_SERVICE));
+        refreshList();
+    }
+
+    public int getWhitelistSize() {
+        return mWhitelistedApps.size();
+    }
+
+    public boolean isSysWhitelisted(String pkg) {
+        return mSysWhitelistedApps.contains(pkg);
+    }
+
+    public boolean isWhitelisted(String pkg) {
+        return mWhitelistedApps.contains(pkg);
+    }
+
+    public void addApp(String pkg) {
+        try {
+            mDeviceIdleService.addPowerSaveWhitelistApp(pkg);
+            mWhitelistedApps.add(pkg);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Unable to reach IDeviceIdleController", e);
+        }
+    }
+
+    public void removeApp(String pkg) {
+        try {
+            mDeviceIdleService.removePowerSaveWhitelistApp(pkg);
+            mWhitelistedApps.remove(pkg);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Unable to reach IDeviceIdleController", e);
+        }
+    }
+
+    private void refreshList() {
+        mSysWhitelistedApps.clear();
+        mWhitelistedApps.clear();
+        try {
+            String[] whitelistedApps = mDeviceIdleService.getFullPowerWhitelist();
+            for (String app : whitelistedApps) {
+                mWhitelistedApps.add(app);
+            }
+            String[] sysWhitelistedApps = mDeviceIdleService.getSystemPowerWhitelist();
+            for (String app : sysWhitelistedApps) {
+                mSysWhitelistedApps.add(app);
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, "Unable to reach IDeviceIdleController", e);
+        }
+    }
+
+    public static PowerWhitelistBackend getInstance() {
+        return INSTANCE;
+    }
+
+}