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 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 */ initPowerManagement()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 shutdown()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 getService()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 onLowPowerModeChanged(boolean enabled)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 */ getActiveStatistics()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 */ scheduleWriteToDisk()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 */ removeUid(int uid)240 void removeUid(int uid) { 241 synchronized (mStats) { 242 mStats.removeUidStatsLocked(uid); 243 } 244 } 245 addIsolatedUid(int isolatedUid, int appUid)246 void addIsolatedUid(int isolatedUid, int appUid) { 247 synchronized (mStats) { 248 mStats.addIsolatedUidLocked(isolatedUid, appUid); 249 } 250 } 251 removeIsolatedUid(int isolatedUid, int appUid)252 void removeIsolatedUid(int isolatedUid, int appUid) { 253 synchronized (mStats) { 254 mStats.scheduleRemoveIsolatedUidLocked(isolatedUid, appUid); 255 } 256 } 257 noteProcessStart(String name, int uid)258 void noteProcessStart(String name, int uid) { 259 synchronized (mStats) { 260 mStats.noteProcessStartLocked(name, uid); 261 } 262 } 263 noteProcessCrash(String name, int uid)264 void noteProcessCrash(String name, int uid) { 265 synchronized (mStats) { 266 mStats.noteProcessCrashLocked(name, uid); 267 } 268 } 269 noteProcessAnr(String name, int uid)270 void noteProcessAnr(String name, int uid) { 271 synchronized (mStats) { 272 mStats.noteProcessAnrLocked(name, uid); 273 } 274 } 275 noteProcessState(String name, int uid, int state)276 void noteProcessState(String name, int uid, int state) { 277 synchronized (mStats) { 278 mStats.noteProcessStateLocked(name, uid, state); 279 } 280 } 281 noteProcessFinish(String name, int uid)282 void noteProcessFinish(String name, int uid) { 283 synchronized (mStats) { 284 mStats.noteProcessFinishLocked(name, uid); 285 } 286 } 287 288 // Public interface... 289 getStatistics()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 getStatisticsStream()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 isCharging()325 public boolean isCharging() { 326 synchronized (mStats) { 327 return mStats.isCharging(); 328 } 329 } 330 computeBatteryTimeRemaining()331 public long computeBatteryTimeRemaining() { 332 synchronized (mStats) { 333 long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime()); 334 return time >= 0 ? (time/1000) : time; 335 } 336 } 337 computeChargeTimeRemaining()338 public long computeChargeTimeRemaining() { 339 synchronized (mStats) { 340 long time = mStats.computeChargeTimeRemaining(SystemClock.elapsedRealtime()); 341 return time >= 0 ? (time/1000) : time; 342 } 343 } 344 noteEvent(int code, String name, int uid)345 public void noteEvent(int code, String name, int uid) { 346 enforceCallingPermission(); 347 synchronized (mStats) { 348 mStats.noteEventLocked(code, name, uid); 349 } 350 } 351 noteSyncStart(String name, int uid)352 public void noteSyncStart(String name, int uid) { 353 enforceCallingPermission(); 354 synchronized (mStats) { 355 mStats.noteSyncStartLocked(name, uid); 356 } 357 } 358 noteSyncFinish(String name, int uid)359 public void noteSyncFinish(String name, int uid) { 360 enforceCallingPermission(); 361 synchronized (mStats) { 362 mStats.noteSyncFinishLocked(name, uid); 363 } 364 } 365 noteJobStart(String name, int uid)366 public void noteJobStart(String name, int uid) { 367 enforceCallingPermission(); 368 synchronized (mStats) { 369 mStats.noteJobStartLocked(name, uid); 370 } 371 } 372 noteJobFinish(String name, int uid)373 public void noteJobFinish(String name, int uid) { 374 enforceCallingPermission(); 375 synchronized (mStats) { 376 mStats.noteJobFinishLocked(name, uid); 377 } 378 } 379 noteAlarmStart(String name, int uid)380 public void noteAlarmStart(String name, int uid) { 381 enforceCallingPermission(); 382 synchronized (mStats) { 383 mStats.noteAlarmStartLocked(name, uid); 384 } 385 } 386 noteAlarmFinish(String name, int uid)387 public void noteAlarmFinish(String name, int uid) { 388 enforceCallingPermission(); 389 synchronized (mStats) { 390 mStats.noteAlarmFinishLocked(name, uid); 391 } 392 } 393 noteStartWakelock(int uid, int pid, String name, String historyName, int type, boolean unimportantForLogging)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 noteStopWakelock(int uid, int pid, String name, String historyName, int type)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 noteStartWakelockFromSource(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging)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 noteChangeWakelockFromSource(WorkSource ws, int pid, String name, String historyName, int type, WorkSource newWs, int newPid, String newName, String newHistoryName, int newType, boolean newUnimportantForLogging)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 noteStopWakelockFromSource(WorkSource ws, int pid, String name, String historyName, int type)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 noteStartSensor(int uid, int sensor)438 public void noteStartSensor(int uid, int sensor) { 439 enforceCallingPermission(); 440 synchronized (mStats) { 441 mStats.noteStartSensorLocked(uid, sensor); 442 } 443 } 444 noteStopSensor(int uid, int sensor)445 public void noteStopSensor(int uid, int sensor) { 446 enforceCallingPermission(); 447 synchronized (mStats) { 448 mStats.noteStopSensorLocked(uid, sensor); 449 } 450 } 451 noteVibratorOn(int uid, long durationMillis)452 public void noteVibratorOn(int uid, long durationMillis) { 453 enforceCallingPermission(); 454 synchronized (mStats) { 455 mStats.noteVibratorOnLocked(uid, durationMillis); 456 } 457 } 458 noteVibratorOff(int uid)459 public void noteVibratorOff(int uid) { 460 enforceCallingPermission(); 461 synchronized (mStats) { 462 mStats.noteVibratorOffLocked(uid); 463 } 464 } 465 noteStartGps(int uid)466 public void noteStartGps(int uid) { 467 enforceCallingPermission(); 468 synchronized (mStats) { 469 mStats.noteStartGpsLocked(uid); 470 } 471 } 472 noteStopGps(int uid)473 public void noteStopGps(int uid) { 474 enforceCallingPermission(); 475 synchronized (mStats) { 476 mStats.noteStopGpsLocked(uid); 477 } 478 } 479 noteScreenState(int state)480 public void noteScreenState(int state) { 481 enforceCallingPermission(); 482 synchronized (mStats) { 483 mStats.noteScreenStateLocked(state); 484 } 485 } 486 noteScreenBrightness(int brightness)487 public void noteScreenBrightness(int brightness) { 488 enforceCallingPermission(); 489 synchronized (mStats) { 490 mStats.noteScreenBrightnessLocked(brightness); 491 } 492 } 493 noteUserActivity(int uid, int event)494 public void noteUserActivity(int uid, int event) { 495 enforceCallingPermission(); 496 synchronized (mStats) { 497 mStats.noteUserActivityLocked(uid, event); 498 } 499 } 500 noteWakeUp(String reason, int reasonUid)501 public void noteWakeUp(String reason, int reasonUid) { 502 enforceCallingPermission(); 503 synchronized (mStats) { 504 mStats.noteWakeUpLocked(reason, reasonUid); 505 } 506 } 507 noteInteractive(boolean interactive)508 public void noteInteractive(boolean interactive) { 509 enforceCallingPermission(); 510 synchronized (mStats) { 511 mStats.noteInteractiveLocked(interactive); 512 } 513 } 514 noteConnectivityChanged(int type, String extra)515 public void noteConnectivityChanged(int type, String extra) { 516 enforceCallingPermission(); 517 synchronized (mStats) { 518 mStats.noteConnectivityChangedLocked(type, extra); 519 } 520 } 521 noteMobileRadioPowerState(int powerState, long timestampNs)522 public void noteMobileRadioPowerState(int powerState, long timestampNs) { 523 enforceCallingPermission(); 524 synchronized (mStats) { 525 mStats.noteMobileRadioPowerState(powerState, timestampNs); 526 } 527 } 528 notePhoneOn()529 public void notePhoneOn() { 530 enforceCallingPermission(); 531 synchronized (mStats) { 532 mStats.notePhoneOnLocked(); 533 } 534 } 535 notePhoneOff()536 public void notePhoneOff() { 537 enforceCallingPermission(); 538 synchronized (mStats) { 539 mStats.notePhoneOffLocked(); 540 } 541 } 542 notePhoneSignalStrength(SignalStrength signalStrength)543 public void notePhoneSignalStrength(SignalStrength signalStrength) { 544 enforceCallingPermission(); 545 synchronized (mStats) { 546 mStats.notePhoneSignalStrengthLocked(signalStrength); 547 } 548 } 549 notePhoneDataConnectionState(int dataType, boolean hasData)550 public void notePhoneDataConnectionState(int dataType, boolean hasData) { 551 enforceCallingPermission(); 552 synchronized (mStats) { 553 mStats.notePhoneDataConnectionStateLocked(dataType, hasData); 554 } 555 } 556 notePhoneState(int state)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 noteWifiOn()565 public void noteWifiOn() { 566 enforceCallingPermission(); 567 synchronized (mStats) { 568 mStats.noteWifiOnLocked(); 569 } 570 } 571 noteWifiOff()572 public void noteWifiOff() { 573 enforceCallingPermission(); 574 synchronized (mStats) { 575 mStats.noteWifiOffLocked(); 576 } 577 } 578 noteStartAudio(int uid)579 public void noteStartAudio(int uid) { 580 enforceCallingPermission(); 581 synchronized (mStats) { 582 mStats.noteAudioOnLocked(uid); 583 } 584 } 585 noteStopAudio(int uid)586 public void noteStopAudio(int uid) { 587 enforceCallingPermission(); 588 synchronized (mStats) { 589 mStats.noteAudioOffLocked(uid); 590 } 591 } 592 noteStartVideo(int uid)593 public void noteStartVideo(int uid) { 594 enforceCallingPermission(); 595 synchronized (mStats) { 596 mStats.noteVideoOnLocked(uid); 597 } 598 } 599 noteStopVideo(int uid)600 public void noteStopVideo(int uid) { 601 enforceCallingPermission(); 602 synchronized (mStats) { 603 mStats.noteVideoOffLocked(uid); 604 } 605 } 606 noteResetAudio()607 public void noteResetAudio() { 608 enforceCallingPermission(); 609 synchronized (mStats) { 610 mStats.noteResetAudioLocked(); 611 } 612 } 613 noteResetVideo()614 public void noteResetVideo() { 615 enforceCallingPermission(); 616 synchronized (mStats) { 617 mStats.noteResetVideoLocked(); 618 } 619 } 620 noteFlashlightOn(int uid)621 public void noteFlashlightOn(int uid) { 622 enforceCallingPermission(); 623 synchronized (mStats) { 624 mStats.noteFlashlightOnLocked(uid); 625 } 626 } 627 noteFlashlightOff(int uid)628 public void noteFlashlightOff(int uid) { 629 enforceCallingPermission(); 630 synchronized (mStats) { 631 mStats.noteFlashlightOffLocked(uid); 632 } 633 } 634 noteStartCamera(int uid)635 public void noteStartCamera(int uid) { 636 enforceCallingPermission(); 637 synchronized (mStats) { 638 mStats.noteCameraOnLocked(uid); 639 } 640 } 641 noteStopCamera(int uid)642 public void noteStopCamera(int uid) { 643 enforceCallingPermission(); 644 synchronized (mStats) { 645 mStats.noteCameraOffLocked(uid); 646 } 647 } 648 noteResetCamera()649 public void noteResetCamera() { 650 enforceCallingPermission(); 651 synchronized (mStats) { 652 mStats.noteResetCameraLocked(); 653 } 654 } 655 noteResetFlashlight()656 public void noteResetFlashlight() { 657 enforceCallingPermission(); 658 synchronized (mStats) { 659 mStats.noteResetFlashlightLocked(); 660 } 661 } 662 663 @Override noteWifiRadioPowerState(int powerState, long tsNanos)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 noteWifiRunning(WorkSource ws)680 public void noteWifiRunning(WorkSource ws) { 681 enforceCallingPermission(); 682 synchronized (mStats) { 683 mStats.noteWifiRunningLocked(ws); 684 } 685 } 686 noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs)687 public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) { 688 enforceCallingPermission(); 689 synchronized (mStats) { 690 mStats.noteWifiRunningChangedLocked(oldWs, newWs); 691 } 692 } 693 noteWifiStopped(WorkSource ws)694 public void noteWifiStopped(WorkSource ws) { 695 enforceCallingPermission(); 696 synchronized (mStats) { 697 mStats.noteWifiStoppedLocked(ws); 698 } 699 } 700 noteWifiState(int wifiState, String accessPoint)701 public void noteWifiState(int wifiState, String accessPoint) { 702 enforceCallingPermission(); 703 synchronized (mStats) { 704 mStats.noteWifiStateLocked(wifiState, accessPoint); 705 } 706 } 707 noteWifiSupplicantStateChanged(int supplState, boolean failedAuth)708 public void noteWifiSupplicantStateChanged(int supplState, boolean failedAuth) { 709 enforceCallingPermission(); 710 synchronized (mStats) { 711 mStats.noteWifiSupplicantStateChangedLocked(supplState, failedAuth); 712 } 713 } 714 noteWifiRssiChanged(int newRssi)715 public void noteWifiRssiChanged(int newRssi) { 716 enforceCallingPermission(); 717 synchronized (mStats) { 718 mStats.noteWifiRssiChangedLocked(newRssi); 719 } 720 } 721 noteFullWifiLockAcquired(int uid)722 public void noteFullWifiLockAcquired(int uid) { 723 enforceCallingPermission(); 724 synchronized (mStats) { 725 mStats.noteFullWifiLockAcquiredLocked(uid); 726 } 727 } 728 noteFullWifiLockReleased(int uid)729 public void noteFullWifiLockReleased(int uid) { 730 enforceCallingPermission(); 731 synchronized (mStats) { 732 mStats.noteFullWifiLockReleasedLocked(uid); 733 } 734 } 735 noteWifiScanStarted(int uid)736 public void noteWifiScanStarted(int uid) { 737 enforceCallingPermission(); 738 synchronized (mStats) { 739 mStats.noteWifiScanStartedLocked(uid); 740 } 741 } 742 noteWifiScanStopped(int uid)743 public void noteWifiScanStopped(int uid) { 744 enforceCallingPermission(); 745 synchronized (mStats) { 746 mStats.noteWifiScanStoppedLocked(uid); 747 } 748 } 749 noteWifiMulticastEnabled(int uid)750 public void noteWifiMulticastEnabled(int uid) { 751 enforceCallingPermission(); 752 synchronized (mStats) { 753 mStats.noteWifiMulticastEnabledLocked(uid); 754 } 755 } 756 noteWifiMulticastDisabled(int uid)757 public void noteWifiMulticastDisabled(int uid) { 758 enforceCallingPermission(); 759 synchronized (mStats) { 760 mStats.noteWifiMulticastDisabledLocked(uid); 761 } 762 } 763 noteFullWifiLockAcquiredFromSource(WorkSource ws)764 public void noteFullWifiLockAcquiredFromSource(WorkSource ws) { 765 enforceCallingPermission(); 766 synchronized (mStats) { 767 mStats.noteFullWifiLockAcquiredFromSourceLocked(ws); 768 } 769 } 770 noteFullWifiLockReleasedFromSource(WorkSource ws)771 public void noteFullWifiLockReleasedFromSource(WorkSource ws) { 772 enforceCallingPermission(); 773 synchronized (mStats) { 774 mStats.noteFullWifiLockReleasedFromSourceLocked(ws); 775 } 776 } 777 noteWifiScanStartedFromSource(WorkSource ws)778 public void noteWifiScanStartedFromSource(WorkSource ws) { 779 enforceCallingPermission(); 780 synchronized (mStats) { 781 mStats.noteWifiScanStartedFromSourceLocked(ws); 782 } 783 } 784 noteWifiScanStoppedFromSource(WorkSource ws)785 public void noteWifiScanStoppedFromSource(WorkSource ws) { 786 enforceCallingPermission(); 787 synchronized (mStats) { 788 mStats.noteWifiScanStoppedFromSourceLocked(ws); 789 } 790 } 791 noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph)792 public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) { 793 enforceCallingPermission(); 794 synchronized (mStats) { 795 mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph); 796 } 797 } 798 noteWifiBatchedScanStoppedFromSource(WorkSource ws)799 public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) { 800 enforceCallingPermission(); 801 synchronized (mStats) { 802 mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws); 803 } 804 } 805 noteWifiMulticastEnabledFromSource(WorkSource ws)806 public void noteWifiMulticastEnabledFromSource(WorkSource ws) { 807 enforceCallingPermission(); 808 synchronized (mStats) { 809 mStats.noteWifiMulticastEnabledFromSourceLocked(ws); 810 } 811 } 812 813 @Override noteWifiMulticastDisabledFromSource(WorkSource ws)814 public void noteWifiMulticastDisabledFromSource(WorkSource ws) { 815 enforceCallingPermission(); 816 synchronized (mStats) { 817 mStats.noteWifiMulticastDisabledFromSourceLocked(ws); 818 } 819 } 820 821 @Override noteNetworkInterfaceType(String iface, int networkType)822 public void noteNetworkInterfaceType(String iface, int networkType) { 823 enforceCallingPermission(); 824 synchronized (mStats) { 825 mStats.noteNetworkInterfaceTypeLocked(iface, networkType); 826 } 827 } 828 829 @Override noteNetworkStatsEnabled()830 public void noteNetworkStatsEnabled() { 831 enforceCallingPermission(); 832 synchronized (mStats) { 833 mStats.noteNetworkStatsEnabledLocked(); 834 } 835 } 836 837 @Override noteDeviceIdleMode(boolean enabled, String activeReason, int activeUid)838 public void noteDeviceIdleMode(boolean enabled, String activeReason, int activeUid) { 839 enforceCallingPermission(); 840 synchronized (mStats) { 841 mStats.noteDeviceIdleModeLocked(enabled, activeReason, activeUid); 842 } 843 } 844 notePackageInstalled(String pkgName, int versionCode)845 public void notePackageInstalled(String pkgName, int versionCode) { 846 enforceCallingPermission(); 847 synchronized (mStats) { 848 mStats.notePackageInstalledLocked(pkgName, versionCode); 849 } 850 } 851 notePackageUninstalled(String pkgName)852 public void notePackageUninstalled(String pkgName) { 853 enforceCallingPermission(); 854 synchronized (mStats) { 855 mStats.notePackageUninstalledLocked(pkgName); 856 } 857 } 858 isOnBattery()859 public boolean isOnBattery() { 860 return mStats.isOnBattery(); 861 } 862 863 @Override setBatteryState(final int status, final int health, final int plugType, final int level, final int temp, final int volt)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 getAwakeTimeBattery()893 public long getAwakeTimeBattery() { 894 mContext.enforceCallingOrSelfPermission( 895 android.Manifest.permission.BATTERY_STATS, null); 896 return mStats.getAwakeTimeBattery(); 897 } 898 getAwakeTimePlugged()899 public long getAwakeTimePlugged() { 900 mContext.enforceCallingOrSelfPermission( 901 android.Manifest.permission.BATTERY_STATS, null); 902 return mStats.getAwakeTimePlugged(); 903 } 904 enforceCallingPermission()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 WakeupReasonThread()919 WakeupReasonThread() { 920 super("BatteryStats_wakeupReason"); 921 } 922 run()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 waitWakeup()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 nativeWaitWakeup(ByteBuffer outBuffer)972 private static native int nativeWaitWakeup(ByteBuffer outBuffer); 973 dumpHelp(PrintWriter pw)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 doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable)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 dump(FileDescriptor fd, PrintWriter pw, String[] args)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") pullWifiEnergyInfoLocked()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") pullBluetoothEnergyInfoLocked()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 */ updateExternalStats(final String reason, final int updateFlags)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