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