2 * Copyright (C) 2009 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.settings.fuelgauge;
19 import android.app.Activity;
20 import android.app.ActivityManager;
21 import android.app.ApplicationErrorReport;
22 import android.app.admin.DevicePolicyManager;
23 import android.content.BroadcastReceiver;
24 import android.content.ComponentName;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.pm.ApplicationInfo;
28 import android.content.pm.PackageInfo;
29 import android.content.pm.PackageManager;
30 import android.content.pm.PackageManager.NameNotFoundException;
31 import android.graphics.drawable.Drawable;
32 import android.net.Uri;
33 import android.os.BatteryStats;
34 import android.os.Bundle;
35 import android.os.Process;
36 import android.os.UserHandle;
37 import android.support.v7.preference.Preference;
38 import android.support.v7.preference.Preference.OnPreferenceClickListener;
39 import android.support.v7.preference.PreferenceCategory;
40 import android.support.v7.preference.PreferenceScreen;
41 import android.text.TextUtils;
42 import android.util.Log;
43 import android.view.View;
44 import android.widget.Button;
46 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
47 import com.android.internal.os.BatterySipper;
48 import com.android.internal.os.BatterySipper.DrainType;
49 import com.android.internal.os.BatteryStatsHelper;
50 import com.android.internal.util.FastPrintWriter;
51 import com.android.settings.AppHeader;
52 import com.android.settings.DisplaySettings;
53 import com.android.settings.R;
54 import com.android.settings.SettingsActivity;
55 import com.android.settings.Utils;
56 import com.android.settings.WirelessSettings;
57 import com.android.settings.applications.AppHeaderController;
58 import com.android.settings.applications.InstalledAppDetails;
59 import com.android.settings.applications.LayoutPreference;
60 import com.android.settings.bluetooth.BluetoothSettings;
61 import com.android.settings.location.LocationSettings;
62 import com.android.settings.overlay.FeatureFactory;
63 import com.android.settings.wifi.WifiSettings;
65 import java.io.PrintWriter;
66 import java.io.StringWriter;
67 import java.io.Writer;
69 public class PowerUsageDetail extends PowerUsageBase implements Button.OnClickListener {
71 // Note: Must match the sequence of the DrainType
72 private static int[] sDrainTypeDesciptions = new int[] {
73 R.string.battery_desc_standby,
74 R.string.battery_desc_radio,
75 R.string.battery_desc_voice,
76 R.string.battery_desc_wifi,
77 R.string.battery_desc_bluetooth,
78 R.string.battery_desc_flashlight,
79 R.string.battery_desc_display,
80 R.string.battery_desc_apps,
81 R.string.battery_desc_users,
82 R.string.battery_desc_unaccounted,
83 R.string.battery_desc_overcounted,
84 R.string.battery_desc_camera,
87 public static void startBatteryDetailPage(
88 SettingsActivity caller, BatteryStatsHelper helper, int statsType, BatteryEntry entry,
89 boolean showLocationButton, boolean includeAppInfo) {
90 // Initialize mStats if necessary.
93 final int dischargeAmount = helper.getStats().getDischargeAmount(statsType);
94 Bundle args = new Bundle();
95 args.putString(PowerUsageDetail.EXTRA_TITLE, entry.name);
96 args.putInt(PowerUsageDetail.EXTRA_PERCENT, (int)
97 ((entry.sipper.totalPowerMah * dischargeAmount / helper.getTotalPower()) + .5));
98 args.putInt(PowerUsageDetail.EXTRA_GAUGE, (int)
99 Math.ceil(entry.sipper.totalPowerMah * 100 / helper.getMaxPower()));
100 args.putLong(PowerUsageDetail.EXTRA_USAGE_DURATION, helper.getStatsPeriod());
101 args.putString(PowerUsageDetail.EXTRA_ICON_PACKAGE, entry.defaultPackageName);
102 args.putInt(PowerUsageDetail.EXTRA_ICON_ID, entry.iconId);
103 args.putDouble(PowerUsageDetail.EXTRA_NO_COVERAGE, entry.sipper.noCoveragePercent);
104 if (entry.sipper.uidObj != null) {
105 args.putInt(PowerUsageDetail.EXTRA_UID, entry.sipper.uidObj.getUid());
107 args.putSerializable(PowerUsageDetail.EXTRA_DRAIN_TYPE, entry.sipper.drainType);
108 args.putBoolean(PowerUsageDetail.EXTRA_SHOW_LOCATION_BUTTON, showLocationButton);
109 args.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, !includeAppInfo);
111 int userId = UserHandle.myUserId();
114 switch (entry.sipper.drainType) {
118 BatteryStats.Uid uid = entry.sipper.uidObj;
120 R.string.usage_type_cpu,
121 R.string.usage_type_cpu_foreground,
122 R.string.usage_type_wake_lock,
123 R.string.usage_type_gps,
124 R.string.usage_type_wifi_running,
125 R.string.usage_type_data_recv,
126 R.string.usage_type_data_send,
127 R.string.usage_type_radio_active,
128 R.string.usage_type_data_wifi_recv,
129 R.string.usage_type_data_wifi_send,
130 R.string.usage_type_audio,
131 R.string.usage_type_video,
132 R.string.usage_type_camera,
133 R.string.usage_type_flashlight,
134 R.string.usage_type_computed_power,
136 values = new double[] {
137 entry.sipper.cpuTimeMs,
138 entry.sipper.cpuFgTimeMs,
139 entry.sipper.wakeLockTimeMs,
140 entry.sipper.gpsTimeMs,
141 entry.sipper.wifiRunningTimeMs,
142 entry.sipper.mobileRxPackets,
143 entry.sipper.mobileTxPackets,
144 entry.sipper.mobileActive,
145 entry.sipper.wifiRxPackets,
146 entry.sipper.wifiTxPackets,
149 entry.sipper.cameraTimeMs,
150 entry.sipper.flashlightTimeMs,
151 entry.sipper.totalPowerMah,
154 if (entry.sipper.drainType == BatterySipper.DrainType.APP) {
155 Writer result = new StringWriter();
156 PrintWriter printWriter = new FastPrintWriter(result, false, 1024);
157 helper.getStats().dumpLocked(caller, printWriter, "", helper.getStatsType(),
160 args.putString(PowerUsageDetail.EXTRA_REPORT_DETAILS, result.toString());
162 result = new StringWriter();
163 printWriter = new FastPrintWriter(result, false, 1024);
164 helper.getStats().dumpCheckinLocked(caller, printWriter, helper.getStatsType(),
167 args.putString(PowerUsageDetail.EXTRA_REPORT_CHECKIN_DETAILS,
169 if (uid.getUid() != 0) {
170 userId = UserHandle.getUserId(uid.getUid());
178 R.string.usage_type_on_time,
179 R.string.usage_type_no_coverage,
180 R.string.usage_type_radio_active,
181 R.string.usage_type_computed_power,
183 values = new double[] {
184 entry.sipper.usageTimeMs,
185 entry.sipper.noCoveragePercent,
186 entry.sipper.mobileActive,
187 entry.sipper.totalPowerMah,
194 R.string.usage_type_wifi_running,
195 R.string.usage_type_cpu,
196 R.string.usage_type_cpu_foreground,
197 R.string.usage_type_wake_lock,
198 R.string.usage_type_data_recv,
199 R.string.usage_type_data_send,
200 R.string.usage_type_data_wifi_recv,
201 R.string.usage_type_data_wifi_send,
202 R.string.usage_type_computed_power,
204 values = new double[] {
205 entry.sipper.wifiRunningTimeMs,
206 entry.sipper.cpuTimeMs,
207 entry.sipper.cpuFgTimeMs,
208 entry.sipper.wakeLockTimeMs,
209 entry.sipper.mobileRxPackets,
210 entry.sipper.mobileTxPackets,
211 entry.sipper.wifiRxPackets,
212 entry.sipper.wifiTxPackets,
213 entry.sipper.totalPowerMah,
219 R.string.usage_type_on_time,
220 R.string.usage_type_cpu,
221 R.string.usage_type_cpu_foreground,
222 R.string.usage_type_wake_lock,
223 R.string.usage_type_data_recv,
224 R.string.usage_type_data_send,
225 R.string.usage_type_data_wifi_recv,
226 R.string.usage_type_data_wifi_send,
227 R.string.usage_type_computed_power,
229 values = new double[] {
230 entry.sipper.usageTimeMs,
231 entry.sipper.cpuTimeMs,
232 entry.sipper.cpuFgTimeMs,
233 entry.sipper.wakeLockTimeMs,
234 entry.sipper.mobileRxPackets,
235 entry.sipper.mobileTxPackets,
236 entry.sipper.wifiRxPackets,
237 entry.sipper.wifiTxPackets,
238 entry.sipper.totalPowerMah,
244 R.string.usage_type_total_battery_capacity,
245 R.string.usage_type_computed_power,
246 R.string.usage_type_actual_power,
248 values = new double[] {
249 helper.getPowerProfile().getBatteryCapacity(),
250 helper.getComputedPower(),
251 helper.getMinDrainedPower(),
257 R.string.usage_type_total_battery_capacity,
258 R.string.usage_type_computed_power,
259 R.string.usage_type_actual_power,
261 values = new double[] {
262 helper.getPowerProfile().getBatteryCapacity(),
263 helper.getComputedPower(),
264 helper.getMaxDrainedPower(),
270 R.string.usage_type_on_time,
271 R.string.usage_type_computed_power,
273 values = new double[] {
274 entry.sipper.usageTimeMs,
275 entry.sipper.totalPowerMah,
279 args.putIntArray(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
280 args.putDoubleArray(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
282 caller.startPreferencePanelAsUser(PowerUsageDetail.class.getName(), args,
283 R.string.details_title, null, new UserHandle(userId));
286 public static final int ACTION_DISPLAY_SETTINGS = 1;
287 public static final int ACTION_WIFI_SETTINGS = 2;
288 public static final int ACTION_BLUETOOTH_SETTINGS = 3;
289 public static final int ACTION_WIRELESS_SETTINGS = 4;
290 public static final int ACTION_APP_DETAILS = 5;
291 public static final int ACTION_LOCATION_SETTINGS = 6;
292 public static final int ACTION_FORCE_STOP = 7;
293 public static final int ACTION_REPORT = 8;
295 public static final int USAGE_SINCE_UNPLUGGED = 1;
296 public static final int USAGE_SINCE_RESET = 2;
298 public static final String EXTRA_TITLE = "title";
299 public static final String EXTRA_PERCENT = "percent";
300 public static final String EXTRA_GAUGE = "gauge";
301 public static final String EXTRA_UID = "uid";
302 public static final String EXTRA_USAGE_SINCE = "since";
303 public static final String EXTRA_USAGE_DURATION = "duration";
304 public static final String EXTRA_REPORT_DETAILS = "report_details";
305 public static final String EXTRA_REPORT_CHECKIN_DETAILS = "report_checkin_details";
306 public static final String EXTRA_DETAIL_TYPES = "types"; // Array of usage types (cpu, gps, etc)
307 public static final String EXTRA_DETAIL_VALUES = "values"; // Array of doubles
308 public static final String EXTRA_DRAIN_TYPE = "drainType"; // DrainType
309 public static final String EXTRA_ICON_PACKAGE = "iconPackage"; // String
310 public static final String EXTRA_NO_COVERAGE = "noCoverage";
311 public static final String EXTRA_ICON_ID = "iconId"; // Int
312 public static final String EXTRA_SHOW_LOCATION_BUTTON = "showLocationButton"; // Boolean
314 private static final String TAG = "PowerUsageDetail";
316 private static final String KEY_DETAILS_PARENT = "details_parent";
317 private static final String KEY_CONTROLS_PARENT = "controls_parent";
318 private static final String KEY_MESSAGES_PARENT = "messages_parent";
319 private static final String KEY_PACKAGES_PARENT = "packages_parent";
320 private static final String KEY_TWO_BUTTONS = "two_buttons";
321 private static final String KEY_HIGH_POWER = "high_power";
323 private PackageManager mPm;
324 private DevicePolicyManager mDpm;
325 private int mUsageSince;
326 private int[] mTypes;
328 private double[] mValues;
329 private Button mForceStopButton;
330 private Button mReportButton;
331 private long mStartTime;
332 private BatterySipper.DrainType mDrainType;
333 private double mNoCoverage; // Percentage of time that there was no coverage
334 private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
336 private PreferenceCategory mDetailsParent;
337 private PreferenceCategory mControlsParent;
338 private PreferenceCategory mMessagesParent;
339 private PreferenceCategory mPackagesParent;
341 private boolean mUsesGps;
342 private boolean mShowLocationButton;
344 private String[] mPackages;
346 ApplicationInfo mApp;
347 ComponentName mInstaller;
348 private Preference mHighPower;
351 public void onCreate(Bundle icicle) {
352 super.onCreate(icicle);
354 Activity activity = getActivity();
355 mPm = activity.getPackageManager();
356 mDpm = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
358 addPreferencesFromResource(R.xml.power_usage_details);
359 mDetailsParent = (PreferenceCategory) findPreference(KEY_DETAILS_PARENT);
360 mControlsParent = (PreferenceCategory) findPreference(KEY_CONTROLS_PARENT);
361 mMessagesParent = (PreferenceCategory) findPreference(KEY_MESSAGES_PARENT);
362 mPackagesParent = (PreferenceCategory) findPreference(KEY_PACKAGES_PARENT);
364 mPowerUsageFeatureProvider =
365 FeatureFactory.getFactory(activity).getPowerUsageFeatureProvider(activity);
371 public int getMetricsCategory() {
372 return MetricsEvent.FUELGAUGE_POWER_USAGE_DETAIL;
376 public void onResume() {
378 mStartTime = android.os.Process.getElapsedCpuTime();
380 if (mHighPower != null) {
381 mHighPower.setSummary(HighPowerDetail.getSummary(getActivity(), mApp.packageName));
388 public void onActivityResult(int requestCode, int resultCode, Intent data) {
389 super.onActivityResult(requestCode, resultCode, data);
390 if (mHighPower != null) {
391 mHighPower.setSummary(HighPowerDetail.getSummary(getActivity(), mApp.packageName));
395 private void createDetails() {
396 final Bundle args = getArguments();
397 Context context = getActivity();
398 mUsageSince = args.getInt(EXTRA_USAGE_SINCE, USAGE_SINCE_UNPLUGGED);
399 mUid = args.getInt(EXTRA_UID, 0);
400 mPackages = context.getPackageManager().getPackagesForUid(mUid);
401 mDrainType = (BatterySipper.DrainType) args.getSerializable(EXTRA_DRAIN_TYPE);
402 mNoCoverage = args.getDouble(EXTRA_NO_COVERAGE, 0);
403 mShowLocationButton = args.getBoolean(EXTRA_SHOW_LOCATION_BUTTON);
405 mTypes = args.getIntArray(EXTRA_DETAIL_TYPES);
406 mValues = args.getDoubleArray(EXTRA_DETAIL_VALUES);
408 LayoutPreference twoButtons = (LayoutPreference) findPreference(KEY_TWO_BUTTONS);
409 mForceStopButton = (Button) twoButtons.findViewById(R.id.left_button);
410 mReportButton = (Button) twoButtons.findViewById(R.id.right_button);
411 mForceStopButton.setEnabled(false);
413 if (mUid >= Process.FIRST_APPLICATION_UID) {
414 mForceStopButton.setText(R.string.force_stop);
415 mForceStopButton.setTag(ACTION_FORCE_STOP);
416 mForceStopButton.setOnClickListener(this);
417 mReportButton.setText(com.android.internal.R.string.report);
418 mReportButton.setTag(ACTION_REPORT);
419 mReportButton.setOnClickListener(this);
421 if (mPackages != null && mPackages.length > 0) {
423 mApp = context.getPackageManager().getApplicationInfo(
425 } catch (NameNotFoundException e) {
428 Log.d(TAG, "No packages!!");
430 // check if error reporting is enabled in secure settings
431 int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
432 android.provider.Settings.Global.SEND_ACTION_APP_ERROR, 0);
435 mInstaller = ApplicationErrorReport.getErrorReportReceiver(
436 context, mPackages[0], mApp.flags);
438 mReportButton.setEnabled(mInstaller != null);
440 removePreference(KEY_TWO_BUTTONS);
443 && PowerWhitelistBackend.getInstance().isWhitelisted(mApp.packageName)) {
444 mHighPower = findPreference(KEY_HIGH_POWER);
445 mHighPower.setOnPreferenceClickListener(new OnPreferenceClickListener() {
447 public boolean onPreferenceClick(Preference preference) {
448 HighPowerDetail.show(PowerUsageDetail.this, mApp.packageName, 0, false);
453 mControlsParent.removePreference(findPreference(KEY_HIGH_POWER));
456 removePreference(KEY_TWO_BUTTONS);
457 mControlsParent.removePreference(findPreference(KEY_HIGH_POWER));
462 fillDetailsSection();
463 fillPackagesSection(mUid);
464 fillControlsSection(mUid);
465 fillMessagesSection(mUid);
468 private void setupHeader() {
469 final Activity activity = getActivity();
470 final Bundle args = getArguments();
471 final String title = args.getString(EXTRA_TITLE);
472 final int iconId = args.getInt(EXTRA_ICON_ID, 0);
473 String pkg = args.getString(EXTRA_ICON_PACKAGE);
474 Drawable appIcon = null;
476 final PackageManager pm = activity.getPackageManager();
478 if (!TextUtils.isEmpty(pkg)) {
480 ApplicationInfo ai = pm.getPackageInfo(pkg, 0).applicationInfo;
482 appIcon = ai.loadIcon(pm);
485 } catch (NameNotFoundException nnfe) {
488 } else if (iconId != 0) {
489 appIcon = activity.getDrawable(iconId);
491 if (appIcon == null) {
492 appIcon = activity.getPackageManager().getDefaultActivityIcon();
495 if (pkg == null && mPackages != null) {
498 if (!FeatureFactory.getFactory(activity)
499 .getDashboardFeatureProvider(activity).isEnabled()) {
500 AppHeader.createAppHeader(this, appIcon, title, pkg, uid,
501 mDrainType != DrainType.APP ? android.R.color.white : 0);
503 final PreferenceScreen screen = getPreferenceScreen();
504 final Preference appHeaderPref =
505 findPreference(AppHeaderController.PREF_KEY_APP_HEADER);
506 if (appHeaderPref != null) {
509 final Preference pref = FeatureFactory.getFactory(activity)
510 .getApplicationFeatureProvider(activity)
511 .newAppHeaderController(this, null /* appHeader */)
516 .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
517 AppHeaderController.ActionType.ACTION_NONE)
518 .done(getPrefContext());
519 screen.addPreference(pref);
523 public void onClick(View v) {
524 doAction((Integer) v.getTag());
527 // utility method used to start sub activity
528 private void startApplicationDetailsActivity() {
529 // start new fragment to display extended information
530 Bundle args = new Bundle();
531 args.putString(InstalledAppDetails.ARG_PACKAGE_NAME, mPackages[0]);
533 SettingsActivity sa = (SettingsActivity) getActivity();
534 sa.startPreferencePanel(InstalledAppDetails.class.getName(), args,
535 R.string.application_info_label, null, null, 0);
538 private void doAction(int action) {
539 SettingsActivity sa = (SettingsActivity)getActivity();
541 case ACTION_DISPLAY_SETTINGS:
542 sa.startPreferencePanel(DisplaySettings.class.getName(), null,
543 R.string.display_settings_title, null, null, 0);
545 case ACTION_WIFI_SETTINGS:
546 sa.startPreferencePanel(WifiSettings.class.getName(), null,
547 R.string.wifi_settings, null, null, 0);
549 case ACTION_BLUETOOTH_SETTINGS:
550 sa.startPreferencePanel(BluetoothSettings.class.getName(), null,
551 R.string.bluetooth_settings, null, null, 0);
553 case ACTION_WIRELESS_SETTINGS:
554 sa.startPreferencePanel(WirelessSettings.class.getName(), null,
555 R.string.radio_controls_title, null, null, 0);
557 case ACTION_APP_DETAILS:
558 startApplicationDetailsActivity();
560 case ACTION_LOCATION_SETTINGS:
561 sa.startPreferencePanel(LocationSettings.class.getName(), null,
562 R.string.location_settings_title, null, null, 0);
564 case ACTION_FORCE_STOP:
573 private void fillDetailsSection() {
574 if (mTypes != null && mValues != null) {
575 for (int i = 0; i < mTypes.length; i++) {
576 // Only add an item if the time is greater than zero
577 if (mValues[i] <= 0) continue;
578 final String label = getString(mTypes[i]);
581 case R.string.usage_type_data_recv:
582 case R.string.usage_type_data_send:
583 case R.string.usage_type_data_wifi_recv:
584 case R.string.usage_type_data_wifi_send:
585 final long packets = (long) (mValues[i]);
586 value = Long.toString(packets);
588 case R.string.usage_type_no_coverage:
589 final int percentage = (int) Math.floor(mValues[i]);
590 value = Utils.formatPercentage(percentage);
592 case R.string.usage_type_total_battery_capacity:
593 case R.string.usage_type_computed_power:
594 case R.string.usage_type_actual_power:
595 value = getActivity().getString(R.string.mah, (long)(mValues[i]));
597 case R.string.usage_type_gps:
601 value = Utils.formatElapsedTime(getActivity(), mValues[i], true);
603 addHorizontalPreference(mDetailsParent, label, value);
608 private void addHorizontalPreference(PreferenceCategory parent, CharSequence title,
609 CharSequence summary) {
610 Preference pref = new Preference(getPrefContext());
611 pref.setLayoutResource(R.layout.horizontal_preference);
612 pref.setTitle(title);
613 pref.setSummary(summary);
614 pref.setSelectable(false);
615 parent.addPreference(pref);
618 private void fillControlsSection(int uid) {
619 PackageManager pm = getActivity().getPackageManager();
620 String[] packages = pm.getPackagesForUid(uid);
621 PackageInfo pi = null;
623 pi = packages != null ? pm.getPackageInfo(packages[0], 0) : null;
624 } catch (NameNotFoundException nnfe) { /* Nothing */ }
625 ApplicationInfo ai = pi != null? pi.applicationInfo : null;
627 boolean removeHeader = true;
628 switch (mDrainType) {
630 // If it is a Java application and only one package is associated with the Uid
631 if (packages != null && packages.length == 1) {
632 addControl(R.string.battery_action_app_details,
633 R.string.battery_sugg_apps_info, ACTION_APP_DETAILS);
634 removeHeader = false;
635 // If the application has a settings screen, jump to that
639 // If power usage detail page is launched from location page, suppress "Location"
640 // button to prevent circular loops.
641 if (mUsesGps && mShowLocationButton
642 && mPowerUsageFeatureProvider.isLocationSettingEnabled(packages)) {
643 addControl(R.string.location_settings_title,
644 R.string.battery_sugg_apps_gps, ACTION_LOCATION_SETTINGS);
645 removeHeader = false;
649 addControl(R.string.display_settings,
650 R.string.battery_sugg_display,
651 ACTION_DISPLAY_SETTINGS);
652 removeHeader = false;
655 addControl(R.string.wifi_settings,
656 R.string.battery_sugg_wifi,
657 ACTION_WIFI_SETTINGS);
658 removeHeader = false;
661 addControl(R.string.bluetooth_settings,
662 R.string.battery_sugg_bluetooth_basic,
663 ACTION_BLUETOOTH_SETTINGS);
664 removeHeader = false;
667 if (mNoCoverage > 10) {
668 addControl(R.string.radio_controls_title,
669 R.string.battery_sugg_radio,
670 ACTION_WIRELESS_SETTINGS);
671 removeHeader = false;
676 mControlsParent.setTitle(null);
680 private void addControl(int pageSummary, int actionTitle, final int action) {
681 Preference pref = new Preference(getPrefContext());
682 pref.setTitle(actionTitle);
683 pref.setLayoutResource(R.layout.horizontal_preference);
684 pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
686 public boolean onPreferenceClick(Preference preference) {
691 mControlsParent.addPreference(pref);
694 private void fillMessagesSection(int uid) {
695 boolean removeHeader = true;
696 switch (mDrainType) {
698 addMessage(R.string.battery_msg_unaccounted);
699 removeHeader = false;
703 mMessagesParent.setTitle(null);
707 private void addMessage(int message) {
708 addHorizontalPreference(mMessagesParent, getString(message), null);
711 private void removePackagesSection() {
712 getPreferenceScreen().removePreference(mPackagesParent);
715 private void killProcesses() {
716 if (mPackages == null) return;
717 ActivityManager am = (ActivityManager)getActivity().getSystemService(
718 Context.ACTIVITY_SERVICE);
719 final int userId = UserHandle.getUserId(mUid);
720 for (int i = 0; i < mPackages.length; i++) {
721 am.forceStopPackageAsUser(mPackages[i], userId);
726 private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() {
728 public void onReceive(Context context, Intent intent) {
729 mForceStopButton.setEnabled(getResultCode() != Activity.RESULT_CANCELED);
733 private void checkForceStop() {
734 if (mPackages == null || mUid < Process.FIRST_APPLICATION_UID) {
735 mForceStopButton.setEnabled(false);
738 for (int i = 0; i < mPackages.length; i++) {
739 if (mDpm.packageHasActiveAdmins(mPackages[i])) {
740 mForceStopButton.setEnabled(false);
744 for (int i = 0; i < mPackages.length; i++) {
746 ApplicationInfo info = mPm.getApplicationInfo(mPackages[i], 0);
747 if ((info.flags&ApplicationInfo.FLAG_STOPPED) == 0) {
748 mForceStopButton.setEnabled(true);
751 } catch (PackageManager.NameNotFoundException e) {
754 Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
755 Uri.fromParts("package", mPackages[0], null));
756 intent.putExtra(Intent.EXTRA_PACKAGES, mPackages);
757 intent.putExtra(Intent.EXTRA_UID, mUid);
758 intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(mUid));
759 getActivity().sendOrderedBroadcast(intent, null, mCheckKillProcessesReceiver, null,
760 Activity.RESULT_CANCELED, null, null);
763 private void reportBatteryUse() {
764 if (mPackages == null) return;
766 ApplicationErrorReport report = new ApplicationErrorReport();
767 report.type = ApplicationErrorReport.TYPE_BATTERY;
768 report.packageName = mPackages[0];
769 report.installerPackageName = mInstaller.getPackageName();
770 report.processName = mPackages[0];
771 report.time = System.currentTimeMillis();
772 report.systemApp = (mApp.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
774 final Bundle args = getArguments();
775 ApplicationErrorReport.BatteryInfo batteryInfo = new ApplicationErrorReport.BatteryInfo();
776 batteryInfo.usagePercent = args.getInt(EXTRA_PERCENT, 1);
777 batteryInfo.durationMicros = args.getLong(EXTRA_USAGE_DURATION, 0);
778 batteryInfo.usageDetails = args.getString(EXTRA_REPORT_DETAILS);
779 batteryInfo.checkinDetails = args.getString(EXTRA_REPORT_CHECKIN_DETAILS);
780 report.batteryInfo = batteryInfo;
782 Intent result = new Intent(Intent.ACTION_APP_ERROR);
783 result.setComponent(mInstaller);
784 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
785 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
786 startActivity(result);
789 private void fillPackagesSection(int uid) {
791 removePackagesSection();
794 if (mPackages == null || mPackages.length < 2) {
795 removePackagesSection();
799 PackageManager pm = getPackageManager();
800 // Convert package names to user-facing labels where possible
801 for (int i = 0; i < mPackages.length; i++) {
803 ApplicationInfo ai = pm.getApplicationInfo(mPackages[i], 0);
804 CharSequence label = ai.loadLabel(pm);
806 mPackages[i] = label.toString();
808 addHorizontalPreference(mPackagesParent, mPackages[i], null);
809 } catch (NameNotFoundException e) {