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 = 4096;
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, int serviceType)725     public void notePhoneDataConnectionState(int dataType, boolean hasData, int serviceType) {
726         enforceCallingPermission();
727         synchronized (mStats) {
728             mStats.notePhoneDataConnectionStateLocked(dataType, hasData, serviceType);
729         }
730     }
731 
notePhoneState(int state)732     public void notePhoneState(int state) {
733         enforceCallingPermission();
734         int simState = mContext.getSystemService(TelephonyManager.class).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         enforceCallingPermission();
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         enforceCallingPermission();
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         enforceCallingPermission();
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         enforceCallingPermission();
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, final long chargeTimeToFullSeconds)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, final long chargeTimeToFullSeconds) {
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, chargeTimeToFullSeconds);
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, chargeTimeToFullSeconds);
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 
1187     final class WakeupReasonThread extends Thread {
1188         private static final int MAX_REASON_SIZE = 512;
1189         private CharsetDecoder mDecoder;
1190         private ByteBuffer mUtf8Buffer;
1191         private CharBuffer mUtf16Buffer;
1192 
WakeupReasonThread()1193         WakeupReasonThread() {
1194             super("BatteryStats_wakeupReason");
1195         }
1196 
run()1197         public void run() {
1198             Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
1199 
1200             mDecoder = StandardCharsets.UTF_8
1201                     .newDecoder()
1202                     .onMalformedInput(CodingErrorAction.REPLACE)
1203                     .onUnmappableCharacter(CodingErrorAction.REPLACE)
1204                     .replaceWith("?");
1205 
1206             mUtf8Buffer = ByteBuffer.allocateDirect(MAX_REASON_SIZE);
1207             mUtf16Buffer = CharBuffer.allocate(MAX_REASON_SIZE);
1208 
1209             try {
1210                 String reason;
1211                 while ((reason = waitWakeup()) != null) {
1212                     synchronized (mStats) {
1213                         mStats.noteWakeupReasonLocked(reason);
1214                     }
1215                 }
1216             } catch (RuntimeException e) {
1217                 Slog.e(TAG, "Failure reading wakeup reasons", e);
1218             }
1219         }
1220 
waitWakeup()1221         private String waitWakeup() {
1222             mUtf8Buffer.clear();
1223             mUtf16Buffer.clear();
1224             mDecoder.reset();
1225 
1226             int bytesWritten = nativeWaitWakeup(mUtf8Buffer);
1227             if (bytesWritten < 0) {
1228                 return null;
1229             } else if (bytesWritten == 0) {
1230                 return "unknown";
1231             }
1232 
1233             // Set the buffer's limit to the number of bytes written.
1234             mUtf8Buffer.limit(bytesWritten);
1235 
1236             // Decode the buffer from UTF-8 to UTF-16.
1237             // Unmappable characters will be replaced.
1238             mDecoder.decode(mUtf8Buffer, mUtf16Buffer, true);
1239             mUtf16Buffer.flip();
1240 
1241             // Create a String from the UTF-16 buffer.
1242             return mUtf16Buffer.toString();
1243         }
1244     }
1245 
nativeWaitWakeup(ByteBuffer outBuffer)1246     private static native int nativeWaitWakeup(ByteBuffer outBuffer);
1247 
dumpHelp(PrintWriter pw)1248     private void dumpHelp(PrintWriter pw) {
1249         pw.println("Battery stats (batterystats) dump options:");
1250         pw.println("  [--checkin] [--proto] [--history] [--history-start] [--charged] [-c]");
1251         pw.println("  [--daily] [--reset] [--write] [--new-daily] [--read-daily] [-h] [<package.name>]");
1252         pw.println("  --checkin: generate output for a checkin report; will write (and clear) the");
1253         pw.println("             last old completed stats when they had been reset.");
1254         pw.println("  -c: write the current stats in checkin format.");
1255         pw.println("  --proto: write the current aggregate stats (without history) in proto format.");
1256         pw.println("  --history: show only history data.");
1257         pw.println("  --history-start <num>: show only history data starting at given time offset.");
1258         pw.println("  --history-create-events <num>: create <num> of battery history events.");
1259         pw.println("  --charged: only output data since last charged.");
1260         pw.println("  --daily: only output full daily data.");
1261         pw.println("  --reset: reset the stats, clearing all current data.");
1262         pw.println("  --write: force write current collected stats to disk.");
1263         pw.println("  --new-daily: immediately create and write new daily stats record.");
1264         pw.println("  --read-daily: read-load last written daily stats.");
1265         pw.println("  --settings: dump the settings key/values related to batterystats");
1266         pw.println("  --cpu: dump cpu stats for debugging purpose");
1267         pw.println("  <package.name>: optional name of package to filter output by.");
1268         pw.println("  -h: print this help text.");
1269         pw.println("Battery stats (batterystats) commands:");
1270         pw.println("  enable|disable <option>");
1271         pw.println("    Enable or disable a running option.  Option state is not saved across boots.");
1272         pw.println("    Options are:");
1273         pw.println("      full-history: include additional detailed events in battery history:");
1274         pw.println("          wake_lock_in, alarms and proc events");
1275         pw.println("      no-auto-reset: don't automatically reset stats when unplugged");
1276         pw.println("      pretend-screen-off: pretend the screen is off, even if screen state changes");
1277     }
1278 
dumpSettings(PrintWriter pw)1279     private void dumpSettings(PrintWriter pw) {
1280         synchronized (mStats) {
1281             mStats.dumpConstantsLocked(pw);
1282         }
1283     }
1284 
dumpCpuStats(PrintWriter pw)1285     private void dumpCpuStats(PrintWriter pw) {
1286         synchronized (mStats) {
1287             mStats.dumpCpuStatsLocked(pw);
1288         }
1289     }
1290 
doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable)1291     private int doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable) {
1292         i++;
1293         if (i >= args.length) {
1294             pw.println("Missing option argument for " + (enable ? "--enable" : "--disable"));
1295             dumpHelp(pw);
1296             return -1;
1297         }
1298         if ("full-wake-history".equals(args[i]) || "full-history".equals(args[i])) {
1299             synchronized (mStats) {
1300                 mStats.setRecordAllHistoryLocked(enable);
1301             }
1302         } else if ("no-auto-reset".equals(args[i])) {
1303             synchronized (mStats) {
1304                 mStats.setNoAutoReset(enable);
1305             }
1306         } else if ("pretend-screen-off".equals(args[i])) {
1307             synchronized (mStats) {
1308                 mStats.setPretendScreenOff(enable);
1309             }
1310         } else {
1311             pw.println("Unknown enable/disable option: " + args[i]);
1312             dumpHelp(pw);
1313             return -1;
1314         }
1315         return i;
1316     }
1317 
1318 
1319     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)1320     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1321         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
1322 
1323         int flags = 0;
1324         boolean useCheckinFormat = false;
1325         boolean toProto = false;
1326         boolean isRealCheckin = false;
1327         boolean noOutput = false;
1328         boolean writeData = false;
1329         long historyStart = -1;
1330         int reqUid = -1;
1331         if (args != null) {
1332             for (int i=0; i<args.length; i++) {
1333                 String arg = args[i];
1334                 if ("--checkin".equals(arg)) {
1335                     useCheckinFormat = true;
1336                     isRealCheckin = true;
1337                 } else if ("--history".equals(arg)) {
1338                     flags |= BatteryStats.DUMP_HISTORY_ONLY;
1339                 } else if ("--history-start".equals(arg)) {
1340                     flags |= BatteryStats.DUMP_HISTORY_ONLY;
1341                     i++;
1342                     if (i >= args.length) {
1343                         pw.println("Missing time argument for --history-since");
1344                         dumpHelp(pw);
1345                         return;
1346                     }
1347                     historyStart = ParseUtils.parseLong(args[i], 0);
1348                     writeData = true;
1349                 } else if ("--history-create-events".equals(arg)) {
1350                     i++;
1351                     if (i >= args.length) {
1352                         pw.println("Missing events argument for --history-create-events");
1353                         dumpHelp(pw);
1354                         return;
1355                     }
1356                     final long events = ParseUtils.parseLong(args[i], 0);
1357                     synchronized (mStats) {
1358                         mStats.createFakeHistoryEvents(events);
1359                         pw.println("Battery history create events started.");
1360                         noOutput = true;
1361                     }
1362                 } else if ("-c".equals(arg)) {
1363                     useCheckinFormat = true;
1364                     flags |= BatteryStats.DUMP_INCLUDE_HISTORY;
1365                 } else if ("--proto".equals(arg)) {
1366                     toProto = true;
1367                 } else if ("--charged".equals(arg)) {
1368                     flags |= BatteryStats.DUMP_CHARGED_ONLY;
1369                 } else if ("--daily".equals(arg)) {
1370                     flags |= BatteryStats.DUMP_DAILY_ONLY;
1371                 } else if ("--reset".equals(arg)) {
1372                     synchronized (mStats) {
1373                         mStats.resetAllStatsCmdLocked();
1374                         pw.println("Battery stats reset.");
1375                         noOutput = true;
1376                     }
1377                     mWorker.scheduleSync("dump", BatteryExternalStatsWorker.UPDATE_ALL);
1378                 } else if ("--write".equals(arg)) {
1379                     syncStats("dump", BatteryExternalStatsWorker.UPDATE_ALL);
1380                     synchronized (mStats) {
1381                         mStats.writeSyncLocked();
1382                         pw.println("Battery stats written.");
1383                         noOutput = true;
1384                     }
1385                 } else if ("--new-daily".equals(arg)) {
1386                     synchronized (mStats) {
1387                         mStats.recordDailyStatsLocked();
1388                         pw.println("New daily stats written.");
1389                         noOutput = true;
1390                     }
1391                 } else if ("--read-daily".equals(arg)) {
1392                     synchronized (mStats) {
1393                         mStats.readDailyStatsLocked();
1394                         pw.println("Last daily stats read.");
1395                         noOutput = true;
1396                     }
1397                 } else if ("--enable".equals(arg) || "enable".equals(arg)) {
1398                     i = doEnableOrDisable(pw, i, args, true);
1399                     if (i < 0) {
1400                         return;
1401                     }
1402                     pw.println("Enabled: " + args[i]);
1403                     return;
1404                 } else if ("--disable".equals(arg) || "disable".equals(arg)) {
1405                     i = doEnableOrDisable(pw, i, args, false);
1406                     if (i < 0) {
1407                         return;
1408                     }
1409                     pw.println("Disabled: " + args[i]);
1410                     return;
1411                 } else if ("-h".equals(arg)) {
1412                     dumpHelp(pw);
1413                     return;
1414                 } else if ("--settings".equals(arg)) {
1415                     dumpSettings(pw);
1416                     return;
1417                 } else if ("--cpu".equals(arg)) {
1418                     dumpCpuStats(pw);
1419                     return;
1420                 } else if ("-a".equals(arg)) {
1421                     flags |= BatteryStats.DUMP_VERBOSE;
1422                 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
1423                     pw.println("Unknown option: " + arg);
1424                     dumpHelp(pw);
1425                     return;
1426                 } else {
1427                     // Not an option, last argument must be a package name.
1428                     try {
1429                         reqUid = mContext.getPackageManager().getPackageUidAsUser(arg,
1430                                 UserHandle.getCallingUserId());
1431                     } catch (PackageManager.NameNotFoundException e) {
1432                         pw.println("Unknown package: " + arg);
1433                         dumpHelp(pw);
1434                         return;
1435                     }
1436                 }
1437             }
1438         }
1439         if (noOutput) {
1440             return;
1441         }
1442 
1443         long ident = Binder.clearCallingIdentity();
1444         try {
1445             if (BatteryStatsHelper.checkWifiOnly(mContext)) {
1446                 flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY;
1447             }
1448             // Fetch data from external sources and update the BatteryStatsImpl object with them.
1449             syncStats("dump", BatteryExternalStatsWorker.UPDATE_ALL);
1450         } finally {
1451             Binder.restoreCallingIdentity(ident);
1452         }
1453 
1454         if (reqUid >= 0) {
1455             // By default, if the caller is only interested in a specific package, then
1456             // we only dump the aggregated data since charged.
1457             if ((flags&(BatteryStats.DUMP_HISTORY_ONLY|BatteryStats.DUMP_CHARGED_ONLY)) == 0) {
1458                 flags |= BatteryStats.DUMP_CHARGED_ONLY;
1459                 // Also if they are doing -c, we don't want history.
1460                 flags &= ~BatteryStats.DUMP_INCLUDE_HISTORY;
1461             }
1462         }
1463 
1464         if (toProto) {
1465             List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
1466                     PackageManager.MATCH_ANY_USER | PackageManager.MATCH_ALL);
1467             if (isRealCheckin) {
1468                 // For a real checkin, first we want to prefer to use the last complete checkin
1469                 // file if there is one.
1470                 synchronized (mStats.mCheckinFile) {
1471                     if (mStats.mCheckinFile.exists()) {
1472                         try {
1473                             byte[] raw = mStats.mCheckinFile.readFully();
1474                             if (raw != null) {
1475                                 Parcel in = Parcel.obtain();
1476                                 in.unmarshall(raw, 0, raw.length);
1477                                 in.setDataPosition(0);
1478                                 BatteryStatsImpl checkinStats = new BatteryStatsImpl(
1479                                         null, mStats.mHandler, null, null,
1480                                         mUserManagerUserInfoProvider);
1481                                 checkinStats.readSummaryFromParcel(in);
1482                                 in.recycle();
1483                                 checkinStats.dumpProtoLocked(
1484                                         mContext, fd, apps, flags, historyStart);
1485                                 mStats.mCheckinFile.delete();
1486                                 return;
1487                             }
1488                         } catch (IOException | ParcelFormatException e) {
1489                             Slog.w(TAG, "Failure reading checkin file "
1490                                     + mStats.mCheckinFile.getBaseFile(), e);
1491                         }
1492                     }
1493                 }
1494             }
1495             if (DBG) Slog.d(TAG, "begin dumpProtoLocked from UID " + Binder.getCallingUid());
1496             synchronized (mStats) {
1497                 mStats.dumpProtoLocked(mContext, fd, apps, flags, historyStart);
1498                 if (writeData) {
1499                     mStats.writeAsyncLocked();
1500                 }
1501             }
1502             if (DBG) Slog.d(TAG, "end dumpProtoLocked");
1503         } else if (useCheckinFormat) {
1504             List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
1505                     PackageManager.MATCH_ANY_USER | PackageManager.MATCH_ALL);
1506             if (isRealCheckin) {
1507                 // For a real checkin, first we want to prefer to use the last complete checkin
1508                 // file if there is one.
1509                 synchronized (mStats.mCheckinFile) {
1510                     if (mStats.mCheckinFile.exists()) {
1511                         try {
1512                             byte[] raw = mStats.mCheckinFile.readFully();
1513                             if (raw != null) {
1514                                 Parcel in = Parcel.obtain();
1515                                 in.unmarshall(raw, 0, raw.length);
1516                                 in.setDataPosition(0);
1517                                 BatteryStatsImpl checkinStats = new BatteryStatsImpl(
1518                                         null, mStats.mHandler, null, null,
1519                                         mUserManagerUserInfoProvider);
1520                                 checkinStats.readSummaryFromParcel(in);
1521                                 in.recycle();
1522                                 checkinStats.dumpCheckinLocked(mContext, pw, apps, flags,
1523                                         historyStart);
1524                                 mStats.mCheckinFile.delete();
1525                                 return;
1526                             }
1527                         } catch (IOException | ParcelFormatException e) {
1528                             Slog.w(TAG, "Failure reading checkin file "
1529                                     + mStats.mCheckinFile.getBaseFile(), e);
1530                         }
1531                     }
1532                 }
1533             }
1534             if (DBG) Slog.d(TAG, "begin dumpCheckinLocked from UID " + Binder.getCallingUid());
1535             synchronized (mStats) {
1536                 mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
1537                 if (writeData) {
1538                     mStats.writeAsyncLocked();
1539                 }
1540             }
1541             if (DBG) Slog.d(TAG, "end dumpCheckinLocked");
1542         } else {
1543             if (DBG) Slog.d(TAG, "begin dumpLocked from UID " + Binder.getCallingUid());
1544             synchronized (mStats) {
1545                 mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart);
1546                 if (writeData) {
1547                     mStats.writeAsyncLocked();
1548                 }
1549             }
1550             if (DBG) Slog.d(TAG, "end dumpLocked");
1551         }
1552     }
1553 
1554     /**
1555      * Gets a snapshot of cellular stats
1556      * @hide
1557      */
getCellularBatteryStats()1558     public CellularBatteryStats getCellularBatteryStats() {
1559         synchronized (mStats) {
1560             return mStats.getCellularBatteryStats();
1561         }
1562     }
1563 
1564     /**
1565      * Gets a snapshot of Wifi stats
1566      * @hide
1567      */
getWifiBatteryStats()1568     public WifiBatteryStats getWifiBatteryStats() {
1569         synchronized (mStats) {
1570             return mStats.getWifiBatteryStats();
1571         }
1572     }
1573 
1574     /**
1575      * Gets a snapshot of Gps stats
1576      * @hide
1577      */
getGpsBatteryStats()1578     public GpsBatteryStats getGpsBatteryStats() {
1579         synchronized (mStats) {
1580             return mStats.getGpsBatteryStats();
1581         }
1582     }
1583 
1584     /**
1585      * Gets a snapshot of the system health for a particular uid.
1586      */
1587     @Override
takeUidSnapshot(int requestUid)1588     public HealthStatsParceler takeUidSnapshot(int requestUid) {
1589         if (requestUid != Binder.getCallingUid()) {
1590             mContext.enforceCallingOrSelfPermission(
1591                     android.Manifest.permission.BATTERY_STATS, null);
1592         }
1593         long ident = Binder.clearCallingIdentity();
1594         try {
1595             if (shouldCollectExternalStats()) {
1596                 syncStats("get-health-stats-for-uids", BatteryExternalStatsWorker.UPDATE_ALL);
1597             }
1598             synchronized (mStats) {
1599                 return getHealthStatsForUidLocked(requestUid);
1600             }
1601         } catch (Exception ex) {
1602             Slog.w(TAG, "Crashed while writing for takeUidSnapshot(" + requestUid + ")", ex);
1603             throw ex;
1604         } finally {
1605             Binder.restoreCallingIdentity(ident);
1606         }
1607     }
1608 
1609     /**
1610      * Gets a snapshot of the system health for a number of uids.
1611      */
1612     @Override
takeUidSnapshots(int[] requestUids)1613     public HealthStatsParceler[] takeUidSnapshots(int[] requestUids) {
1614         if (!onlyCaller(requestUids)) {
1615             mContext.enforceCallingOrSelfPermission(
1616                     android.Manifest.permission.BATTERY_STATS, null);
1617         }
1618         long ident = Binder.clearCallingIdentity();
1619         int i=-1;
1620         try {
1621             if (shouldCollectExternalStats()) {
1622                 syncStats("get-health-stats-for-uids", BatteryExternalStatsWorker.UPDATE_ALL);
1623             }
1624             synchronized (mStats) {
1625                 final int N = requestUids.length;
1626                 final HealthStatsParceler[] results = new HealthStatsParceler[N];
1627                 for (i=0; i<N; i++) {
1628                     results[i] = getHealthStatsForUidLocked(requestUids[i]);
1629                 }
1630                 return results;
1631             }
1632         } catch (Exception ex) {
1633             if (DBG) Slog.d(TAG, "Crashed while writing for takeUidSnapshots("
1634                     + Arrays.toString(requestUids) + ") i=" + i, ex);
1635             throw ex;
1636         } finally {
1637             Binder.restoreCallingIdentity(ident);
1638         }
1639     }
1640 
shouldCollectExternalStats()1641     private boolean shouldCollectExternalStats() {
1642         return (SystemClock.elapsedRealtime() - mWorker.getLastCollectionTimeStamp())
1643                 > mStats.getExternalStatsCollectionRateLimitMs();
1644     }
1645 
1646     /**
1647      * Returns whether the Binder.getCallingUid is the only thing in requestUids.
1648      */
onlyCaller(int[] requestUids)1649     private static boolean onlyCaller(int[] requestUids) {
1650         final int caller = Binder.getCallingUid();
1651         final int N = requestUids.length;
1652         for (int i=0; i<N; i++) {
1653             if (requestUids[i] != caller) {
1654                 return false;
1655             }
1656         }
1657         return true;
1658     }
1659 
1660     /**
1661      * Gets a HealthStatsParceler for the given uid. You should probably call
1662      * updateExternalStatsSync first.
1663      */
getHealthStatsForUidLocked(int requestUid)1664     HealthStatsParceler getHealthStatsForUidLocked(int requestUid) {
1665         final HealthStatsBatteryStatsWriter writer = new HealthStatsBatteryStatsWriter();
1666         final HealthStatsWriter uidWriter = new HealthStatsWriter(UidHealthStats.CONSTANTS);
1667         final BatteryStats.Uid uid = mStats.getUidStats().get(requestUid);
1668         if (uid != null) {
1669             writer.writeUid(uidWriter, mStats, uid);
1670         }
1671         return new HealthStatsParceler(uidWriter);
1672     }
1673 
1674     /**
1675      * Delay for sending ACTION_CHARGING after device is plugged in.
1676      *
1677      * @hide
1678      */
setChargingStateUpdateDelayMillis(int delayMillis)1679     public boolean setChargingStateUpdateDelayMillis(int delayMillis) {
1680         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER, null);
1681         final long ident = Binder.clearCallingIdentity();
1682 
1683         try {
1684             final ContentResolver contentResolver = mContext.getContentResolver();
1685             return Settings.Global.putLong(contentResolver,
1686                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
1687                     delayMillis);
1688         } finally {
1689             Binder.restoreCallingIdentity(ident);
1690         }
1691     }
1692 
1693 }
1694