blob: deaf3b8861c8981789284a36758ef0803923afc2 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package com.android.server.am;
18
Sudheer Shanka671985f2017-05-19 11:33:42 -070019import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU;
Adam Lesinski14ae39a2017-05-26 11:50:40 -070020import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO;
21import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI;
Sudheer Shanka671985f2017-05-19 11:33:42 -070022
Adam Lesinski010bf372016-04-11 12:18:18 -070023import android.annotation.Nullable;
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -070024import android.bluetooth.BluetoothActivityEnergyInfo;
Jaikumar Ganesh3f034962010-09-27 17:02:23 -070025import android.bluetooth.BluetoothAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.content.Context;
Dianne Hackborne4a59512010-12-07 11:08:07 -080027import android.content.pm.ApplicationInfo;
Kenny Root3abd75b2011-09-29 11:00:41 -070028import android.content.pm.PackageManager;
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -070029import android.net.wifi.IWifiManager;
30import android.net.wifi.WifiActivityEnergyInfo;
jackqdyulei455e90a2017-02-09 15:29:16 -080031import android.os.PowerSaveState;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070032import android.os.BatteryStats;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.os.Binder;
Jeff Brown6f357d32014-01-15 20:40:55 -080034import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.os.IBinder;
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -070036import android.os.Looper;
37import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.os.Parcel;
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -070039import android.os.ParcelFileDescriptor;
Adam Lesinski9ae9cba2015-07-08 17:09:34 -070040import android.os.ParcelFormatException;
Adam Lesinski010bf372016-04-11 12:18:18 -070041import android.os.Parcelable;
Dianne Hackborncbefd8d2014-05-14 11:42:00 -070042import android.os.PowerManagerInternal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.os.Process;
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -070044import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.os.ServiceManager;
Adam Lesinski010bf372016-04-11 12:18:18 -070046import android.os.SynchronousResultReceiver;
Dianne Hackborne5167ca2014-03-08 14:39:10 -080047import android.os.SystemClock;
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070048import android.os.UserHandle;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070049import android.os.WorkSource;
Joe Onorato713fec82016-03-04 10:34:02 -080050import android.os.health.HealthStatsParceler;
51import android.os.health.HealthStatsWriter;
52import android.os.health.UidHealthStats;
Adam Lesinski06f46cb2015-06-23 13:42:53 -070053import android.telephony.DataConnectionRealTimeInfo;
Adam Lesinski21f76aa2016-01-25 12:27:06 -080054import android.telephony.ModemActivityInfo;
Wink Savillee9b06d72009-05-18 21:47:50 -070055import android.telephony.SignalStrength;
Dianne Hackborne4a59512010-12-07 11:08:07 -080056import android.telephony.TelephonyManager;
Adam Lesinski61db88f2015-07-01 15:05:07 -070057import android.util.IntArray;
Joe Onorato8a9b2202010-02-26 18:56:32 -080058import android.util.Slog;
Adam Lesinskibd6704f2015-06-18 18:05:20 -070059import android.util.TimeUtils;
Amith Yamasani674c9bb2017-02-01 09:45:17 -080060
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -070061import com.android.internal.annotations.GuardedBy;
Amith Yamasani32dbefd2009-06-19 09:21:17 -070062import com.android.internal.app.IBatteryStats;
Dianne Hackbornd953c532014-08-16 18:17:38 -070063import com.android.internal.os.BatteryStatsHelper;
Amith Yamasani32dbefd2009-06-19 09:21:17 -070064import com.android.internal.os.BatteryStatsImpl;
Amith Yamasanie43530a2009-08-21 13:11:37 -070065import com.android.internal.os.PowerProfile;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060066import com.android.internal.util.DumpUtils;
Dianne Hackborncbefd8d2014-05-14 11:42:00 -070067import com.android.server.LocalServices;
Adam Lesinski20b84df2016-04-19 17:33:33 -070068import com.android.server.ServiceThread;
jackqdyulei455e90a2017-02-09 15:29:16 -080069import com.android.server.power.BatterySaverPolicy.ServiceType;
Amith Yamasani32dbefd2009-06-19 09:21:17 -070070
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -070071import java.io.File;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import java.io.FileDescriptor;
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -070073import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074import java.io.PrintWriter;
Adam Lesinski515702c2015-07-23 18:13:38 -070075import java.nio.ByteBuffer;
76import java.nio.CharBuffer;
77import java.nio.charset.CharsetDecoder;
78import java.nio.charset.CodingErrorAction;
79import java.nio.charset.StandardCharsets;
Joe Onorato713fec82016-03-04 10:34:02 -080080import java.util.Arrays;
Dianne Hackborne4a59512010-12-07 11:08:07 -080081import java.util.List;
Adam Lesinski010bf372016-04-11 12:18:18 -070082import java.util.concurrent.TimeoutException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083
84/**
85 * All information we are collecting about things that can happen that impact
86 * battery life.
87 */
Dianne Hackborncbefd8d2014-05-14 11:42:00 -070088public final class BatteryStatsService extends IBatteryStats.Stub
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -070089 implements PowerManagerInternal.LowPowerModeListener,
90 BatteryStatsImpl.PlatformIdleStateCallback {
Dianne Hackbornc51cf032014-03-02 19:08:15 -080091 static final String TAG = "BatteryStatsService";
Joe Onorato82ba91d2017-04-27 16:18:05 -070092 static final boolean DBG = false;
Dianne Hackbornc51cf032014-03-02 19:08:15 -080093
Adam Lesinski010bf372016-04-11 12:18:18 -070094 /**
95 * How long to wait on an individual subsystem to return its stats.
96 */
97 private static final long EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS = 2000;
98
Roshan Pius2078d342016-05-25 09:32:17 -070099 // There is some accuracy error in wifi reports so allow some slop in the results.
100 private static final long MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS = 750;
101
Adam Lesinski010bf372016-04-11 12:18:18 -0700102 private static IBatteryStats sService;
103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104 final BatteryStatsImpl mStats;
Adam Lesinski010bf372016-04-11 12:18:18 -0700105 private final BatteryStatsHandler mHandler;
106 private Context mContext;
107 private IWifiManager mWifiManager;
108 private TelephonyManager mTelephony;
109
110 // Lock acquired when extracting data from external sources.
111 private final Object mExternalStatsLock = new Object();
112
113 // WiFi keeps an accumulated total of stats, unlike Bluetooth.
114 // Keep the last WiFi stats so we can compute a delta.
115 @GuardedBy("mExternalStatsLock")
116 private WifiActivityEnergyInfo mLastInfo =
117 new WifiActivityEnergyInfo(0, 0, 0, new long[]{0}, 0, 0, 0);
Amith Yamasani3f7e35c2009-07-13 16:02:45 -0700118
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700119 class BatteryStatsHandler extends Handler implements BatteryStatsImpl.ExternalStatsSync {
120 public static final int MSG_SYNC_EXTERNAL_STATS = 1;
121 public static final int MSG_WRITE_TO_DISK = 2;
Adam Lesinski010bf372016-04-11 12:18:18 -0700122
Adam Lesinskia7c90c82015-06-18 14:52:24 -0700123 private int mUpdateFlags = 0;
Adam Lesinski61db88f2015-07-01 15:05:07 -0700124 private IntArray mUidsToRemove = new IntArray();
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700125
126 public BatteryStatsHandler(Looper looper) {
127 super(looper);
128 }
129
130 @Override
131 public void handleMessage(Message msg) {
132 switch (msg.what) {
133 case MSG_SYNC_EXTERNAL_STATS:
Adam Lesinskia7c90c82015-06-18 14:52:24 -0700134 final int updateFlags;
135 synchronized (this) {
136 removeMessages(MSG_SYNC_EXTERNAL_STATS);
137 updateFlags = mUpdateFlags;
138 mUpdateFlags = 0;
139 }
Adam Lesinski010bf372016-04-11 12:18:18 -0700140 updateExternalStatsSync((String)msg.obj, updateFlags);
Adam Lesinski56d82dd2015-07-14 16:27:40 -0700141
142 // other parts of the system could be calling into us
143 // from mStats in order to report of changes. We must grab the mStats
144 // lock before grabbing our own or we'll end up in a deadlock.
145 synchronized (mStats) {
146 synchronized (this) {
Adam Lesinski61db88f2015-07-01 15:05:07 -0700147 final int numUidsToRemove = mUidsToRemove.size();
148 for (int i = 0; i < numUidsToRemove; i++) {
149 mStats.removeIsolatedUidLocked(mUidsToRemove.get(i));
150 }
151 }
152 mUidsToRemove.clear();
153 }
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700154 break;
155
156 case MSG_WRITE_TO_DISK:
Adam Lesinski010bf372016-04-11 12:18:18 -0700157 updateExternalStatsSync("write", UPDATE_ALL);
Joe Onorato82ba91d2017-04-27 16:18:05 -0700158 if (DBG) Slog.d(TAG, "begin writeAsyncLocked");
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700159 synchronized (mStats) {
160 mStats.writeAsyncLocked();
161 }
Joe Onorato82ba91d2017-04-27 16:18:05 -0700162 if (DBG) Slog.d(TAG, "end writeAsyncLocked");
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700163 break;
164 }
165 }
166
167 @Override
Adam Lesinski9f55cc72016-01-27 20:42:14 -0800168 public void scheduleSync(String reason, int updateFlags) {
Adam Lesinski61db88f2015-07-01 15:05:07 -0700169 synchronized (this) {
Adam Lesinski9f55cc72016-01-27 20:42:14 -0800170 scheduleSyncLocked(reason, updateFlags);
Adam Lesinski61db88f2015-07-01 15:05:07 -0700171 }
Adam Lesinskia7c90c82015-06-18 14:52:24 -0700172 }
173
Adam Lesinski61db88f2015-07-01 15:05:07 -0700174 @Override
175 public void scheduleCpuSyncDueToRemovedUid(int uid) {
Adam Lesinskia7c90c82015-06-18 14:52:24 -0700176 synchronized (this) {
Adam Lesinski61db88f2015-07-01 15:05:07 -0700177 scheduleSyncLocked("remove-uid", UPDATE_CPU);
178 mUidsToRemove.add(uid);
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700179 }
180 }
Adam Lesinski61db88f2015-07-01 15:05:07 -0700181
182 private void scheduleSyncLocked(String reason, int updateFlags) {
183 if (mUpdateFlags == 0) {
184 sendMessage(Message.obtain(this, MSG_SYNC_EXTERNAL_STATS, reason));
185 }
186 mUpdateFlags |= updateFlags;
187 }
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700188 }
189
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700190 private native int getPlatformLowPowerStats(ByteBuffer outBuffer);
191 private CharsetDecoder mDecoderStat = StandardCharsets.UTF_8
192 .newDecoder()
193 .onMalformedInput(CodingErrorAction.REPLACE)
194 .onUnmappableCharacter(CodingErrorAction.REPLACE)
195 .replaceWith("?");
196 private ByteBuffer mUtf8BufferStat = ByteBuffer.allocateDirect(MAX_LOW_POWER_STATS_SIZE);
197 private CharBuffer mUtf16BufferStat = CharBuffer.allocate(MAX_LOW_POWER_STATS_SIZE);
198 private static final int MAX_LOW_POWER_STATS_SIZE = 512;
199
200 @Override
201 public String getPlatformLowPowerStats() {
Joe Onorato82ba91d2017-04-27 16:18:05 -0700202 if (DBG) Slog.d(TAG, "begin getPlatformLowPowerStats");
Adam Lesinskicd722082017-03-30 13:54:09 -0700203 try {
204 mUtf8BufferStat.clear();
205 mUtf16BufferStat.clear();
206 mDecoderStat.reset();
207 int bytesWritten = getPlatformLowPowerStats(mUtf8BufferStat);
208 if (bytesWritten < 0) {
209 return null;
210 } else if (bytesWritten == 0) {
211 return "Empty";
212 }
213 mUtf8BufferStat.limit(bytesWritten);
214 mDecoderStat.decode(mUtf8BufferStat, mUtf16BufferStat, true);
215 mUtf16BufferStat.flip();
216 return mUtf16BufferStat.toString();
217 } finally {
Joe Onorato82ba91d2017-04-27 16:18:05 -0700218 if (DBG) Slog.d(TAG, "end getPlatformLowPowerStats");
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700219 }
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700220 }
221
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -0700222 BatteryStatsService(File systemDir, Handler handler) {
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700223 // Our handler here will be accessing the disk, use a different thread than
224 // what the ActivityManagerService gave us (no I/O on that one!).
Adam Lesinski20b84df2016-04-19 17:33:33 -0700225 final ServiceThread thread = new ServiceThread("batterystats-sync",
226 Process.THREAD_PRIORITY_DEFAULT, true);
227 thread.start();
228 mHandler = new BatteryStatsHandler(thread.getLooper());
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700229
230 // BatteryStatsImpl expects the ActivityManagerService handler, so pass that one through.
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700231 mStats = new BatteryStatsImpl(systemDir, handler, mHandler, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 }
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 public void publish(Context context) {
235 mContext = context;
Adam Lesinski14ae39a2017-05-26 11:50:40 -0700236 synchronized (mStats) {
237 mStats.setRadioScanningTimeoutLocked(mContext.getResources().getInteger(
238 com.android.internal.R.integer.config_radioScanningTimeout)
239 * 1000L);
240 mStats.setPowerProfileLocked(new PowerProfile(context));
241 }
Adam Lesinski6832f392015-09-05 18:05:40 -0700242 ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
Jeff Brown2c43c332014-06-12 22:38:59 -0700243 }
244
245 /**
246 * At the time when the constructor runs, the power manager has not yet been
247 * initialized. So we initialize the low power observer later.
248 */
249 public void initPowerManagement() {
Adam Lesinski010bf372016-04-11 12:18:18 -0700250 final PowerManagerInternal powerMgr = LocalServices.getService(PowerManagerInternal.class);
251 powerMgr.registerLowPowerModeObserver(this);
Adam Lesinski14ae39a2017-05-26 11:50:40 -0700252 synchronized (mStats) {
253 mStats.notePowerSaveModeLocked(
254 powerMgr.getLowPowerState(ServiceType.BATTERY_STATS)
255 .batterySaverEnabled);
256 }
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800257 (new WakeupReasonThread()).start();
Jeff Brown2c43c332014-06-12 22:38:59 -0700258 }
259
Dianne Hackborn55280a92009-05-07 15:53:46 -0700260 public void shutdown() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800261 Slog.w("BatteryStats", "Writing battery stats before shutdown...");
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700262
Adam Lesinski010bf372016-04-11 12:18:18 -0700263 updateExternalStatsSync("shutdown", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
Dianne Hackborn55280a92009-05-07 15:53:46 -0700264 synchronized (mStats) {
Dianne Hackborn6b7b4842010-06-14 17:17:44 -0700265 mStats.shutdownLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -0700266 }
Adam Lesinski20b84df2016-04-19 17:33:33 -0700267
268 // Shutdown the thread we made.
269 mHandler.getLooper().quit();
Dianne Hackborn55280a92009-05-07 15:53:46 -0700270 }
271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 public static IBatteryStats getService() {
273 if (sService != null) {
274 return sService;
275 }
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700276 IBinder b = ServiceManager.getService(BatteryStats.SERVICE_NAME);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 sService = asInterface(b);
278 return sService;
279 }
Dianne Hackborncbefd8d2014-05-14 11:42:00 -0700280
281 @Override
jackqdyulei455e90a2017-02-09 15:29:16 -0800282 public int getServiceType() {
283 return ServiceType.BATTERY_STATS;
284 }
285
286 @Override
287 public void onLowPowerModeChanged(PowerSaveState result) {
Dianne Hackborncbefd8d2014-05-14 11:42:00 -0700288 synchronized (mStats) {
Adam Lesinski14ae39a2017-05-26 11:50:40 -0700289 mStats.notePowerSaveModeLocked(result.batterySaverEnabled);
Dianne Hackborncbefd8d2014-05-14 11:42:00 -0700290 }
291 }
292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293 /**
294 * @return the current statistics object, which may be modified
295 * to reflect events that affect battery usage. You must lock the
296 * stats object before doing anything with it.
297 */
298 public BatteryStatsImpl getActiveStatistics() {
299 return mStats;
300 }
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -0700301
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700302 /**
303 * Schedules a write to disk to occur. This will cause the BatteryStatsImpl
304 * object to update with the latest info, then write to disk.
305 */
306 public void scheduleWriteToDisk() {
307 mHandler.sendEmptyMessage(BatteryStatsHandler.MSG_WRITE_TO_DISK);
308 }
309
Dianne Hackborn2f1993e2014-09-26 11:28:01 -0700310 // These are for direct use by the activity manager...
311
Adam Lesinskib83ffee2015-05-12 14:43:47 -0700312 /**
313 * Remove a UID from the BatteryStats and BatteryStats' external dependencies.
314 */
315 void removeUid(int uid) {
316 synchronized (mStats) {
317 mStats.removeUidStatsLocked(uid);
318 }
319 }
320
Dianne Hackborn2f1993e2014-09-26 11:28:01 -0700321 void addIsolatedUid(int isolatedUid, int appUid) {
322 synchronized (mStats) {
323 mStats.addIsolatedUidLocked(isolatedUid, appUid);
324 }
325 }
326
327 void removeIsolatedUid(int isolatedUid, int appUid) {
328 synchronized (mStats) {
Adam Lesinski61db88f2015-07-01 15:05:07 -0700329 mStats.scheduleRemoveIsolatedUidLocked(isolatedUid, appUid);
Dianne Hackborn2f1993e2014-09-26 11:28:01 -0700330 }
331 }
332
333 void noteProcessStart(String name, int uid) {
334 synchronized (mStats) {
335 mStats.noteProcessStartLocked(name, uid);
336 }
337 }
338
Dianne Hackborn1e01d162014-12-04 17:46:42 -0800339 void noteProcessCrash(String name, int uid) {
340 synchronized (mStats) {
341 mStats.noteProcessCrashLocked(name, uid);
342 }
343 }
344
345 void noteProcessAnr(String name, int uid) {
346 synchronized (mStats) {
347 mStats.noteProcessAnrLocked(name, uid);
348 }
349 }
350
Dianne Hackborn2f1993e2014-09-26 11:28:01 -0700351 void noteProcessFinish(String name, int uid) {
352 synchronized (mStats) {
353 mStats.noteProcessFinishLocked(name, uid);
354 }
355 }
356
Dianne Hackborna8d10942015-11-19 17:55:19 -0800357 void noteUidProcessState(int uid, int state) {
358 synchronized (mStats) {
359 mStats.noteUidProcessStateLocked(uid, state);
360 }
361 }
362
Dianne Hackborn2f1993e2014-09-26 11:28:01 -0700363 // Public interface...
364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 public byte[] getStatistics() {
366 mContext.enforceCallingPermission(
367 android.Manifest.permission.BATTERY_STATS, null);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800368 //Slog.i("foo", "SENDING BATTERY INFO:");
369 //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 Parcel out = Parcel.obtain();
Adam Lesinski010bf372016-04-11 12:18:18 -0700371 updateExternalStatsSync("get-stats", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700372 synchronized (mStats) {
373 mStats.writeToParcel(out, 0);
374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375 byte[] data = out.marshall();
376 out.recycle();
377 return data;
378 }
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -0700379
380 public ParcelFileDescriptor getStatisticsStream() {
381 mContext.enforceCallingPermission(
382 android.Manifest.permission.BATTERY_STATS, null);
383 //Slog.i("foo", "SENDING BATTERY INFO:");
384 //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
385 Parcel out = Parcel.obtain();
Adam Lesinski010bf372016-04-11 12:18:18 -0700386 updateExternalStatsSync("get-stats", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700387 synchronized (mStats) {
388 mStats.writeToParcel(out, 0);
389 }
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -0700390 byte[] data = out.marshall();
391 out.recycle();
392 try {
393 return ParcelFileDescriptor.fromData(data, "battery-stats");
394 } catch (IOException e) {
395 Slog.w(TAG, "Unable to create shared memory", e);
396 return null;
397 }
398 }
399
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700400 public boolean isCharging() {
401 synchronized (mStats) {
402 return mStats.isCharging();
403 }
404 }
405
Dianne Hackbornab5c0ea2014-04-29 14:53:32 -0700406 public long computeBatteryTimeRemaining() {
407 synchronized (mStats) {
408 long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
409 return time >= 0 ? (time/1000) : time;
410 }
411 }
412
413 public long computeChargeTimeRemaining() {
414 synchronized (mStats) {
415 long time = mStats.computeChargeTimeRemaining(SystemClock.elapsedRealtime());
416 return time >= 0 ? (time/1000) : time;
417 }
418 }
419
Dianne Hackborn099bc622014-01-22 13:39:16 -0800420 public void noteEvent(int code, String name, int uid) {
421 enforceCallingPermission();
422 synchronized (mStats) {
423 mStats.noteEventLocked(code, name, uid);
424 }
425 }
426
Dianne Hackbornfdb19562014-07-11 16:03:36 -0700427 public void noteSyncStart(String name, int uid) {
428 enforceCallingPermission();
429 synchronized (mStats) {
430 mStats.noteSyncStartLocked(name, uid);
431 }
432 }
433
434 public void noteSyncFinish(String name, int uid) {
435 enforceCallingPermission();
436 synchronized (mStats) {
437 mStats.noteSyncFinishLocked(name, uid);
438 }
439 }
440
441 public void noteJobStart(String name, int uid) {
442 enforceCallingPermission();
443 synchronized (mStats) {
444 mStats.noteJobStartLocked(name, uid);
445 }
446 }
447
448 public void noteJobFinish(String name, int uid) {
449 enforceCallingPermission();
450 synchronized (mStats) {
451 mStats.noteJobFinishLocked(name, uid);
452 }
453 }
454
Dianne Hackborn1e383822015-04-10 14:02:33 -0700455 public void noteAlarmStart(String name, int uid) {
456 enforceCallingPermission();
457 synchronized (mStats) {
458 mStats.noteAlarmStartLocked(name, uid);
459 }
460 }
461
462 public void noteAlarmFinish(String name, int uid) {
463 enforceCallingPermission();
464 synchronized (mStats) {
465 mStats.noteAlarmFinishLocked(name, uid);
466 }
467 }
468
Dianne Hackborna1f1a3c2014-02-24 18:12:28 -0800469 public void noteStartWakelock(int uid, int pid, String name, String historyName, int type,
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800470 boolean unimportantForLogging) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800471 enforceCallingPermission();
472 synchronized (mStats) {
Dianne Hackborne5167ca2014-03-08 14:39:10 -0800473 mStats.noteStartWakeLocked(uid, pid, name, historyName, type, unimportantForLogging,
Dianne Hackborn40c87252014-03-19 16:55:40 -0700474 SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 }
476 }
477
Dianne Hackborncbefd8d2014-05-14 11:42:00 -0700478 public void noteStopWakelock(int uid, int pid, String name, String historyName, int type) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 enforceCallingPermission();
480 synchronized (mStats) {
Dianne Hackborncbefd8d2014-05-14 11:42:00 -0700481 mStats.noteStopWakeLocked(uid, pid, name, historyName, type,
482 SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483 }
484 }
485
Dianne Hackborna1f1a3c2014-02-24 18:12:28 -0800486 public void noteStartWakelockFromSource(WorkSource ws, int pid, String name,
487 String historyName, int type, boolean unimportantForLogging) {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700488 enforceCallingPermission();
489 synchronized (mStats) {
Dianne Hackborna1f1a3c2014-02-24 18:12:28 -0800490 mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName,
491 type, unimportantForLogging);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700492 }
493 }
494
Dianne Hackborncbefd8d2014-05-14 11:42:00 -0700495 public void noteChangeWakelockFromSource(WorkSource ws, int pid, String name,
496 String historyName, int type, WorkSource newWs, int newPid, String newName,
Dianne Hackborne5167ca2014-03-08 14:39:10 -0800497 String newHistoryName, int newType, boolean newUnimportantForLogging) {
498 enforceCallingPermission();
499 synchronized (mStats) {
Dianne Hackborncbefd8d2014-05-14 11:42:00 -0700500 mStats.noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type,
Dianne Hackborne5167ca2014-03-08 14:39:10 -0800501 newWs, newPid, newName, newHistoryName, newType, newUnimportantForLogging);
502 }
503 }
504
Dianne Hackborncbefd8d2014-05-14 11:42:00 -0700505 public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, String historyName,
506 int type) {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700507 enforceCallingPermission();
508 synchronized (mStats) {
Dianne Hackborncbefd8d2014-05-14 11:42:00 -0700509 mStats.noteStopWakeFromSourceLocked(ws, pid, name, historyName, type);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700510 }
511 }
512
Dianne Hackbornd0db6f02016-07-18 14:14:20 -0700513 public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
514 enforceCallingPermission();
515 synchronized (mStats) {
516 mStats.noteLongPartialWakelockStart(name, historyName, uid);
517 }
518 }
519
520 public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
521 enforceCallingPermission();
522 synchronized (mStats) {
523 mStats.noteLongPartialWakelockFinish(name, historyName, uid);
524 }
525 }
526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800527 public void noteStartSensor(int uid, int sensor) {
528 enforceCallingPermission();
529 synchronized (mStats) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700530 mStats.noteStartSensorLocked(uid, sensor);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 }
532 }
533
534 public void noteStopSensor(int uid, int sensor) {
535 enforceCallingPermission();
536 synchronized (mStats) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700537 mStats.noteStopSensorLocked(uid, sensor);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 }
539 }
540
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800541 public void noteVibratorOn(int uid, long durationMillis) {
542 enforceCallingPermission();
543 synchronized (mStats) {
544 mStats.noteVibratorOnLocked(uid, durationMillis);
545 }
546 }
547
548 public void noteVibratorOff(int uid) {
549 enforceCallingPermission();
550 synchronized (mStats) {
551 mStats.noteVibratorOffLocked(uid);
552 }
553 }
554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 public void noteStartGps(int uid) {
556 enforceCallingPermission();
557 synchronized (mStats) {
Dianne Hackborn6b7b4842010-06-14 17:17:44 -0700558 mStats.noteStartGpsLocked(uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559 }
560 }
561
562 public void noteStopGps(int uid) {
563 enforceCallingPermission();
564 synchronized (mStats) {
Dianne Hackborn6b7b4842010-06-14 17:17:44 -0700565 mStats.noteStopGpsLocked(uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 }
567 }
568
Jeff Browne95c3cd2014-05-02 16:59:26 -0700569 public void noteScreenState(int state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 enforceCallingPermission();
Joe Onorato82ba91d2017-04-27 16:18:05 -0700571 if (DBG) Slog.d(TAG, "begin noteScreenState");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572 synchronized (mStats) {
Jeff Browne95c3cd2014-05-02 16:59:26 -0700573 mStats.noteScreenStateLocked(state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800574 }
Joe Onorato82ba91d2017-04-27 16:18:05 -0700575 if (DBG) Slog.d(TAG, "end noteScreenState");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800576 }
577
Dianne Hackborn617f8772009-03-31 15:04:46 -0700578 public void noteScreenBrightness(int brightness) {
579 enforceCallingPermission();
580 synchronized (mStats) {
581 mStats.noteScreenBrightnessLocked(brightness);
582 }
583 }
584
Dianne Hackborn617f8772009-03-31 15:04:46 -0700585 public void noteUserActivity(int uid, int event) {
586 enforceCallingPermission();
587 synchronized (mStats) {
588 mStats.noteUserActivityLocked(uid, event);
589 }
590 }
Jeff Browne95c3cd2014-05-02 16:59:26 -0700591
Dianne Hackborn280a64e2015-07-13 14:48:08 -0700592 public void noteWakeUp(String reason, int reasonUid) {
593 enforceCallingPermission();
594 synchronized (mStats) {
595 mStats.noteWakeUpLocked(reason, reasonUid);
596 }
597 }
598
Jeff Browne95c3cd2014-05-02 16:59:26 -0700599 public void noteInteractive(boolean interactive) {
600 enforceCallingPermission();
601 synchronized (mStats) {
602 mStats.noteInteractiveLocked(interactive);
603 }
604 }
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800605
Dianne Hackborn1e01d162014-12-04 17:46:42 -0800606 public void noteConnectivityChanged(int type, String extra) {
607 enforceCallingPermission();
608 synchronized (mStats) {
609 mStats.noteConnectivityChangedLocked(type, extra);
610 }
611 }
612
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -0700613 public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) {
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800614 enforceCallingPermission();
Adam Lesinski14ae39a2017-05-26 11:50:40 -0700615 boolean update;
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800616 synchronized (mStats) {
Adam Lesinski14ae39a2017-05-26 11:50:40 -0700617 update = mStats.noteMobileRadioPowerStateLocked(powerState, timestampNs, uid);
618 }
619
620 if (update) {
621 mHandler.scheduleSync("modem-data", UPDATE_RADIO);
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800622 }
623 }
624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 public void notePhoneOn() {
626 enforceCallingPermission();
627 synchronized (mStats) {
628 mStats.notePhoneOnLocked();
629 }
630 }
631
632 public void notePhoneOff() {
633 enforceCallingPermission();
634 synchronized (mStats) {
635 mStats.notePhoneOffLocked();
636 }
637 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700638
Wink Savillee9b06d72009-05-18 21:47:50 -0700639 public void notePhoneSignalStrength(SignalStrength signalStrength) {
Dianne Hackborn627bba72009-03-24 22:32:56 -0700640 enforceCallingPermission();
641 synchronized (mStats) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700642 mStats.notePhoneSignalStrengthLocked(signalStrength);
Dianne Hackborn627bba72009-03-24 22:32:56 -0700643 }
644 }
645
646 public void notePhoneDataConnectionState(int dataType, boolean hasData) {
647 enforceCallingPermission();
648 synchronized (mStats) {
649 mStats.notePhoneDataConnectionStateLocked(dataType, hasData);
650 }
651 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700652
Amith Yamasanif37447b2009-10-08 18:28:01 -0700653 public void notePhoneState(int state) {
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700654 enforceCallingPermission();
Dianne Hackborne4a59512010-12-07 11:08:07 -0800655 int simState = TelephonyManager.getDefault().getSimState();
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700656 synchronized (mStats) {
Dianne Hackborne4a59512010-12-07 11:08:07 -0800657 mStats.notePhoneStateLocked(state, simState);
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700658 }
659 }
660
Dianne Hackborn58e0eef2010-09-16 01:22:10 -0700661 public void noteWifiOn() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700662 enforceCallingPermission();
663 synchronized (mStats) {
Dianne Hackborn58e0eef2010-09-16 01:22:10 -0700664 mStats.noteWifiOnLocked();
The Android Open Source Project10592532009-03-18 17:39:46 -0700665 }
666 }
667
Dianne Hackborn58e0eef2010-09-16 01:22:10 -0700668 public void noteWifiOff() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700669 enforceCallingPermission();
670 synchronized (mStats) {
Dianne Hackborn58e0eef2010-09-16 01:22:10 -0700671 mStats.noteWifiOffLocked();
The Android Open Source Project10592532009-03-18 17:39:46 -0700672 }
673 }
Eric Shienbroodd4c5f892009-03-24 18:13:20 -0700674
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700675 public void noteStartAudio(int uid) {
676 enforceCallingPermission();
677 synchronized (mStats) {
678 mStats.noteAudioOnLocked(uid);
679 }
680 }
681
682 public void noteStopAudio(int uid) {
683 enforceCallingPermission();
684 synchronized (mStats) {
685 mStats.noteAudioOffLocked(uid);
686 }
687 }
688
689 public void noteStartVideo(int uid) {
690 enforceCallingPermission();
691 synchronized (mStats) {
692 mStats.noteVideoOnLocked(uid);
693 }
694 }
695
696 public void noteStopVideo(int uid) {
697 enforceCallingPermission();
698 synchronized (mStats) {
699 mStats.noteVideoOffLocked(uid);
700 }
701 }
702
Dianne Hackborn10eaa852014-07-22 22:54:55 -0700703 public void noteResetAudio() {
704 enforceCallingPermission();
705 synchronized (mStats) {
706 mStats.noteResetAudioLocked();
707 }
708 }
709
710 public void noteResetVideo() {
711 enforceCallingPermission();
712 synchronized (mStats) {
713 mStats.noteResetVideoLocked();
714 }
715 }
716
Ruben Brunk6d2c3632015-05-26 17:32:16 -0700717 public void noteFlashlightOn(int uid) {
Dianne Hackbornabc7c492014-06-30 16:57:46 -0700718 enforceCallingPermission();
719 synchronized (mStats) {
Ruben Brunk6d2c3632015-05-26 17:32:16 -0700720 mStats.noteFlashlightOnLocked(uid);
Dianne Hackbornabc7c492014-06-30 16:57:46 -0700721 }
722 }
723
Ruben Brunk6d2c3632015-05-26 17:32:16 -0700724 public void noteFlashlightOff(int uid) {
Dianne Hackbornabc7c492014-06-30 16:57:46 -0700725 enforceCallingPermission();
726 synchronized (mStats) {
Ruben Brunk6d2c3632015-05-26 17:32:16 -0700727 mStats.noteFlashlightOffLocked(uid);
728 }
729 }
730
731 public void noteStartCamera(int uid) {
732 enforceCallingPermission();
Joe Onorato82ba91d2017-04-27 16:18:05 -0700733 if (DBG) Slog.d(TAG, "begin noteStartCamera");
Ruben Brunk6d2c3632015-05-26 17:32:16 -0700734 synchronized (mStats) {
735 mStats.noteCameraOnLocked(uid);
736 }
Joe Onorato82ba91d2017-04-27 16:18:05 -0700737 if (DBG) Slog.d(TAG, "end noteStartCamera");
Ruben Brunk6d2c3632015-05-26 17:32:16 -0700738 }
739
740 public void noteStopCamera(int uid) {
741 enforceCallingPermission();
742 synchronized (mStats) {
743 mStats.noteCameraOffLocked(uid);
744 }
745 }
746
747 public void noteResetCamera() {
748 enforceCallingPermission();
749 synchronized (mStats) {
750 mStats.noteResetCameraLocked();
751 }
752 }
753
754 public void noteResetFlashlight() {
755 enforceCallingPermission();
756 synchronized (mStats) {
757 mStats.noteResetFlashlightLocked();
Dianne Hackbornabc7c492014-06-30 16:57:46 -0700758 }
759 }
760
Adam Lesinskie08af192015-03-25 16:42:59 -0700761 @Override
Adam Lesinski5f056f62016-07-14 16:56:08 -0700762 public void noteWifiRadioPowerState(int powerState, long tsNanos, int uid) {
Adam Lesinskie08af192015-03-25 16:42:59 -0700763 enforceCallingPermission();
764
765 // There was a change in WiFi power state.
766 // Collect data now for the past activity.
Dianne Hackborn0c820db2015-04-14 17:47:34 -0700767 synchronized (mStats) {
Adam Lesinskia7c90c82015-06-18 14:52:24 -0700768 if (mStats.isOnBattery()) {
Adam Lesinski06f46cb2015-06-23 13:42:53 -0700769 final String type = (powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH ||
770 powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM) ? "active"
771 : "inactive";
Adam Lesinski9f55cc72016-01-27 20:42:14 -0800772 mHandler.scheduleSync("wifi-data: " + type,
Adam Lesinski14ae39a2017-05-26 11:50:40 -0700773 UPDATE_WIFI);
Adam Lesinskia7c90c82015-06-18 14:52:24 -0700774 }
Adam Lesinski5f056f62016-07-14 16:56:08 -0700775 mStats.noteWifiRadioPowerState(powerState, tsNanos, uid);
Dianne Hackborn0c820db2015-04-14 17:47:34 -0700776 }
Adam Lesinskie08af192015-03-25 16:42:59 -0700777 }
778
Dianne Hackborn58e0eef2010-09-16 01:22:10 -0700779 public void noteWifiRunning(WorkSource ws) {
Eric Shienbroodd4c5f892009-03-24 18:13:20 -0700780 enforceCallingPermission();
781 synchronized (mStats) {
Dianne Hackborn58e0eef2010-09-16 01:22:10 -0700782 mStats.noteWifiRunningLocked(ws);
Eric Shienbroodd4c5f892009-03-24 18:13:20 -0700783 }
784 }
785
Dianne Hackborn58e0eef2010-09-16 01:22:10 -0700786 public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) {
Eric Shienbroodd4c5f892009-03-24 18:13:20 -0700787 enforceCallingPermission();
788 synchronized (mStats) {
Dianne Hackborn58e0eef2010-09-16 01:22:10 -0700789 mStats.noteWifiRunningChangedLocked(oldWs, newWs);
790 }
791 }
792
793 public void noteWifiStopped(WorkSource ws) {
794 enforceCallingPermission();
795 synchronized (mStats) {
796 mStats.noteWifiStoppedLocked(ws);
Eric Shienbroodd4c5f892009-03-24 18:13:20 -0700797 }
798 }
799
Dianne Hackbornca1bf212014-02-14 14:18:36 -0800800 public void noteWifiState(int wifiState, String accessPoint) {
801 enforceCallingPermission();
802 synchronized (mStats) {
803 mStats.noteWifiStateLocked(wifiState, accessPoint);
804 }
805 }
806
Dianne Hackborn3251b902014-06-20 14:40:53 -0700807 public void noteWifiSupplicantStateChanged(int supplState, boolean failedAuth) {
808 enforceCallingPermission();
809 synchronized (mStats) {
810 mStats.noteWifiSupplicantStateChangedLocked(supplState, failedAuth);
811 }
812 }
813
814 public void noteWifiRssiChanged(int newRssi) {
815 enforceCallingPermission();
816 synchronized (mStats) {
817 mStats.noteWifiRssiChangedLocked(newRssi);
818 }
819 }
820
The Android Open Source Project10592532009-03-18 17:39:46 -0700821 public void noteFullWifiLockAcquired(int uid) {
822 enforceCallingPermission();
823 synchronized (mStats) {
824 mStats.noteFullWifiLockAcquiredLocked(uid);
825 }
826 }
827
828 public void noteFullWifiLockReleased(int uid) {
829 enforceCallingPermission();
830 synchronized (mStats) {
831 mStats.noteFullWifiLockReleasedLocked(uid);
832 }
833 }
Nick Pelly6ccaa542012-06-15 15:22:47 -0700834
835 public void noteWifiScanStarted(int uid) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700836 enforceCallingPermission();
837 synchronized (mStats) {
Nick Pelly6ccaa542012-06-15 15:22:47 -0700838 mStats.noteWifiScanStartedLocked(uid);
The Android Open Source Project10592532009-03-18 17:39:46 -0700839 }
840 }
Nick Pelly6ccaa542012-06-15 15:22:47 -0700841
842 public void noteWifiScanStopped(int uid) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700843 enforceCallingPermission();
844 synchronized (mStats) {
Nick Pelly6ccaa542012-06-15 15:22:47 -0700845 mStats.noteWifiScanStoppedLocked(uid);
The Android Open Source Project10592532009-03-18 17:39:46 -0700846 }
847 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848
Robert Greenwalt5347bd42009-05-13 15:10:16 -0700849 public void noteWifiMulticastEnabled(int uid) {
850 enforceCallingPermission();
851 synchronized (mStats) {
852 mStats.noteWifiMulticastEnabledLocked(uid);
853 }
854 }
855
856 public void noteWifiMulticastDisabled(int uid) {
857 enforceCallingPermission();
858 synchronized (mStats) {
859 mStats.noteWifiMulticastDisabledLocked(uid);
860 }
861 }
862
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700863 public void noteFullWifiLockAcquiredFromSource(WorkSource ws) {
864 enforceCallingPermission();
865 synchronized (mStats) {
866 mStats.noteFullWifiLockAcquiredFromSourceLocked(ws);
867 }
868 }
869
870 public void noteFullWifiLockReleasedFromSource(WorkSource ws) {
871 enforceCallingPermission();
872 synchronized (mStats) {
873 mStats.noteFullWifiLockReleasedFromSourceLocked(ws);
874 }
875 }
876
Nick Pelly6ccaa542012-06-15 15:22:47 -0700877 public void noteWifiScanStartedFromSource(WorkSource ws) {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700878 enforceCallingPermission();
879 synchronized (mStats) {
Nick Pelly6ccaa542012-06-15 15:22:47 -0700880 mStats.noteWifiScanStartedFromSourceLocked(ws);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700881 }
882 }
883
Nick Pelly6ccaa542012-06-15 15:22:47 -0700884 public void noteWifiScanStoppedFromSource(WorkSource ws) {
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700885 enforceCallingPermission();
886 synchronized (mStats) {
Nick Pelly6ccaa542012-06-15 15:22:47 -0700887 mStats.noteWifiScanStoppedFromSourceLocked(ws);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700888 }
889 }
890
Robert Greenwalta029ea12013-09-25 16:38:12 -0700891 public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) {
892 enforceCallingPermission();
893 synchronized (mStats) {
894 mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph);
895 }
896 }
897
898 public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) {
899 enforceCallingPermission();
900 synchronized (mStats) {
901 mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws);
902 }
903 }
904
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700905 public void noteWifiMulticastEnabledFromSource(WorkSource ws) {
906 enforceCallingPermission();
907 synchronized (mStats) {
908 mStats.noteWifiMulticastEnabledFromSourceLocked(ws);
909 }
910 }
911
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700912 @Override
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700913 public void noteWifiMulticastDisabledFromSource(WorkSource ws) {
914 enforceCallingPermission();
915 synchronized (mStats) {
916 mStats.noteWifiMulticastDisabledFromSourceLocked(ws);
917 }
918 }
919
Jeff Sharkey7a1c3fc2013-06-04 12:29:00 -0700920 @Override
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700921 public void noteNetworkInterfaceType(String iface, int networkType) {
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700922 enforceCallingPermission();
923 synchronized (mStats) {
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -0700924 mStats.noteNetworkInterfaceTypeLocked(iface, networkType);
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700925 }
926 }
927
Jeff Sharkey7a1c3fc2013-06-04 12:29:00 -0700928 @Override
929 public void noteNetworkStatsEnabled() {
930 enforceCallingPermission();
Adam Lesinski14ae39a2017-05-26 11:50:40 -0700931 mHandler.scheduleSync("network-stats-enabled", UPDATE_RADIO | UPDATE_WIFI);
Jeff Sharkey7a1c3fc2013-06-04 12:29:00 -0700932 }
933
Dianne Hackborn8ad2af72015-03-17 17:00:24 -0700934 @Override
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700935 public void noteDeviceIdleMode(int mode, String activeReason, int activeUid) {
Dianne Hackborn8ad2af72015-03-17 17:00:24 -0700936 enforceCallingPermission();
937 synchronized (mStats) {
Dianne Hackborn08c47a52015-10-15 12:38:14 -0700938 mStats.noteDeviceIdleModeLocked(mode, activeReason, activeUid);
Dianne Hackborn8ad2af72015-03-17 17:00:24 -0700939 }
940 }
941
942 public void notePackageInstalled(String pkgName, int versionCode) {
943 enforceCallingPermission();
944 synchronized (mStats) {
945 mStats.notePackageInstalledLocked(pkgName, versionCode);
946 }
947 }
948
949 public void notePackageUninstalled(String pkgName) {
950 enforceCallingPermission();
951 synchronized (mStats) {
952 mStats.notePackageUninstalledLocked(pkgName);
953 }
954 }
955
Adam Lesinski6771d622016-01-15 18:14:47 -0800956 @Override
Bookatzb1f04f32017-05-19 13:57:32 -0700957 public void noteBleScanStarted(WorkSource ws, boolean isUnoptimized) {
Adam Lesinski6771d622016-01-15 18:14:47 -0800958 enforceCallingPermission();
Adam Lesinski9f55cc72016-01-27 20:42:14 -0800959 synchronized (mStats) {
Bookatzb1f04f32017-05-19 13:57:32 -0700960 mStats.noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized);
Adam Lesinski9f55cc72016-01-27 20:42:14 -0800961 }
Adam Lesinski6771d622016-01-15 18:14:47 -0800962 }
963
964 @Override
Bookatz20e22f62017-07-11 16:49:17 -0700965 public void noteBleScanStopped(WorkSource ws, boolean isUnoptimized) {
Adam Lesinski6771d622016-01-15 18:14:47 -0800966 enforceCallingPermission();
Adam Lesinski9f55cc72016-01-27 20:42:14 -0800967 synchronized (mStats) {
Bookatz20e22f62017-07-11 16:49:17 -0700968 mStats.noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized);
Adam Lesinski9f55cc72016-01-27 20:42:14 -0800969 }
970 }
971
972 @Override
973 public void noteResetBleScan() {
974 enforceCallingPermission();
975 synchronized (mStats) {
976 mStats.noteResetBluetoothScanLocked();
977 }
Adam Lesinski6771d622016-01-15 18:14:47 -0800978 }
979
Adam Lesinski010bf372016-04-11 12:18:18 -0700980 @Override
Bookatz4ebc0642017-05-11 12:21:19 -0700981 public void noteBleScanResults(WorkSource ws, int numNewResults) {
Bookatz956f36bf2017-04-28 09:48:17 -0700982 enforceCallingPermission();
983 synchronized (mStats) {
Bookatz4ebc0642017-05-11 12:21:19 -0700984 mStats.noteBluetoothScanResultsFromSourceLocked(ws, numNewResults);
Bookatz956f36bf2017-04-28 09:48:17 -0700985 }
986 }
987
988 @Override
Adam Lesinski010bf372016-04-11 12:18:18 -0700989 public void noteWifiControllerActivity(WifiActivityEnergyInfo info) {
990 enforceCallingPermission();
991
992 if (info == null || !info.isValid()) {
993 Slog.e(TAG, "invalid wifi data given: " + info);
994 return;
995 }
996
Adam Lesinski14ae39a2017-05-26 11:50:40 -0700997 mStats.updateWifiState(info);
Adam Lesinski010bf372016-04-11 12:18:18 -0700998 }
999
1000 @Override
1001 public void noteBluetoothControllerActivity(BluetoothActivityEnergyInfo info) {
1002 enforceCallingPermission();
1003 if (info == null || !info.isValid()) {
1004 Slog.e(TAG, "invalid bluetooth data given: " + info);
1005 return;
1006 }
1007
1008 synchronized (mStats) {
1009 mStats.updateBluetoothStateLocked(info);
1010 }
1011 }
1012
1013 @Override
1014 public void noteModemControllerActivity(ModemActivityInfo info) {
1015 enforceCallingPermission();
1016
1017 if (info == null || !info.isValid()) {
1018 Slog.e(TAG, "invalid modem data given: " + info);
1019 return;
1020 }
1021
Adam Lesinski14ae39a2017-05-26 11:50:40 -07001022 mStats.updateMobileRadioState(info);
Adam Lesinski010bf372016-04-11 12:18:18 -07001023 }
1024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 public boolean isOnBattery() {
1026 return mStats.isOnBattery();
1027 }
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001028
Adam Lesinskid7616ef2015-07-27 11:43:05 -07001029 @Override
1030 public void setBatteryState(final int status, final int health, final int plugType,
Adam Lesinski041d9172016-12-12 12:03:56 -08001031 final int level, final int temp, final int volt, final int chargeUAh,
1032 final int chargeFullUAh) {
Adam Lesinskid7616ef2015-07-27 11:43:05 -07001033 enforceCallingPermission();
1034
1035 // BatteryService calls us here and we may update external state. It would be wrong
1036 // to block such a low level service like BatteryService on external stats like WiFi.
1037 mHandler.post(new Runnable() {
1038 @Override
1039 public void run() {
Adam Lesinski63934522017-04-05 17:54:13 -07001040 synchronized (mStats) {
1041 final boolean onBattery = plugType == BatteryStatsImpl.BATTERY_PLUGGED_NONE;
1042 if (mStats.isOnBattery() == onBattery) {
1043 // The battery state has not changed, so we don't need to sync external
1044 // stats immediately.
1045 mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt,
1046 chargeUAh, chargeFullUAh);
1047 return;
Adam Lesinskid7616ef2015-07-27 11:43:05 -07001048 }
1049 }
1050
1051 // Sync external stats first as the battery has changed states. If we don't sync
1052 // immediately here, we may not collect the relevant data later.
Adam Lesinski010bf372016-04-11 12:18:18 -07001053 updateExternalStatsSync("battery-state", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
Adam Lesinskid7616ef2015-07-27 11:43:05 -07001054 synchronized (mStats) {
Adam Lesinski926969b2016-04-28 17:31:12 -07001055 mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt,
Adam Lesinski041d9172016-12-12 12:03:56 -08001056 chargeUAh, chargeFullUAh);
Adam Lesinskid7616ef2015-07-27 11:43:05 -07001057 }
1058 }
1059 });
Evan Millar633a1742009-04-02 16:36:33 -07001060 }
1061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 public long getAwakeTimeBattery() {
1063 mContext.enforceCallingOrSelfPermission(
1064 android.Manifest.permission.BATTERY_STATS, null);
1065 return mStats.getAwakeTimeBattery();
1066 }
1067
1068 public long getAwakeTimePlugged() {
1069 mContext.enforceCallingOrSelfPermission(
1070 android.Manifest.permission.BATTERY_STATS, null);
1071 return mStats.getAwakeTimePlugged();
1072 }
1073
1074 public void enforceCallingPermission() {
1075 if (Binder.getCallingPid() == Process.myPid()) {
1076 return;
1077 }
1078 mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
1079 Binder.getCallingPid(), Binder.getCallingUid(), null);
1080 }
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001081
1082 final class WakeupReasonThread extends Thread {
Adam Lesinski515702c2015-07-23 18:13:38 -07001083 private static final int MAX_REASON_SIZE = 512;
1084 private CharsetDecoder mDecoder;
1085 private ByteBuffer mUtf8Buffer;
1086 private CharBuffer mUtf16Buffer;
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001087
1088 WakeupReasonThread() {
1089 super("BatteryStats_wakeupReason");
1090 }
1091
1092 public void run() {
1093 Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
1094
Adam Lesinski515702c2015-07-23 18:13:38 -07001095 mDecoder = StandardCharsets.UTF_8
1096 .newDecoder()
1097 .onMalformedInput(CodingErrorAction.REPLACE)
1098 .onUnmappableCharacter(CodingErrorAction.REPLACE)
1099 .replaceWith("?");
1100
1101 mUtf8Buffer = ByteBuffer.allocateDirect(MAX_REASON_SIZE);
1102 mUtf16Buffer = CharBuffer.allocate(MAX_REASON_SIZE);
1103
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001104 try {
Adam Lesinski515702c2015-07-23 18:13:38 -07001105 String reason;
1106 while ((reason = waitWakeup()) != null) {
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001107 synchronized (mStats) {
Adam Lesinski515702c2015-07-23 18:13:38 -07001108 mStats.noteWakeupReasonLocked(reason);
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001109 }
1110 }
1111 } catch (RuntimeException e) {
1112 Slog.e(TAG, "Failure reading wakeup reasons", e);
1113 }
1114 }
Adam Lesinski515702c2015-07-23 18:13:38 -07001115
1116 private String waitWakeup() {
1117 mUtf8Buffer.clear();
1118 mUtf16Buffer.clear();
1119 mDecoder.reset();
1120
1121 int bytesWritten = nativeWaitWakeup(mUtf8Buffer);
1122 if (bytesWritten < 0) {
1123 return null;
1124 } else if (bytesWritten == 0) {
1125 return "unknown";
1126 }
1127
1128 // Set the buffer's limit to the number of bytes written.
1129 mUtf8Buffer.limit(bytesWritten);
1130
1131 // Decode the buffer from UTF-8 to UTF-16.
1132 // Unmappable characters will be replaced.
1133 mDecoder.decode(mUtf8Buffer, mUtf16Buffer, true);
1134 mUtf16Buffer.flip();
1135
1136 // Create a String from the UTF-16 buffer.
1137 return mUtf16Buffer.toString();
1138 }
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001139 }
1140
Adam Lesinski515702c2015-07-23 18:13:38 -07001141 private static native int nativeWaitWakeup(ByteBuffer outBuffer);
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001142
Dianne Hackbornae384452011-06-28 12:33:48 -07001143 private void dumpHelp(PrintWriter pw) {
Dianne Hackborn91268cf2013-06-13 19:06:50 -07001144 pw.println("Battery stats (batterystats) dump options:");
Dianne Hackborn1e725a72015-03-24 18:23:19 -07001145 pw.println(" [--checkin] [--history] [--history-start] [--charged] [-c]");
Dianne Hackbornd4a8af72015-03-03 10:06:15 -08001146 pw.println(" [--daily] [--reset] [--write] [--new-daily] [--read-daily] [-h] [<package.name>]");
Dianne Hackborn865b79b2015-08-18 17:33:00 -07001147 pw.println(" --checkin: generate output for a checkin report; will write (and clear) the");
1148 pw.println(" last old completed stats when they had been reset.");
Joe Onorato1476d322016-05-05 14:46:15 -07001149 pw.println(" -c: write the current stats in checkin format.");
Dianne Hackborn099bc622014-01-22 13:39:16 -08001150 pw.println(" --history: show only history data.");
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001151 pw.println(" --history-start <num>: show only history data starting at given time offset.");
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001152 pw.println(" --charged: only output data since last charged.");
Dianne Hackbornd4a8af72015-03-03 10:06:15 -08001153 pw.println(" --daily: only output full daily data.");
Dianne Hackbornae384452011-06-28 12:33:48 -07001154 pw.println(" --reset: reset the stats, clearing all current data.");
1155 pw.println(" --write: force write current collected stats to disk.");
Dianne Hackbornd4a8af72015-03-03 10:06:15 -08001156 pw.println(" --new-daily: immediately create and write new daily stats record.");
1157 pw.println(" --read-daily: read-load last written daily stats.");
Dianne Hackborncbfd23e2013-06-11 14:26:53 -07001158 pw.println(" <package.name>: optional name of package to filter output by.");
Dianne Hackbornfc064132014-06-02 12:42:12 -07001159 pw.println(" -h: print this help text.");
1160 pw.println("Battery stats (batterystats) commands:");
1161 pw.println(" enable|disable <option>");
1162 pw.println(" Enable or disable a running option. Option state is not saved across boots.");
1163 pw.println(" Options are:");
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -07001164 pw.println(" full-history: include additional detailed events in battery history:");
Dianne Hackborn1e383822015-04-10 14:02:33 -07001165 pw.println(" wake_lock_in, alarms and proc events");
Dianne Hackbornfc064132014-06-02 12:42:12 -07001166 pw.println(" no-auto-reset: don't automatically reset stats when unplugged");
Amith Yamasani674c9bb2017-02-01 09:45:17 -08001167 pw.println(" pretend-screen-off: pretend the screen is off, even if screen state changes");
Dianne Hackbornae384452011-06-28 12:33:48 -07001168 }
1169
Dianne Hackborncbefd8d2014-05-14 11:42:00 -07001170 private int doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable) {
1171 i++;
1172 if (i >= args.length) {
1173 pw.println("Missing option argument for " + (enable ? "--enable" : "--disable"));
1174 dumpHelp(pw);
1175 return -1;
1176 }
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -07001177 if ("full-wake-history".equals(args[i]) || "full-history".equals(args[i])) {
Dianne Hackborncbefd8d2014-05-14 11:42:00 -07001178 synchronized (mStats) {
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -07001179 mStats.setRecordAllHistoryLocked(enable);
Dianne Hackborncbefd8d2014-05-14 11:42:00 -07001180 }
Dianne Hackborn9a755432014-05-15 17:05:22 -07001181 } else if ("no-auto-reset".equals(args[i])) {
1182 synchronized (mStats) {
1183 mStats.setNoAutoReset(enable);
1184 }
Amith Yamasani674c9bb2017-02-01 09:45:17 -08001185 } else if ("pretend-screen-off".equals(args[i])) {
1186 synchronized (mStats) {
1187 mStats.setPretendScreenOff(enable);
1188 }
Dianne Hackborncbefd8d2014-05-14 11:42:00 -07001189 } else {
1190 pw.println("Unknown enable/disable option: " + args[i]);
1191 dumpHelp(pw);
1192 return -1;
1193 }
1194 return i;
1195 }
1196
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001198 @Override
1199 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkey6df866a2017-03-31 14:08:23 -06001200 if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
Kenny Root3abd75b2011-09-29 11:00:41 -07001201
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001202 int flags = 0;
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -07001203 boolean useCheckinFormat = false;
1204 boolean isRealCheckin = false;
Dianne Hackborn0ffc9882011-04-13 18:15:56 -07001205 boolean noOutput = false;
Dianne Hackborn16b0b562014-06-03 17:24:42 -07001206 boolean writeData = false;
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001207 long historyStart = -1;
Dianne Hackborncbfd23e2013-06-11 14:26:53 -07001208 int reqUid = -1;
Dianne Hackborne4a59512010-12-07 11:08:07 -08001209 if (args != null) {
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001210 for (int i=0; i<args.length; i++) {
1211 String arg = args[i];
Dianne Hackborne4a59512010-12-07 11:08:07 -08001212 if ("--checkin".equals(arg)) {
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -07001213 useCheckinFormat = true;
1214 isRealCheckin = true;
Dianne Hackborn099bc622014-01-22 13:39:16 -08001215 } else if ("--history".equals(arg)) {
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001216 flags |= BatteryStats.DUMP_HISTORY_ONLY;
1217 } else if ("--history-start".equals(arg)) {
1218 flags |= BatteryStats.DUMP_HISTORY_ONLY;
1219 i++;
1220 if (i >= args.length) {
1221 pw.println("Missing time argument for --history-since");
1222 dumpHelp(pw);
1223 return;
1224 }
1225 historyStart = Long.parseLong(args[i]);
Dianne Hackborn16b0b562014-06-03 17:24:42 -07001226 writeData = true;
Dianne Hackborn49021f52013-09-04 18:03:40 -07001227 } else if ("-c".equals(arg)) {
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -07001228 useCheckinFormat = true;
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001229 flags |= BatteryStats.DUMP_INCLUDE_HISTORY;
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001230 } else if ("--charged".equals(arg)) {
1231 flags |= BatteryStats.DUMP_CHARGED_ONLY;
Dianne Hackbornd4a8af72015-03-03 10:06:15 -08001232 } else if ("--daily".equals(arg)) {
1233 flags |= BatteryStats.DUMP_DAILY_ONLY;
Dianne Hackborne4a59512010-12-07 11:08:07 -08001234 } else if ("--reset".equals(arg)) {
1235 synchronized (mStats) {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001236 mStats.resetAllStatsCmdLocked();
Dianne Hackborne4a59512010-12-07 11:08:07 -08001237 pw.println("Battery stats reset.");
Dianne Hackborn0ffc9882011-04-13 18:15:56 -07001238 noOutput = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 }
Adam Lesinski010bf372016-04-11 12:18:18 -07001240 updateExternalStatsSync("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
Dianne Hackborn0ffc9882011-04-13 18:15:56 -07001241 } else if ("--write".equals(arg)) {
Adam Lesinski010bf372016-04-11 12:18:18 -07001242 updateExternalStatsSync("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
Dianne Hackborn0ffc9882011-04-13 18:15:56 -07001243 synchronized (mStats) {
1244 mStats.writeSyncLocked();
1245 pw.println("Battery stats written.");
1246 noOutput = true;
1247 }
Dianne Hackbornd4a8af72015-03-03 10:06:15 -08001248 } else if ("--new-daily".equals(arg)) {
1249 synchronized (mStats) {
1250 mStats.recordDailyStatsLocked();
1251 pw.println("New daily stats written.");
1252 noOutput = true;
1253 }
1254 } else if ("--read-daily".equals(arg)) {
1255 synchronized (mStats) {
1256 mStats.readDailyStatsLocked();
1257 pw.println("Last daily stats read.");
1258 noOutput = true;
1259 }
Dianne Hackbornfc064132014-06-02 12:42:12 -07001260 } else if ("--enable".equals(arg) || "enable".equals(arg)) {
Dianne Hackborncbefd8d2014-05-14 11:42:00 -07001261 i = doEnableOrDisable(pw, i, args, true);
1262 if (i < 0) {
1263 return;
1264 }
1265 pw.println("Enabled: " + args[i]);
1266 return;
Dianne Hackbornfc064132014-06-02 12:42:12 -07001267 } else if ("--disable".equals(arg) || "disable".equals(arg)) {
Dianne Hackborncbefd8d2014-05-14 11:42:00 -07001268 i = doEnableOrDisable(pw, i, args, false);
1269 if (i < 0) {
1270 return;
1271 }
1272 pw.println("Disabled: " + args[i]);
1273 return;
Dianne Hackbornae384452011-06-28 12:33:48 -07001274 } else if ("-h".equals(arg)) {
1275 dumpHelp(pw);
1276 return;
Mike Lockwoode8174042011-08-16 12:53:43 -07001277 } else if ("-a".equals(arg)) {
Dianne Hackborna1bd7922014-03-21 11:07:11 -07001278 flags |= BatteryStats.DUMP_VERBOSE;
Dianne Hackborncbfd23e2013-06-11 14:26:53 -07001279 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
Dianne Hackborn0ffc9882011-04-13 18:15:56 -07001280 pw.println("Unknown option: " + arg);
Dianne Hackbornae384452011-06-28 12:33:48 -07001281 dumpHelp(pw);
Dianne Hackborncbfd23e2013-06-11 14:26:53 -07001282 return;
1283 } else {
1284 // Not an option, last argument must be a package name.
1285 try {
Jeff Sharkeye06b4d12016-01-06 14:51:50 -07001286 reqUid = mContext.getPackageManager().getPackageUidAsUser(arg,
Dianne Hackborncbfd23e2013-06-11 14:26:53 -07001287 UserHandle.getCallingUserId());
1288 } catch (PackageManager.NameNotFoundException e) {
1289 pw.println("Unknown package: " + arg);
1290 dumpHelp(pw);
1291 return;
1292 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001293 }
1294 }
Dianne Hackborne4a59512010-12-07 11:08:07 -08001295 }
Dianne Hackborn0ffc9882011-04-13 18:15:56 -07001296 if (noOutput) {
1297 return;
1298 }
Dianne Hackborn13a6a9b2015-04-22 18:03:59 -07001299
1300 long ident = Binder.clearCallingIdentity();
1301 try {
1302 if (BatteryStatsHelper.checkWifiOnly(mContext)) {
1303 flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY;
1304 }
1305 // Fetch data from external sources and update the BatteryStatsImpl object with them.
Adam Lesinski010bf372016-04-11 12:18:18 -07001306 updateExternalStatsSync("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
Dianne Hackborn13a6a9b2015-04-22 18:03:59 -07001307 } finally {
1308 Binder.restoreCallingIdentity(ident);
Dianne Hackbornd953c532014-08-16 18:17:38 -07001309 }
Dianne Hackborn13a6a9b2015-04-22 18:03:59 -07001310
Dianne Hackbornab4a81b2014-10-09 17:59:38 -07001311 if (reqUid >= 0) {
1312 // By default, if the caller is only interested in a specific package, then
1313 // we only dump the aggregated data since charged.
Dianne Hackborn1e725a72015-03-24 18:23:19 -07001314 if ((flags&(BatteryStats.DUMP_HISTORY_ONLY|BatteryStats.DUMP_CHARGED_ONLY)) == 0) {
Dianne Hackbornab4a81b2014-10-09 17:59:38 -07001315 flags |= BatteryStats.DUMP_CHARGED_ONLY;
1316 // Also if they are doing -c, we don't want history.
1317 flags &= ~BatteryStats.DUMP_INCLUDE_HISTORY;
1318 }
1319 }
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001320
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -07001321 if (useCheckinFormat) {
Dianne Hackborn9cfba352016-03-24 17:31:28 -07001322 List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07001323 PackageManager.MATCH_ANY_USER | PackageManager.MATCH_ALL);
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -07001324 if (isRealCheckin) {
1325 // For a real checkin, first we want to prefer to use the last complete checkin
1326 // file if there is one.
1327 synchronized (mStats.mCheckinFile) {
1328 if (mStats.mCheckinFile.exists()) {
1329 try {
1330 byte[] raw = mStats.mCheckinFile.readFully();
1331 if (raw != null) {
1332 Parcel in = Parcel.obtain();
1333 in.unmarshall(raw, 0, raw.length);
1334 in.setDataPosition(0);
1335 BatteryStatsImpl checkinStats = new BatteryStatsImpl(
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001336 null, mStats.mHandler, null);
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -07001337 checkinStats.readSummaryFromParcel(in);
1338 in.recycle();
1339 checkinStats.dumpCheckinLocked(mContext, pw, apps, flags,
1340 historyStart);
1341 mStats.mCheckinFile.delete();
1342 return;
1343 }
Adam Lesinski9ae9cba2015-07-08 17:09:34 -07001344 } catch (IOException | ParcelFormatException e) {
Dianne Hackborn0068d3dc2014-08-06 19:20:25 -07001345 Slog.w(TAG, "Failure reading checkin file "
1346 + mStats.mCheckinFile.getBaseFile(), e);
1347 }
1348 }
1349 }
1350 }
Joe Onorato82ba91d2017-04-27 16:18:05 -07001351 if (DBG) Slog.d(TAG, "begin dumpCheckinLocked from UID " + Binder.getCallingUid());
Dianne Hackborne4a59512010-12-07 11:08:07 -08001352 synchronized (mStats) {
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001353 mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
Dianne Hackborn16b0b562014-06-03 17:24:42 -07001354 if (writeData) {
1355 mStats.writeAsyncLocked();
1356 }
Dianne Hackborne4a59512010-12-07 11:08:07 -08001357 }
Joe Onorato82ba91d2017-04-27 16:18:05 -07001358 if (DBG) Slog.d(TAG, "end dumpCheckinLocked");
Dianne Hackborne4a59512010-12-07 11:08:07 -08001359 } else {
Joe Onorato82ba91d2017-04-27 16:18:05 -07001360 if (DBG) Slog.d(TAG, "begin dumpLocked from UID " + Binder.getCallingUid());
Dianne Hackborne4a59512010-12-07 11:08:07 -08001361 synchronized (mStats) {
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001362 mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart);
Dianne Hackborn16b0b562014-06-03 17:24:42 -07001363 if (writeData) {
1364 mStats.writeAsyncLocked();
1365 }
Dianne Hackborne4a59512010-12-07 11:08:07 -08001366 }
Joe Onorato82ba91d2017-04-27 16:18:05 -07001367 if (DBG) Slog.d(TAG, "end dumpLocked");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 }
1369 }
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001370
Adam Lesinski010bf372016-04-11 12:18:18 -07001371 private WifiActivityEnergyInfo extractDelta(WifiActivityEnergyInfo latest) {
1372 final long timePeriodMs = latest.mTimestamp - mLastInfo.mTimestamp;
1373 final long lastIdleMs = mLastInfo.mControllerIdleTimeMs;
1374 final long lastTxMs = mLastInfo.mControllerTxTimeMs;
1375 final long lastRxMs = mLastInfo.mControllerRxTimeMs;
1376 final long lastEnergy = mLastInfo.mControllerEnergyUsed;
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001377
Adam Lesinski010bf372016-04-11 12:18:18 -07001378 // We will modify the last info object to be the delta, and store the new
1379 // WifiActivityEnergyInfo object as our last one.
1380 final WifiActivityEnergyInfo delta = mLastInfo;
1381 delta.mTimestamp = latest.getTimeStamp();
1382 delta.mStackState = latest.getStackState();
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001383
Roshan Pius68459112016-05-16 13:00:25 -07001384 final long txTimeMs = latest.mControllerTxTimeMs - lastTxMs;
1385 final long rxTimeMs = latest.mControllerRxTimeMs - lastRxMs;
1386 final long idleTimeMs = latest.mControllerIdleTimeMs - lastIdleMs;
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001387
Roshan Pius68459112016-05-16 13:00:25 -07001388 if (txTimeMs < 0 || rxTimeMs < 0) {
Adam Lesinski010bf372016-04-11 12:18:18 -07001389 // The stats were reset by the WiFi system (which is why our delta is negative).
1390 // Returns the unaltered stats.
1391 delta.mControllerEnergyUsed = latest.mControllerEnergyUsed;
1392 delta.mControllerRxTimeMs = latest.mControllerRxTimeMs;
1393 delta.mControllerTxTimeMs = latest.mControllerTxTimeMs;
1394 delta.mControllerIdleTimeMs = latest.mControllerIdleTimeMs;
Adam Lesinski010bf372016-04-11 12:18:18 -07001395 Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + delta);
Roshan Pius68459112016-05-16 13:00:25 -07001396 } else {
1397 final long totalActiveTimeMs = txTimeMs + rxTimeMs;
1398 long maxExpectedIdleTimeMs;
Roshan Pius68459112016-05-16 13:00:25 -07001399 if (totalActiveTimeMs > timePeriodMs) {
Roshan Pius2078d342016-05-25 09:32:17 -07001400 // Cap the max idle time at zero since the active time consumed the whole time
1401 maxExpectedIdleTimeMs = 0;
1402 if (totalActiveTimeMs > timePeriodMs + MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS) {
1403 StringBuilder sb = new StringBuilder();
1404 sb.append("Total Active time ");
1405 TimeUtils.formatDuration(totalActiveTimeMs, sb);
1406 sb.append(" is longer than sample period ");
1407 TimeUtils.formatDuration(timePeriodMs, sb);
1408 sb.append(".\n");
1409 sb.append("Previous WiFi snapshot: ").append("idle=");
1410 TimeUtils.formatDuration(lastIdleMs, sb);
1411 sb.append(" rx=");
1412 TimeUtils.formatDuration(lastRxMs, sb);
1413 sb.append(" tx=");
1414 TimeUtils.formatDuration(lastTxMs, sb);
1415 sb.append(" e=").append(lastEnergy);
1416 sb.append("\n");
1417 sb.append("Current WiFi snapshot: ").append("idle=");
1418 TimeUtils.formatDuration(latest.mControllerIdleTimeMs, sb);
1419 sb.append(" rx=");
1420 TimeUtils.formatDuration(latest.mControllerRxTimeMs, sb);
1421 sb.append(" tx=");
1422 TimeUtils.formatDuration(latest.mControllerTxTimeMs, sb);
1423 sb.append(" e=").append(latest.mControllerEnergyUsed);
1424 Slog.wtf(TAG, sb.toString());
1425 }
Roshan Pius68459112016-05-16 13:00:25 -07001426 } else {
1427 maxExpectedIdleTimeMs = timePeriodMs - totalActiveTimeMs;
1428 }
1429 // These times seem to be the most reliable.
1430 delta.mControllerTxTimeMs = txTimeMs;
1431 delta.mControllerRxTimeMs = rxTimeMs;
1432 // WiFi calculates the idle time as a difference from the on time and the various
1433 // Rx + Tx times. There seems to be some missing time there because this sometimes
1434 // becomes negative. Just cap it at 0 and ensure that it is less than the expected idle
1435 // time from the difference in timestamps.
1436 // b/21613534
1437 delta.mControllerIdleTimeMs = Math.min(maxExpectedIdleTimeMs, Math.max(0, idleTimeMs));
1438 delta.mControllerEnergyUsed = Math.max(0, latest.mControllerEnergyUsed - lastEnergy);
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001439 }
Adam Lesinski010bf372016-04-11 12:18:18 -07001440
1441 mLastInfo = latest;
1442 return delta;
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001443 }
1444
Adam Lesinski010bf372016-04-11 12:18:18 -07001445 /**
1446 * Helper method to extract the Parcelable controller info from a
1447 * SynchronousResultReceiver.
1448 */
1449 private static <T extends Parcelable> T awaitControllerInfo(
1450 @Nullable SynchronousResultReceiver receiver) throws TimeoutException {
1451 if (receiver == null) {
1452 return null;
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001453 }
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001454
Adam Lesinski010bf372016-04-11 12:18:18 -07001455 final SynchronousResultReceiver.Result result =
1456 receiver.awaitResult(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS);
1457 if (result.bundle != null) {
1458 // This is the final destination for the Bundle.
1459 result.bundle.setDefusable(true);
1460
1461 final T data = result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
1462 if (data != null) {
1463 return data;
Adam Lesinski21f76aa2016-01-25 12:27:06 -08001464 }
Adam Lesinski21f76aa2016-01-25 12:27:06 -08001465 }
Adam Lesinski010bf372016-04-11 12:18:18 -07001466 Slog.e(TAG, "no controller energy info supplied");
Adam Lesinski21f76aa2016-01-25 12:27:06 -08001467 return null;
1468 }
1469
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001470 /**
1471 * Fetches data from external sources (WiFi controller, bluetooth chipset) and updates
1472 * batterystats with that information.
1473 *
1474 * We first grab a lock specific to this method, then once all the data has been collected,
1475 * we grab the mStats lock and update the data.
Adam Lesinskic14c2732015-05-21 15:04:18 -07001476 *
Adam Lesinskic14c2732015-05-21 15:04:18 -07001477 * @param reason The reason why this collection was requested. Useful for debugging.
Adam Lesinskia7c90c82015-06-18 14:52:24 -07001478 * @param updateFlags Which external stats to update. Can be a combination of
Adam Lesinski9f55cc72016-01-27 20:42:14 -08001479 * {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_CPU},
1480 * {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_RADIO},
1481 * {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_WIFI},
1482 * and {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_BT}.
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001483 */
Adam Lesinski010bf372016-04-11 12:18:18 -07001484 void updateExternalStatsSync(final String reason, int updateFlags) {
1485 SynchronousResultReceiver wifiReceiver = null;
1486 SynchronousResultReceiver bluetoothReceiver = null;
1487 SynchronousResultReceiver modemReceiver = null;
1488
Joe Onorato82ba91d2017-04-27 16:18:05 -07001489 if (DBG) Slog.d(TAG, "begin updateExternalStatsSync reason=" + reason);
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001490 synchronized (mExternalStatsLock) {
Adam Lesinskie08af192015-03-25 16:42:59 -07001491 if (mContext == null) {
Adam Lesinski010bf372016-04-11 12:18:18 -07001492 // Don't do any work yet.
Joe Onorato82ba91d2017-04-27 16:18:05 -07001493 if (DBG) Slog.d(TAG, "end updateExternalStatsSync");
Adam Lesinskie08af192015-03-25 16:42:59 -07001494 return;
1495 }
1496
Adam Lesinski14ae39a2017-05-26 11:50:40 -07001497 if ((updateFlags & UPDATE_WIFI) != 0) {
Adam Lesinski010bf372016-04-11 12:18:18 -07001498 if (mWifiManager == null) {
1499 mWifiManager = IWifiManager.Stub.asInterface(
1500 ServiceManager.getService(Context.WIFI_SERVICE));
1501 }
1502
1503 if (mWifiManager != null) {
1504 try {
1505 wifiReceiver = new SynchronousResultReceiver();
1506 mWifiManager.requestActivityInfo(wifiReceiver);
1507 } catch (RemoteException e) {
1508 // Oh well.
1509 }
1510 }
Adam Lesinskia7c90c82015-06-18 14:52:24 -07001511 }
1512
Adam Lesinski9f55cc72016-01-27 20:42:14 -08001513 if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_BT) != 0) {
Adam Lesinski010bf372016-04-11 12:18:18 -07001514 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
1515 if (adapter != null) {
1516 bluetoothReceiver = new SynchronousResultReceiver();
Adam Lesinski991357f2016-05-10 14:00:03 -07001517 adapter.requestControllerActivityEnergyInfo(bluetoothReceiver);
Adam Lesinski010bf372016-04-11 12:18:18 -07001518 }
1519 }
1520
1521 if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO) != 0) {
1522 if (mTelephony == null) {
1523 mTelephony = TelephonyManager.from(mContext);
1524 }
1525
1526 if (mTelephony != null) {
1527 modemReceiver = new SynchronousResultReceiver();
1528 mTelephony.requestModemActivityInfo(modemReceiver);
1529 }
1530 }
1531
1532 WifiActivityEnergyInfo wifiInfo = null;
1533 BluetoothActivityEnergyInfo bluetoothInfo = null;
1534 ModemActivityInfo modemInfo = null;
1535 try {
1536 wifiInfo = awaitControllerInfo(wifiReceiver);
1537 } catch (TimeoutException e) {
1538 Slog.w(TAG, "Timeout reading wifi stats");
1539 }
1540
1541 try {
1542 bluetoothInfo = awaitControllerInfo(bluetoothReceiver);
1543 } catch (TimeoutException e) {
1544 Slog.w(TAG, "Timeout reading bt stats");
1545 }
1546
1547 try {
1548 modemInfo = awaitControllerInfo(modemReceiver);
1549 } catch (TimeoutException e) {
1550 Slog.w(TAG, "Timeout reading modem stats");
Adam Lesinskic14c2732015-05-21 15:04:18 -07001551 }
1552
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001553 synchronized (mStats) {
Adam Lesinski010bf372016-04-11 12:18:18 -07001554 mStats.addHistoryEventLocked(
1555 SystemClock.elapsedRealtime(),
1556 SystemClock.uptimeMillis(),
1557 BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS,
1558 reason, 0);
1559
Sudheer Shanka671985f2017-05-19 11:33:42 -07001560 if ((updateFlags & UPDATE_CPU) != 0) {
1561 mStats.updateCpuTimeLocked(true /* updateCpuFreqData */);
1562 }
Adam Lesinski010bf372016-04-11 12:18:18 -07001563 mStats.updateKernelWakelocksLocked();
James Carr2dd7e5e2016-07-20 18:48:39 -07001564 mStats.updateKernelMemoryBandwidthLocked();
Adam Lesinski010bf372016-04-11 12:18:18 -07001565
Adam Lesinski010bf372016-04-11 12:18:18 -07001566 if (bluetoothInfo != null) {
1567 if (bluetoothInfo.isValid()) {
1568 mStats.updateBluetoothStateLocked(bluetoothInfo);
1569 } else {
1570 Slog.e(TAG, "bluetooth info is invalid: " + bluetoothInfo);
1571 }
Adam Lesinski72478f02015-06-17 15:39:43 -07001572 }
Adam Lesinski14ae39a2017-05-26 11:50:40 -07001573 }
Adam Lesinskia7c90c82015-06-18 14:52:24 -07001574
Adam Lesinski14ae39a2017-05-26 11:50:40 -07001575 if (wifiInfo != null) {
1576 if (wifiInfo.isValid()) {
1577 mStats.updateWifiState(extractDelta(wifiInfo));
1578 } else {
1579 Slog.e(TAG, "wifi info is invalid: " + wifiInfo);
1580 }
1581 }
1582
1583 if (modemInfo != null) {
1584 if (modemInfo.isValid()) {
1585 mStats.updateMobileRadioState(modemInfo);
1586 } else {
1587 Slog.e(TAG, "modem info is invalid: " + modemInfo);
Adam Lesinskia7c90c82015-06-18 14:52:24 -07001588 }
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001589 }
1590 }
Joe Onorato82ba91d2017-04-27 16:18:05 -07001591 if (DBG) Slog.d(TAG, "end updateExternalStatsSync");
Adam Lesinski4b6bd8d2015-03-19 14:35:45 -07001592 }
Joe Onorato713fec82016-03-04 10:34:02 -08001593
1594 /**
1595 * Gets a snapshot of the system health for a particular uid.
1596 */
1597 @Override
1598 public HealthStatsParceler takeUidSnapshot(int requestUid) {
1599 if (requestUid != Binder.getCallingUid()) {
1600 mContext.enforceCallingOrSelfPermission(
1601 android.Manifest.permission.BATTERY_STATS, null);
1602 }
1603 long ident = Binder.clearCallingIdentity();
1604 try {
Adam Lesinski010bf372016-04-11 12:18:18 -07001605 updateExternalStatsSync("get-health-stats-for-uid",
Joe Onorato713fec82016-03-04 10:34:02 -08001606 BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
1607 synchronized (mStats) {
1608 return getHealthStatsForUidLocked(requestUid);
1609 }
1610 } catch (Exception ex) {
Joe Onorato82ba91d2017-04-27 16:18:05 -07001611 Slog.w(TAG, "Crashed while writing for takeUidSnapshot(" + requestUid + ")", ex);
Joe Onorato713fec82016-03-04 10:34:02 -08001612 throw ex;
1613 } finally {
1614 Binder.restoreCallingIdentity(ident);
1615 }
1616 }
1617
1618 /**
1619 * Gets a snapshot of the system health for a number of uids.
1620 */
1621 @Override
1622 public HealthStatsParceler[] takeUidSnapshots(int[] requestUids) {
1623 if (!onlyCaller(requestUids)) {
1624 mContext.enforceCallingOrSelfPermission(
1625 android.Manifest.permission.BATTERY_STATS, null);
1626 }
1627 long ident = Binder.clearCallingIdentity();
1628 int i=-1;
1629 try {
Adam Lesinski010bf372016-04-11 12:18:18 -07001630 updateExternalStatsSync("get-health-stats-for-uids",
Joe Onorato713fec82016-03-04 10:34:02 -08001631 BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
1632 synchronized (mStats) {
1633 final int N = requestUids.length;
1634 final HealthStatsParceler[] results = new HealthStatsParceler[N];
1635 for (i=0; i<N; i++) {
1636 results[i] = getHealthStatsForUidLocked(requestUids[i]);
1637 }
1638 return results;
1639 }
1640 } catch (Exception ex) {
Joe Onorato82ba91d2017-04-27 16:18:05 -07001641 if (DBG) Slog.d(TAG, "Crashed while writing for takeUidSnapshots("
Joe Onorato713fec82016-03-04 10:34:02 -08001642 + Arrays.toString(requestUids) + ") i=" + i, ex);
1643 throw ex;
1644 } finally {
1645 Binder.restoreCallingIdentity(ident);
1646 }
1647 }
1648
1649 /**
1650 * Returns whether the Binder.getCallingUid is the only thing in requestUids.
1651 */
1652 private static boolean onlyCaller(int[] requestUids) {
1653 final int caller = Binder.getCallingUid();
1654 final int N = requestUids.length;
1655 for (int i=0; i<N; i++) {
1656 if (requestUids[i] != caller) {
1657 return false;
1658 }
1659 }
1660 return true;
1661 }
1662
1663 /**
1664 * Gets a HealthStatsParceler for the given uid. You should probably call
Adam Lesinski010bf372016-04-11 12:18:18 -07001665 * updateExternalStatsSync first.
Joe Onorato713fec82016-03-04 10:34:02 -08001666 */
1667 HealthStatsParceler getHealthStatsForUidLocked(int requestUid) {
1668 final HealthStatsBatteryStatsWriter writer = new HealthStatsBatteryStatsWriter();
1669 final HealthStatsWriter uidWriter = new HealthStatsWriter(UidHealthStats.CONSTANTS);
1670 final BatteryStats.Uid uid = mStats.getUidStats().get(requestUid);
1671 if (uid != null) {
1672 writer.writeUid(uidWriter, mStats, uid);
1673 }
1674 return new HealthStatsParceler(uidWriter);
1675 }
1676
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677}