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