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