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