PowerUsageDetail.java revision 3c741d2be8277b4ffd7e2d71853f74bba613ff51
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 17package com.android.settings.fuelgauge; 18 19import static com.android.settings.Utils.prepareCustomPreferencesList; 20 21import android.app.Activity; 22import android.app.ActivityManager; 23import android.app.ApplicationErrorReport; 24import android.app.Fragment; 25import android.app.admin.DevicePolicyManager; 26import android.content.BroadcastReceiver; 27import android.content.ComponentName; 28import android.content.Context; 29import android.content.Intent; 30import android.content.pm.ApplicationInfo; 31import android.content.pm.PackageInfo; 32import android.content.pm.PackageManager; 33import android.content.pm.PackageManager.NameNotFoundException; 34import android.content.res.Resources; 35import android.graphics.drawable.Drawable; 36import android.net.Uri; 37import android.os.BatteryStats; 38import android.os.Bundle; 39import android.os.Process; 40import android.os.UserHandle; 41import android.text.TextUtils; 42import android.view.LayoutInflater; 43import android.view.View; 44import android.view.ViewGroup; 45import android.widget.Button; 46import android.widget.ImageView; 47import android.widget.ProgressBar; 48import android.widget.TextView; 49 50import com.android.internal.os.BatterySipper; 51import com.android.internal.os.BatteryStatsHelper; 52import com.android.internal.util.FastPrintWriter; 53import com.android.settings.DisplaySettings; 54import com.android.settings.R; 55import com.android.settings.SettingsActivity; 56import com.android.settings.WirelessSettings; 57import com.android.settings.applications.InstalledAppDetails; 58import com.android.settings.bluetooth.BluetoothSettings; 59import com.android.settings.location.LocationSettings; 60import com.android.settings.wifi.WifiSettings; 61 62import java.io.PrintWriter; 63import java.io.StringWriter; 64import java.io.Writer; 65 66public class PowerUsageDetail extends Fragment implements Button.OnClickListener { 67 68 // Note: Must match the sequence of the DrainType 69 private static int[] sDrainTypeDesciptions = new int[] { 70 R.string.battery_desc_standby, 71 R.string.battery_desc_radio, 72 R.string.battery_desc_voice, 73 R.string.battery_desc_wifi, 74 R.string.battery_desc_bluetooth, 75 R.string.battery_desc_display, 76 R.string.battery_desc_apps, 77 R.string.battery_desc_users, 78 R.string.battery_desc_unaccounted, 79 R.string.battery_desc_overcounted, 80 }; 81 82 public static void startBatteryDetailPage( 83 SettingsActivity caller, BatteryStatsHelper helper, BatteryEntry entry, 84 boolean showLocationButton) { 85 // Initialize mStats if necessary. 86 helper.getStats(); 87 88 Bundle args = new Bundle(); 89 args.putString(PowerUsageDetail.EXTRA_TITLE, entry.name); 90 args.putInt(PowerUsageDetail.EXTRA_PERCENT, (int) 91 Math.ceil(entry.sipper.value * 100 / helper.getTotalPower())); 92 args.putInt(PowerUsageDetail.EXTRA_GAUGE, (int) 93 Math.ceil(entry.sipper.value * 100 / helper.getMaxPower())); 94 args.putLong(PowerUsageDetail.EXTRA_USAGE_DURATION, helper.getStatsPeriod()); 95 args.putString(PowerUsageDetail.EXTRA_ICON_PACKAGE, entry.defaultPackageName); 96 args.putInt(PowerUsageDetail.EXTRA_ICON_ID, entry.iconId); 97 args.putDouble(PowerUsageDetail.EXTRA_NO_COVERAGE, entry.sipper.noCoveragePercent); 98 if (entry.sipper.uidObj != null) { 99 args.putInt(PowerUsageDetail.EXTRA_UID, entry.sipper.uidObj.getUid()); 100 } 101 args.putSerializable(PowerUsageDetail.EXTRA_DRAIN_TYPE, entry.sipper.drainType); 102 args.putBoolean(PowerUsageDetail.EXTRA_SHOW_LOCATION_BUTTON, showLocationButton); 103 104 int[] types; 105 double[] values; 106 switch (entry.sipper.drainType) { 107 case APP: 108 case USER: 109 { 110 BatteryStats.Uid uid = entry.sipper.uidObj; 111 types = new int[] { 112 R.string.usage_type_cpu, 113 R.string.usage_type_cpu_foreground, 114 R.string.usage_type_wake_lock, 115 R.string.usage_type_gps, 116 R.string.usage_type_wifi_running, 117 R.string.usage_type_data_recv, 118 R.string.usage_type_data_send, 119 R.string.usage_type_radio_active, 120 R.string.usage_type_data_wifi_recv, 121 R.string.usage_type_data_wifi_send, 122 R.string.usage_type_audio, 123 R.string.usage_type_video, 124 }; 125 values = new double[] { 126 entry.sipper.cpuTime, 127 entry.sipper.cpuFgTime, 128 entry.sipper.wakeLockTime, 129 entry.sipper.gpsTime, 130 entry.sipper.wifiRunningTime, 131 entry.sipper.mobileRxPackets, 132 entry.sipper.mobileTxPackets, 133 entry.sipper.mobileActive, 134 entry.sipper.wifiRxPackets, 135 entry.sipper.wifiTxPackets, 136 0, 137 0 138 }; 139 140 if (entry.sipper.drainType == BatterySipper.DrainType.APP) { 141 Writer result = new StringWriter(); 142 PrintWriter printWriter = new FastPrintWriter(result, false, 1024); 143 helper.getStats().dumpLocked(caller, printWriter, "", helper.getStatsType(), 144 uid.getUid()); 145 printWriter.flush(); 146 args.putString(PowerUsageDetail.EXTRA_REPORT_DETAILS, result.toString()); 147 148 result = new StringWriter(); 149 printWriter = new FastPrintWriter(result, false, 1024); 150 helper.getStats().dumpCheckinLocked(caller, printWriter, helper.getStatsType(), 151 uid.getUid()); 152 printWriter.flush(); 153 args.putString(PowerUsageDetail.EXTRA_REPORT_CHECKIN_DETAILS, 154 result.toString()); 155 } 156 } 157 break; 158 case CELL: 159 { 160 types = new int[] { 161 R.string.usage_type_on_time, 162 R.string.usage_type_no_coverage, 163 R.string.usage_type_radio_active, 164 }; 165 values = new double[] { 166 entry.sipper.usageTime, 167 entry.sipper.noCoveragePercent, 168 entry.sipper.mobileActive 169 }; 170 } 171 break; 172 case WIFI: 173 { 174 types = new int[] { 175 R.string.usage_type_wifi_running, 176 R.string.usage_type_cpu, 177 R.string.usage_type_cpu_foreground, 178 R.string.usage_type_wake_lock, 179 R.string.usage_type_data_recv, 180 R.string.usage_type_data_send, 181 R.string.usage_type_data_wifi_recv, 182 R.string.usage_type_data_wifi_send, 183 }; 184 values = new double[] { 185 entry.sipper.usageTime, 186 entry.sipper.cpuTime, 187 entry.sipper.cpuFgTime, 188 entry.sipper.wakeLockTime, 189 entry.sipper.mobileRxPackets, 190 entry.sipper.mobileTxPackets, 191 entry.sipper.wifiRxPackets, 192 entry.sipper.wifiTxPackets, 193 }; 194 } break; 195 case BLUETOOTH: 196 { 197 types = new int[] { 198 R.string.usage_type_on_time, 199 R.string.usage_type_cpu, 200 R.string.usage_type_cpu_foreground, 201 R.string.usage_type_wake_lock, 202 R.string.usage_type_data_recv, 203 R.string.usage_type_data_send, 204 R.string.usage_type_data_wifi_recv, 205 R.string.usage_type_data_wifi_send, 206 }; 207 values = new double[] { 208 entry.sipper.usageTime, 209 entry.sipper.cpuTime, 210 entry.sipper.cpuFgTime, 211 entry.sipper.wakeLockTime, 212 entry.sipper.mobileRxPackets, 213 entry.sipper.mobileTxPackets, 214 entry.sipper.wifiRxPackets, 215 entry.sipper.wifiTxPackets, 216 }; 217 } break; 218 case UNACCOUNTED: 219 case OVERCOUNTED: 220 { 221 types = new int[] { 222 R.string.usage_type_total_battery_capacity, 223 R.string.usage_type_computed_power, 224 R.string.usage_type_min_actual_power, 225 R.string.usage_type_max_actual_power, 226 }; 227 values = new double[] { 228 helper.getPowerProfile().getBatteryCapacity(), 229 helper.getComputedPower(), 230 helper.getMinDrainedPower(), 231 helper.getMaxDrainedPower(), 232 }; 233 } break; 234 default: 235 { 236 types = new int[] { 237 R.string.usage_type_on_time 238 }; 239 values = new double[] { 240 entry.sipper.usageTime 241 }; 242 } 243 } 244 args.putIntArray(PowerUsageDetail.EXTRA_DETAIL_TYPES, types); 245 args.putDoubleArray(PowerUsageDetail.EXTRA_DETAIL_VALUES, values); 246 caller.startPreferencePanel(PowerUsageDetail.class.getName(), args, 247 R.string.details_title, null, null, 0); 248 } 249 250 public static final int ACTION_DISPLAY_SETTINGS = 1; 251 public static final int ACTION_WIFI_SETTINGS = 2; 252 public static final int ACTION_BLUETOOTH_SETTINGS = 3; 253 public static final int ACTION_WIRELESS_SETTINGS = 4; 254 public static final int ACTION_APP_DETAILS = 5; 255 public static final int ACTION_LOCATION_SETTINGS = 6; 256 public static final int ACTION_FORCE_STOP = 7; 257 public static final int ACTION_REPORT = 8; 258 259 public static final int USAGE_SINCE_UNPLUGGED = 1; 260 public static final int USAGE_SINCE_RESET = 2; 261 262 public static final String EXTRA_TITLE = "title"; 263 public static final String EXTRA_PERCENT = "percent"; 264 public static final String EXTRA_GAUGE = "gauge"; 265 public static final String EXTRA_UID = "uid"; 266 public static final String EXTRA_USAGE_SINCE = "since"; 267 public static final String EXTRA_USAGE_DURATION = "duration"; 268 public static final String EXTRA_REPORT_DETAILS = "report_details"; 269 public static final String EXTRA_REPORT_CHECKIN_DETAILS = "report_checkin_details"; 270 public static final String EXTRA_DETAIL_TYPES = "types"; // Array of usage types (cpu, gps, etc) 271 public static final String EXTRA_DETAIL_VALUES = "values"; // Array of doubles 272 public static final String EXTRA_DRAIN_TYPE = "drainType"; // DrainType 273 public static final String EXTRA_ICON_PACKAGE = "iconPackage"; // String 274 public static final String EXTRA_NO_COVERAGE = "noCoverage"; 275 public static final String EXTRA_ICON_ID = "iconId"; // Int 276 public static final String EXTRA_SHOW_LOCATION_BUTTON = "showLocationButton"; // Boolean 277 278 private PackageManager mPm; 279 private DevicePolicyManager mDpm; 280 private String mTitle; 281 private int mUsageSince; 282 private int[] mTypes; 283 private int mUid; 284 private double[] mValues; 285 private View mRootView; 286 private TextView mTitleView; 287 private ViewGroup mTwoButtonsPanel; 288 private Button mForceStopButton; 289 private Button mReportButton; 290 private ViewGroup mDetailsParent; 291 private ViewGroup mControlsParent; 292 private long mStartTime; 293 private BatterySipper.DrainType mDrainType; 294 private Drawable mAppIcon; 295 private double mNoCoverage; // Percentage of time that there was no coverage 296 297 private boolean mUsesGps; 298 private boolean mShowLocationButton; 299 300 private static final String TAG = "PowerUsageDetail"; 301 private String[] mPackages; 302 303 ApplicationInfo mApp; 304 ComponentName mInstaller; 305 306 @Override 307 public void onCreate(Bundle icicle) { 308 super.onCreate(icicle); 309 mPm = getActivity().getPackageManager(); 310 mDpm = (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE); 311 } 312 313 @Override 314 public View onCreateView( 315 LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 316 final View view = inflater.inflate(R.layout.power_usage_details, container, false); 317 prepareCustomPreferencesList(container, view, view, false); 318 319 mRootView = view; 320 createDetails(); 321 return view; 322 } 323 324 @Override 325 public void onResume() { 326 super.onResume(); 327 mStartTime = android.os.Process.getElapsedCpuTime(); 328 checkForceStop(); 329 } 330 331 @Override 332 public void onPause() { 333 super.onPause(); 334 } 335 336 private void createDetails() { 337 final Bundle args = getArguments(); 338 mTitle = args.getString(EXTRA_TITLE); 339 final int percentage = args.getInt(EXTRA_PERCENT, 1); 340 final int gaugeValue = args.getInt(EXTRA_GAUGE, 1); 341 mUsageSince = args.getInt(EXTRA_USAGE_SINCE, USAGE_SINCE_UNPLUGGED); 342 mUid = args.getInt(EXTRA_UID, 0); 343 mDrainType = (BatterySipper.DrainType) args.getSerializable(EXTRA_DRAIN_TYPE); 344 mNoCoverage = args.getDouble(EXTRA_NO_COVERAGE, 0); 345 String iconPackage = args.getString(EXTRA_ICON_PACKAGE); 346 int iconId = args.getInt(EXTRA_ICON_ID, 0); 347 mShowLocationButton = args.getBoolean(EXTRA_SHOW_LOCATION_BUTTON); 348 if (!TextUtils.isEmpty(iconPackage)) { 349 try { 350 final PackageManager pm = getActivity().getPackageManager(); 351 ApplicationInfo ai = pm.getPackageInfo(iconPackage, 0).applicationInfo; 352 if (ai != null) { 353 mAppIcon = ai.loadIcon(pm); 354 } 355 } catch (NameNotFoundException nnfe) { 356 // Use default icon 357 } 358 } else if (iconId != 0) { 359 mAppIcon = getActivity().getResources().getDrawable(iconId); 360 } 361 if (mAppIcon == null) { 362 mAppIcon = getActivity().getPackageManager().getDefaultActivityIcon(); 363 } 364 365 // Set the description 366 final TextView summary = (TextView) mRootView.findViewById(android.R.id.summary); 367 summary.setText(getDescriptionForDrainType()); 368 summary.setVisibility(View.VISIBLE); 369 370 mTypes = args.getIntArray(EXTRA_DETAIL_TYPES); 371 mValues = args.getDoubleArray(EXTRA_DETAIL_VALUES); 372 373 mTitleView = (TextView) mRootView.findViewById(android.R.id.title); 374 mTitleView.setText(mTitle); 375 376 final TextView text1 = (TextView)mRootView.findViewById(android.R.id.text1); 377 text1.setText(getString(R.string.percentage, percentage)); 378 379 mTwoButtonsPanel = (ViewGroup)mRootView.findViewById(R.id.two_buttons_panel); 380 mForceStopButton = (Button)mRootView.findViewById(R.id.left_button); 381 mReportButton = (Button)mRootView.findViewById(R.id.right_button); 382 mForceStopButton.setEnabled(false); 383 384 final ProgressBar progress = (ProgressBar) mRootView.findViewById(android.R.id.progress); 385 progress.setProgress(gaugeValue); 386 387 final ImageView icon = (ImageView) mRootView.findViewById(android.R.id.icon); 388 icon.setImageDrawable(mAppIcon); 389 390 mDetailsParent = (ViewGroup)mRootView.findViewById(R.id.details); 391 mControlsParent = (ViewGroup)mRootView.findViewById(R.id.controls); 392 393 fillDetailsSection(); 394 fillPackagesSection(mUid); 395 fillControlsSection(mUid); 396 397 if (mUid >= Process.FIRST_APPLICATION_UID) { 398 mForceStopButton.setText(R.string.force_stop); 399 mForceStopButton.setTag(ACTION_FORCE_STOP); 400 mForceStopButton.setOnClickListener(this); 401 mReportButton.setText(com.android.internal.R.string.report); 402 mReportButton.setTag(ACTION_REPORT); 403 mReportButton.setOnClickListener(this); 404 405 // check if error reporting is enabled in secure settings 406 int enabled = android.provider.Settings.Global.getInt(getActivity().getContentResolver(), 407 android.provider.Settings.Global.SEND_ACTION_APP_ERROR, 0); 408 if (enabled != 0) { 409 if (mPackages != null && mPackages.length > 0) { 410 try { 411 mApp = getActivity().getPackageManager().getApplicationInfo( 412 mPackages[0], 0); 413 mInstaller = ApplicationErrorReport.getErrorReportReceiver( 414 getActivity(), mPackages[0], mApp.flags); 415 } catch (NameNotFoundException e) { 416 } 417 } 418 mReportButton.setEnabled(mInstaller != null); 419 } else { 420 mTwoButtonsPanel.setVisibility(View.GONE); 421 } 422 } else { 423 mTwoButtonsPanel.setVisibility(View.GONE); 424 } 425 } 426 427 public void onClick(View v) { 428 doAction((Integer) v.getTag()); 429 } 430 431 // utility method used to start sub activity 432 private void startApplicationDetailsActivity() { 433 // start new fragment to display extended information 434 Bundle args = new Bundle(); 435 args.putString(InstalledAppDetails.ARG_PACKAGE_NAME, mPackages[0]); 436 437 SettingsActivity sa = (SettingsActivity) getActivity(); 438 sa.startPreferencePanel(InstalledAppDetails.class.getName(), args, 439 R.string.application_info_label, null, null, 0); 440 } 441 442 private void doAction(int action) { 443 SettingsActivity sa = (SettingsActivity)getActivity(); 444 switch (action) { 445 case ACTION_DISPLAY_SETTINGS: 446 sa.startPreferencePanel(DisplaySettings.class.getName(), null, 447 R.string.display_settings_title, null, null, 0); 448 break; 449 case ACTION_WIFI_SETTINGS: 450 sa.startPreferencePanel(WifiSettings.class.getName(), null, 451 R.string.wifi_settings, null, null, 0); 452 break; 453 case ACTION_BLUETOOTH_SETTINGS: 454 sa.startPreferencePanel(BluetoothSettings.class.getName(), null, 455 R.string.bluetooth_settings, null, null, 0); 456 break; 457 case ACTION_WIRELESS_SETTINGS: 458 sa.startPreferencePanel(WirelessSettings.class.getName(), null, 459 R.string.radio_controls_title, null, null, 0); 460 break; 461 case ACTION_APP_DETAILS: 462 startApplicationDetailsActivity(); 463 break; 464 case ACTION_LOCATION_SETTINGS: 465 sa.startPreferencePanel(LocationSettings.class.getName(), null, 466 R.string.location_settings_title, null, null, 0); 467 break; 468 case ACTION_FORCE_STOP: 469 killProcesses(); 470 break; 471 case ACTION_REPORT: 472 reportBatteryUse(); 473 break; 474 } 475 } 476 477 private void fillDetailsSection() { 478 LayoutInflater inflater = getActivity().getLayoutInflater(); 479 if (mTypes != null && mValues != null) { 480 for (int i = 0; i < mTypes.length; i++) { 481 // Only add an item if the time is greater than zero 482 if (mValues[i] <= 0) continue; 483 final String label = getString(mTypes[i]); 484 String value = null; 485 switch (mTypes[i]) { 486 case R.string.usage_type_data_recv: 487 case R.string.usage_type_data_send: 488 case R.string.usage_type_data_wifi_recv: 489 case R.string.usage_type_data_wifi_send: 490 final long packets = (long) (mValues[i]); 491 value = Long.toString(packets); 492 break; 493 case R.string.usage_type_no_coverage: 494 final int percentage = (int) Math.floor(mValues[i]); 495 value = getActivity().getString(R.string.percentage, percentage); 496 break; 497 case R.string.usage_type_total_battery_capacity: 498 case R.string.usage_type_computed_power: 499 case R.string.usage_type_min_actual_power: 500 case R.string.usage_type_max_actual_power: 501 value = getActivity().getString(R.string.mah, (long)(mValues[i])); 502 break; 503 case R.string.usage_type_gps: 504 mUsesGps = true; 505 // Fall through 506 default: 507 value = Utils.formatElapsedTime(getActivity(), mValues[i], true); 508 } 509 ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_detail_item_text, 510 null); 511 mDetailsParent.addView(item); 512 TextView labelView = (TextView) item.findViewById(R.id.label); 513 TextView valueView = (TextView) item.findViewById(R.id.value); 514 labelView.setText(label); 515 valueView.setText(value); 516 } 517 } 518 } 519 520 private void fillControlsSection(int uid) { 521 PackageManager pm = getActivity().getPackageManager(); 522 String[] packages = pm.getPackagesForUid(uid); 523 PackageInfo pi = null; 524 try { 525 pi = packages != null ? pm.getPackageInfo(packages[0], 0) : null; 526 } catch (NameNotFoundException nnfe) { /* Nothing */ } 527 ApplicationInfo ai = pi != null? pi.applicationInfo : null; 528 529 boolean removeHeader = true; 530 switch (mDrainType) { 531 case APP: 532 // If it is a Java application and only one package is associated with the Uid 533 if (packages != null && packages.length == 1) { 534 addControl(R.string.battery_action_app_details, 535 R.string.battery_sugg_apps_info, ACTION_APP_DETAILS); 536 removeHeader = false; 537 // If the application has a settings screen, jump to that 538 // TODO: 539 } 540 // If power usage detail page is launched from location page, suppress "Location" 541 // button to prevent circular loops. 542 if (mUsesGps && mShowLocationButton) { 543 addControl(R.string.location_settings_title, 544 R.string.battery_sugg_apps_gps, ACTION_LOCATION_SETTINGS); 545 removeHeader = false; 546 } 547 break; 548 case SCREEN: 549 addControl(R.string.display_settings, 550 R.string.battery_sugg_display, 551 ACTION_DISPLAY_SETTINGS); 552 removeHeader = false; 553 break; 554 case WIFI: 555 addControl(R.string.wifi_settings, 556 R.string.battery_sugg_wifi, 557 ACTION_WIFI_SETTINGS); 558 removeHeader = false; 559 break; 560 case BLUETOOTH: 561 addControl(R.string.bluetooth_settings, 562 R.string.battery_sugg_bluetooth_basic, 563 ACTION_BLUETOOTH_SETTINGS); 564 removeHeader = false; 565 break; 566 case CELL: 567 if (mNoCoverage > 10) { 568 addControl(R.string.radio_controls_title, 569 R.string.battery_sugg_radio, 570 ACTION_WIRELESS_SETTINGS); 571 removeHeader = false; 572 } 573 break; 574 } 575 if (removeHeader) { 576 mControlsParent.setVisibility(View.GONE); 577 } 578 } 579 580 private void addControl(int title, int summary, int action) { 581 final Resources res = getResources(); 582 LayoutInflater inflater = getActivity().getLayoutInflater(); 583 ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_action_item,null); 584 mControlsParent.addView(item); 585 Button actionButton = (Button) item.findViewById(R.id.action_button); 586 TextView summaryView = (TextView) item.findViewById(R.id.summary); 587 actionButton.setText(res.getString(title)); 588 summaryView.setText(res.getString(summary)); 589 actionButton.setOnClickListener(this); 590 actionButton.setTag(new Integer(action)); 591 } 592 593 private void removePackagesSection() { 594 View view; 595 if ((view = mRootView.findViewById(R.id.packages_section_title)) != null) { 596 view.setVisibility(View.GONE); 597 } 598 if ((view = mRootView.findViewById(R.id.packages_section)) != null) { 599 view.setVisibility(View.GONE); 600 } 601 } 602 603 private void killProcesses() { 604 if (mPackages == null) return; 605 ActivityManager am = (ActivityManager)getActivity().getSystemService( 606 Context.ACTIVITY_SERVICE); 607 for (int i = 0; i < mPackages.length; i++) { 608 am.forceStopPackage(mPackages[i]); 609 } 610 checkForceStop(); 611 } 612 613 private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() { 614 @Override 615 public void onReceive(Context context, Intent intent) { 616 mForceStopButton.setEnabled(getResultCode() != Activity.RESULT_CANCELED); 617 } 618 }; 619 620 private void checkForceStop() { 621 if (mPackages == null || mUid < Process.FIRST_APPLICATION_UID) { 622 mForceStopButton.setEnabled(false); 623 return; 624 } 625 for (int i = 0; i < mPackages.length; i++) { 626 if (mDpm.packageHasActiveAdmins(mPackages[i])) { 627 mForceStopButton.setEnabled(false); 628 return; 629 } 630 } 631 for (int i = 0; i < mPackages.length; i++) { 632 try { 633 ApplicationInfo info = mPm.getApplicationInfo(mPackages[i], 0); 634 if ((info.flags&ApplicationInfo.FLAG_STOPPED) == 0) { 635 mForceStopButton.setEnabled(true); 636 break; 637 } 638 } catch (PackageManager.NameNotFoundException e) { 639 } 640 } 641 Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART, 642 Uri.fromParts("package", mPackages[0], null)); 643 intent.putExtra(Intent.EXTRA_PACKAGES, mPackages); 644 intent.putExtra(Intent.EXTRA_UID, mUid); 645 intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(mUid)); 646 getActivity().sendOrderedBroadcast(intent, null, mCheckKillProcessesReceiver, null, 647 Activity.RESULT_CANCELED, null, null); 648 } 649 650 private void reportBatteryUse() { 651 if (mPackages == null) return; 652 653 ApplicationErrorReport report = new ApplicationErrorReport(); 654 report.type = ApplicationErrorReport.TYPE_BATTERY; 655 report.packageName = mPackages[0]; 656 report.installerPackageName = mInstaller.getPackageName(); 657 report.processName = mPackages[0]; 658 report.time = System.currentTimeMillis(); 659 report.systemApp = (mApp.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 660 661 final Bundle args = getArguments(); 662 ApplicationErrorReport.BatteryInfo batteryInfo = new ApplicationErrorReport.BatteryInfo(); 663 batteryInfo.usagePercent = args.getInt(EXTRA_PERCENT, 1); 664 batteryInfo.durationMicros = args.getLong(EXTRA_USAGE_DURATION, 0); 665 batteryInfo.usageDetails = args.getString(EXTRA_REPORT_DETAILS); 666 batteryInfo.checkinDetails = args.getString(EXTRA_REPORT_CHECKIN_DETAILS); 667 report.batteryInfo = batteryInfo; 668 669 Intent result = new Intent(Intent.ACTION_APP_ERROR); 670 result.setComponent(mInstaller); 671 result.putExtra(Intent.EXTRA_BUG_REPORT, report); 672 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 673 startActivity(result); 674 } 675 676 private void fillPackagesSection(int uid) { 677 if (uid < 1) { 678 removePackagesSection(); 679 return; 680 } 681 ViewGroup packagesParent = (ViewGroup)mRootView.findViewById(R.id.packages_section); 682 if (packagesParent == null) return; 683 LayoutInflater inflater = getActivity().getLayoutInflater(); 684 685 PackageManager pm = getActivity().getPackageManager(); 686 //final Drawable defaultActivityIcon = pm.getDefaultActivityIcon(); 687 mPackages = pm.getPackagesForUid(uid); 688 if (mPackages == null || mPackages.length < 2) { 689 removePackagesSection(); 690 return; 691 } 692 693 // Convert package names to user-facing labels where possible 694 for (int i = 0; i < mPackages.length; i++) { 695 try { 696 ApplicationInfo ai = pm.getApplicationInfo(mPackages[i], 0); 697 CharSequence label = ai.loadLabel(pm); 698 //Drawable icon = defaultActivityIcon; 699 if (label != null) { 700 mPackages[i] = label.toString(); 701 } 702 //if (ai.icon != 0) { 703 // icon = ai.loadIcon(pm); 704 //} 705 ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_package_item, 706 null); 707 packagesParent.addView(item); 708 TextView labelView = (TextView) item.findViewById(R.id.label); 709 labelView.setText(mPackages[i]); 710 } catch (NameNotFoundException e) { 711 } 712 } 713 } 714 715 private String getDescriptionForDrainType() { 716 return getResources().getString(sDrainTypeDesciptions[mDrainType.ordinal()]); 717 } 718} 719