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 95 private native void getLowPowerStats(RpmStats rpmStats); 96 private native int getPlatformLowPowerStats(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 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 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 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 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 185 public void publish() { 186 LocalServices.addService(BatteryStatsInternal.class, new LocalService()); 187 ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder()); 188 } 189 190 public void systemServicesReady() { 191 mStats.systemServicesReady(mContext); 192 } 193 194 private final class LocalService extends BatteryStatsInternal { 195 @Override 196 public String[] getWifiIfaces() { 197 return mStats.getWifiIfaces().clone(); 198 } 199 200 @Override 201 public String[] getMobileIfaces() { 202 return mStats.getMobileIfaces().clone(); 203 } 204 205 @Override 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 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 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 */ 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 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 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 267 public int getServiceType() { 268 return ServiceType.BATTERY_STATS; 269 } 270 271 @Override 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 */ 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 */ 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 */ 300 void removeUid(int uid) { 301 synchronized (mStats) { 302 mStats.removeUidStatsLocked(uid); 303 } 304 } 305 306 void onCleanupUser(int userId) { 307 synchronized (mStats) { 308 mStats.onCleanupUserLocked(userId); 309 } 310 } 311 312 void onUserRemoved(int userId) { 313 synchronized (mStats) { 314 mStats.onUserRemovedLocked(userId); 315 } 316 } 317 318 void addIsolatedUid(int isolatedUid, int appUid) { 319 synchronized (mStats) { 320 mStats.addIsolatedUidLocked(isolatedUid, appUid); 321 } 322 } 323 324 void removeIsolatedUid(int isolatedUid, int appUid) { 325 synchronized (mStats) { 326 mStats.scheduleRemoveIsolatedUidLocked(isolatedUid, appUid); 327 } 328 } 329 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 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 346 void noteProcessAnr(String name, int uid) { 347 synchronized (mStats) { 348 mStats.noteProcessAnrLocked(name, uid); 349 } 350 } 351 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. */ 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 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 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 407 public boolean isCharging() { 408 synchronized (mStats) { 409 return mStats.isCharging(); 410 } 411 } 412 413 public long computeBatteryTimeRemaining() { 414 synchronized (mStats) { 415 long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime()); 416 return time >= 0 ? (time/1000) : time; 417 } 418 } 419 420 public long computeChargeTimeRemaining() { 421 synchronized (mStats) { 422 long time = mStats.computeChargeTimeRemaining(SystemClock.elapsedRealtime()); 423 return time >= 0 ? (time/1000) : time; 424 } 425 } 426 427 public void noteEvent(int code, String name, int uid) { 428 enforceCallingPermission(); 429 synchronized (mStats) { 430 mStats.noteEventLocked(code, name, uid); 431 } 432 } 433 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 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 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 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 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 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 486 public void noteAlarmStart(String name, WorkSource workSource, int uid) { 487 enforceCallingPermission(); 488 synchronized (mStats) { 489 mStats.noteAlarmStartLocked(name, workSource, uid); 490 } 491 } 492 493 public void noteAlarmFinish(String name, WorkSource workSource, int uid) { 494 enforceCallingPermission(); 495 synchronized (mStats) { 496 mStats.noteAlarmFinishLocked(name, workSource, uid); 497 } 498 } 499 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 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 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 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 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 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 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 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 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 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 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 597 public void noteVibratorOn(int uid, long durationMillis) { 598 enforceCallingPermission(); 599 synchronized (mStats) { 600 mStats.noteVibratorOnLocked(uid, durationMillis); 601 } 602 } 603 604 public void noteVibratorOff(int uid) { 605 enforceCallingPermission(); 606 synchronized (mStats) { 607 mStats.noteVibratorOffLocked(uid); 608 } 609 } 610 611 @Override 612 public void noteGpsChanged(WorkSource oldWs, WorkSource newWs) { 613 enforceCallingPermission(); 614 synchronized (mStats) { 615 mStats.noteGpsChangedLocked(oldWs, newWs); 616 } 617 } 618 619 public void noteGpsSignalQuality(int signalLevel) { 620 synchronized (mStats) { 621 mStats.noteGpsSignalQualityLocked(signalLevel); 622 } 623 } 624 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 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 644 public void noteUserActivity(int uid, int event) { 645 enforceCallingPermission(); 646 synchronized (mStats) { 647 mStats.noteUserActivityLocked(uid, event); 648 } 649 } 650 651 public void noteWakeUp(String reason, int reasonUid) { 652 enforceCallingPermission(); 653 synchronized (mStats) { 654 mStats.noteWakeUpLocked(reason, reasonUid); 655 } 656 } 657 658 public void noteInteractive(boolean interactive) { 659 enforceCallingPermission(); 660 synchronized (mStats) { 661 mStats.noteInteractiveLocked(interactive); 662 } 663 } 664 665 public void noteConnectivityChanged(int type, String extra) { 666 enforceCallingPermission(); 667 synchronized (mStats) { 668 mStats.noteConnectivityChangedLocked(type, extra); 669 } 670 } 671 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 684 public void notePhoneOn() { 685 enforceCallingPermission(); 686 synchronized (mStats) { 687 mStats.notePhoneOnLocked(); 688 } 689 } 690 691 public void notePhoneOff() { 692 enforceCallingPermission(); 693 synchronized (mStats) { 694 mStats.notePhoneOffLocked(); 695 } 696 } 697 698 public void notePhoneSignalStrength(SignalStrength signalStrength) { 699 enforceCallingPermission(); 700 synchronized (mStats) { 701 mStats.notePhoneSignalStrengthLocked(signalStrength); 702 } 703 } 704 705 public void notePhoneDataConnectionState(int dataType, boolean hasData) { 706 enforceCallingPermission(); 707 synchronized (mStats) { 708 mStats.notePhoneDataConnectionStateLocked(dataType, hasData); 709 } 710 } 711 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 720 public void noteWifiOn() { 721 enforceCallingPermission(); 722 synchronized (mStats) { 723 mStats.noteWifiOnLocked(); 724 } 725 } 726 727 public void noteWifiOff() { 728 enforceCallingPermission(); 729 synchronized (mStats) { 730 mStats.noteWifiOffLocked(); 731 } 732 } 733 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 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 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 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 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 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 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 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 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 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 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 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 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 861 public void noteWifiRunning(WorkSource ws) { 862 enforceCallingPermission(); 863 synchronized (mStats) { 864 mStats.noteWifiRunningLocked(ws); 865 } 866 } 867 868 public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) { 869 enforceCallingPermission(); 870 synchronized (mStats) { 871 mStats.noteWifiRunningChangedLocked(oldWs, newWs); 872 } 873 } 874 875 public void noteWifiStopped(WorkSource ws) { 876 enforceCallingPermission(); 877 synchronized (mStats) { 878 mStats.noteWifiStoppedLocked(ws); 879 } 880 } 881 882 public void noteWifiState(int wifiState, String accessPoint) { 883 enforceCallingPermission(); 884 synchronized (mStats) { 885 mStats.noteWifiStateLocked(wifiState, accessPoint); 886 } 887 } 888 889 public void noteWifiSupplicantStateChanged(int supplState, boolean failedAuth) { 890 enforceCallingPermission(); 891 synchronized (mStats) { 892 mStats.noteWifiSupplicantStateChangedLocked(supplState, failedAuth); 893 } 894 } 895 896 public void noteWifiRssiChanged(int newRssi) { 897 enforceCallingPermission(); 898 synchronized (mStats) { 899 mStats.noteWifiRssiChangedLocked(newRssi); 900 } 901 } 902 903 public void noteFullWifiLockAcquired(int uid) { 904 enforceCallingPermission(); 905 synchronized (mStats) { 906 mStats.noteFullWifiLockAcquiredLocked(uid); 907 } 908 } 909 910 public void noteFullWifiLockReleased(int uid) { 911 enforceCallingPermission(); 912 synchronized (mStats) { 913 mStats.noteFullWifiLockReleasedLocked(uid); 914 } 915 } 916 917 public void noteWifiScanStarted(int uid) { 918 enforceCallingPermission(); 919 synchronized (mStats) { 920 mStats.noteWifiScanStartedLocked(uid); 921 } 922 } 923 924 public void noteWifiScanStopped(int uid) { 925 enforceCallingPermission(); 926 synchronized (mStats) { 927 mStats.noteWifiScanStoppedLocked(uid); 928 } 929 } 930 931 public void noteWifiMulticastEnabled(int uid) { 932 enforceCallingPermission(); 933 synchronized (mStats) { 934 mStats.noteWifiMulticastEnabledLocked(uid); 935 } 936 } 937 938 public void noteWifiMulticastDisabled(int uid) { 939 enforceCallingPermission(); 940 synchronized (mStats) { 941 mStats.noteWifiMulticastDisabledLocked(uid); 942 } 943 } 944 945 public void noteFullWifiLockAcquiredFromSource(WorkSource ws) { 946 enforceCallingPermission(); 947 synchronized (mStats) { 948 mStats.noteFullWifiLockAcquiredFromSourceLocked(ws); 949 } 950 } 951 952 public void noteFullWifiLockReleasedFromSource(WorkSource ws) { 953 enforceCallingPermission(); 954 synchronized (mStats) { 955 mStats.noteFullWifiLockReleasedFromSourceLocked(ws); 956 } 957 } 958 959 public void noteWifiScanStartedFromSource(WorkSource ws) { 960 enforceCallingPermission(); 961 synchronized (mStats) { 962 mStats.noteWifiScanStartedFromSourceLocked(ws); 963 } 964 } 965 966 public void noteWifiScanStoppedFromSource(WorkSource ws) { 967 enforceCallingPermission(); 968 synchronized (mStats) { 969 mStats.noteWifiScanStoppedFromSourceLocked(ws); 970 } 971 } 972 973 public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) { 974 enforceCallingPermission(); 975 synchronized (mStats) { 976 mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph); 977 } 978 } 979 980 public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) { 981 enforceCallingPermission(); 982 synchronized (mStats) { 983 mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws); 984 } 985 } 986 987 @Override 988 public void noteNetworkInterfaceType(String iface, int networkType) { 989 enforceCallingPermission(); 990 synchronized (mStats) { 991 mStats.noteNetworkInterfaceTypeLocked(iface, networkType); 992 } 993 } 994 995 @Override 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 1006 public void noteDeviceIdleMode(int mode, String activeReason, int activeUid) { 1007 enforceCallingPermission(); 1008 synchronized (mStats) { 1009 mStats.noteDeviceIdleModeLocked(mode, activeReason, activeUid); 1010 } 1011 } 1012 1013 public void notePackageInstalled(String pkgName, long versionCode) { 1014 enforceCallingPermission(); 1015 synchronized (mStats) { 1016 mStats.notePackageInstalledLocked(pkgName, versionCode); 1017 } 1018 } 1019 1020 public void notePackageUninstalled(String pkgName) { 1021 enforceCallingPermission(); 1022 synchronized (mStats) { 1023 mStats.notePackageUninstalledLocked(pkgName); 1024 } 1025 } 1026 1027 @Override 1028 public void noteBleScanStarted(WorkSource ws, boolean isUnoptimized) { 1029 enforceCallingPermission(); 1030 synchronized (mStats) { 1031 mStats.noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized); 1032 } 1033 } 1034 1035 @Override 1036 public void noteBleScanStopped(WorkSource ws, boolean isUnoptimized) { 1037 enforceCallingPermission(); 1038 synchronized (mStats) { 1039 mStats.noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized); 1040 } 1041 } 1042 1043 @Override 1044 public void noteResetBleScan() { 1045 enforceCallingPermission(); 1046 synchronized (mStats) { 1047 mStats.noteResetBluetoothScanLocked(); 1048 } 1049 } 1050 1051 @Override 1052 public void noteBleScanResults(WorkSource ws, int numNewResults) { 1053 enforceCallingPermission(); 1054 synchronized (mStats) { 1055 mStats.noteBluetoothScanResultsFromSourceLocked(ws, numNewResults); 1056 } 1057 } 1058 1059 @Override 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 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 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 1096 public boolean isOnBattery() { 1097 return mStats.isOnBattery(); 1098 } 1099 1100 @Override 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 1134 public long getAwakeTimeBattery() { 1135 mContext.enforceCallingOrSelfPermission( 1136 android.Manifest.permission.BATTERY_STATS, null); 1137 return mStats.getAwakeTimeBattery(); 1138 } 1139 1140 public long getAwakeTimePlugged() { 1141 mContext.enforceCallingOrSelfPermission( 1142 android.Manifest.permission.BATTERY_STATS, null); 1143 return mStats.getAwakeTimePlugged(); 1144 } 1145 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 1160 WakeupReasonThread() { 1161 super("BatteryStats_wakeupReason"); 1162 } 1163 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 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 1213 private static native int nativeWaitWakeup(ByteBuffer outBuffer); 1214 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 1245 private void dumpSettings(PrintWriter pw) { 1246 synchronized (mStats) { 1247 mStats.dumpConstantsLocked(pw); 1248 } 1249 } 1250 1251 private void dumpCpuStats(PrintWriter pw) { 1252 synchronized (mStats) { 1253 mStats.dumpCpuStatsLocked(pw); 1254 } 1255 } 1256 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 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 */ 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 */ 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 */ 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 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 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 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 */ 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 */ 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