OSDN Git Service

Import translations. DO NOT MERGE am: a6d9842695 -s ours am: c027907edc -s ours...
[android-x86/packages-apps-Settings.git] / src / com / android / settings / fuelgauge / PowerUsageDetail.java
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package com.android.settings.fuelgauge;
18
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;
45
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;
64
65 import java.io.PrintWriter;
66 import java.io.StringWriter;
67 import java.io.Writer;
68
69 public class PowerUsageDetail extends PowerUsageBase implements Button.OnClickListener {
70
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,
85     };
86
87     public static void startBatteryDetailPage(
88             SettingsActivity caller, BatteryStatsHelper helper, int statsType, BatteryEntry entry,
89             boolean showLocationButton, boolean includeAppInfo) {
90         // Initialize mStats if necessary.
91         helper.getStats();
92
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());
106         }
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);
110
111         int userId = UserHandle.myUserId();
112         int[] types;
113         double[] values;
114         switch (entry.sipper.drainType) {
115             case APP:
116             case USER:
117             {
118                 BatteryStats.Uid uid = entry.sipper.uidObj;
119                 types = new int[] {
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,
135                 };
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,
147                     0,
148                     0,
149                     entry.sipper.cameraTimeMs,
150                     entry.sipper.flashlightTimeMs,
151                     entry.sipper.totalPowerMah,
152                 };
153
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(),
158                             uid.getUid());
159                     printWriter.flush();
160                     args.putString(PowerUsageDetail.EXTRA_REPORT_DETAILS, result.toString());
161
162                     result = new StringWriter();
163                     printWriter = new FastPrintWriter(result, false, 1024);
164                     helper.getStats().dumpCheckinLocked(caller, printWriter, helper.getStatsType(),
165                             uid.getUid());
166                     printWriter.flush();
167                     args.putString(PowerUsageDetail.EXTRA_REPORT_CHECKIN_DETAILS,
168                             result.toString());
169                     if (uid.getUid() != 0) {
170                         userId = UserHandle.getUserId(uid.getUid());
171                     }
172                 }
173             }
174             break;
175             case CELL:
176             {
177                 types = new int[] {
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,
182                 };
183                 values = new double[] {
184                     entry.sipper.usageTimeMs,
185                     entry.sipper.noCoveragePercent,
186                     entry.sipper.mobileActive,
187                     entry.sipper.totalPowerMah,
188                 };
189             }
190             break;
191             case WIFI:
192             {
193                 types = new int[] {
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,
203                 };
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,
214                 };
215             } break;
216             case BLUETOOTH:
217             {
218                 types = new int[] {
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,
228                 };
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,
239                 };
240             } break;
241             case UNACCOUNTED:
242             {
243                 types = new int[] {
244                     R.string.usage_type_total_battery_capacity,
245                     R.string.usage_type_computed_power,
246                     R.string.usage_type_actual_power,
247                 };
248                 values = new double[] {
249                     helper.getPowerProfile().getBatteryCapacity(),
250                     helper.getComputedPower(),
251                     helper.getMinDrainedPower(),
252                 };
253             } break;
254             case OVERCOUNTED:
255             {
256                 types = new int[] {
257                     R.string.usage_type_total_battery_capacity,
258                     R.string.usage_type_computed_power,
259                     R.string.usage_type_actual_power,
260                 };
261                 values = new double[] {
262                     helper.getPowerProfile().getBatteryCapacity(),
263                     helper.getComputedPower(),
264                     helper.getMaxDrainedPower(),
265                 };
266             } break;
267             default:
268             {
269                 types = new int[] {
270                     R.string.usage_type_on_time,
271                     R.string.usage_type_computed_power,
272                 };
273                 values = new double[] {
274                     entry.sipper.usageTimeMs,
275                     entry.sipper.totalPowerMah,
276                 };
277             }
278         }
279         args.putIntArray(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
280         args.putDoubleArray(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
281
282         caller.startPreferencePanelAsUser(PowerUsageDetail.class.getName(), args,
283                 R.string.details_title, null, new UserHandle(userId));
284     }
285
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;
294
295     public static final int USAGE_SINCE_UNPLUGGED = 1;
296     public static final int USAGE_SINCE_RESET = 2;
297
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
313
314     private static final String TAG = "PowerUsageDetail";
315
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";
322
323     private PackageManager mPm;
324     private DevicePolicyManager mDpm;
325     private int mUsageSince;
326     private int[] mTypes;
327     private int mUid;
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;
335
336     private PreferenceCategory mDetailsParent;
337     private PreferenceCategory mControlsParent;
338     private PreferenceCategory mMessagesParent;
339     private PreferenceCategory mPackagesParent;
340
341     private boolean mUsesGps;
342     private boolean mShowLocationButton;
343
344     private String[] mPackages;
345
346     ApplicationInfo mApp;
347     ComponentName mInstaller;
348     private Preference mHighPower;
349
350     @Override
351     public void onCreate(Bundle icicle) {
352         super.onCreate(icicle);
353         mPm = getActivity().getPackageManager();
354         mDpm = (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
355
356         addPreferencesFromResource(R.xml.power_usage_details);
357         mDetailsParent = (PreferenceCategory) findPreference(KEY_DETAILS_PARENT);
358         mControlsParent = (PreferenceCategory) findPreference(KEY_CONTROLS_PARENT);
359         mMessagesParent = (PreferenceCategory) findPreference(KEY_MESSAGES_PARENT);
360         mPackagesParent = (PreferenceCategory) findPreference(KEY_PACKAGES_PARENT);
361
362         mPowerUsageFeatureProvider =
363                 FeatureFactory.getFactory(getActivity()).getPowerUsageFeatureProvider();
364
365         createDetails();
366     }
367
368     @Override
369     public int getMetricsCategory() {
370         return MetricsEvent.FUELGAUGE_POWER_USAGE_DETAIL;
371     }
372
373     @Override
374     public void onResume() {
375         super.onResume();
376         mStartTime = android.os.Process.getElapsedCpuTime();
377         checkForceStop();
378         if (mHighPower != null) {
379             mHighPower.setSummary(HighPowerDetail.getSummary(getActivity(), mApp.packageName));
380         }
381
382         setupHeader();
383     }
384
385     @Override
386     public void onActivityResult(int requestCode, int resultCode, Intent data) {
387         super.onActivityResult(requestCode, resultCode, data);
388         if (mHighPower != null) {
389             mHighPower.setSummary(HighPowerDetail.getSummary(getActivity(), mApp.packageName));
390         }
391     }
392
393     private void createDetails() {
394         final Bundle args = getArguments();
395         Context context = getActivity();
396         mUsageSince = args.getInt(EXTRA_USAGE_SINCE, USAGE_SINCE_UNPLUGGED);
397         mUid = args.getInt(EXTRA_UID, 0);
398         mPackages = context.getPackageManager().getPackagesForUid(mUid);
399         mDrainType = (BatterySipper.DrainType) args.getSerializable(EXTRA_DRAIN_TYPE);
400         mNoCoverage = args.getDouble(EXTRA_NO_COVERAGE, 0);
401         mShowLocationButton = args.getBoolean(EXTRA_SHOW_LOCATION_BUTTON);
402
403         mTypes = args.getIntArray(EXTRA_DETAIL_TYPES);
404         mValues = args.getDoubleArray(EXTRA_DETAIL_VALUES);
405
406         LayoutPreference twoButtons = (LayoutPreference) findPreference(KEY_TWO_BUTTONS);
407         mForceStopButton = (Button) twoButtons.findViewById(R.id.left_button);
408         mReportButton = (Button) twoButtons.findViewById(R.id.right_button);
409         mForceStopButton.setEnabled(false);
410
411         if (mUid >= Process.FIRST_APPLICATION_UID) {
412             mForceStopButton.setText(R.string.force_stop);
413             mForceStopButton.setTag(ACTION_FORCE_STOP);
414             mForceStopButton.setOnClickListener(this);
415             mReportButton.setText(com.android.internal.R.string.report);
416             mReportButton.setTag(ACTION_REPORT);
417             mReportButton.setOnClickListener(this);
418
419             if (mPackages != null && mPackages.length > 0) {
420                 try {
421                     mApp = context.getPackageManager().getApplicationInfo(
422                             mPackages[0], 0);
423                 } catch (NameNotFoundException e) {
424                 }
425             } else {
426                 Log.d(TAG, "No packages!!");
427             }
428             // check if error reporting is enabled in secure settings
429             int enabled = android.provider.Settings.Global.getInt(context.getContentResolver(),
430                     android.provider.Settings.Global.SEND_ACTION_APP_ERROR, 0);
431             if (enabled != 0) {
432                 if (mApp != null) {
433                     mInstaller = ApplicationErrorReport.getErrorReportReceiver(
434                             context, mPackages[0], mApp.flags);
435                 }
436                 mReportButton.setEnabled(mInstaller != null);
437             } else {
438                 removePreference(KEY_TWO_BUTTONS);
439             }
440             if (mApp != null
441                     && PowerWhitelistBackend.getInstance().isWhitelisted(mApp.packageName)) {
442                 mHighPower = findPreference(KEY_HIGH_POWER);
443                 mHighPower.setOnPreferenceClickListener(new OnPreferenceClickListener() {
444                     @Override
445                     public boolean onPreferenceClick(Preference preference) {
446                         HighPowerDetail.show(PowerUsageDetail.this, mApp.packageName, 0, false);
447                         return true;
448                     }
449                 });
450             } else {
451                 mControlsParent.removePreference(findPreference(KEY_HIGH_POWER));
452             }
453         } else {
454             removePreference(KEY_TWO_BUTTONS);
455             mControlsParent.removePreference(findPreference(KEY_HIGH_POWER));
456         }
457
458         refreshStats();
459
460         fillDetailsSection();
461         fillPackagesSection(mUid);
462         fillControlsSection(mUid);
463         fillMessagesSection(mUid);
464     }
465
466     private void setupHeader() {
467         final Activity activity = getActivity();
468         final Bundle args = getArguments();
469         final String title = args.getString(EXTRA_TITLE);
470         final int iconId = args.getInt(EXTRA_ICON_ID, 0);
471         String pkg = args.getString(EXTRA_ICON_PACKAGE);
472         Drawable appIcon = null;
473         int uid = -1;
474         final PackageManager pm = activity.getPackageManager();
475
476         if (!TextUtils.isEmpty(pkg)) {
477             try {
478                 ApplicationInfo ai = pm.getPackageInfo(pkg, 0).applicationInfo;
479                 if (ai != null) {
480                     appIcon = ai.loadIcon(pm);
481                     uid = ai.uid;
482                 }
483             } catch (NameNotFoundException nnfe) {
484                 // Use default icon
485             }
486         } else if (iconId != 0) {
487             appIcon = activity.getDrawable(iconId);
488         }
489         if (appIcon == null) {
490             appIcon = activity.getPackageManager().getDefaultActivityIcon();
491         }
492
493         if (pkg == null && mPackages != null) {
494             pkg = mPackages[0];
495         }
496         if (!FeatureFactory.getFactory(activity)
497                 .getDashboardFeatureProvider(activity).isEnabled()) {
498             AppHeader.createAppHeader(this, appIcon, title, pkg, uid,
499                     mDrainType != DrainType.APP ? android.R.color.white : 0);
500         } else {
501             final PreferenceScreen screen = getPreferenceScreen();
502             final Preference appHeaderPref =
503                     findPreference(AppHeaderController.PREF_KEY_APP_HEADER);
504             if (appHeaderPref != null) {
505                 return;
506             }
507             final Preference pref = FeatureFactory.getFactory(activity)
508                     .getApplicationFeatureProvider(activity)
509                     .newAppHeaderController(this, null /* appHeader */)
510                     .setIcon(appIcon)
511                     .setLabel(title)
512                     .setPackageName(pkg)
513                     .setUid(uid)
514                     .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
515                             AppHeaderController.ActionType.ACTION_NONE)
516                     .done(getPrefContext());
517             screen.addPreference(pref);
518         }
519     }
520
521     public void onClick(View v) {
522         doAction((Integer) v.getTag());
523     }
524
525     // utility method used to start sub activity
526     private void startApplicationDetailsActivity() {
527         // start new fragment to display extended information
528         Bundle args = new Bundle();
529         args.putString(InstalledAppDetails.ARG_PACKAGE_NAME, mPackages[0]);
530
531         SettingsActivity sa = (SettingsActivity) getActivity();
532         sa.startPreferencePanel(InstalledAppDetails.class.getName(), args,
533                 R.string.application_info_label, null, null, 0);
534     }
535
536     private void doAction(int action) {
537         SettingsActivity sa = (SettingsActivity)getActivity();
538         switch (action) {
539             case ACTION_DISPLAY_SETTINGS:
540                 sa.startPreferencePanel(DisplaySettings.class.getName(), null,
541                         R.string.display_settings_title, null, null, 0);
542                 break;
543             case ACTION_WIFI_SETTINGS:
544                 sa.startPreferencePanel(WifiSettings.class.getName(), null,
545                         R.string.wifi_settings, null, null, 0);
546                 break;
547             case ACTION_BLUETOOTH_SETTINGS:
548                 sa.startPreferencePanel(BluetoothSettings.class.getName(), null,
549                         R.string.bluetooth_settings, null, null, 0);
550                 break;
551             case ACTION_WIRELESS_SETTINGS:
552                 sa.startPreferencePanel(WirelessSettings.class.getName(), null,
553                         R.string.radio_controls_title, null, null, 0);
554                 break;
555             case ACTION_APP_DETAILS:
556                 startApplicationDetailsActivity();
557                 break;
558             case ACTION_LOCATION_SETTINGS:
559                 sa.startPreferencePanel(LocationSettings.class.getName(), null,
560                         R.string.location_settings_title, null, null, 0);
561                 break;
562             case ACTION_FORCE_STOP:
563                 killProcesses();
564                 break;
565             case ACTION_REPORT:
566                 reportBatteryUse();
567                 break;
568         }
569     }
570
571     private void fillDetailsSection() {
572         if (mTypes != null && mValues != null) {
573             for (int i = 0; i < mTypes.length; i++) {
574                 // Only add an item if the time is greater than zero
575                 if (mValues[i] <= 0) continue;
576                 final String label = getString(mTypes[i]);
577                 String value = null;
578                 switch (mTypes[i]) {
579                     case R.string.usage_type_data_recv:
580                     case R.string.usage_type_data_send:
581                     case R.string.usage_type_data_wifi_recv:
582                     case R.string.usage_type_data_wifi_send:
583                         final long packets = (long) (mValues[i]);
584                         value = Long.toString(packets);
585                         break;
586                     case R.string.usage_type_no_coverage:
587                         final int percentage = (int) Math.floor(mValues[i]);
588                         value = Utils.formatPercentage(percentage);
589                         break;
590                     case R.string.usage_type_total_battery_capacity:
591                     case R.string.usage_type_computed_power:
592                     case R.string.usage_type_actual_power:
593                         value = getActivity().getString(R.string.mah, (long)(mValues[i]));
594                         break;
595                     case R.string.usage_type_gps:
596                         mUsesGps = true;
597                         // Fall through
598                     default:
599                         value = Utils.formatElapsedTime(getActivity(), mValues[i], true);
600                 }
601                 addHorizontalPreference(mDetailsParent, label, value);
602             }
603         }
604     }
605
606     private void addHorizontalPreference(PreferenceCategory parent, CharSequence title,
607             CharSequence summary) {
608         Preference pref = new Preference(getPrefContext());
609         pref.setLayoutResource(R.layout.horizontal_preference);
610         pref.setTitle(title);
611         pref.setSummary(summary);
612         pref.setSelectable(false);
613         parent.addPreference(pref);
614     }
615
616     private void fillControlsSection(int uid) {
617         PackageManager pm = getActivity().getPackageManager();
618         String[] packages = pm.getPackagesForUid(uid);
619         PackageInfo pi = null;
620         try {
621             pi = packages != null ? pm.getPackageInfo(packages[0], 0) : null;
622         } catch (NameNotFoundException nnfe) { /* Nothing */ }
623         ApplicationInfo ai = pi != null? pi.applicationInfo : null;
624
625         boolean removeHeader = true;
626         switch (mDrainType) {
627             case APP:
628                 // If it is a Java application and only one package is associated with the Uid
629                 if (packages != null && packages.length == 1) {
630                     addControl(R.string.battery_action_app_details,
631                             R.string.battery_sugg_apps_info, ACTION_APP_DETAILS);
632                     removeHeader = false;
633                     // If the application has a settings screen, jump to  that
634                     // TODO:
635                 }
636
637                 // If power usage detail page is launched from location page, suppress "Location"
638                 // button to prevent circular loops.
639                 if (mUsesGps && mShowLocationButton
640                         && mPowerUsageFeatureProvider.isLocationSettingEnabled(packages)) {
641                     addControl(R.string.location_settings_title,
642                             R.string.battery_sugg_apps_gps, ACTION_LOCATION_SETTINGS);
643                     removeHeader = false;
644                 }
645                 break;
646             case SCREEN:
647                 addControl(R.string.display_settings,
648                         R.string.battery_sugg_display,
649                         ACTION_DISPLAY_SETTINGS);
650                 removeHeader = false;
651                 break;
652             case WIFI:
653                 addControl(R.string.wifi_settings,
654                         R.string.battery_sugg_wifi,
655                         ACTION_WIFI_SETTINGS);
656                 removeHeader = false;
657                 break;
658             case BLUETOOTH:
659                 addControl(R.string.bluetooth_settings,
660                         R.string.battery_sugg_bluetooth_basic,
661                         ACTION_BLUETOOTH_SETTINGS);
662                 removeHeader = false;
663                 break;
664             case CELL:
665                 if (mNoCoverage > 10) {
666                     addControl(R.string.radio_controls_title,
667                             R.string.battery_sugg_radio,
668                             ACTION_WIRELESS_SETTINGS);
669                     removeHeader = false;
670                 }
671                 break;
672         }
673         if (removeHeader) {
674             mControlsParent.setTitle(null);
675         }
676     }
677
678     private void addControl(int pageSummary, int actionTitle, final int action) {
679         Preference pref = new Preference(getPrefContext());
680         pref.setTitle(actionTitle);
681         pref.setLayoutResource(R.layout.horizontal_preference);
682         pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
683             @Override
684             public boolean onPreferenceClick(Preference preference) {
685                 doAction(action);
686                 return true;
687             }
688         });
689         mControlsParent.addPreference(pref);
690     }
691
692     private void fillMessagesSection(int uid) {
693         boolean removeHeader = true;
694         switch (mDrainType) {
695             case UNACCOUNTED:
696                 addMessage(R.string.battery_msg_unaccounted);
697                 removeHeader = false;
698                 break;
699         }
700         if (removeHeader) {
701             mMessagesParent.setTitle(null);
702         }
703     }
704
705     private void addMessage(int message) {
706         addHorizontalPreference(mMessagesParent, getString(message), null);
707     }
708
709     private void removePackagesSection() {
710         getPreferenceScreen().removePreference(mPackagesParent);
711     }
712
713     private void killProcesses() {
714         if (mPackages == null) return;
715         ActivityManager am = (ActivityManager)getActivity().getSystemService(
716                 Context.ACTIVITY_SERVICE);
717         final int userId = UserHandle.getUserId(mUid);
718         for (int i = 0; i < mPackages.length; i++) {
719             am.forceStopPackageAsUser(mPackages[i], userId);
720         }
721         checkForceStop();
722     }
723
724     private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() {
725         @Override
726         public void onReceive(Context context, Intent intent) {
727             mForceStopButton.setEnabled(getResultCode() != Activity.RESULT_CANCELED);
728         }
729     };
730
731     private void checkForceStop() {
732         if (mPackages == null || mUid < Process.FIRST_APPLICATION_UID) {
733             mForceStopButton.setEnabled(false);
734             return;
735         }
736         for (int i = 0; i < mPackages.length; i++) {
737             if (mDpm.packageHasActiveAdmins(mPackages[i])) {
738                 mForceStopButton.setEnabled(false);
739                 return;
740             }
741         }
742         for (int i = 0; i < mPackages.length; i++) {
743             try {
744                 ApplicationInfo info = mPm.getApplicationInfo(mPackages[i], 0);
745                 if ((info.flags&ApplicationInfo.FLAG_STOPPED) == 0) {
746                     mForceStopButton.setEnabled(true);
747                     break;
748                 }
749             } catch (PackageManager.NameNotFoundException e) {
750             }
751         }
752         Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
753                 Uri.fromParts("package", mPackages[0], null));
754         intent.putExtra(Intent.EXTRA_PACKAGES, mPackages);
755         intent.putExtra(Intent.EXTRA_UID, mUid);
756         intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(mUid));
757         getActivity().sendOrderedBroadcast(intent, null, mCheckKillProcessesReceiver, null,
758                 Activity.RESULT_CANCELED, null, null);
759     }
760
761     private void reportBatteryUse() {
762         if (mPackages == null) return;
763
764         ApplicationErrorReport report = new ApplicationErrorReport();
765         report.type = ApplicationErrorReport.TYPE_BATTERY;
766         report.packageName = mPackages[0];
767         report.installerPackageName = mInstaller.getPackageName();
768         report.processName = mPackages[0];
769         report.time = System.currentTimeMillis();
770         report.systemApp = (mApp.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
771
772         final Bundle args = getArguments();
773         ApplicationErrorReport.BatteryInfo batteryInfo = new ApplicationErrorReport.BatteryInfo();
774         batteryInfo.usagePercent = args.getInt(EXTRA_PERCENT, 1);
775         batteryInfo.durationMicros = args.getLong(EXTRA_USAGE_DURATION, 0);
776         batteryInfo.usageDetails = args.getString(EXTRA_REPORT_DETAILS);
777         batteryInfo.checkinDetails = args.getString(EXTRA_REPORT_CHECKIN_DETAILS);
778         report.batteryInfo = batteryInfo;
779
780         Intent result = new Intent(Intent.ACTION_APP_ERROR);
781         result.setComponent(mInstaller);
782         result.putExtra(Intent.EXTRA_BUG_REPORT, report);
783         result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
784         startActivity(result);
785     }
786
787     private void fillPackagesSection(int uid) {
788         if (uid < 1) {
789             removePackagesSection();
790             return;
791         }
792         if (mPackages == null || mPackages.length < 2) {
793             removePackagesSection();
794             return;
795         }
796
797         PackageManager pm = getPackageManager();
798         // Convert package names to user-facing labels where possible
799         for (int i = 0; i < mPackages.length; i++) {
800             try {
801                 ApplicationInfo ai = pm.getApplicationInfo(mPackages[i], 0);
802                 CharSequence label = ai.loadLabel(pm);
803                 if (label != null) {
804                     mPackages[i] = label.toString();
805                 }
806                 addHorizontalPreference(mPackagesParent, mPackages[i], null);
807             } catch (NameNotFoundException e) {
808             }
809         }
810     }
811 }