summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Monk <jmonk@google.com>2015-05-04 18:50:19 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-05-04 18:50:19 +0000
commit0ab13b8326d6f31caff922fd95828254cb95a618 (patch)
treef514c7a42486c9d599a5fc27891bf32c6999cab6
parent32ba436b0b8b955874dd2797a4c317951385fcde (diff)
parent1eb54eb2ff250eccdd700601011bd6457ddcbec1 (diff)
downloadpackages_apps_Settings-0ab13b8326d6f31caff922fd95828254cb95a618.zip
packages_apps_Settings-0ab13b8326d6f31caff922fd95828254cb95a618.tar.gz
packages_apps_Settings-0ab13b8326d6f31caff922fd95828254cb95a618.tar.bz2
Merge "Add high power whitelist for apps" into mnc-dev
-rw-r--r--AndroidManifest.xml9
-rw-r--r--res/layout/horizontal_preference.xml43
-rw-r--r--res/layout/power_usage_action_item.xml54
-rw-r--r--res/layout/power_usage_detail_item_text.xml48
-rw-r--r--res/layout/power_usage_details.xml111
-rw-r--r--res/layout/power_usage_message_item.xml27
-rw-r--r--res/layout/preference_batteryhistory.xml36
-rw-r--r--res/values/strings.xml27
-rw-r--r--res/xml/advanced_apps.xml19
-rw-r--r--res/xml/high_power_details.xml (renamed from res/layout/power_usage_package_item.xml)25
-rw-r--r--res/xml/installed_app_details.xml9
-rw-r--r--res/xml/power_usage_details.xml47
-rw-r--r--res/xml/power_usage_summary.xml11
-rw-r--r--src/com/android/settings/AppHeader.java9
-rw-r--r--src/com/android/settings/InstrumentedFragment.java2
-rw-r--r--src/com/android/settings/Settings.java1
-rw-r--r--src/com/android/settings/SettingsActivity.java2
-rw-r--r--src/com/android/settings/applications/AdvancedAppSettings.java8
-rw-r--r--src/com/android/settings/applications/AppInfoBase.java13
-rw-r--r--src/com/android/settings/applications/AppStatePowerBridge.java78
-rwxr-xr-xsrc/com/android/settings/applications/InstalledAppDetails.java62
-rw-r--r--src/com/android/settings/applications/LayoutPreference.java4
-rw-r--r--src/com/android/settings/applications/ManageApplications.java42
-rw-r--r--src/com/android/settings/fuelgauge/BatteryHistoryPreference.java70
-rw-r--r--src/com/android/settings/fuelgauge/HighPowerDetail.java84
-rw-r--r--src/com/android/settings/fuelgauge/PowerUsageBase.java172
-rw-r--r--src/com/android/settings/fuelgauge/PowerUsageDetail.java295
-rw-r--r--src/com/android/settings/fuelgauge/PowerUsageSummary.java140
-rw-r--r--src/com/android/settings/fuelgauge/PowerWhitelistBackend.java97
29 files changed, 950 insertions, 595 deletions
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/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,18 +26,27 @@
settings:keywords="@string/keywords_default_apps" />
<PreferenceScreen
+ android:key="domain_urls"
+ android:title="@string/domain_urls_title"
+ android:fragment="com.android.settings.applications.ManageApplications">
+ <extra
+ android:name="classname"
+ 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="domain_urls"
- android:title="@string/domain_urls_title"
- android:fragment="com.android.settings.applications.ManageApplications">
+ 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$DomainsURLsAppListActivity" />
+ android:name="classname"
+ android:value="com.android.settings.Settings$HighPowerApplicationsActivity" />
</PreferenceScreen>
</PreferenceScreen>
diff --git a/res/layout/power_usage_package_item.xml b/res/xml/high_power_details.xml
index 6c31792..81f7806 100644
--- a/res/layout/power_usage_package_item.xml
+++ b/res/xml/high_power_details.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- 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.
@@ -14,13 +14,16 @@
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" />
+<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 @@ package com.android.settings;
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 class AppHeader {
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 @@ public class AppHeader {
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 abstract class InstrumentedFragment extends PreferenceFragment {
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 class Settings extends SettingsActivity {
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.PublicVolumeSettings;
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 @@ public class SettingsActivity extends Activity
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.R;
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 @@ public class AdvancedAppSettings extends SettingsPreferenceFragment implements
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 @@ public class AdvancedAppSettings extends SettingsPreferenceFragment implements
mAppPermsPreference = findPreference(KEY_APP_PERM);
mAppDomainURLsPreference = findPreference(KEY_APP_DOMAIN_URLS);
+ mHighPowerPreference = findPreference(KEY_HIGH_POWER_APPS);
updateUI();
}
@@ -70,6 +74,10 @@ public class AdvancedAppSettings extends SettingsPreferenceFragment implements
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.Activity;
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 android.util.Log;
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 @@ public abstract class AppInfoBase extends InstrumentedPreferenceFragment
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.NetworkTemplate;
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.ImageView;
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 @@ public class InstalledAppDetails extends AppInfoBase
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 @@ public class InstalledAppDetails extends AppInfoBase
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 @@ public class InstalledAppDetails extends AppInfoBase
} catch (RemoteException e) {
throw new RuntimeException(e);
}
+ mBatteryHelper = new BatteryStatsHelper(getActivity(), true);
}
@Override
@@ -236,6 +248,7 @@ public class InstalledAppDetails extends AppInfoBase
getLoaderManager().restartLoader(LOADER_CHART_DATA,
ChartDataLoader.buildArgs(NetworkTemplate.buildTemplateMobileWildcard(), app),
mDataCallbacks);
+ new BatteryUpdater().execute();
}
@Override
@@ -263,6 +276,9 @@ public class InstalledAppDetails extends AppInfoBase
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 @@ public class InstalledAppDetails extends AppInfoBase
mBackend));
mDataPreference.setSummary(getDataSummary());
+ updateBattery();
+
if (!mInitialized) {
// First time init: are we displaying an uninstalled app?
mInitialized = true;
@@ -459,6 +477,20 @@ public class InstalledAppDetails extends AppInfoBase
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 @@ public class InstalledAppDetails extends AppInfoBase
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 @@ public class InstalledAppDetails extends AppInfoBase
}
}
- 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 @@ public class LayoutPreference extends Preference {
.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.InstrumentedFragment;
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.AppEntry;
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 class ManageApplications extends InstrumentedFragment
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 @@ public class ManageApplications extends InstrumentedFragment
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 @@ public class ManageApplications extends InstrumentedFragment
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 @@ public class ManageApplications extends InstrumentedFragment
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 @@ public class ManageApplications extends InstrumentedFragment
} 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 @@ public class ManageApplications extends InstrumentedFragment
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 @@ public class ManageApplications extends InstrumentedFragment
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 @@ public class ManageApplications extends InstrumentedFragment
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 @@ public class ManageApplications extends InstrumentedFragment
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 @@ public class ManageApplications extends InstrumentedFragment
}
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 @@ public class ManageApplications extends InstrumentedFragment
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 @@ public class ManageApplications extends InstrumentedFragment
}
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 @@ package com.android.settings.fuelgauge;
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 @@ import com.android.settings.R;
*/
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 BatteryStats mStats;
+ private Intent mBatteryBroadcast;
- private boolean mHideLabels;
- private View mLabelHeader;
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);
}
- BatteryStats getStats() {
- return mStats;
+ @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 setHideLabels(boolean hide) {
- if (mHideLabels != hide) {
- mHideLabels = hide;
- if (mLabelHeader != null) {
- mLabelHeader.setVisibility(hide ? View.GONE : View.VISIBLE);
- }
+ 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;
}
@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 @@ public class BatteryHistoryPreference extends Preference {
} 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.ApplicationInfo;
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.PrintWriter;
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 class PowerUsageDetail extends InstrumentedFragment implements Button.OnC
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 @@ public class PowerUsageDetail extends InstrumentedFragment implements Button.OnC
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 @@ public class PowerUsageDetail extends InstrumentedFragment implements Button.OnC
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 @@ public class PowerUsageDetail extends InstrumentedFragment implements Button.OnC
}
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 @@ public class PowerUsageDetail extends InstrumentedFragment implements Button.OnC
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 @@ public class PowerUsageDetail extends InstrumentedFragment implements Button.OnC
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 @@ public class PowerUsageDetail extends InstrumentedFragment implements Button.OnC
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 @@ public class PowerUsageDetail extends InstrumentedFragment implements Button.OnC
mForceStopButton.setEnabled(getResultCode() != Activity.RESULT_CANCELED);
}
};
-
+
private void checkForceStop() {
if (mPackages == null || mUid < Process.FIRST_APPLICATION_UID) {
mForceStopButton.setEnabled(false);
@@ -693,10 +705,10 @@ public class PowerUsageDetail extends InstrumentedFragment implements Button.OnC
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 @@ public class PowerUsageDetail extends InstrumentedFragment implements Button.OnC
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.Bundle;
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 android.view.MenuItem;
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 @@ import java.util.List;
* 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 @@ public class PowerUsageSummary extends InstrumentedPreferenceFragment {
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 @@ public class PowerUsageSummary extends InstrumentedPreferenceFragment {
@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 class PowerUsageSummary extends InstrumentedPreferenceFragment {
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 @@ public class PowerUsageSummary extends InstrumentedPreferenceFragment {
@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 @@ public class PowerUsageSummary extends InstrumentedPreferenceFragment {
@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 @@ public class PowerUsageSummary extends InstrumentedPreferenceFragment {
}
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);
+ if (averagePower >= MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP) {
final List<BatterySipper> usageList = mStatsHelper.getUsageList();
final int dischargeAmount = stats != null ? stats.getDischargeAmount(mStatsType) : 0;
@@ -320,7 +234,8 @@ public class PowerUsageSummary extends InstrumentedPreferenceFragment {
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 @@ public class PowerUsageSummary extends InstrumentedPreferenceFragment {
BatteryEntry.startRequestQueue();
}
- static final int MSG_REFRESH_STATS = 100;
-
Handler mHandler = new Handler() {
@Override
@@ -367,9 +280,6 @@ public class PowerUsageSummary extends InstrumentedPreferenceFragment {
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;
+ }
+
+}