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