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