2 * Copyright (C) 2006-2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server.am;
19 import android.annotation.Nullable;
20 import android.bluetooth.BluetoothActivityEnergyInfo;
21 import android.bluetooth.BluetoothAdapter;
22 import android.content.Context;
23 import android.content.pm.ApplicationInfo;
24 import android.content.pm.PackageManager;
25 import android.net.wifi.IWifiManager;
26 import android.net.wifi.WifiActivityEnergyInfo;
27 import android.os.BatteryStats;
28 import android.os.Binder;
29 import android.os.Handler;
30 import android.os.IBinder;
31 import android.os.Looper;
32 import android.os.Message;
33 import android.os.Parcel;
34 import android.os.ParcelFileDescriptor;
35 import android.os.ParcelFormatException;
36 import android.os.Parcelable;
37 import android.os.PowerManagerInternal;
38 import android.os.Process;
39 import android.os.RemoteException;
40 import android.os.ServiceManager;
41 import android.os.SynchronousResultReceiver;
42 import android.os.SystemClock;
43 import android.os.UserHandle;
44 import android.os.WorkSource;
45 import android.os.health.HealthStatsParceler;
46 import android.os.health.HealthStatsWriter;
47 import android.os.health.UidHealthStats;
48 import android.telephony.DataConnectionRealTimeInfo;
49 import android.telephony.ModemActivityInfo;
50 import android.telephony.SignalStrength;
51 import android.telephony.TelephonyManager;
52 import android.util.IntArray;
53 import android.util.Slog;
55 import android.util.TimeUtils;
56 import com.android.internal.annotations.GuardedBy;
57 import com.android.internal.app.IBatteryStats;
58 import com.android.internal.os.BatteryStatsHelper;
59 import com.android.internal.os.BatteryStatsImpl;
60 import com.android.internal.os.PowerProfile;
61 import com.android.server.LocalServices;
62 import com.android.server.ServiceThread;
65 import java.io.FileDescriptor;
66 import java.io.IOException;
67 import java.io.PrintWriter;
68 import java.nio.ByteBuffer;
69 import java.nio.CharBuffer;
70 import java.nio.charset.CharsetDecoder;
71 import java.nio.charset.CodingErrorAction;
72 import java.nio.charset.StandardCharsets;
73 import java.util.Arrays;
74 import java.util.List;
75 import java.util.concurrent.TimeoutException;
78 * All information we are collecting about things that can happen that impact
81 public final class BatteryStatsService extends IBatteryStats.Stub
82 implements PowerManagerInternal.LowPowerModeListener,
83 BatteryStatsImpl.PlatformIdleStateCallback {
84 static final String TAG = "BatteryStatsService";
87 * How long to wait on an individual subsystem to return its stats.
89 private static final long EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS = 2000;
91 // There is some accuracy error in wifi reports so allow some slop in the results.
92 private static final long MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS = 750;
94 private static IBatteryStats sService;
96 final BatteryStatsImpl mStats;
97 private final BatteryStatsHandler mHandler;
98 private Context mContext;
99 private IWifiManager mWifiManager;
100 private TelephonyManager mTelephony;
102 // Lock acquired when extracting data from external sources.
103 private final Object mExternalStatsLock = new Object();
105 // WiFi keeps an accumulated total of stats, unlike Bluetooth.
106 // Keep the last WiFi stats so we can compute a delta.
107 @GuardedBy("mExternalStatsLock")
108 private WifiActivityEnergyInfo mLastInfo =
109 new WifiActivityEnergyInfo(0, 0, 0, new long[]{0}, 0, 0, 0);
111 class BatteryStatsHandler extends Handler implements BatteryStatsImpl.ExternalStatsSync {
112 public static final int MSG_SYNC_EXTERNAL_STATS = 1;
113 public static final int MSG_WRITE_TO_DISK = 2;
115 private int mUpdateFlags = 0;
116 private IntArray mUidsToRemove = new IntArray();
118 public BatteryStatsHandler(Looper looper) {
123 public void handleMessage(Message msg) {
125 case MSG_SYNC_EXTERNAL_STATS:
126 final int updateFlags;
127 synchronized (this) {
128 removeMessages(MSG_SYNC_EXTERNAL_STATS);
129 updateFlags = mUpdateFlags;
132 updateExternalStatsSync((String)msg.obj, updateFlags);
134 // other parts of the system could be calling into us
135 // from mStats in order to report of changes. We must grab the mStats
136 // lock before grabbing our own or we'll end up in a deadlock.
137 synchronized (mStats) {
138 synchronized (this) {
139 final int numUidsToRemove = mUidsToRemove.size();
140 for (int i = 0; i < numUidsToRemove; i++) {
141 mStats.removeIsolatedUidLocked(mUidsToRemove.get(i));
144 mUidsToRemove.clear();
148 case MSG_WRITE_TO_DISK:
149 updateExternalStatsSync("write", UPDATE_ALL);
150 synchronized (mStats) {
151 mStats.writeAsyncLocked();
158 public void scheduleSync(String reason, int updateFlags) {
159 synchronized (this) {
160 scheduleSyncLocked(reason, updateFlags);
165 public void scheduleCpuSyncDueToRemovedUid(int uid) {
166 synchronized (this) {
167 scheduleSyncLocked("remove-uid", UPDATE_CPU);
168 mUidsToRemove.add(uid);
172 private void scheduleSyncLocked(String reason, int updateFlags) {
173 if (mUpdateFlags == 0) {
174 sendMessage(Message.obtain(this, MSG_SYNC_EXTERNAL_STATS, reason));
176 mUpdateFlags |= updateFlags;
180 private native int getPlatformLowPowerStats(ByteBuffer outBuffer);
181 private CharsetDecoder mDecoderStat = StandardCharsets.UTF_8
183 .onMalformedInput(CodingErrorAction.REPLACE)
184 .onUnmappableCharacter(CodingErrorAction.REPLACE)
186 private ByteBuffer mUtf8BufferStat = ByteBuffer.allocateDirect(MAX_LOW_POWER_STATS_SIZE);
187 private CharBuffer mUtf16BufferStat = CharBuffer.allocate(MAX_LOW_POWER_STATS_SIZE);
188 private static final int MAX_LOW_POWER_STATS_SIZE = 512;
191 public String getPlatformLowPowerStats() {
192 mUtf8BufferStat.clear();
193 mUtf16BufferStat.clear();
194 mDecoderStat.reset();
195 int bytesWritten = getPlatformLowPowerStats(mUtf8BufferStat);
196 if (bytesWritten < 0) {
198 } else if (bytesWritten == 0) {
201 mUtf8BufferStat.limit(bytesWritten);
202 mDecoderStat.decode(mUtf8BufferStat, mUtf16BufferStat, true);
203 mUtf16BufferStat.flip();
204 return mUtf16BufferStat.toString();
207 BatteryStatsService(File systemDir, Handler handler) {
208 // Our handler here will be accessing the disk, use a different thread than
209 // what the ActivityManagerService gave us (no I/O on that one!).
210 final ServiceThread thread = new ServiceThread("batterystats-sync",
211 Process.THREAD_PRIORITY_DEFAULT, true);
213 mHandler = new BatteryStatsHandler(thread.getLooper());
215 // BatteryStatsImpl expects the ActivityManagerService handler, so pass that one through.
216 mStats = new BatteryStatsImpl(systemDir, handler, mHandler, this);
219 public void publish(Context context) {
221 mStats.setRadioScanningTimeout(mContext.getResources().getInteger(
222 com.android.internal.R.integer.config_radioScanningTimeout)
224 mStats.setPowerProfile(new PowerProfile(context));
225 ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
229 * At the time when the constructor runs, the power manager has not yet been
230 * initialized. So we initialize the low power observer later.
232 public void initPowerManagement() {
233 final PowerManagerInternal powerMgr = LocalServices.getService(PowerManagerInternal.class);
234 powerMgr.registerLowPowerModeObserver(this);
235 mStats.notePowerSaveMode(powerMgr.getLowPowerModeEnabled());
236 (new WakeupReasonThread()).start();
239 public void shutdown() {
240 Slog.w("BatteryStats", "Writing battery stats before shutdown...");
242 updateExternalStatsSync("shutdown", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
243 synchronized (mStats) {
244 mStats.shutdownLocked();
247 // Shutdown the thread we made.
248 mHandler.getLooper().quit();
251 public static IBatteryStats getService() {
252 if (sService != null) {
255 IBinder b = ServiceManager.getService(BatteryStats.SERVICE_NAME);
256 sService = asInterface(b);
261 public void onLowPowerModeChanged(boolean enabled) {
262 synchronized (mStats) {
263 mStats.notePowerSaveMode(enabled);
268 * @return the current statistics object, which may be modified
269 * to reflect events that affect battery usage. You must lock the
270 * stats object before doing anything with it.
272 public BatteryStatsImpl getActiveStatistics() {
277 * Schedules a write to disk to occur. This will cause the BatteryStatsImpl
278 * object to update with the latest info, then write to disk.
280 public void scheduleWriteToDisk() {
281 mHandler.sendEmptyMessage(BatteryStatsHandler.MSG_WRITE_TO_DISK);
284 // These are for direct use by the activity manager...
287 * Remove a UID from the BatteryStats and BatteryStats' external dependencies.
289 void removeUid(int uid) {
290 synchronized (mStats) {
291 mStats.removeUidStatsLocked(uid);
295 void addIsolatedUid(int isolatedUid, int appUid) {
296 synchronized (mStats) {
297 mStats.addIsolatedUidLocked(isolatedUid, appUid);
301 void removeIsolatedUid(int isolatedUid, int appUid) {
302 synchronized (mStats) {
303 mStats.scheduleRemoveIsolatedUidLocked(isolatedUid, appUid);
307 void noteProcessStart(String name, int uid) {
308 synchronized (mStats) {
309 mStats.noteProcessStartLocked(name, uid);
313 void noteProcessCrash(String name, int uid) {
314 synchronized (mStats) {
315 mStats.noteProcessCrashLocked(name, uid);
319 void noteProcessAnr(String name, int uid) {
320 synchronized (mStats) {
321 mStats.noteProcessAnrLocked(name, uid);
325 void noteProcessFinish(String name, int uid) {
326 synchronized (mStats) {
327 mStats.noteProcessFinishLocked(name, uid);
331 void noteUidProcessState(int uid, int state) {
332 synchronized (mStats) {
333 mStats.noteUidProcessStateLocked(uid, state);
337 // Public interface...
339 public byte[] getStatistics() {
340 mContext.enforceCallingPermission(
341 android.Manifest.permission.BATTERY_STATS, null);
342 //Slog.i("foo", "SENDING BATTERY INFO:");
343 //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
344 Parcel out = Parcel.obtain();
345 updateExternalStatsSync("get-stats", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
346 synchronized (mStats) {
347 mStats.writeToParcel(out, 0);
349 byte[] data = out.marshall();
354 public ParcelFileDescriptor getStatisticsStream() {
355 mContext.enforceCallingPermission(
356 android.Manifest.permission.BATTERY_STATS, null);
357 //Slog.i("foo", "SENDING BATTERY INFO:");
358 //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
359 Parcel out = Parcel.obtain();
360 updateExternalStatsSync("get-stats", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
361 synchronized (mStats) {
362 mStats.writeToParcel(out, 0);
364 byte[] data = out.marshall();
367 return ParcelFileDescriptor.fromData(data, "battery-stats");
368 } catch (IOException e) {
369 Slog.w(TAG, "Unable to create shared memory", e);
374 public boolean isCharging() {
375 synchronized (mStats) {
376 return mStats.isCharging();
380 public long computeBatteryTimeRemaining() {
381 synchronized (mStats) {
382 long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
383 return time >= 0 ? (time/1000) : time;
387 public long computeChargeTimeRemaining() {
388 synchronized (mStats) {
389 long time = mStats.computeChargeTimeRemaining(SystemClock.elapsedRealtime());
390 return time >= 0 ? (time/1000) : time;
394 public void noteEvent(int code, String name, int uid) {
395 enforceCallingPermission();
396 synchronized (mStats) {
397 mStats.noteEventLocked(code, name, uid);
401 public void noteSyncStart(String name, int uid) {
402 enforceCallingPermission();
403 synchronized (mStats) {
404 mStats.noteSyncStartLocked(name, uid);
408 public void noteSyncFinish(String name, int uid) {
409 enforceCallingPermission();
410 synchronized (mStats) {
411 mStats.noteSyncFinishLocked(name, uid);
415 public void noteJobStart(String name, int uid) {
416 enforceCallingPermission();
417 synchronized (mStats) {
418 mStats.noteJobStartLocked(name, uid);
422 public void noteJobFinish(String name, int uid) {
423 enforceCallingPermission();
424 synchronized (mStats) {
425 mStats.noteJobFinishLocked(name, uid);
429 public void noteAlarmStart(String name, int uid) {
430 enforceCallingPermission();
431 synchronized (mStats) {
432 mStats.noteAlarmStartLocked(name, uid);
436 public void noteAlarmFinish(String name, int uid) {
437 enforceCallingPermission();
438 synchronized (mStats) {
439 mStats.noteAlarmFinishLocked(name, uid);
443 public void noteStartWakelock(int uid, int pid, String name, String historyName, int type,
444 boolean unimportantForLogging) {
445 enforceCallingPermission();
446 synchronized (mStats) {
447 mStats.noteStartWakeLocked(uid, pid, name, historyName, type, unimportantForLogging,
448 SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
452 public void noteStopWakelock(int uid, int pid, String name, String historyName, int type) {
453 enforceCallingPermission();
454 synchronized (mStats) {
455 mStats.noteStopWakeLocked(uid, pid, name, historyName, type,
456 SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
460 public void noteStartWakelockFromSource(WorkSource ws, int pid, String name,
461 String historyName, int type, boolean unimportantForLogging) {
462 enforceCallingPermission();
463 synchronized (mStats) {
464 mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName,
465 type, unimportantForLogging);
469 public void noteChangeWakelockFromSource(WorkSource ws, int pid, String name,
470 String historyName, int type, WorkSource newWs, int newPid, String newName,
471 String newHistoryName, int newType, boolean newUnimportantForLogging) {
472 enforceCallingPermission();
473 synchronized (mStats) {
474 mStats.noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type,
475 newWs, newPid, newName, newHistoryName, newType, newUnimportantForLogging);
479 public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, String historyName,
481 enforceCallingPermission();
482 synchronized (mStats) {
483 mStats.noteStopWakeFromSourceLocked(ws, pid, name, historyName, type);
487 public void noteStartSensor(int uid, int sensor) {
488 enforceCallingPermission();
489 synchronized (mStats) {
490 mStats.noteStartSensorLocked(uid, sensor);
494 public void noteStopSensor(int uid, int sensor) {
495 enforceCallingPermission();
496 synchronized (mStats) {
497 mStats.noteStopSensorLocked(uid, sensor);
501 public void noteVibratorOn(int uid, long durationMillis) {
502 enforceCallingPermission();
503 synchronized (mStats) {
504 mStats.noteVibratorOnLocked(uid, durationMillis);
508 public void noteVibratorOff(int uid) {
509 enforceCallingPermission();
510 synchronized (mStats) {
511 mStats.noteVibratorOffLocked(uid);
515 public void noteStartGps(int uid) {
516 enforceCallingPermission();
517 synchronized (mStats) {
518 mStats.noteStartGpsLocked(uid);
522 public void noteStopGps(int uid) {
523 enforceCallingPermission();
524 synchronized (mStats) {
525 mStats.noteStopGpsLocked(uid);
529 public void noteScreenState(int state) {
530 enforceCallingPermission();
531 synchronized (mStats) {
532 mStats.noteScreenStateLocked(state);
536 public void noteScreenBrightness(int brightness) {
537 enforceCallingPermission();
538 synchronized (mStats) {
539 mStats.noteScreenBrightnessLocked(brightness);
543 public void noteUserActivity(int uid, int event) {
544 enforceCallingPermission();
545 synchronized (mStats) {
546 mStats.noteUserActivityLocked(uid, event);
550 public void noteWakeUp(String reason, int reasonUid) {
551 enforceCallingPermission();
552 synchronized (mStats) {
553 mStats.noteWakeUpLocked(reason, reasonUid);
557 public void noteInteractive(boolean interactive) {
558 enforceCallingPermission();
559 synchronized (mStats) {
560 mStats.noteInteractiveLocked(interactive);
564 public void noteConnectivityChanged(int type, String extra) {
565 enforceCallingPermission();
566 synchronized (mStats) {
567 mStats.noteConnectivityChangedLocked(type, extra);
571 public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) {
572 enforceCallingPermission();
573 synchronized (mStats) {
574 mStats.noteMobileRadioPowerState(powerState, timestampNs, uid);
578 public void notePhoneOn() {
579 enforceCallingPermission();
580 synchronized (mStats) {
581 mStats.notePhoneOnLocked();
585 public void notePhoneOff() {
586 enforceCallingPermission();
587 synchronized (mStats) {
588 mStats.notePhoneOffLocked();
592 public void notePhoneSignalStrength(SignalStrength signalStrength) {
593 enforceCallingPermission();
594 synchronized (mStats) {
595 mStats.notePhoneSignalStrengthLocked(signalStrength);
599 public void notePhoneDataConnectionState(int dataType, boolean hasData) {
600 enforceCallingPermission();
601 synchronized (mStats) {
602 mStats.notePhoneDataConnectionStateLocked(dataType, hasData);
606 public void notePhoneState(int state) {
607 enforceCallingPermission();
608 int simState = TelephonyManager.getDefault().getSimState();
609 synchronized (mStats) {
610 mStats.notePhoneStateLocked(state, simState);
614 public void noteWifiOn() {
615 enforceCallingPermission();
616 synchronized (mStats) {
617 mStats.noteWifiOnLocked();
621 public void noteWifiOff() {
622 enforceCallingPermission();
623 synchronized (mStats) {
624 mStats.noteWifiOffLocked();
628 public void noteStartAudio(int uid) {
629 enforceCallingPermission();
630 synchronized (mStats) {
631 mStats.noteAudioOnLocked(uid);
635 public void noteStopAudio(int uid) {
636 enforceCallingPermission();
637 synchronized (mStats) {
638 mStats.noteAudioOffLocked(uid);
642 public void noteStartVideo(int uid) {
643 enforceCallingPermission();
644 synchronized (mStats) {
645 mStats.noteVideoOnLocked(uid);
649 public void noteStopVideo(int uid) {
650 enforceCallingPermission();
651 synchronized (mStats) {
652 mStats.noteVideoOffLocked(uid);
656 public void noteResetAudio() {
657 enforceCallingPermission();
658 synchronized (mStats) {
659 mStats.noteResetAudioLocked();
663 public void noteResetVideo() {
664 enforceCallingPermission();
665 synchronized (mStats) {
666 mStats.noteResetVideoLocked();
670 public void noteFlashlightOn(int uid) {
671 enforceCallingPermission();
672 synchronized (mStats) {
673 mStats.noteFlashlightOnLocked(uid);
677 public void noteFlashlightOff(int uid) {
678 enforceCallingPermission();
679 synchronized (mStats) {
680 mStats.noteFlashlightOffLocked(uid);
684 public void noteStartCamera(int uid) {
685 enforceCallingPermission();
686 synchronized (mStats) {
687 mStats.noteCameraOnLocked(uid);
691 public void noteStopCamera(int uid) {
692 enforceCallingPermission();
693 synchronized (mStats) {
694 mStats.noteCameraOffLocked(uid);
698 public void noteResetCamera() {
699 enforceCallingPermission();
700 synchronized (mStats) {
701 mStats.noteResetCameraLocked();
705 public void noteResetFlashlight() {
706 enforceCallingPermission();
707 synchronized (mStats) {
708 mStats.noteResetFlashlightLocked();
713 public void noteWifiRadioPowerState(int powerState, long tsNanos) {
714 enforceCallingPermission();
716 // There was a change in WiFi power state.
717 // Collect data now for the past activity.
718 synchronized (mStats) {
719 if (mStats.isOnBattery()) {
720 final String type = (powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH ||
721 powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM) ? "active"
723 mHandler.scheduleSync("wifi-data: " + type,
724 BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI);
726 mStats.noteWifiRadioPowerState(powerState, tsNanos);
730 public void noteWifiRunning(WorkSource ws) {
731 enforceCallingPermission();
732 synchronized (mStats) {
733 mStats.noteWifiRunningLocked(ws);
737 public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) {
738 enforceCallingPermission();
739 synchronized (mStats) {
740 mStats.noteWifiRunningChangedLocked(oldWs, newWs);
744 public void noteWifiStopped(WorkSource ws) {
745 enforceCallingPermission();
746 synchronized (mStats) {
747 mStats.noteWifiStoppedLocked(ws);
751 public void noteWifiState(int wifiState, String accessPoint) {
752 enforceCallingPermission();
753 synchronized (mStats) {
754 mStats.noteWifiStateLocked(wifiState, accessPoint);
758 public void noteWifiSupplicantStateChanged(int supplState, boolean failedAuth) {
759 enforceCallingPermission();
760 synchronized (mStats) {
761 mStats.noteWifiSupplicantStateChangedLocked(supplState, failedAuth);
765 public void noteWifiRssiChanged(int newRssi) {
766 enforceCallingPermission();
767 synchronized (mStats) {
768 mStats.noteWifiRssiChangedLocked(newRssi);
772 public void noteFullWifiLockAcquired(int uid) {
773 enforceCallingPermission();
774 synchronized (mStats) {
775 mStats.noteFullWifiLockAcquiredLocked(uid);
779 public void noteFullWifiLockReleased(int uid) {
780 enforceCallingPermission();
781 synchronized (mStats) {
782 mStats.noteFullWifiLockReleasedLocked(uid);
786 public void noteWifiScanStarted(int uid) {
787 enforceCallingPermission();
788 synchronized (mStats) {
789 mStats.noteWifiScanStartedLocked(uid);
793 public void noteWifiScanStopped(int uid) {
794 enforceCallingPermission();
795 synchronized (mStats) {
796 mStats.noteWifiScanStoppedLocked(uid);
800 public void noteWifiMulticastEnabled(int uid) {
801 enforceCallingPermission();
802 synchronized (mStats) {
803 mStats.noteWifiMulticastEnabledLocked(uid);
807 public void noteWifiMulticastDisabled(int uid) {
808 enforceCallingPermission();
809 synchronized (mStats) {
810 mStats.noteWifiMulticastDisabledLocked(uid);
814 public void noteFullWifiLockAcquiredFromSource(WorkSource ws) {
815 enforceCallingPermission();
816 synchronized (mStats) {
817 mStats.noteFullWifiLockAcquiredFromSourceLocked(ws);
821 public void noteFullWifiLockReleasedFromSource(WorkSource ws) {
822 enforceCallingPermission();
823 synchronized (mStats) {
824 mStats.noteFullWifiLockReleasedFromSourceLocked(ws);
828 public void noteWifiScanStartedFromSource(WorkSource ws) {
829 enforceCallingPermission();
830 synchronized (mStats) {
831 mStats.noteWifiScanStartedFromSourceLocked(ws);
835 public void noteWifiScanStoppedFromSource(WorkSource ws) {
836 enforceCallingPermission();
837 synchronized (mStats) {
838 mStats.noteWifiScanStoppedFromSourceLocked(ws);
842 public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) {
843 enforceCallingPermission();
844 synchronized (mStats) {
845 mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph);
849 public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) {
850 enforceCallingPermission();
851 synchronized (mStats) {
852 mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws);
856 public void noteWifiMulticastEnabledFromSource(WorkSource ws) {
857 enforceCallingPermission();
858 synchronized (mStats) {
859 mStats.noteWifiMulticastEnabledFromSourceLocked(ws);
864 public void noteWifiMulticastDisabledFromSource(WorkSource ws) {
865 enforceCallingPermission();
866 synchronized (mStats) {
867 mStats.noteWifiMulticastDisabledFromSourceLocked(ws);
872 public void noteNetworkInterfaceType(String iface, int networkType) {
873 enforceCallingPermission();
874 synchronized (mStats) {
875 mStats.noteNetworkInterfaceTypeLocked(iface, networkType);
880 public void noteNetworkStatsEnabled() {
881 enforceCallingPermission();
882 synchronized (mStats) {
883 mStats.noteNetworkStatsEnabledLocked();
888 public void noteDeviceIdleMode(int mode, String activeReason, int activeUid) {
889 enforceCallingPermission();
890 synchronized (mStats) {
891 mStats.noteDeviceIdleModeLocked(mode, activeReason, activeUid);
895 public void notePackageInstalled(String pkgName, int versionCode) {
896 enforceCallingPermission();
897 synchronized (mStats) {
898 mStats.notePackageInstalledLocked(pkgName, versionCode);
902 public void notePackageUninstalled(String pkgName) {
903 enforceCallingPermission();
904 synchronized (mStats) {
905 mStats.notePackageUninstalledLocked(pkgName);
910 public void noteBleScanStarted(WorkSource ws) {
911 enforceCallingPermission();
912 synchronized (mStats) {
913 mStats.noteBluetoothScanStartedFromSourceLocked(ws);
918 public void noteBleScanStopped(WorkSource ws) {
919 enforceCallingPermission();
920 synchronized (mStats) {
921 mStats.noteBluetoothScanStoppedFromSourceLocked(ws);
926 public void noteResetBleScan() {
927 enforceCallingPermission();
928 synchronized (mStats) {
929 mStats.noteResetBluetoothScanLocked();
934 public void noteWifiControllerActivity(WifiActivityEnergyInfo info) {
935 enforceCallingPermission();
937 if (info == null || !info.isValid()) {
938 Slog.e(TAG, "invalid wifi data given: " + info);
942 synchronized (mStats) {
943 mStats.updateWifiStateLocked(info);
948 public void noteBluetoothControllerActivity(BluetoothActivityEnergyInfo info) {
949 enforceCallingPermission();
950 if (info == null || !info.isValid()) {
951 Slog.e(TAG, "invalid bluetooth data given: " + info);
955 synchronized (mStats) {
956 mStats.updateBluetoothStateLocked(info);
961 public void noteModemControllerActivity(ModemActivityInfo info) {
962 enforceCallingPermission();
964 if (info == null || !info.isValid()) {
965 Slog.e(TAG, "invalid modem data given: " + info);
969 synchronized (mStats) {
970 mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime(), info);
974 public boolean isOnBattery() {
975 return mStats.isOnBattery();
979 public void setBatteryState(final int status, final int health, final int plugType,
980 final int level, final int temp, final int volt, final int chargeUAh) {
981 enforceCallingPermission();
983 // BatteryService calls us here and we may update external state. It would be wrong
984 // to block such a low level service like BatteryService on external stats like WiFi.
985 mHandler.post(new Runnable() {
988 synchronized (mStats) {
989 final boolean onBattery = plugType == BatteryStatsImpl.BATTERY_PLUGGED_NONE;
990 if (mStats.isOnBattery() == onBattery) {
991 // The battery state has not changed, so we don't need to sync external
992 // stats immediately.
993 mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt,
999 // Sync external stats first as the battery has changed states. If we don't sync
1000 // immediately here, we may not collect the relevant data later.
1001 updateExternalStatsSync("battery-state", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
1002 synchronized (mStats) {
1003 mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt,
1010 public long getAwakeTimeBattery() {
1011 mContext.enforceCallingOrSelfPermission(
1012 android.Manifest.permission.BATTERY_STATS, null);
1013 return mStats.getAwakeTimeBattery();
1016 public long getAwakeTimePlugged() {
1017 mContext.enforceCallingOrSelfPermission(
1018 android.Manifest.permission.BATTERY_STATS, null);
1019 return mStats.getAwakeTimePlugged();
1022 public void enforceCallingPermission() {
1023 if (Binder.getCallingPid() == Process.myPid()) {
1026 mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
1027 Binder.getCallingPid(), Binder.getCallingUid(), null);
1030 final class WakeupReasonThread extends Thread {
1031 private static final int MAX_REASON_SIZE = 512;
1032 private CharsetDecoder mDecoder;
1033 private ByteBuffer mUtf8Buffer;
1034 private CharBuffer mUtf16Buffer;
1036 WakeupReasonThread() {
1037 super("BatteryStats_wakeupReason");
1041 Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
1043 mDecoder = StandardCharsets.UTF_8
1045 .onMalformedInput(CodingErrorAction.REPLACE)
1046 .onUnmappableCharacter(CodingErrorAction.REPLACE)
1049 mUtf8Buffer = ByteBuffer.allocateDirect(MAX_REASON_SIZE);
1050 mUtf16Buffer = CharBuffer.allocate(MAX_REASON_SIZE);
1054 while ((reason = waitWakeup()) != null) {
1055 synchronized (mStats) {
1056 mStats.noteWakeupReasonLocked(reason);
1059 } catch (RuntimeException e) {
1060 Slog.e(TAG, "Failure reading wakeup reasons", e);
1064 private String waitWakeup() {
1065 mUtf8Buffer.clear();
1066 mUtf16Buffer.clear();
1069 int bytesWritten = nativeWaitWakeup(mUtf8Buffer);
1070 if (bytesWritten < 0) {
1072 } else if (bytesWritten == 0) {
1076 // Set the buffer's limit to the number of bytes written.
1077 mUtf8Buffer.limit(bytesWritten);
1079 // Decode the buffer from UTF-8 to UTF-16.
1080 // Unmappable characters will be replaced.
1081 mDecoder.decode(mUtf8Buffer, mUtf16Buffer, true);
1082 mUtf16Buffer.flip();
1084 // Create a String from the UTF-16 buffer.
1085 return mUtf16Buffer.toString();
1089 private static native int nativeWaitWakeup(ByteBuffer outBuffer);
1091 private void dumpHelp(PrintWriter pw) {
1092 pw.println("Battery stats (batterystats) dump options:");
1093 pw.println(" [--checkin] [--history] [--history-start] [--charged] [-c]");
1094 pw.println(" [--daily] [--reset] [--write] [--new-daily] [--read-daily] [-h] [<package.name>]");
1095 pw.println(" --checkin: generate output for a checkin report; will write (and clear) the");
1096 pw.println(" last old completed stats when they had been reset.");
1097 pw.println(" -c: write the current stats in checkin format.");
1098 pw.println(" --history: show only history data.");
1099 pw.println(" --history-start <num>: show only history data starting at given time offset.");
1100 pw.println(" --charged: only output data since last charged.");
1101 pw.println(" --daily: only output full daily data.");
1102 pw.println(" --reset: reset the stats, clearing all current data.");
1103 pw.println(" --write: force write current collected stats to disk.");
1104 pw.println(" --new-daily: immediately create and write new daily stats record.");
1105 pw.println(" --read-daily: read-load last written daily stats.");
1106 pw.println(" <package.name>: optional name of package to filter output by.");
1107 pw.println(" -h: print this help text.");
1108 pw.println("Battery stats (batterystats) commands:");
1109 pw.println(" enable|disable <option>");
1110 pw.println(" Enable or disable a running option. Option state is not saved across boots.");
1111 pw.println(" Options are:");
1112 pw.println(" full-history: include additional detailed events in battery history:");
1113 pw.println(" wake_lock_in, alarms and proc events");
1114 pw.println(" no-auto-reset: don't automatically reset stats when unplugged");
1117 private int doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable) {
1119 if (i >= args.length) {
1120 pw.println("Missing option argument for " + (enable ? "--enable" : "--disable"));
1124 if ("full-wake-history".equals(args[i]) || "full-history".equals(args[i])) {
1125 synchronized (mStats) {
1126 mStats.setRecordAllHistoryLocked(enable);
1128 } else if ("no-auto-reset".equals(args[i])) {
1129 synchronized (mStats) {
1130 mStats.setNoAutoReset(enable);
1133 pw.println("Unknown enable/disable option: " + args[i]);
1142 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1143 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1144 != PackageManager.PERMISSION_GRANTED) {
1145 pw.println("Permission Denial: can't dump BatteryStats from from pid="
1146 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1147 + " without permission " + android.Manifest.permission.DUMP);
1152 boolean useCheckinFormat = false;
1153 boolean isRealCheckin = false;
1154 boolean noOutput = false;
1155 boolean writeData = false;
1156 long historyStart = -1;
1159 for (int i=0; i<args.length; i++) {
1160 String arg = args[i];
1161 if ("--checkin".equals(arg)) {
1162 useCheckinFormat = true;
1163 isRealCheckin = true;
1164 } else if ("--history".equals(arg)) {
1165 flags |= BatteryStats.DUMP_HISTORY_ONLY;
1166 } else if ("--history-start".equals(arg)) {
1167 flags |= BatteryStats.DUMP_HISTORY_ONLY;
1169 if (i >= args.length) {
1170 pw.println("Missing time argument for --history-since");
1174 historyStart = Long.parseLong(args[i]);
1176 } else if ("-c".equals(arg)) {
1177 useCheckinFormat = true;
1178 flags |= BatteryStats.DUMP_INCLUDE_HISTORY;
1179 } else if ("--charged".equals(arg)) {
1180 flags |= BatteryStats.DUMP_CHARGED_ONLY;
1181 } else if ("--daily".equals(arg)) {
1182 flags |= BatteryStats.DUMP_DAILY_ONLY;
1183 } else if ("--reset".equals(arg)) {
1184 synchronized (mStats) {
1185 mStats.resetAllStatsCmdLocked();
1186 pw.println("Battery stats reset.");
1189 updateExternalStatsSync("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
1190 } else if ("--write".equals(arg)) {
1191 updateExternalStatsSync("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
1192 synchronized (mStats) {
1193 mStats.writeSyncLocked();
1194 pw.println("Battery stats written.");
1197 } else if ("--new-daily".equals(arg)) {
1198 synchronized (mStats) {
1199 mStats.recordDailyStatsLocked();
1200 pw.println("New daily stats written.");
1203 } else if ("--read-daily".equals(arg)) {
1204 synchronized (mStats) {
1205 mStats.readDailyStatsLocked();
1206 pw.println("Last daily stats read.");
1209 } else if ("--enable".equals(arg) || "enable".equals(arg)) {
1210 i = doEnableOrDisable(pw, i, args, true);
1214 pw.println("Enabled: " + args[i]);
1216 } else if ("--disable".equals(arg) || "disable".equals(arg)) {
1217 i = doEnableOrDisable(pw, i, args, false);
1221 pw.println("Disabled: " + args[i]);
1223 } else if ("-h".equals(arg)) {
1226 } else if ("-a".equals(arg)) {
1227 flags |= BatteryStats.DUMP_VERBOSE;
1228 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
1229 pw.println("Unknown option: " + arg);
1233 // Not an option, last argument must be a package name.
1235 reqUid = mContext.getPackageManager().getPackageUidAsUser(arg,
1236 UserHandle.getCallingUserId());
1237 } catch (PackageManager.NameNotFoundException e) {
1238 pw.println("Unknown package: " + arg);
1249 long ident = Binder.clearCallingIdentity();
1251 if (BatteryStatsHelper.checkWifiOnly(mContext)) {
1252 flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY;
1254 // Fetch data from external sources and update the BatteryStatsImpl object with them.
1255 updateExternalStatsSync("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
1257 Binder.restoreCallingIdentity(ident);
1261 // By default, if the caller is only interested in a specific package, then
1262 // we only dump the aggregated data since charged.
1263 if ((flags&(BatteryStats.DUMP_HISTORY_ONLY|BatteryStats.DUMP_CHARGED_ONLY)) == 0) {
1264 flags |= BatteryStats.DUMP_CHARGED_ONLY;
1265 // Also if they are doing -c, we don't want history.
1266 flags &= ~BatteryStats.DUMP_INCLUDE_HISTORY;
1270 if (useCheckinFormat) {
1271 List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
1272 PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.MATCH_ALL);
1273 if (isRealCheckin) {
1274 // For a real checkin, first we want to prefer to use the last complete checkin
1275 // file if there is one.
1276 synchronized (mStats.mCheckinFile) {
1277 if (mStats.mCheckinFile.exists()) {
1279 byte[] raw = mStats.mCheckinFile.readFully();
1281 Parcel in = Parcel.obtain();
1282 in.unmarshall(raw, 0, raw.length);
1283 in.setDataPosition(0);
1284 BatteryStatsImpl checkinStats = new BatteryStatsImpl(
1285 null, mStats.mHandler, null);
1286 checkinStats.readSummaryFromParcel(in);
1288 checkinStats.dumpCheckinLocked(mContext, pw, apps, flags,
1290 mStats.mCheckinFile.delete();
1293 } catch (IOException | ParcelFormatException e) {
1294 Slog.w(TAG, "Failure reading checkin file "
1295 + mStats.mCheckinFile.getBaseFile(), e);
1300 synchronized (mStats) {
1301 mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
1303 mStats.writeAsyncLocked();
1307 synchronized (mStats) {
1308 mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart);
1310 mStats.writeAsyncLocked();
1316 private WifiActivityEnergyInfo extractDelta(WifiActivityEnergyInfo latest) {
1317 final long timePeriodMs = latest.mTimestamp - mLastInfo.mTimestamp;
1318 final long lastIdleMs = mLastInfo.mControllerIdleTimeMs;
1319 final long lastTxMs = mLastInfo.mControllerTxTimeMs;
1320 final long lastRxMs = mLastInfo.mControllerRxTimeMs;
1321 final long lastEnergy = mLastInfo.mControllerEnergyUsed;
1323 // We will modify the last info object to be the delta, and store the new
1324 // WifiActivityEnergyInfo object as our last one.
1325 final WifiActivityEnergyInfo delta = mLastInfo;
1326 delta.mTimestamp = latest.getTimeStamp();
1327 delta.mStackState = latest.getStackState();
1329 final long txTimeMs = latest.mControllerTxTimeMs - lastTxMs;
1330 final long rxTimeMs = latest.mControllerRxTimeMs - lastRxMs;
1331 final long idleTimeMs = latest.mControllerIdleTimeMs - lastIdleMs;
1333 if (txTimeMs < 0 || rxTimeMs < 0) {
1334 // The stats were reset by the WiFi system (which is why our delta is negative).
1335 // Returns the unaltered stats.
1336 delta.mControllerEnergyUsed = latest.mControllerEnergyUsed;
1337 delta.mControllerRxTimeMs = latest.mControllerRxTimeMs;
1338 delta.mControllerTxTimeMs = latest.mControllerTxTimeMs;
1339 delta.mControllerIdleTimeMs = latest.mControllerIdleTimeMs;
1340 Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + delta);
1342 final long totalActiveTimeMs = txTimeMs + rxTimeMs;
1343 long maxExpectedIdleTimeMs;
1344 if (totalActiveTimeMs > timePeriodMs) {
1345 // Cap the max idle time at zero since the active time consumed the whole time
1346 maxExpectedIdleTimeMs = 0;
1347 if (totalActiveTimeMs > timePeriodMs + MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS) {
1348 StringBuilder sb = new StringBuilder();
1349 sb.append("Total Active time ");
1350 TimeUtils.formatDuration(totalActiveTimeMs, sb);
1351 sb.append(" is longer than sample period ");
1352 TimeUtils.formatDuration(timePeriodMs, sb);
1354 sb.append("Previous WiFi snapshot: ").append("idle=");
1355 TimeUtils.formatDuration(lastIdleMs, sb);
1357 TimeUtils.formatDuration(lastRxMs, sb);
1359 TimeUtils.formatDuration(lastTxMs, sb);
1360 sb.append(" e=").append(lastEnergy);
1362 sb.append("Current WiFi snapshot: ").append("idle=");
1363 TimeUtils.formatDuration(latest.mControllerIdleTimeMs, sb);
1365 TimeUtils.formatDuration(latest.mControllerRxTimeMs, sb);
1367 TimeUtils.formatDuration(latest.mControllerTxTimeMs, sb);
1368 sb.append(" e=").append(latest.mControllerEnergyUsed);
1369 Slog.wtf(TAG, sb.toString());
1372 maxExpectedIdleTimeMs = timePeriodMs - totalActiveTimeMs;
1374 // These times seem to be the most reliable.
1375 delta.mControllerTxTimeMs = txTimeMs;
1376 delta.mControllerRxTimeMs = rxTimeMs;
1377 // WiFi calculates the idle time as a difference from the on time and the various
1378 // Rx + Tx times. There seems to be some missing time there because this sometimes
1379 // becomes negative. Just cap it at 0 and ensure that it is less than the expected idle
1380 // time from the difference in timestamps.
1382 delta.mControllerIdleTimeMs = Math.min(maxExpectedIdleTimeMs, Math.max(0, idleTimeMs));
1383 delta.mControllerEnergyUsed = Math.max(0, latest.mControllerEnergyUsed - lastEnergy);
1391 * Helper method to extract the Parcelable controller info from a
1392 * SynchronousResultReceiver.
1394 private static <T extends Parcelable> T awaitControllerInfo(
1395 @Nullable SynchronousResultReceiver receiver) throws TimeoutException {
1396 if (receiver == null) {
1400 final SynchronousResultReceiver.Result result =
1401 receiver.awaitResult(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS);
1402 if (result.bundle != null) {
1403 // This is the final destination for the Bundle.
1404 result.bundle.setDefusable(true);
1406 final T data = result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
1411 Slog.e(TAG, "no controller energy info supplied");
1416 * Fetches data from external sources (WiFi controller, bluetooth chipset) and updates
1417 * batterystats with that information.
1419 * We first grab a lock specific to this method, then once all the data has been collected,
1420 * we grab the mStats lock and update the data.
1422 * @param reason The reason why this collection was requested. Useful for debugging.
1423 * @param updateFlags Which external stats to update. Can be a combination of
1424 * {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_CPU},
1425 * {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_RADIO},
1426 * {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_WIFI},
1427 * and {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_BT}.
1429 void updateExternalStatsSync(final String reason, int updateFlags) {
1430 SynchronousResultReceiver wifiReceiver = null;
1431 SynchronousResultReceiver bluetoothReceiver = null;
1432 SynchronousResultReceiver modemReceiver = null;
1434 synchronized (mExternalStatsLock) {
1435 if (mContext == null) {
1436 // Don't do any work yet.
1440 if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) {
1441 if (mWifiManager == null) {
1442 mWifiManager = IWifiManager.Stub.asInterface(
1443 ServiceManager.getService(Context.WIFI_SERVICE));
1446 if (mWifiManager != null) {
1448 wifiReceiver = new SynchronousResultReceiver();
1449 mWifiManager.requestActivityInfo(wifiReceiver);
1450 } catch (RemoteException e) {
1456 if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_BT) != 0) {
1457 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
1458 if (adapter != null) {
1459 bluetoothReceiver = new SynchronousResultReceiver();
1460 adapter.requestControllerActivityEnergyInfo(bluetoothReceiver);
1464 if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO) != 0) {
1465 if (mTelephony == null) {
1466 mTelephony = TelephonyManager.from(mContext);
1469 if (mTelephony != null) {
1470 modemReceiver = new SynchronousResultReceiver();
1471 mTelephony.requestModemActivityInfo(modemReceiver);
1475 WifiActivityEnergyInfo wifiInfo = null;
1476 BluetoothActivityEnergyInfo bluetoothInfo = null;
1477 ModemActivityInfo modemInfo = null;
1479 wifiInfo = awaitControllerInfo(wifiReceiver);
1480 } catch (TimeoutException e) {
1481 Slog.w(TAG, "Timeout reading wifi stats");
1485 bluetoothInfo = awaitControllerInfo(bluetoothReceiver);
1486 } catch (TimeoutException e) {
1487 Slog.w(TAG, "Timeout reading bt stats");
1491 modemInfo = awaitControllerInfo(modemReceiver);
1492 } catch (TimeoutException e) {
1493 Slog.w(TAG, "Timeout reading modem stats");
1496 synchronized (mStats) {
1497 mStats.addHistoryEventLocked(
1498 SystemClock.elapsedRealtime(),
1499 SystemClock.uptimeMillis(),
1500 BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS,
1503 mStats.updateCpuTimeLocked();
1504 mStats.updateKernelWakelocksLocked();
1506 if (wifiInfo != null) {
1507 if (wifiInfo.isValid()) {
1508 mStats.updateWifiStateLocked(extractDelta(wifiInfo));
1510 Slog.e(TAG, "wifi info is invalid: " + wifiInfo);
1514 if (bluetoothInfo != null) {
1515 if (bluetoothInfo.isValid()) {
1516 mStats.updateBluetoothStateLocked(bluetoothInfo);
1518 Slog.e(TAG, "bluetooth info is invalid: " + bluetoothInfo);
1522 if (modemInfo != null) {
1523 if (modemInfo.isValid()) {
1524 mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime(),
1527 Slog.e(TAG, "modem info is invalid: " + modemInfo);
1535 * Gets a snapshot of the system health for a particular uid.
1538 public HealthStatsParceler takeUidSnapshot(int requestUid) {
1539 if (requestUid != Binder.getCallingUid()) {
1540 mContext.enforceCallingOrSelfPermission(
1541 android.Manifest.permission.BATTERY_STATS, null);
1543 long ident = Binder.clearCallingIdentity();
1545 updateExternalStatsSync("get-health-stats-for-uid",
1546 BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
1547 synchronized (mStats) {
1548 return getHealthStatsForUidLocked(requestUid);
1550 } catch (Exception ex) {
1551 Slog.d(TAG, "Crashed while writing for takeUidSnapshot(" + requestUid + ")", ex);
1554 Binder.restoreCallingIdentity(ident);
1559 * Gets a snapshot of the system health for a number of uids.
1562 public HealthStatsParceler[] takeUidSnapshots(int[] requestUids) {
1563 if (!onlyCaller(requestUids)) {
1564 mContext.enforceCallingOrSelfPermission(
1565 android.Manifest.permission.BATTERY_STATS, null);
1567 long ident = Binder.clearCallingIdentity();
1570 updateExternalStatsSync("get-health-stats-for-uids",
1571 BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
1572 synchronized (mStats) {
1573 final int N = requestUids.length;
1574 final HealthStatsParceler[] results = new HealthStatsParceler[N];
1575 for (i=0; i<N; i++) {
1576 results[i] = getHealthStatsForUidLocked(requestUids[i]);
1580 } catch (Exception ex) {
1581 Slog.d(TAG, "Crashed while writing for takeUidSnapshots("
1582 + Arrays.toString(requestUids) + ") i=" + i, ex);
1585 Binder.restoreCallingIdentity(ident);
1590 * Returns whether the Binder.getCallingUid is the only thing in requestUids.
1592 private static boolean onlyCaller(int[] requestUids) {
1593 final int caller = Binder.getCallingUid();
1594 final int N = requestUids.length;
1595 for (int i=0; i<N; i++) {
1596 if (requestUids[i] != caller) {
1604 * Gets a HealthStatsParceler for the given uid. You should probably call
1605 * updateExternalStatsSync first.
1607 HealthStatsParceler getHealthStatsForUidLocked(int requestUid) {
1608 final HealthStatsBatteryStatsWriter writer = new HealthStatsBatteryStatsWriter();
1609 final HealthStatsWriter uidWriter = new HealthStatsWriter(UidHealthStats.CONSTANTS);
1610 final BatteryStats.Uid uid = mStats.getUidStats().get(requestUid);
1612 writer.writeUid(uidWriter, mStats, uid);
1614 return new HealthStatsParceler(uidWriter);