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