1 /* 2 * Copyright (C) 2006-2007 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.server.am; 18 19 import android.bluetooth.BluetoothAdapter; 20 import android.bluetooth.BluetoothHeadset; 21 import android.bluetooth.BluetoothProfile; 22 import android.content.Context; 23 import android.content.pm.ApplicationInfo; 24 import android.content.pm.PackageManager; 25 import android.os.BatteryStats; 26 import android.os.Binder; 27 import android.os.Handler; 28 import android.os.IBinder; 29 import android.os.Parcel; 30 import android.os.ParcelFileDescriptor; 31 import android.os.PowerManagerInternal; 32 import android.os.Process; 33 import android.os.ServiceManager; 34 import android.os.SystemClock; 35 import android.os.UserHandle; 36 import android.os.WorkSource; 37 import android.telephony.SignalStrength; 38 import android.telephony.TelephonyManager; 39 import android.util.Slog; 40 41 import com.android.internal.app.IBatteryStats; 42 import com.android.internal.os.BatteryStatsHelper; 43 import com.android.internal.os.BatteryStatsImpl; 44 import com.android.internal.os.PowerProfile; 45 import com.android.server.LocalServices; 46 47 import java.io.File; 48 import java.io.FileDescriptor; 49 import java.io.FileOutputStream; 50 import java.io.IOException; 51 import java.io.PrintWriter; 52 import java.util.List; 53 54 /** 55 * All information we are collecting about things that can happen that impact 56 * battery life. 57 */ 58 public final class BatteryStatsService extends IBatteryStats.Stub 59 implements PowerManagerInternal.LowPowerModeListener { 60 static final String TAG = "BatteryStatsService"; 61 62 static IBatteryStats sService; 63 64 final BatteryStatsImpl mStats; 65 Context mContext; 66 private boolean mBluetoothPendingStats; 67 private BluetoothHeadset mBluetoothHeadset; 68 PowerManagerInternal mPowerManagerInternal; 69 70 BatteryStatsService(File systemDir, Handler handler) { 71 mStats = new BatteryStatsImpl(systemDir, handler); 72 } 73 74 public void publish(Context context) { 75 mContext = context; 76 ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder()); 77 mStats.setNumSpeedSteps(new PowerProfile(mContext).getNumSpeedSteps()); 78 mStats.setRadioScanningTimeout(mContext.getResources().getInteger( 79 com.android.internal.R.integer.config_radioScanningTimeout) 80 * 1000L); 81 } 82 83 /** 84 * At the time when the constructor runs, the power manager has not yet been 85 * initialized. So we initialize the low power observer later. 86 */ 87 public void initPowerManagement() { 88 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 89 mPowerManagerInternal.registerLowPowerModeObserver(this); 90 mStats.noteLowPowerMode(mPowerManagerInternal.getLowPowerModeEnabled()); 91 (new WakeupReasonThread()).start(); 92 } 93 94 public void shutdown() { 95 Slog.w("BatteryStats", "Writing battery stats before shutdown..."); 96 synchronized (mStats) { 97 mStats.shutdownLocked(); 98 } 99 } 100 101 public static IBatteryStats getService() { 102 if (sService != null) { 103 return sService; 104 } 105 IBinder b = ServiceManager.getService(BatteryStats.SERVICE_NAME); 106 sService = asInterface(b); 107 return sService; 108 } 109 110 @Override 111 public void onLowPowerModeChanged(boolean enabled) { 112 synchronized (mStats) { 113 mStats.noteLowPowerMode(enabled); 114 } 115 } 116 117 /** 118 * @return the current statistics object, which may be modified 119 * to reflect events that affect battery usage. You must lock the 120 * stats object before doing anything with it. 121 */ 122 public BatteryStatsImpl getActiveStatistics() { 123 return mStats; 124 } 125 126 // These are for direct use by the activity manager... 127 128 void addIsolatedUid(int isolatedUid, int appUid) { 129 synchronized (mStats) { 130 mStats.addIsolatedUidLocked(isolatedUid, appUid); 131 } 132 } 133 134 void removeIsolatedUid(int isolatedUid, int appUid) { 135 synchronized (mStats) { 136 mStats.removeIsolatedUidLocked(isolatedUid, appUid); 137 } 138 } 139 140 void noteProcessStart(String name, int uid) { 141 synchronized (mStats) { 142 mStats.noteProcessStartLocked(name, uid); 143 } 144 } 145 146 void noteProcessCrash(String name, int uid) { 147 synchronized (mStats) { 148 mStats.noteProcessCrashLocked(name, uid); 149 } 150 } 151 152 void noteProcessAnr(String name, int uid) { 153 synchronized (mStats) { 154 mStats.noteProcessAnrLocked(name, uid); 155 } 156 } 157 158 void noteProcessState(String name, int uid, int state) { 159 synchronized (mStats) { 160 mStats.noteProcessStateLocked(name, uid, state); 161 } 162 } 163 164 void noteProcessFinish(String name, int uid) { 165 synchronized (mStats) { 166 mStats.noteProcessFinishLocked(name, uid); 167 } 168 } 169 170 // Public interface... 171 172 public byte[] getStatistics() { 173 mContext.enforceCallingPermission( 174 android.Manifest.permission.BATTERY_STATS, null); 175 //Slog.i("foo", "SENDING BATTERY INFO:"); 176 //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); 177 Parcel out = Parcel.obtain(); 178 mStats.writeToParcel(out, 0); 179 byte[] data = out.marshall(); 180 out.recycle(); 181 return data; 182 } 183 184 public ParcelFileDescriptor getStatisticsStream() { 185 mContext.enforceCallingPermission( 186 android.Manifest.permission.BATTERY_STATS, null); 187 //Slog.i("foo", "SENDING BATTERY INFO:"); 188 //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); 189 Parcel out = Parcel.obtain(); 190 mStats.writeToParcel(out, 0); 191 byte[] data = out.marshall(); 192 out.recycle(); 193 try { 194 return ParcelFileDescriptor.fromData(data, "battery-stats"); 195 } catch (IOException e) { 196 Slog.w(TAG, "Unable to create shared memory", e); 197 return null; 198 } 199 } 200 201 public long computeBatteryTimeRemaining() { 202 synchronized (mStats) { 203 long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime()); 204 return time >= 0 ? (time/1000) : time; 205 } 206 } 207 208 public long computeChargeTimeRemaining() { 209 synchronized (mStats) { 210 long time = mStats.computeChargeTimeRemaining(SystemClock.elapsedRealtime()); 211 return time >= 0 ? (time/1000) : time; 212 } 213 } 214 215 public void noteEvent(int code, String name, int uid) { 216 enforceCallingPermission(); 217 synchronized (mStats) { 218 mStats.noteEventLocked(code, name, uid); 219 } 220 } 221 222 public void noteSyncStart(String name, int uid) { 223 enforceCallingPermission(); 224 synchronized (mStats) { 225 mStats.noteSyncStartLocked(name, uid); 226 } 227 } 228 229 public void noteSyncFinish(String name, int uid) { 230 enforceCallingPermission(); 231 synchronized (mStats) { 232 mStats.noteSyncFinishLocked(name, uid); 233 } 234 } 235 236 public void noteJobStart(String name, int uid) { 237 enforceCallingPermission(); 238 synchronized (mStats) { 239 mStats.noteJobStartLocked(name, uid); 240 } 241 } 242 243 public void noteJobFinish(String name, int uid) { 244 enforceCallingPermission(); 245 synchronized (mStats) { 246 mStats.noteJobFinishLocked(name, uid); 247 } 248 } 249 250 public void noteStartWakelock(int uid, int pid, String name, String historyName, int type, 251 boolean unimportantForLogging) { 252 enforceCallingPermission(); 253 synchronized (mStats) { 254 mStats.noteStartWakeLocked(uid, pid, name, historyName, type, unimportantForLogging, 255 SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); 256 } 257 } 258 259 public void noteStopWakelock(int uid, int pid, String name, String historyName, int type) { 260 enforceCallingPermission(); 261 synchronized (mStats) { 262 mStats.noteStopWakeLocked(uid, pid, name, historyName, type, 263 SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); 264 } 265 } 266 267 public void noteStartWakelockFromSource(WorkSource ws, int pid, String name, 268 String historyName, int type, boolean unimportantForLogging) { 269 enforceCallingPermission(); 270 synchronized (mStats) { 271 mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName, 272 type, unimportantForLogging); 273 } 274 } 275 276 public void noteChangeWakelockFromSource(WorkSource ws, int pid, String name, 277 String historyName, int type, WorkSource newWs, int newPid, String newName, 278 String newHistoryName, int newType, boolean newUnimportantForLogging) { 279 enforceCallingPermission(); 280 synchronized (mStats) { 281 mStats.noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type, 282 newWs, newPid, newName, newHistoryName, newType, newUnimportantForLogging); 283 } 284 } 285 286 public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, String historyName, 287 int type) { 288 enforceCallingPermission(); 289 synchronized (mStats) { 290 mStats.noteStopWakeFromSourceLocked(ws, pid, name, historyName, type); 291 } 292 } 293 294 public void noteStartSensor(int uid, int sensor) { 295 enforceCallingPermission(); 296 synchronized (mStats) { 297 mStats.noteStartSensorLocked(uid, sensor); 298 } 299 } 300 301 public void noteStopSensor(int uid, int sensor) { 302 enforceCallingPermission(); 303 synchronized (mStats) { 304 mStats.noteStopSensorLocked(uid, sensor); 305 } 306 } 307 308 public void noteVibratorOn(int uid, long durationMillis) { 309 enforceCallingPermission(); 310 synchronized (mStats) { 311 mStats.noteVibratorOnLocked(uid, durationMillis); 312 } 313 } 314 315 public void noteVibratorOff(int uid) { 316 enforceCallingPermission(); 317 synchronized (mStats) { 318 mStats.noteVibratorOffLocked(uid); 319 } 320 } 321 322 public void noteStartGps(int uid) { 323 enforceCallingPermission(); 324 synchronized (mStats) { 325 mStats.noteStartGpsLocked(uid); 326 } 327 } 328 329 public void noteStopGps(int uid) { 330 enforceCallingPermission(); 331 synchronized (mStats) { 332 mStats.noteStopGpsLocked(uid); 333 } 334 } 335 336 public void noteScreenState(int state) { 337 enforceCallingPermission(); 338 synchronized (mStats) { 339 mStats.noteScreenStateLocked(state); 340 } 341 } 342 343 public void noteScreenBrightness(int brightness) { 344 enforceCallingPermission(); 345 synchronized (mStats) { 346 mStats.noteScreenBrightnessLocked(brightness); 347 } 348 } 349 350 public void noteUserActivity(int uid, int event) { 351 enforceCallingPermission(); 352 synchronized (mStats) { 353 mStats.noteUserActivityLocked(uid, event); 354 } 355 } 356 357 public void noteInteractive(boolean interactive) { 358 enforceCallingPermission(); 359 synchronized (mStats) { 360 mStats.noteInteractiveLocked(interactive); 361 } 362 } 363 364 public void noteConnectivityChanged(int type, String extra) { 365 enforceCallingPermission(); 366 synchronized (mStats) { 367 mStats.noteConnectivityChangedLocked(type, extra); 368 } 369 } 370 371 public void noteMobileRadioPowerState(int powerState, long timestampNs) { 372 enforceCallingPermission(); 373 synchronized (mStats) { 374 mStats.noteMobileRadioPowerState(powerState, timestampNs); 375 } 376 } 377 378 public void notePhoneOn() { 379 enforceCallingPermission(); 380 synchronized (mStats) { 381 mStats.notePhoneOnLocked(); 382 } 383 } 384 385 public void notePhoneOff() { 386 enforceCallingPermission(); 387 synchronized (mStats) { 388 mStats.notePhoneOffLocked(); 389 } 390 } 391 392 public void notePhoneSignalStrength(SignalStrength signalStrength) { 393 enforceCallingPermission(); 394 synchronized (mStats) { 395 mStats.notePhoneSignalStrengthLocked(signalStrength); 396 } 397 } 398 399 public void notePhoneDataConnectionState(int dataType, boolean hasData) { 400 enforceCallingPermission(); 401 synchronized (mStats) { 402 mStats.notePhoneDataConnectionStateLocked(dataType, hasData); 403 } 404 } 405 406 public void notePhoneState(int state) { 407 enforceCallingPermission(); 408 int simState = TelephonyManager.getDefault().getSimState(); 409 synchronized (mStats) { 410 mStats.notePhoneStateLocked(state, simState); 411 } 412 } 413 414 public void noteWifiOn() { 415 enforceCallingPermission(); 416 synchronized (mStats) { 417 mStats.noteWifiOnLocked(); 418 } 419 } 420 421 public void noteWifiOff() { 422 enforceCallingPermission(); 423 synchronized (mStats) { 424 mStats.noteWifiOffLocked(); 425 } 426 } 427 428 public void noteStartAudio(int uid) { 429 enforceCallingPermission(); 430 synchronized (mStats) { 431 mStats.noteAudioOnLocked(uid); 432 } 433 } 434 435 public void noteStopAudio(int uid) { 436 enforceCallingPermission(); 437 synchronized (mStats) { 438 mStats.noteAudioOffLocked(uid); 439 } 440 } 441 442 public void noteStartVideo(int uid) { 443 enforceCallingPermission(); 444 synchronized (mStats) { 445 mStats.noteVideoOnLocked(uid); 446 } 447 } 448 449 public void noteStopVideo(int uid) { 450 enforceCallingPermission(); 451 synchronized (mStats) { 452 mStats.noteVideoOffLocked(uid); 453 } 454 } 455 456 public void noteResetAudio() { 457 enforceCallingPermission(); 458 synchronized (mStats) { 459 mStats.noteResetAudioLocked(); 460 } 461 } 462 463 public void noteResetVideo() { 464 enforceCallingPermission(); 465 synchronized (mStats) { 466 mStats.noteResetVideoLocked(); 467 } 468 } 469 470 public void noteFlashlightOn() { 471 enforceCallingPermission(); 472 synchronized (mStats) { 473 mStats.noteFlashlightOnLocked(); 474 } 475 } 476 477 public void noteFlashlightOff() { 478 enforceCallingPermission(); 479 synchronized (mStats) { 480 mStats.noteFlashlightOffLocked(); 481 } 482 } 483 484 public void noteWifiRunning(WorkSource ws) { 485 enforceCallingPermission(); 486 synchronized (mStats) { 487 mStats.noteWifiRunningLocked(ws); 488 } 489 } 490 491 public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) { 492 enforceCallingPermission(); 493 synchronized (mStats) { 494 mStats.noteWifiRunningChangedLocked(oldWs, newWs); 495 } 496 } 497 498 public void noteWifiStopped(WorkSource ws) { 499 enforceCallingPermission(); 500 synchronized (mStats) { 501 mStats.noteWifiStoppedLocked(ws); 502 } 503 } 504 505 public void noteWifiState(int wifiState, String accessPoint) { 506 enforceCallingPermission(); 507 synchronized (mStats) { 508 mStats.noteWifiStateLocked(wifiState, accessPoint); 509 } 510 } 511 512 public void noteWifiSupplicantStateChanged(int supplState, boolean failedAuth) { 513 enforceCallingPermission(); 514 synchronized (mStats) { 515 mStats.noteWifiSupplicantStateChangedLocked(supplState, failedAuth); 516 } 517 } 518 519 public void noteWifiRssiChanged(int newRssi) { 520 enforceCallingPermission(); 521 synchronized (mStats) { 522 mStats.noteWifiRssiChangedLocked(newRssi); 523 } 524 } 525 526 public void noteBluetoothOn() { 527 enforceCallingPermission(); 528 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 529 if (adapter != null) { 530 adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 531 BluetoothProfile.HEADSET); 532 } 533 synchronized (mStats) { 534 if (mBluetoothHeadset != null) { 535 mStats.noteBluetoothOnLocked(); 536 mStats.setBtHeadset(mBluetoothHeadset); 537 } else { 538 mBluetoothPendingStats = true; 539 } 540 } 541 } 542 543 private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 544 new BluetoothProfile.ServiceListener() { 545 public void onServiceConnected(int profile, BluetoothProfile proxy) { 546 mBluetoothHeadset = (BluetoothHeadset) proxy; 547 synchronized (mStats) { 548 if (mBluetoothPendingStats) { 549 mStats.noteBluetoothOnLocked(); 550 mStats.setBtHeadset(mBluetoothHeadset); 551 mBluetoothPendingStats = false; 552 } 553 } 554 } 555 556 public void onServiceDisconnected(int profile) { 557 mBluetoothHeadset = null; 558 } 559 }; 560 561 public void noteBluetoothOff() { 562 enforceCallingPermission(); 563 synchronized (mStats) { 564 mBluetoothPendingStats = false; 565 mStats.noteBluetoothOffLocked(); 566 } 567 } 568 569 public void noteBluetoothState(int bluetoothState) { 570 enforceCallingPermission(); 571 synchronized (mStats) { 572 mStats.noteBluetoothStateLocked(bluetoothState); 573 } 574 } 575 576 public void noteFullWifiLockAcquired(int uid) { 577 enforceCallingPermission(); 578 synchronized (mStats) { 579 mStats.noteFullWifiLockAcquiredLocked(uid); 580 } 581 } 582 583 public void noteFullWifiLockReleased(int uid) { 584 enforceCallingPermission(); 585 synchronized (mStats) { 586 mStats.noteFullWifiLockReleasedLocked(uid); 587 } 588 } 589 590 public void noteWifiScanStarted(int uid) { 591 enforceCallingPermission(); 592 synchronized (mStats) { 593 mStats.noteWifiScanStartedLocked(uid); 594 } 595 } 596 597 public void noteWifiScanStopped(int uid) { 598 enforceCallingPermission(); 599 synchronized (mStats) { 600 mStats.noteWifiScanStoppedLocked(uid); 601 } 602 } 603 604 public void noteWifiMulticastEnabled(int uid) { 605 enforceCallingPermission(); 606 synchronized (mStats) { 607 mStats.noteWifiMulticastEnabledLocked(uid); 608 } 609 } 610 611 public void noteWifiMulticastDisabled(int uid) { 612 enforceCallingPermission(); 613 synchronized (mStats) { 614 mStats.noteWifiMulticastDisabledLocked(uid); 615 } 616 } 617 618 public void noteFullWifiLockAcquiredFromSource(WorkSource ws) { 619 enforceCallingPermission(); 620 synchronized (mStats) { 621 mStats.noteFullWifiLockAcquiredFromSourceLocked(ws); 622 } 623 } 624 625 public void noteFullWifiLockReleasedFromSource(WorkSource ws) { 626 enforceCallingPermission(); 627 synchronized (mStats) { 628 mStats.noteFullWifiLockReleasedFromSourceLocked(ws); 629 } 630 } 631 632 public void noteWifiScanStartedFromSource(WorkSource ws) { 633 enforceCallingPermission(); 634 synchronized (mStats) { 635 mStats.noteWifiScanStartedFromSourceLocked(ws); 636 } 637 } 638 639 public void noteWifiScanStoppedFromSource(WorkSource ws) { 640 enforceCallingPermission(); 641 synchronized (mStats) { 642 mStats.noteWifiScanStoppedFromSourceLocked(ws); 643 } 644 } 645 646 public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) { 647 enforceCallingPermission(); 648 synchronized (mStats) { 649 mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph); 650 } 651 } 652 653 public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) { 654 enforceCallingPermission(); 655 synchronized (mStats) { 656 mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws); 657 } 658 } 659 660 public void noteWifiMulticastEnabledFromSource(WorkSource ws) { 661 enforceCallingPermission(); 662 synchronized (mStats) { 663 mStats.noteWifiMulticastEnabledFromSourceLocked(ws); 664 } 665 } 666 667 public void noteWifiMulticastDisabledFromSource(WorkSource ws) { 668 enforceCallingPermission(); 669 synchronized (mStats) { 670 mStats.noteWifiMulticastDisabledFromSourceLocked(ws); 671 } 672 } 673 674 @Override 675 public void noteNetworkInterfaceType(String iface, int type) { 676 enforceCallingPermission(); 677 synchronized (mStats) { 678 mStats.noteNetworkInterfaceTypeLocked(iface, type); 679 } 680 } 681 682 @Override 683 public void noteNetworkStatsEnabled() { 684 enforceCallingPermission(); 685 synchronized (mStats) { 686 mStats.noteNetworkStatsEnabledLocked(); 687 } 688 } 689 690 public boolean isOnBattery() { 691 return mStats.isOnBattery(); 692 } 693 694 public void setBatteryState(int status, int health, int plugType, int level, 695 int temp, int volt) { 696 enforceCallingPermission(); 697 mStats.setBatteryState(status, health, plugType, level, temp, volt); 698 } 699 700 public long getAwakeTimeBattery() { 701 mContext.enforceCallingOrSelfPermission( 702 android.Manifest.permission.BATTERY_STATS, null); 703 return mStats.getAwakeTimeBattery(); 704 } 705 706 public long getAwakeTimePlugged() { 707 mContext.enforceCallingOrSelfPermission( 708 android.Manifest.permission.BATTERY_STATS, null); 709 return mStats.getAwakeTimePlugged(); 710 } 711 712 public void enforceCallingPermission() { 713 if (Binder.getCallingPid() == Process.myPid()) { 714 return; 715 } 716 mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 717 Binder.getCallingPid(), Binder.getCallingUid(), null); 718 } 719 720 final class WakeupReasonThread extends Thread { 721 final int[] mIrqs = new int[32]; 722 final String[] mReasons = new String[32]; 723 724 WakeupReasonThread() { 725 super("BatteryStats_wakeupReason"); 726 } 727 728 public void run() { 729 Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND); 730 731 try { 732 int num; 733 while ((num=nativeWaitWakeup(mIrqs, mReasons)) >= 0) { 734 synchronized (mStats) { 735 if (num > 0) { 736 for (int i=0; i<num; i++) { 737 mStats.noteWakeupReasonLocked(mReasons[i]); 738 } 739 } else { 740 mStats.noteWakeupReasonLocked("unknown"); 741 } 742 } 743 } 744 } catch (RuntimeException e) { 745 Slog.e(TAG, "Failure reading wakeup reasons", e); 746 } 747 } 748 } 749 750 private static native int nativeWaitWakeup(int[] outIrqs, String[] outReasons); 751 752 private void dumpHelp(PrintWriter pw) { 753 pw.println("Battery stats (batterystats) dump options:"); 754 pw.println(" [--checkin] [--history] [--history-start] [--unplugged] [--charged] [-c]"); 755 pw.println(" [--reset] [--write] [-h] [<package.name>]"); 756 pw.println(" --checkin: format output for a checkin report."); 757 pw.println(" --history: show only history data."); 758 pw.println(" --history-start <num>: show only history data starting at given time offset."); 759 pw.println(" --unplugged: only output data since last unplugged."); 760 pw.println(" --charged: only output data since last charged."); 761 pw.println(" --reset: reset the stats, clearing all current data."); 762 pw.println(" --write: force write current collected stats to disk."); 763 pw.println(" <package.name>: optional name of package to filter output by."); 764 pw.println(" -h: print this help text."); 765 pw.println("Battery stats (batterystats) commands:"); 766 pw.println(" enable|disable <option>"); 767 pw.println(" Enable or disable a running option. Option state is not saved across boots."); 768 pw.println(" Options are:"); 769 pw.println(" full-history: include additional detailed events in battery history:"); 770 pw.println(" wake_lock_in and proc events"); 771 pw.println(" no-auto-reset: don't automatically reset stats when unplugged"); 772 } 773 774 private int doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable) { 775 i++; 776 if (i >= args.length) { 777 pw.println("Missing option argument for " + (enable ? "--enable" : "--disable")); 778 dumpHelp(pw); 779 return -1; 780 } 781 if ("full-wake-history".equals(args[i]) || "full-history".equals(args[i])) { 782 synchronized (mStats) { 783 mStats.setRecordAllHistoryLocked(enable); 784 } 785 } else if ("no-auto-reset".equals(args[i])) { 786 synchronized (mStats) { 787 mStats.setNoAutoReset(enable); 788 } 789 } else { 790 pw.println("Unknown enable/disable option: " + args[i]); 791 dumpHelp(pw); 792 return -1; 793 } 794 return i; 795 } 796 797 @Override 798 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 799 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 800 != PackageManager.PERMISSION_GRANTED) { 801 pw.println("Permission Denial: can't dump BatteryStats from from pid=" 802 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 803 + " without permission " + android.Manifest.permission.DUMP); 804 return; 805 } 806 807 int flags = 0; 808 boolean useCheckinFormat = false; 809 boolean isRealCheckin = false; 810 boolean noOutput = false; 811 boolean writeData = false; 812 long historyStart = -1; 813 int reqUid = -1; 814 if (args != null) { 815 for (int i=0; i<args.length; i++) { 816 String arg = args[i]; 817 if ("--checkin".equals(arg)) { 818 useCheckinFormat = true; 819 isRealCheckin = true; 820 } else if ("--history".equals(arg)) { 821 flags |= BatteryStats.DUMP_HISTORY_ONLY; 822 } else if ("--history-start".equals(arg)) { 823 flags |= BatteryStats.DUMP_HISTORY_ONLY; 824 i++; 825 if (i >= args.length) { 826 pw.println("Missing time argument for --history-since"); 827 dumpHelp(pw); 828 return; 829 } 830 historyStart = Long.parseLong(args[i]); 831 writeData = true; 832 } else if ("-c".equals(arg)) { 833 useCheckinFormat = true; 834 flags |= BatteryStats.DUMP_INCLUDE_HISTORY; 835 } else if ("--unplugged".equals(arg)) { 836 flags |= BatteryStats.DUMP_UNPLUGGED_ONLY; 837 } else if ("--charged".equals(arg)) { 838 flags |= BatteryStats.DUMP_CHARGED_ONLY; 839 } else if ("--reset".equals(arg)) { 840 synchronized (mStats) { 841 mStats.resetAllStatsCmdLocked(); 842 pw.println("Battery stats reset."); 843 noOutput = true; 844 } 845 } else if ("--write".equals(arg)) { 846 synchronized (mStats) { 847 mStats.writeSyncLocked(); 848 pw.println("Battery stats written."); 849 noOutput = true; 850 } 851 } else if ("--enable".equals(arg) || "enable".equals(arg)) { 852 i = doEnableOrDisable(pw, i, args, true); 853 if (i < 0) { 854 return; 855 } 856 pw.println("Enabled: " + args[i]); 857 return; 858 } else if ("--disable".equals(arg) || "disable".equals(arg)) { 859 i = doEnableOrDisable(pw, i, args, false); 860 if (i < 0) { 861 return; 862 } 863 pw.println("Disabled: " + args[i]); 864 return; 865 } else if ("-h".equals(arg)) { 866 dumpHelp(pw); 867 return; 868 } else if ("-a".equals(arg)) { 869 flags |= BatteryStats.DUMP_VERBOSE; 870 } else if (arg.length() > 0 && arg.charAt(0) == '-'){ 871 pw.println("Unknown option: " + arg); 872 dumpHelp(pw); 873 return; 874 } else { 875 // Not an option, last argument must be a package name. 876 try { 877 reqUid = mContext.getPackageManager().getPackageUid(arg, 878 UserHandle.getCallingUserId()); 879 } catch (PackageManager.NameNotFoundException e) { 880 pw.println("Unknown package: " + arg); 881 dumpHelp(pw); 882 return; 883 } 884 } 885 } 886 } 887 if (noOutput) { 888 return; 889 } 890 if (BatteryStatsHelper.checkWifiOnly(mContext)) { 891 flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY; 892 } 893 if (reqUid >= 0) { 894 // By default, if the caller is only interested in a specific package, then 895 // we only dump the aggregated data since charged. 896 if ((flags&(BatteryStats.DUMP_HISTORY_ONLY|BatteryStats.DUMP_UNPLUGGED_ONLY 897 |BatteryStats.DUMP_CHARGED_ONLY)) == 0) { 898 flags |= BatteryStats.DUMP_CHARGED_ONLY; 899 // Also if they are doing -c, we don't want history. 900 flags &= ~BatteryStats.DUMP_INCLUDE_HISTORY; 901 } 902 } 903 if (useCheckinFormat) { 904 List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0); 905 if (isRealCheckin) { 906 // For a real checkin, first we want to prefer to use the last complete checkin 907 // file if there is one. 908 synchronized (mStats.mCheckinFile) { 909 if (mStats.mCheckinFile.exists()) { 910 try { 911 byte[] raw = mStats.mCheckinFile.readFully(); 912 if (raw != null) { 913 Parcel in = Parcel.obtain(); 914 in.unmarshall(raw, 0, raw.length); 915 in.setDataPosition(0); 916 BatteryStatsImpl checkinStats = new BatteryStatsImpl( 917 null, mStats.mHandler); 918 checkinStats.readSummaryFromParcel(in); 919 in.recycle(); 920 checkinStats.dumpCheckinLocked(mContext, pw, apps, flags, 921 historyStart); 922 mStats.mCheckinFile.delete(); 923 return; 924 } 925 } catch (IOException e) { 926 Slog.w(TAG, "Failure reading checkin file " 927 + mStats.mCheckinFile.getBaseFile(), e); 928 } 929 } 930 } 931 } 932 synchronized (mStats) { 933 mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart); 934 if (writeData) { 935 mStats.writeAsyncLocked(); 936 } 937 } 938 } else { 939 synchronized (mStats) { 940 mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart); 941 if (writeData) { 942 mStats.writeAsyncLocked(); 943 } 944 } 945 } 946 } 947 } 948