BatteryStatsService.java revision 9f55cc71b9b0a27604d448b5c54e3c377b7a067f
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 17package com.android.server.am; 18 19import android.bluetooth.BluetoothActivityEnergyInfo; 20import android.bluetooth.BluetoothAdapter; 21import android.content.Context; 22import android.content.pm.ApplicationInfo; 23import android.content.pm.PackageManager; 24import android.net.wifi.IWifiManager; 25import android.net.wifi.WifiActivityEnergyInfo; 26import android.os.BatteryStats; 27import android.os.Binder; 28import android.os.Handler; 29import android.os.IBinder; 30import android.os.Looper; 31import android.os.Message; 32import android.os.Parcel; 33import android.os.ParcelFileDescriptor; 34import android.os.ParcelFormatException; 35import android.os.PowerManagerInternal; 36import android.os.Process; 37import android.os.RemoteException; 38import android.os.ServiceManager; 39import android.os.SystemClock; 40import android.os.UserHandle; 41import android.os.WorkSource; 42import android.telephony.DataConnectionRealTimeInfo; 43import android.telephony.ModemActivityInfo; 44import android.telephony.SignalStrength; 45import android.telephony.TelephonyManager; 46import android.util.IntArray; 47import android.util.Slog; 48 49import android.util.TimeUtils; 50import com.android.internal.annotations.GuardedBy; 51import com.android.internal.app.IBatteryStats; 52import com.android.internal.os.BatteryStatsHelper; 53import com.android.internal.os.BatteryStatsImpl; 54import com.android.internal.os.PowerProfile; 55import com.android.internal.telephony.ITelephony; 56import com.android.server.FgThread; 57import com.android.server.LocalServices; 58 59import java.io.File; 60import java.io.FileDescriptor; 61import java.io.IOException; 62import java.io.PrintWriter; 63import java.nio.ByteBuffer; 64import java.nio.CharBuffer; 65import java.nio.charset.CharsetDecoder; 66import java.nio.charset.CodingErrorAction; 67import java.nio.charset.StandardCharsets; 68import java.util.List; 69 70/** 71 * All information we are collecting about things that can happen that impact 72 * battery life. 73 */ 74public final class BatteryStatsService extends IBatteryStats.Stub 75 implements PowerManagerInternal.LowPowerModeListener { 76 static final String TAG = "BatteryStatsService"; 77 78 static IBatteryStats sService; 79 final BatteryStatsImpl mStats; 80 final BatteryStatsHandler mHandler; 81 Context mContext; 82 PowerManagerInternal mPowerManagerInternal; 83 84 class BatteryStatsHandler extends Handler implements BatteryStatsImpl.ExternalStatsSync { 85 public static final int MSG_SYNC_EXTERNAL_STATS = 1; 86 public static final int MSG_WRITE_TO_DISK = 2; 87 private int mUpdateFlags = 0; 88 private IntArray mUidsToRemove = new IntArray(); 89 90 public BatteryStatsHandler(Looper looper) { 91 super(looper); 92 } 93 94 @Override 95 public void handleMessage(Message msg) { 96 switch (msg.what) { 97 case MSG_SYNC_EXTERNAL_STATS: 98 final int updateFlags; 99 synchronized (this) { 100 removeMessages(MSG_SYNC_EXTERNAL_STATS); 101 updateFlags = mUpdateFlags; 102 mUpdateFlags = 0; 103 } 104 updateExternalStats((String)msg.obj, updateFlags); 105 106 // other parts of the system could be calling into us 107 // from mStats in order to report of changes. We must grab the mStats 108 // lock before grabbing our own or we'll end up in a deadlock. 109 synchronized (mStats) { 110 synchronized (this) { 111 final int numUidsToRemove = mUidsToRemove.size(); 112 for (int i = 0; i < numUidsToRemove; i++) { 113 mStats.removeIsolatedUidLocked(mUidsToRemove.get(i)); 114 } 115 } 116 mUidsToRemove.clear(); 117 } 118 break; 119 120 case MSG_WRITE_TO_DISK: 121 updateExternalStats("write", UPDATE_ALL); 122 synchronized (mStats) { 123 mStats.writeAsyncLocked(); 124 } 125 break; 126 } 127 } 128 129 @Override 130 public void scheduleSync(String reason, int updateFlags) { 131 synchronized (this) { 132 scheduleSyncLocked(reason, updateFlags); 133 } 134 } 135 136 @Override 137 public void scheduleCpuSyncDueToRemovedUid(int uid) { 138 synchronized (this) { 139 scheduleSyncLocked("remove-uid", UPDATE_CPU); 140 mUidsToRemove.add(uid); 141 } 142 } 143 144 private void scheduleSyncLocked(String reason, int updateFlags) { 145 if (mUpdateFlags == 0) { 146 sendMessage(Message.obtain(this, MSG_SYNC_EXTERNAL_STATS, reason)); 147 } 148 mUpdateFlags |= updateFlags; 149 } 150 } 151 152 BatteryStatsService(File systemDir, Handler handler) { 153 // Our handler here will be accessing the disk, use a different thread than 154 // what the ActivityManagerService gave us (no I/O on that one!). 155 mHandler = new BatteryStatsHandler(FgThread.getHandler().getLooper()); 156 157 // BatteryStatsImpl expects the ActivityManagerService handler, so pass that one through. 158 mStats = new BatteryStatsImpl(systemDir, handler, mHandler); 159 } 160 161 public void publish(Context context) { 162 mContext = context; 163 mStats.setRadioScanningTimeout(mContext.getResources().getInteger( 164 com.android.internal.R.integer.config_radioScanningTimeout) 165 * 1000L); 166 mStats.setPowerProfile(new PowerProfile(context)); 167 ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder()); 168 } 169 170 /** 171 * At the time when the constructor runs, the power manager has not yet been 172 * initialized. So we initialize the low power observer later. 173 */ 174 public void initPowerManagement() { 175 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 176 mPowerManagerInternal.registerLowPowerModeObserver(this); 177 mStats.notePowerSaveMode(mPowerManagerInternal.getLowPowerModeEnabled()); 178 (new WakeupReasonThread()).start(); 179 } 180 181 public void shutdown() { 182 Slog.w("BatteryStats", "Writing battery stats before shutdown..."); 183 184 updateExternalStats("shutdown", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL); 185 synchronized (mStats) { 186 mStats.shutdownLocked(); 187 } 188 } 189 190 public static IBatteryStats getService() { 191 if (sService != null) { 192 return sService; 193 } 194 IBinder b = ServiceManager.getService(BatteryStats.SERVICE_NAME); 195 sService = asInterface(b); 196 return sService; 197 } 198 199 @Override 200 public void onLowPowerModeChanged(boolean enabled) { 201 synchronized (mStats) { 202 mStats.notePowerSaveMode(enabled); 203 } 204 } 205 206 /** 207 * @return the current statistics object, which may be modified 208 * to reflect events that affect battery usage. You must lock the 209 * stats object before doing anything with it. 210 */ 211 public BatteryStatsImpl getActiveStatistics() { 212 return mStats; 213 } 214 215 /** 216 * Schedules a write to disk to occur. This will cause the BatteryStatsImpl 217 * object to update with the latest info, then write to disk. 218 */ 219 public void scheduleWriteToDisk() { 220 mHandler.sendEmptyMessage(BatteryStatsHandler.MSG_WRITE_TO_DISK); 221 } 222 223 // These are for direct use by the activity manager... 224 225 /** 226 * Remove a UID from the BatteryStats and BatteryStats' external dependencies. 227 */ 228 void removeUid(int uid) { 229 synchronized (mStats) { 230 mStats.removeUidStatsLocked(uid); 231 } 232 } 233 234 void addIsolatedUid(int isolatedUid, int appUid) { 235 synchronized (mStats) { 236 mStats.addIsolatedUidLocked(isolatedUid, appUid); 237 } 238 } 239 240 void removeIsolatedUid(int isolatedUid, int appUid) { 241 synchronized (mStats) { 242 mStats.scheduleRemoveIsolatedUidLocked(isolatedUid, appUid); 243 } 244 } 245 246 void noteProcessStart(String name, int uid) { 247 synchronized (mStats) { 248 mStats.noteProcessStartLocked(name, uid); 249 } 250 } 251 252 void noteProcessCrash(String name, int uid) { 253 synchronized (mStats) { 254 mStats.noteProcessCrashLocked(name, uid); 255 } 256 } 257 258 void noteProcessAnr(String name, int uid) { 259 synchronized (mStats) { 260 mStats.noteProcessAnrLocked(name, uid); 261 } 262 } 263 264 void noteProcessFinish(String name, int uid) { 265 synchronized (mStats) { 266 mStats.noteProcessFinishLocked(name, uid); 267 } 268 } 269 270 void noteUidProcessState(int uid, int state) { 271 synchronized (mStats) { 272 mStats.noteUidProcessStateLocked(uid, state); 273 } 274 } 275 276 // Public interface... 277 278 public byte[] getStatistics() { 279 mContext.enforceCallingPermission( 280 android.Manifest.permission.BATTERY_STATS, null); 281 //Slog.i("foo", "SENDING BATTERY INFO:"); 282 //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); 283 Parcel out = Parcel.obtain(); 284 updateExternalStats("get-stats", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL); 285 synchronized (mStats) { 286 mStats.writeToParcel(out, 0); 287 } 288 byte[] data = out.marshall(); 289 out.recycle(); 290 return data; 291 } 292 293 public ParcelFileDescriptor getStatisticsStream() { 294 mContext.enforceCallingPermission( 295 android.Manifest.permission.BATTERY_STATS, null); 296 //Slog.i("foo", "SENDING BATTERY INFO:"); 297 //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); 298 Parcel out = Parcel.obtain(); 299 updateExternalStats("get-stats", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL); 300 synchronized (mStats) { 301 mStats.writeToParcel(out, 0); 302 } 303 byte[] data = out.marshall(); 304 out.recycle(); 305 try { 306 return ParcelFileDescriptor.fromData(data, "battery-stats"); 307 } catch (IOException e) { 308 Slog.w(TAG, "Unable to create shared memory", e); 309 return null; 310 } 311 } 312 313 public boolean isCharging() { 314 synchronized (mStats) { 315 return mStats.isCharging(); 316 } 317 } 318 319 public long computeBatteryTimeRemaining() { 320 synchronized (mStats) { 321 long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime()); 322 return time >= 0 ? (time/1000) : time; 323 } 324 } 325 326 public long computeChargeTimeRemaining() { 327 synchronized (mStats) { 328 long time = mStats.computeChargeTimeRemaining(SystemClock.elapsedRealtime()); 329 return time >= 0 ? (time/1000) : time; 330 } 331 } 332 333 public void noteEvent(int code, String name, int uid) { 334 enforceCallingPermission(); 335 synchronized (mStats) { 336 mStats.noteEventLocked(code, name, uid); 337 } 338 } 339 340 public void noteSyncStart(String name, int uid) { 341 enforceCallingPermission(); 342 synchronized (mStats) { 343 mStats.noteSyncStartLocked(name, uid); 344 } 345 } 346 347 public void noteSyncFinish(String name, int uid) { 348 enforceCallingPermission(); 349 synchronized (mStats) { 350 mStats.noteSyncFinishLocked(name, uid); 351 } 352 } 353 354 public void noteJobStart(String name, int uid) { 355 enforceCallingPermission(); 356 synchronized (mStats) { 357 mStats.noteJobStartLocked(name, uid); 358 } 359 } 360 361 public void noteJobFinish(String name, int uid) { 362 enforceCallingPermission(); 363 synchronized (mStats) { 364 mStats.noteJobFinishLocked(name, uid); 365 } 366 } 367 368 public void noteAlarmStart(String name, int uid) { 369 enforceCallingPermission(); 370 synchronized (mStats) { 371 mStats.noteAlarmStartLocked(name, uid); 372 } 373 } 374 375 public void noteAlarmFinish(String name, int uid) { 376 enforceCallingPermission(); 377 synchronized (mStats) { 378 mStats.noteAlarmFinishLocked(name, uid); 379 } 380 } 381 382 public void noteStartWakelock(int uid, int pid, String name, String historyName, int type, 383 boolean unimportantForLogging) { 384 enforceCallingPermission(); 385 synchronized (mStats) { 386 mStats.noteStartWakeLocked(uid, pid, name, historyName, type, unimportantForLogging, 387 SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); 388 } 389 } 390 391 public void noteStopWakelock(int uid, int pid, String name, String historyName, int type) { 392 enforceCallingPermission(); 393 synchronized (mStats) { 394 mStats.noteStopWakeLocked(uid, pid, name, historyName, type, 395 SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); 396 } 397 } 398 399 public void noteStartWakelockFromSource(WorkSource ws, int pid, String name, 400 String historyName, int type, boolean unimportantForLogging) { 401 enforceCallingPermission(); 402 synchronized (mStats) { 403 mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName, 404 type, unimportantForLogging); 405 } 406 } 407 408 public void noteChangeWakelockFromSource(WorkSource ws, int pid, String name, 409 String historyName, int type, WorkSource newWs, int newPid, String newName, 410 String newHistoryName, int newType, boolean newUnimportantForLogging) { 411 enforceCallingPermission(); 412 synchronized (mStats) { 413 mStats.noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type, 414 newWs, newPid, newName, newHistoryName, newType, newUnimportantForLogging); 415 } 416 } 417 418 public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, String historyName, 419 int type) { 420 enforceCallingPermission(); 421 synchronized (mStats) { 422 mStats.noteStopWakeFromSourceLocked(ws, pid, name, historyName, type); 423 } 424 } 425 426 public void noteStartSensor(int uid, int sensor) { 427 enforceCallingPermission(); 428 synchronized (mStats) { 429 mStats.noteStartSensorLocked(uid, sensor); 430 } 431 } 432 433 public void noteStopSensor(int uid, int sensor) { 434 enforceCallingPermission(); 435 synchronized (mStats) { 436 mStats.noteStopSensorLocked(uid, sensor); 437 } 438 } 439 440 public void noteVibratorOn(int uid, long durationMillis) { 441 enforceCallingPermission(); 442 synchronized (mStats) { 443 mStats.noteVibratorOnLocked(uid, durationMillis); 444 } 445 } 446 447 public void noteVibratorOff(int uid) { 448 enforceCallingPermission(); 449 synchronized (mStats) { 450 mStats.noteVibratorOffLocked(uid); 451 } 452 } 453 454 public void noteStartGps(int uid) { 455 enforceCallingPermission(); 456 synchronized (mStats) { 457 mStats.noteStartGpsLocked(uid); 458 } 459 } 460 461 public void noteStopGps(int uid) { 462 enforceCallingPermission(); 463 synchronized (mStats) { 464 mStats.noteStopGpsLocked(uid); 465 } 466 } 467 468 public void noteScreenState(int state) { 469 enforceCallingPermission(); 470 synchronized (mStats) { 471 mStats.noteScreenStateLocked(state); 472 } 473 } 474 475 public void noteScreenBrightness(int brightness) { 476 enforceCallingPermission(); 477 synchronized (mStats) { 478 mStats.noteScreenBrightnessLocked(brightness); 479 } 480 } 481 482 public void noteUserActivity(int uid, int event) { 483 enforceCallingPermission(); 484 synchronized (mStats) { 485 mStats.noteUserActivityLocked(uid, event); 486 } 487 } 488 489 public void noteWakeUp(String reason, int reasonUid) { 490 enforceCallingPermission(); 491 synchronized (mStats) { 492 mStats.noteWakeUpLocked(reason, reasonUid); 493 } 494 } 495 496 public void noteInteractive(boolean interactive) { 497 enforceCallingPermission(); 498 synchronized (mStats) { 499 mStats.noteInteractiveLocked(interactive); 500 } 501 } 502 503 public void noteConnectivityChanged(int type, String extra) { 504 enforceCallingPermission(); 505 synchronized (mStats) { 506 mStats.noteConnectivityChangedLocked(type, extra); 507 } 508 } 509 510 public void noteMobileRadioPowerState(int powerState, long timestampNs) { 511 enforceCallingPermission(); 512 synchronized (mStats) { 513 mStats.noteMobileRadioPowerState(powerState, timestampNs); 514 } 515 } 516 517 public void notePhoneOn() { 518 enforceCallingPermission(); 519 synchronized (mStats) { 520 mStats.notePhoneOnLocked(); 521 } 522 } 523 524 public void notePhoneOff() { 525 enforceCallingPermission(); 526 synchronized (mStats) { 527 mStats.notePhoneOffLocked(); 528 } 529 } 530 531 public void notePhoneSignalStrength(SignalStrength signalStrength) { 532 enforceCallingPermission(); 533 synchronized (mStats) { 534 mStats.notePhoneSignalStrengthLocked(signalStrength); 535 } 536 } 537 538 public void notePhoneDataConnectionState(int dataType, boolean hasData) { 539 enforceCallingPermission(); 540 synchronized (mStats) { 541 mStats.notePhoneDataConnectionStateLocked(dataType, hasData); 542 } 543 } 544 545 public void notePhoneState(int state) { 546 enforceCallingPermission(); 547 int simState = TelephonyManager.getDefault().getSimState(); 548 synchronized (mStats) { 549 mStats.notePhoneStateLocked(state, simState); 550 } 551 } 552 553 public void noteWifiOn() { 554 enforceCallingPermission(); 555 synchronized (mStats) { 556 mStats.noteWifiOnLocked(); 557 } 558 } 559 560 public void noteWifiOff() { 561 enforceCallingPermission(); 562 synchronized (mStats) { 563 mStats.noteWifiOffLocked(); 564 } 565 } 566 567 public void noteStartAudio(int uid) { 568 enforceCallingPermission(); 569 synchronized (mStats) { 570 mStats.noteAudioOnLocked(uid); 571 } 572 } 573 574 public void noteStopAudio(int uid) { 575 enforceCallingPermission(); 576 synchronized (mStats) { 577 mStats.noteAudioOffLocked(uid); 578 } 579 } 580 581 public void noteStartVideo(int uid) { 582 enforceCallingPermission(); 583 synchronized (mStats) { 584 mStats.noteVideoOnLocked(uid); 585 } 586 } 587 588 public void noteStopVideo(int uid) { 589 enforceCallingPermission(); 590 synchronized (mStats) { 591 mStats.noteVideoOffLocked(uid); 592 } 593 } 594 595 public void noteResetAudio() { 596 enforceCallingPermission(); 597 synchronized (mStats) { 598 mStats.noteResetAudioLocked(); 599 } 600 } 601 602 public void noteResetVideo() { 603 enforceCallingPermission(); 604 synchronized (mStats) { 605 mStats.noteResetVideoLocked(); 606 } 607 } 608 609 public void noteFlashlightOn(int uid) { 610 enforceCallingPermission(); 611 synchronized (mStats) { 612 mStats.noteFlashlightOnLocked(uid); 613 } 614 } 615 616 public void noteFlashlightOff(int uid) { 617 enforceCallingPermission(); 618 synchronized (mStats) { 619 mStats.noteFlashlightOffLocked(uid); 620 } 621 } 622 623 public void noteStartCamera(int uid) { 624 enforceCallingPermission(); 625 synchronized (mStats) { 626 mStats.noteCameraOnLocked(uid); 627 } 628 } 629 630 public void noteStopCamera(int uid) { 631 enforceCallingPermission(); 632 synchronized (mStats) { 633 mStats.noteCameraOffLocked(uid); 634 } 635 } 636 637 public void noteResetCamera() { 638 enforceCallingPermission(); 639 synchronized (mStats) { 640 mStats.noteResetCameraLocked(); 641 } 642 } 643 644 public void noteResetFlashlight() { 645 enforceCallingPermission(); 646 synchronized (mStats) { 647 mStats.noteResetFlashlightLocked(); 648 } 649 } 650 651 @Override 652 public void noteWifiRadioPowerState(int powerState, long tsNanos) { 653 enforceCallingPermission(); 654 655 // There was a change in WiFi power state. 656 // Collect data now for the past activity. 657 synchronized (mStats) { 658 if (mStats.isOnBattery()) { 659 final String type = (powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH || 660 powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM) ? "active" 661 : "inactive"; 662 mHandler.scheduleSync("wifi-data: " + type, 663 BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI); 664 } 665 mStats.noteWifiRadioPowerState(powerState, tsNanos); 666 } 667 } 668 669 public void noteWifiRunning(WorkSource ws) { 670 enforceCallingPermission(); 671 synchronized (mStats) { 672 mStats.noteWifiRunningLocked(ws); 673 } 674 } 675 676 public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) { 677 enforceCallingPermission(); 678 synchronized (mStats) { 679 mStats.noteWifiRunningChangedLocked(oldWs, newWs); 680 } 681 } 682 683 public void noteWifiStopped(WorkSource ws) { 684 enforceCallingPermission(); 685 synchronized (mStats) { 686 mStats.noteWifiStoppedLocked(ws); 687 } 688 } 689 690 public void noteWifiState(int wifiState, String accessPoint) { 691 enforceCallingPermission(); 692 synchronized (mStats) { 693 mStats.noteWifiStateLocked(wifiState, accessPoint); 694 } 695 } 696 697 public void noteWifiSupplicantStateChanged(int supplState, boolean failedAuth) { 698 enforceCallingPermission(); 699 synchronized (mStats) { 700 mStats.noteWifiSupplicantStateChangedLocked(supplState, failedAuth); 701 } 702 } 703 704 public void noteWifiRssiChanged(int newRssi) { 705 enforceCallingPermission(); 706 synchronized (mStats) { 707 mStats.noteWifiRssiChangedLocked(newRssi); 708 } 709 } 710 711 public void noteFullWifiLockAcquired(int uid) { 712 enforceCallingPermission(); 713 synchronized (mStats) { 714 mStats.noteFullWifiLockAcquiredLocked(uid); 715 } 716 } 717 718 public void noteFullWifiLockReleased(int uid) { 719 enforceCallingPermission(); 720 synchronized (mStats) { 721 mStats.noteFullWifiLockReleasedLocked(uid); 722 } 723 } 724 725 public void noteWifiScanStarted(int uid) { 726 enforceCallingPermission(); 727 synchronized (mStats) { 728 mStats.noteWifiScanStartedLocked(uid); 729 } 730 } 731 732 public void noteWifiScanStopped(int uid) { 733 enforceCallingPermission(); 734 synchronized (mStats) { 735 mStats.noteWifiScanStoppedLocked(uid); 736 } 737 } 738 739 public void noteWifiMulticastEnabled(int uid) { 740 enforceCallingPermission(); 741 synchronized (mStats) { 742 mStats.noteWifiMulticastEnabledLocked(uid); 743 } 744 } 745 746 public void noteWifiMulticastDisabled(int uid) { 747 enforceCallingPermission(); 748 synchronized (mStats) { 749 mStats.noteWifiMulticastDisabledLocked(uid); 750 } 751 } 752 753 public void noteFullWifiLockAcquiredFromSource(WorkSource ws) { 754 enforceCallingPermission(); 755 synchronized (mStats) { 756 mStats.noteFullWifiLockAcquiredFromSourceLocked(ws); 757 } 758 } 759 760 public void noteFullWifiLockReleasedFromSource(WorkSource ws) { 761 enforceCallingPermission(); 762 synchronized (mStats) { 763 mStats.noteFullWifiLockReleasedFromSourceLocked(ws); 764 } 765 } 766 767 public void noteWifiScanStartedFromSource(WorkSource ws) { 768 enforceCallingPermission(); 769 synchronized (mStats) { 770 mStats.noteWifiScanStartedFromSourceLocked(ws); 771 } 772 } 773 774 public void noteWifiScanStoppedFromSource(WorkSource ws) { 775 enforceCallingPermission(); 776 synchronized (mStats) { 777 mStats.noteWifiScanStoppedFromSourceLocked(ws); 778 } 779 } 780 781 public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) { 782 enforceCallingPermission(); 783 synchronized (mStats) { 784 mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph); 785 } 786 } 787 788 public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) { 789 enforceCallingPermission(); 790 synchronized (mStats) { 791 mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws); 792 } 793 } 794 795 public void noteWifiMulticastEnabledFromSource(WorkSource ws) { 796 enforceCallingPermission(); 797 synchronized (mStats) { 798 mStats.noteWifiMulticastEnabledFromSourceLocked(ws); 799 } 800 } 801 802 @Override 803 public void noteWifiMulticastDisabledFromSource(WorkSource ws) { 804 enforceCallingPermission(); 805 synchronized (mStats) { 806 mStats.noteWifiMulticastDisabledFromSourceLocked(ws); 807 } 808 } 809 810 @Override 811 public void noteNetworkInterfaceType(String iface, int networkType) { 812 enforceCallingPermission(); 813 synchronized (mStats) { 814 mStats.noteNetworkInterfaceTypeLocked(iface, networkType); 815 } 816 } 817 818 @Override 819 public void noteNetworkStatsEnabled() { 820 enforceCallingPermission(); 821 synchronized (mStats) { 822 mStats.noteNetworkStatsEnabledLocked(); 823 } 824 } 825 826 @Override 827 public void noteDeviceIdleMode(int mode, String activeReason, int activeUid) { 828 enforceCallingPermission(); 829 synchronized (mStats) { 830 mStats.noteDeviceIdleModeLocked(mode, activeReason, activeUid); 831 } 832 } 833 834 public void notePackageInstalled(String pkgName, int versionCode) { 835 enforceCallingPermission(); 836 synchronized (mStats) { 837 mStats.notePackageInstalledLocked(pkgName, versionCode); 838 } 839 } 840 841 public void notePackageUninstalled(String pkgName) { 842 enforceCallingPermission(); 843 synchronized (mStats) { 844 mStats.notePackageUninstalledLocked(pkgName); 845 } 846 } 847 848 @Override 849 public void noteBleScanStarted(WorkSource ws) { 850 enforceCallingPermission(); 851 synchronized (mStats) { 852 mStats.noteBluetoothScanStartedFromSourceLocked(ws); 853 } 854 } 855 856 @Override 857 public void noteBleScanStopped(WorkSource ws) { 858 enforceCallingPermission(); 859 synchronized (mStats) { 860 mStats.noteBluetoothScanStoppedFromSourceLocked(ws); 861 } 862 } 863 864 @Override 865 public void noteResetBleScan() { 866 enforceCallingPermission(); 867 synchronized (mStats) { 868 mStats.noteResetBluetoothScanLocked(); 869 } 870 } 871 872 public boolean isOnBattery() { 873 return mStats.isOnBattery(); 874 } 875 876 @Override 877 public void setBatteryState(final int status, final int health, final int plugType, 878 final int level, final int temp, final int volt) { 879 enforceCallingPermission(); 880 881 // BatteryService calls us here and we may update external state. It would be wrong 882 // to block such a low level service like BatteryService on external stats like WiFi. 883 mHandler.post(new Runnable() { 884 @Override 885 public void run() { 886 synchronized (mStats) { 887 final boolean onBattery = plugType == BatteryStatsImpl.BATTERY_PLUGGED_NONE; 888 if (mStats.isOnBattery() == onBattery) { 889 // The battery state has not changed, so we don't need to sync external 890 // stats immediately. 891 mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt); 892 return; 893 } 894 } 895 896 // Sync external stats first as the battery has changed states. If we don't sync 897 // immediately here, we may not collect the relevant data later. 898 updateExternalStats("battery-state", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL); 899 synchronized (mStats) { 900 mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt); 901 } 902 } 903 }); 904 } 905 906 public long getAwakeTimeBattery() { 907 mContext.enforceCallingOrSelfPermission( 908 android.Manifest.permission.BATTERY_STATS, null); 909 return mStats.getAwakeTimeBattery(); 910 } 911 912 public long getAwakeTimePlugged() { 913 mContext.enforceCallingOrSelfPermission( 914 android.Manifest.permission.BATTERY_STATS, null); 915 return mStats.getAwakeTimePlugged(); 916 } 917 918 public void enforceCallingPermission() { 919 if (Binder.getCallingPid() == Process.myPid()) { 920 return; 921 } 922 mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 923 Binder.getCallingPid(), Binder.getCallingUid(), null); 924 } 925 926 final class WakeupReasonThread extends Thread { 927 private static final int MAX_REASON_SIZE = 512; 928 private CharsetDecoder mDecoder; 929 private ByteBuffer mUtf8Buffer; 930 private CharBuffer mUtf16Buffer; 931 932 WakeupReasonThread() { 933 super("BatteryStats_wakeupReason"); 934 } 935 936 public void run() { 937 Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND); 938 939 mDecoder = StandardCharsets.UTF_8 940 .newDecoder() 941 .onMalformedInput(CodingErrorAction.REPLACE) 942 .onUnmappableCharacter(CodingErrorAction.REPLACE) 943 .replaceWith("?"); 944 945 mUtf8Buffer = ByteBuffer.allocateDirect(MAX_REASON_SIZE); 946 mUtf16Buffer = CharBuffer.allocate(MAX_REASON_SIZE); 947 948 try { 949 String reason; 950 while ((reason = waitWakeup()) != null) { 951 synchronized (mStats) { 952 mStats.noteWakeupReasonLocked(reason); 953 } 954 } 955 } catch (RuntimeException e) { 956 Slog.e(TAG, "Failure reading wakeup reasons", e); 957 } 958 } 959 960 private String waitWakeup() { 961 mUtf8Buffer.clear(); 962 mUtf16Buffer.clear(); 963 mDecoder.reset(); 964 965 int bytesWritten = nativeWaitWakeup(mUtf8Buffer); 966 if (bytesWritten < 0) { 967 return null; 968 } else if (bytesWritten == 0) { 969 return "unknown"; 970 } 971 972 // Set the buffer's limit to the number of bytes written. 973 mUtf8Buffer.limit(bytesWritten); 974 975 // Decode the buffer from UTF-8 to UTF-16. 976 // Unmappable characters will be replaced. 977 mDecoder.decode(mUtf8Buffer, mUtf16Buffer, true); 978 mUtf16Buffer.flip(); 979 980 // Create a String from the UTF-16 buffer. 981 return mUtf16Buffer.toString(); 982 } 983 } 984 985 private static native int nativeWaitWakeup(ByteBuffer outBuffer); 986 987 private void dumpHelp(PrintWriter pw) { 988 pw.println("Battery stats (batterystats) dump options:"); 989 pw.println(" [--checkin] [--history] [--history-start] [--charged] [-c]"); 990 pw.println(" [--daily] [--reset] [--write] [--new-daily] [--read-daily] [-h] [<package.name>]"); 991 pw.println(" --checkin: generate output for a checkin report; will write (and clear) the"); 992 pw.println(" last old completed stats when they had been reset."); 993 pw.println(" --c: write the current stats in checkin format."); 994 pw.println(" --history: show only history data."); 995 pw.println(" --history-start <num>: show only history data starting at given time offset."); 996 pw.println(" --charged: only output data since last charged."); 997 pw.println(" --daily: only output full daily data."); 998 pw.println(" --reset: reset the stats, clearing all current data."); 999 pw.println(" --write: force write current collected stats to disk."); 1000 pw.println(" --new-daily: immediately create and write new daily stats record."); 1001 pw.println(" --read-daily: read-load last written daily stats."); 1002 pw.println(" <package.name>: optional name of package to filter output by."); 1003 pw.println(" -h: print this help text."); 1004 pw.println("Battery stats (batterystats) commands:"); 1005 pw.println(" enable|disable <option>"); 1006 pw.println(" Enable or disable a running option. Option state is not saved across boots."); 1007 pw.println(" Options are:"); 1008 pw.println(" full-history: include additional detailed events in battery history:"); 1009 pw.println(" wake_lock_in, alarms and proc events"); 1010 pw.println(" no-auto-reset: don't automatically reset stats when unplugged"); 1011 } 1012 1013 private int doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable) { 1014 i++; 1015 if (i >= args.length) { 1016 pw.println("Missing option argument for " + (enable ? "--enable" : "--disable")); 1017 dumpHelp(pw); 1018 return -1; 1019 } 1020 if ("full-wake-history".equals(args[i]) || "full-history".equals(args[i])) { 1021 synchronized (mStats) { 1022 mStats.setRecordAllHistoryLocked(enable); 1023 } 1024 } else if ("no-auto-reset".equals(args[i])) { 1025 synchronized (mStats) { 1026 mStats.setNoAutoReset(enable); 1027 } 1028 } else { 1029 pw.println("Unknown enable/disable option: " + args[i]); 1030 dumpHelp(pw); 1031 return -1; 1032 } 1033 return i; 1034 } 1035 1036 1037 @Override 1038 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1039 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1040 != PackageManager.PERMISSION_GRANTED) { 1041 pw.println("Permission Denial: can't dump BatteryStats from from pid=" 1042 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 1043 + " without permission " + android.Manifest.permission.DUMP); 1044 return; 1045 } 1046 1047 int flags = 0; 1048 boolean useCheckinFormat = false; 1049 boolean isRealCheckin = false; 1050 boolean noOutput = false; 1051 boolean writeData = false; 1052 long historyStart = -1; 1053 int reqUid = -1; 1054 if (args != null) { 1055 for (int i=0; i<args.length; i++) { 1056 String arg = args[i]; 1057 if ("--checkin".equals(arg)) { 1058 useCheckinFormat = true; 1059 isRealCheckin = true; 1060 } else if ("--history".equals(arg)) { 1061 flags |= BatteryStats.DUMP_HISTORY_ONLY; 1062 } else if ("--history-start".equals(arg)) { 1063 flags |= BatteryStats.DUMP_HISTORY_ONLY; 1064 i++; 1065 if (i >= args.length) { 1066 pw.println("Missing time argument for --history-since"); 1067 dumpHelp(pw); 1068 return; 1069 } 1070 historyStart = Long.parseLong(args[i]); 1071 writeData = true; 1072 } else if ("-c".equals(arg)) { 1073 useCheckinFormat = true; 1074 flags |= BatteryStats.DUMP_INCLUDE_HISTORY; 1075 } else if ("--charged".equals(arg)) { 1076 flags |= BatteryStats.DUMP_CHARGED_ONLY; 1077 } else if ("--daily".equals(arg)) { 1078 flags |= BatteryStats.DUMP_DAILY_ONLY; 1079 } else if ("--reset".equals(arg)) { 1080 synchronized (mStats) { 1081 mStats.resetAllStatsCmdLocked(); 1082 pw.println("Battery stats reset."); 1083 noOutput = true; 1084 } 1085 updateExternalStats("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL); 1086 } else if ("--write".equals(arg)) { 1087 updateExternalStats("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL); 1088 synchronized (mStats) { 1089 mStats.writeSyncLocked(); 1090 pw.println("Battery stats written."); 1091 noOutput = true; 1092 } 1093 } else if ("--new-daily".equals(arg)) { 1094 synchronized (mStats) { 1095 mStats.recordDailyStatsLocked(); 1096 pw.println("New daily stats written."); 1097 noOutput = true; 1098 } 1099 } else if ("--read-daily".equals(arg)) { 1100 synchronized (mStats) { 1101 mStats.readDailyStatsLocked(); 1102 pw.println("Last daily stats read."); 1103 noOutput = true; 1104 } 1105 } else if ("--enable".equals(arg) || "enable".equals(arg)) { 1106 i = doEnableOrDisable(pw, i, args, true); 1107 if (i < 0) { 1108 return; 1109 } 1110 pw.println("Enabled: " + args[i]); 1111 return; 1112 } else if ("--disable".equals(arg) || "disable".equals(arg)) { 1113 i = doEnableOrDisable(pw, i, args, false); 1114 if (i < 0) { 1115 return; 1116 } 1117 pw.println("Disabled: " + args[i]); 1118 return; 1119 } else if ("-h".equals(arg)) { 1120 dumpHelp(pw); 1121 return; 1122 } else if ("-a".equals(arg)) { 1123 flags |= BatteryStats.DUMP_VERBOSE; 1124 } else if (arg.length() > 0 && arg.charAt(0) == '-'){ 1125 pw.println("Unknown option: " + arg); 1126 dumpHelp(pw); 1127 return; 1128 } else { 1129 // Not an option, last argument must be a package name. 1130 try { 1131 reqUid = mContext.getPackageManager().getPackageUidAsUser(arg, 1132 UserHandle.getCallingUserId()); 1133 } catch (PackageManager.NameNotFoundException e) { 1134 pw.println("Unknown package: " + arg); 1135 dumpHelp(pw); 1136 return; 1137 } 1138 } 1139 } 1140 } 1141 if (noOutput) { 1142 return; 1143 } 1144 1145 long ident = Binder.clearCallingIdentity(); 1146 try { 1147 if (BatteryStatsHelper.checkWifiOnly(mContext)) { 1148 flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY; 1149 } 1150 // Fetch data from external sources and update the BatteryStatsImpl object with them. 1151 updateExternalStats("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL); 1152 } finally { 1153 Binder.restoreCallingIdentity(ident); 1154 } 1155 1156 if (reqUid >= 0) { 1157 // By default, if the caller is only interested in a specific package, then 1158 // we only dump the aggregated data since charged. 1159 if ((flags&(BatteryStats.DUMP_HISTORY_ONLY|BatteryStats.DUMP_CHARGED_ONLY)) == 0) { 1160 flags |= BatteryStats.DUMP_CHARGED_ONLY; 1161 // Also if they are doing -c, we don't want history. 1162 flags &= ~BatteryStats.DUMP_INCLUDE_HISTORY; 1163 } 1164 } 1165 1166 if (useCheckinFormat) { 1167 List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0); 1168 if (isRealCheckin) { 1169 // For a real checkin, first we want to prefer to use the last complete checkin 1170 // file if there is one. 1171 synchronized (mStats.mCheckinFile) { 1172 if (mStats.mCheckinFile.exists()) { 1173 try { 1174 byte[] raw = mStats.mCheckinFile.readFully(); 1175 if (raw != null) { 1176 Parcel in = Parcel.obtain(); 1177 in.unmarshall(raw, 0, raw.length); 1178 in.setDataPosition(0); 1179 BatteryStatsImpl checkinStats = new BatteryStatsImpl( 1180 null, mStats.mHandler, null); 1181 checkinStats.readSummaryFromParcel(in); 1182 in.recycle(); 1183 checkinStats.dumpCheckinLocked(mContext, pw, apps, flags, 1184 historyStart); 1185 mStats.mCheckinFile.delete(); 1186 return; 1187 } 1188 } catch (IOException | ParcelFormatException e) { 1189 Slog.w(TAG, "Failure reading checkin file " 1190 + mStats.mCheckinFile.getBaseFile(), e); 1191 } 1192 } 1193 } 1194 } 1195 synchronized (mStats) { 1196 mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart); 1197 if (writeData) { 1198 mStats.writeAsyncLocked(); 1199 } 1200 } 1201 } else { 1202 synchronized (mStats) { 1203 mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart); 1204 if (writeData) { 1205 mStats.writeAsyncLocked(); 1206 } 1207 } 1208 } 1209 } 1210 1211 // Objects for extracting data from external sources. 1212 private final Object mExternalStatsLock = new Object(); 1213 1214 @GuardedBy("mExternalStatsLock") 1215 private IWifiManager mWifiManager; 1216 1217 // WiFi keeps an accumulated total of stats, unlike Bluetooth. 1218 // Keep the last WiFi stats so we can compute a delta. 1219 @GuardedBy("mExternalStatsLock") 1220 private WifiActivityEnergyInfo mLastInfo = new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0); 1221 1222 @GuardedBy("mExternalStatsLock") 1223 private WifiActivityEnergyInfo pullWifiEnergyInfoLocked() { 1224 if (mWifiManager == null) { 1225 mWifiManager = IWifiManager.Stub.asInterface( 1226 ServiceManager.getService(Context.WIFI_SERVICE)); 1227 if (mWifiManager == null) { 1228 return null; 1229 } 1230 } 1231 1232 try { 1233 // We read the data even if we are not on battery. This is so that we keep the 1234 // correct delta from when we should start reading (aka when we are on battery). 1235 WifiActivityEnergyInfo info = mWifiManager.reportActivityInfo(); 1236 if (info != null && info.isValid()) { 1237 if (info.mControllerEnergyUsed < 0 || info.mControllerIdleTimeMs < 0 || 1238 info.mControllerRxTimeMs < 0 || info.mControllerTxTimeMs < 0) { 1239 Slog.wtf(TAG, "Reported WiFi energy data is invalid: " + info); 1240 return null; 1241 } 1242 1243 final long timePeriodMs = info.mTimestamp - mLastInfo.mTimestamp; 1244 final long lastIdleMs = mLastInfo.mControllerIdleTimeMs; 1245 final long lastTxMs = mLastInfo.mControllerTxTimeMs; 1246 final long lastRxMs = mLastInfo.mControllerRxTimeMs; 1247 final long lastEnergy = mLastInfo.mControllerEnergyUsed; 1248 1249 // We will modify the last info object to be the delta, and store the new 1250 // WifiActivityEnergyInfo object as our last one. 1251 final WifiActivityEnergyInfo result = mLastInfo; 1252 result.mTimestamp = info.getTimeStamp(); 1253 result.mStackState = info.getStackState(); 1254 1255 // These times seem to be the most reliable. 1256 result.mControllerTxTimeMs = info.mControllerTxTimeMs - lastTxMs; 1257 result.mControllerRxTimeMs = info.mControllerRxTimeMs - lastRxMs; 1258 1259 // WiFi calculates the idle time as a difference from the on time and the various 1260 // Rx + Tx times. There seems to be some missing time there because this sometimes 1261 // becomes negative. Just cap it at 0 and move on. 1262 // b/21613534 1263 result.mControllerIdleTimeMs = Math.max(0, info.mControllerIdleTimeMs - lastIdleMs); 1264 result.mControllerEnergyUsed = 1265 Math.max(0, info.mControllerEnergyUsed - lastEnergy); 1266 1267 if (result.mControllerTxTimeMs < 0 || 1268 result.mControllerRxTimeMs < 0) { 1269 // The stats were reset by the WiFi system (which is why our delta is negative). 1270 // Returns the unaltered stats. 1271 result.mControllerEnergyUsed = info.mControllerEnergyUsed; 1272 result.mControllerRxTimeMs = info.mControllerRxTimeMs; 1273 result.mControllerTxTimeMs = info.mControllerTxTimeMs; 1274 result.mControllerIdleTimeMs = info.mControllerIdleTimeMs; 1275 1276 Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + result); 1277 } 1278 1279 // There is some accuracy error in reports so allow some slop in the results. 1280 final long SAMPLE_ERROR_MILLIS = 750; 1281 final long totalTimeMs = result.mControllerIdleTimeMs + result.mControllerRxTimeMs + 1282 result.mControllerTxTimeMs; 1283 if (totalTimeMs > timePeriodMs + SAMPLE_ERROR_MILLIS) { 1284 StringBuilder sb = new StringBuilder(); 1285 sb.append("Total time "); 1286 TimeUtils.formatDuration(totalTimeMs, sb); 1287 sb.append(" is longer than sample period "); 1288 TimeUtils.formatDuration(timePeriodMs, sb); 1289 sb.append(".\n"); 1290 sb.append("Previous WiFi snapshot: ").append("idle="); 1291 TimeUtils.formatDuration(lastIdleMs, sb); 1292 sb.append(" rx="); 1293 TimeUtils.formatDuration(lastRxMs, sb); 1294 sb.append(" tx="); 1295 TimeUtils.formatDuration(lastTxMs, sb); 1296 sb.append(" e=").append(lastEnergy); 1297 sb.append("\n"); 1298 sb.append("Current WiFi snapshot: ").append("idle="); 1299 TimeUtils.formatDuration(info.mControllerIdleTimeMs, sb); 1300 sb.append(" rx="); 1301 TimeUtils.formatDuration(info.mControllerRxTimeMs, sb); 1302 sb.append(" tx="); 1303 TimeUtils.formatDuration(info.mControllerTxTimeMs, sb); 1304 sb.append(" e=").append(info.mControllerEnergyUsed); 1305 Slog.wtf(TAG, sb.toString()); 1306 } 1307 1308 mLastInfo = info; 1309 return result; 1310 } 1311 } catch (RemoteException e) { 1312 // Nothing to report, WiFi is dead. 1313 } 1314 return null; 1315 } 1316 1317 @GuardedBy("mExternalStatsLock") 1318 private BluetoothActivityEnergyInfo pullBluetoothEnergyInfoLocked() { 1319 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 1320 if (adapter != null) { 1321 BluetoothActivityEnergyInfo info = adapter.getControllerActivityEnergyInfo( 1322 BluetoothAdapter.ACTIVITY_ENERGY_INFO_REFRESHED); 1323 if (info != null && info.isValid()) { 1324 if (info.getControllerEnergyUsed() < 0 || info.getControllerIdleTimeMillis() < 0 || 1325 info.getControllerRxTimeMillis() < 0 || info.getControllerTxTimeMillis() < 0) { 1326 Slog.wtf(TAG, "Bluetooth energy data is invalid: " + info); 1327 } 1328 return info; 1329 } 1330 } 1331 return null; 1332 } 1333 1334 @GuardedBy("mExternalStatsLock") 1335 private ModemActivityInfo pullModemActivityInfoLocked() { 1336 ITelephony tm = ITelephony.Stub.asInterface(ServiceManager.getService( 1337 Context.TELEPHONY_SERVICE)); 1338 try { 1339 if (tm != null) { 1340 ModemActivityInfo info = tm.getModemActivityInfo(); 1341 if (info == null || info.isValid()) { 1342 return info; 1343 } 1344 Slog.wtf(TAG, "Modem activity info is invalid: " + info); 1345 } 1346 } catch (RemoteException e) { 1347 // Nothing to do. 1348 } 1349 return null; 1350 } 1351 1352 /** 1353 * Fetches data from external sources (WiFi controller, bluetooth chipset) and updates 1354 * batterystats with that information. 1355 * 1356 * We first grab a lock specific to this method, then once all the data has been collected, 1357 * we grab the mStats lock and update the data. 1358 * 1359 * @param reason The reason why this collection was requested. Useful for debugging. 1360 * @param updateFlags Which external stats to update. Can be a combination of 1361 * {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_CPU}, 1362 * {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_RADIO}, 1363 * {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_WIFI}, 1364 * and {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_BT}. 1365 */ 1366 void updateExternalStats(final String reason, final int updateFlags) { 1367 synchronized (mExternalStatsLock) { 1368 if (mContext == null) { 1369 // We haven't started yet (which means the BatteryStatsImpl object has 1370 // no power profile. Don't consume data we can't compute yet. 1371 return; 1372 } 1373 1374 if (BatteryStatsImpl.DEBUG_ENERGY) { 1375 Slog.d(TAG, "Updating external stats: reason=" + reason); 1376 } 1377 1378 WifiActivityEnergyInfo wifiEnergyInfo = null; 1379 if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) { 1380 wifiEnergyInfo = pullWifiEnergyInfoLocked(); 1381 } 1382 1383 ModemActivityInfo modemActivityInfo = null; 1384 if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO) != 0) { 1385 modemActivityInfo = pullModemActivityInfoLocked(); 1386 } 1387 1388 BluetoothActivityEnergyInfo bluetoothEnergyInfo = null; 1389 if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_BT) != 0) { 1390 // We only pull bluetooth stats when we have to, as we are not distributing its 1391 // use amongst apps and the sampling frequency does not matter. 1392 bluetoothEnergyInfo = pullBluetoothEnergyInfoLocked(); 1393 } 1394 1395 synchronized (mStats) { 1396 final long elapsedRealtime = SystemClock.elapsedRealtime(); 1397 final long uptime = SystemClock.uptimeMillis(); 1398 if (mStats.mRecordAllHistory) { 1399 mStats.addHistoryEventLocked(elapsedRealtime, uptime, 1400 BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS, reason, 0); 1401 } 1402 1403 if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU) != 0) { 1404 mStats.updateCpuTimeLocked(); 1405 mStats.updateKernelWakelocksLocked(); 1406 } 1407 1408 if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO) != 0) { 1409 mStats.updateMobileRadioStateLocked(elapsedRealtime, modemActivityInfo); 1410 } 1411 1412 if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) { 1413 mStats.updateWifiStateLocked(wifiEnergyInfo); 1414 } 1415 1416 if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_BT) != 0) { 1417 mStats.updateBluetoothStateLocked(bluetoothEnergyInfo); 1418 } 1419 } 1420 } 1421 } 1422} 1423