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