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.BluetoothAdapter;
20 import android.bluetooth.BluetoothHeadset;
21 import android.bluetooth.BluetoothProfile;
22 import android.content.Context;
23 import android.content.pm.ApplicationInfo;
24 import android.content.pm.PackageManager;
25 import android.os.BatteryStats;
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.PowerManagerInternal;
32 import android.os.Process;
33 import android.os.ServiceManager;
34 import android.os.SystemClock;
35 import android.os.UserHandle;
36 import android.os.WorkSource;
37 import android.telephony.SignalStrength;
38 import android.telephony.TelephonyManager;
39 import android.util.Slog;
40 
41 import com.android.internal.app.IBatteryStats;
42 import com.android.internal.os.BatteryStatsHelper;
43 import com.android.internal.os.BatteryStatsImpl;
44 import com.android.internal.os.PowerProfile;
45 import com.android.server.LocalServices;
46 
47 import java.io.File;
48 import java.io.FileDescriptor;
49 import java.io.FileOutputStream;
50 import java.io.IOException;
51 import java.io.PrintWriter;
52 import java.util.List;
53 
54 /**
55  * All information we are collecting about things that can happen that impact
56  * battery life.
57  */
58 public final class BatteryStatsService extends IBatteryStats.Stub
59         implements PowerManagerInternal.LowPowerModeListener {
60     static final String TAG = "BatteryStatsService";
61 
62     static IBatteryStats sService;
63 
64     final BatteryStatsImpl mStats;
65     Context mContext;
66     private boolean mBluetoothPendingStats;
67     private BluetoothHeadset mBluetoothHeadset;
68     PowerManagerInternal mPowerManagerInternal;
69 
BatteryStatsService(File systemDir, Handler handler)70     BatteryStatsService(File systemDir, Handler handler) {
71         mStats = new BatteryStatsImpl(systemDir, handler);
72     }
73 
publish(Context context)74     public void publish(Context context) {
75         mContext = context;
76         ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
77         mStats.setNumSpeedSteps(new PowerProfile(mContext).getNumSpeedSteps());
78         mStats.setRadioScanningTimeout(mContext.getResources().getInteger(
79                 com.android.internal.R.integer.config_radioScanningTimeout)
80                 * 1000L);
81     }
82 
83     /**
84      * At the time when the constructor runs, the power manager has not yet been
85      * initialized.  So we initialize the low power observer later.
86      */
initPowerManagement()87     public void initPowerManagement() {
88         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
89         mPowerManagerInternal.registerLowPowerModeObserver(this);
90         mStats.noteLowPowerMode(mPowerManagerInternal.getLowPowerModeEnabled());
91         (new WakeupReasonThread()).start();
92     }
93 
shutdown()94     public void shutdown() {
95         Slog.w("BatteryStats", "Writing battery stats before shutdown...");
96         synchronized (mStats) {
97             mStats.shutdownLocked();
98         }
99     }
100 
getService()101     public static IBatteryStats getService() {
102         if (sService != null) {
103             return sService;
104         }
105         IBinder b = ServiceManager.getService(BatteryStats.SERVICE_NAME);
106         sService = asInterface(b);
107         return sService;
108     }
109 
110     @Override
onLowPowerModeChanged(boolean enabled)111     public void onLowPowerModeChanged(boolean enabled) {
112         synchronized (mStats) {
113             mStats.noteLowPowerMode(enabled);
114         }
115     }
116 
117     /**
118      * @return the current statistics object, which may be modified
119      * to reflect events that affect battery usage.  You must lock the
120      * stats object before doing anything with it.
121      */
getActiveStatistics()122     public BatteryStatsImpl getActiveStatistics() {
123         return mStats;
124     }
125 
126     // These are for direct use by the activity manager...
127 
addIsolatedUid(int isolatedUid, int appUid)128     void addIsolatedUid(int isolatedUid, int appUid) {
129         synchronized (mStats) {
130             mStats.addIsolatedUidLocked(isolatedUid, appUid);
131         }
132     }
133 
removeIsolatedUid(int isolatedUid, int appUid)134     void removeIsolatedUid(int isolatedUid, int appUid) {
135         synchronized (mStats) {
136             mStats.removeIsolatedUidLocked(isolatedUid, appUid);
137         }
138     }
139 
noteProcessStart(String name, int uid)140     void noteProcessStart(String name, int uid) {
141         synchronized (mStats) {
142             mStats.noteProcessStartLocked(name, uid);
143         }
144     }
145 
noteProcessCrash(String name, int uid)146     void noteProcessCrash(String name, int uid) {
147         synchronized (mStats) {
148             mStats.noteProcessCrashLocked(name, uid);
149         }
150     }
151 
noteProcessAnr(String name, int uid)152     void noteProcessAnr(String name, int uid) {
153         synchronized (mStats) {
154             mStats.noteProcessAnrLocked(name, uid);
155         }
156     }
157 
noteProcessState(String name, int uid, int state)158     void noteProcessState(String name, int uid, int state) {
159         synchronized (mStats) {
160             mStats.noteProcessStateLocked(name, uid, state);
161         }
162     }
163 
noteProcessFinish(String name, int uid)164     void noteProcessFinish(String name, int uid) {
165         synchronized (mStats) {
166             mStats.noteProcessFinishLocked(name, uid);
167         }
168     }
169 
170     // Public interface...
171 
getStatistics()172     public byte[] getStatistics() {
173         mContext.enforceCallingPermission(
174                 android.Manifest.permission.BATTERY_STATS, null);
175         //Slog.i("foo", "SENDING BATTERY INFO:");
176         //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
177         Parcel out = Parcel.obtain();
178         mStats.writeToParcel(out, 0);
179         byte[] data = out.marshall();
180         out.recycle();
181         return data;
182     }
183 
getStatisticsStream()184     public ParcelFileDescriptor getStatisticsStream() {
185         mContext.enforceCallingPermission(
186                 android.Manifest.permission.BATTERY_STATS, null);
187         //Slog.i("foo", "SENDING BATTERY INFO:");
188         //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
189         Parcel out = Parcel.obtain();
190         mStats.writeToParcel(out, 0);
191         byte[] data = out.marshall();
192         out.recycle();
193         try {
194             return ParcelFileDescriptor.fromData(data, "battery-stats");
195         } catch (IOException e) {
196             Slog.w(TAG, "Unable to create shared memory", e);
197             return null;
198         }
199     }
200 
computeBatteryTimeRemaining()201     public long computeBatteryTimeRemaining() {
202         synchronized (mStats) {
203             long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
204             return time >= 0 ? (time/1000) : time;
205         }
206     }
207 
computeChargeTimeRemaining()208     public long computeChargeTimeRemaining() {
209         synchronized (mStats) {
210             long time = mStats.computeChargeTimeRemaining(SystemClock.elapsedRealtime());
211             return time >= 0 ? (time/1000) : time;
212         }
213     }
214 
noteEvent(int code, String name, int uid)215     public void noteEvent(int code, String name, int uid) {
216         enforceCallingPermission();
217         synchronized (mStats) {
218             mStats.noteEventLocked(code, name, uid);
219         }
220     }
221 
noteSyncStart(String name, int uid)222     public void noteSyncStart(String name, int uid) {
223         enforceCallingPermission();
224         synchronized (mStats) {
225             mStats.noteSyncStartLocked(name, uid);
226         }
227     }
228 
noteSyncFinish(String name, int uid)229     public void noteSyncFinish(String name, int uid) {
230         enforceCallingPermission();
231         synchronized (mStats) {
232             mStats.noteSyncFinishLocked(name, uid);
233         }
234     }
235 
noteJobStart(String name, int uid)236     public void noteJobStart(String name, int uid) {
237         enforceCallingPermission();
238         synchronized (mStats) {
239             mStats.noteJobStartLocked(name, uid);
240         }
241     }
242 
noteJobFinish(String name, int uid)243     public void noteJobFinish(String name, int uid) {
244         enforceCallingPermission();
245         synchronized (mStats) {
246             mStats.noteJobFinishLocked(name, uid);
247         }
248     }
249 
noteStartWakelock(int uid, int pid, String name, String historyName, int type, boolean unimportantForLogging)250     public void noteStartWakelock(int uid, int pid, String name, String historyName, int type,
251             boolean unimportantForLogging) {
252         enforceCallingPermission();
253         synchronized (mStats) {
254             mStats.noteStartWakeLocked(uid, pid, name, historyName, type, unimportantForLogging,
255                     SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
256         }
257     }
258 
noteStopWakelock(int uid, int pid, String name, String historyName, int type)259     public void noteStopWakelock(int uid, int pid, String name, String historyName, int type) {
260         enforceCallingPermission();
261         synchronized (mStats) {
262             mStats.noteStopWakeLocked(uid, pid, name, historyName, type,
263                     SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
264         }
265     }
266 
noteStartWakelockFromSource(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging)267     public void noteStartWakelockFromSource(WorkSource ws, int pid, String name,
268             String historyName, int type, boolean unimportantForLogging) {
269         enforceCallingPermission();
270         synchronized (mStats) {
271             mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName,
272                     type, unimportantForLogging);
273         }
274     }
275 
noteChangeWakelockFromSource(WorkSource ws, int pid, String name, String historyName, int type, WorkSource newWs, int newPid, String newName, String newHistoryName, int newType, boolean newUnimportantForLogging)276     public void noteChangeWakelockFromSource(WorkSource ws, int pid, String name,
277             String historyName, int type, WorkSource newWs, int newPid, String newName,
278             String newHistoryName, int newType, boolean newUnimportantForLogging) {
279         enforceCallingPermission();
280         synchronized (mStats) {
281             mStats.noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type,
282                     newWs, newPid, newName, newHistoryName, newType, newUnimportantForLogging);
283         }
284     }
285 
noteStopWakelockFromSource(WorkSource ws, int pid, String name, String historyName, int type)286     public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, String historyName,
287             int type) {
288         enforceCallingPermission();
289         synchronized (mStats) {
290             mStats.noteStopWakeFromSourceLocked(ws, pid, name, historyName, type);
291         }
292     }
293 
noteStartSensor(int uid, int sensor)294     public void noteStartSensor(int uid, int sensor) {
295         enforceCallingPermission();
296         synchronized (mStats) {
297             mStats.noteStartSensorLocked(uid, sensor);
298         }
299     }
300 
noteStopSensor(int uid, int sensor)301     public void noteStopSensor(int uid, int sensor) {
302         enforceCallingPermission();
303         synchronized (mStats) {
304             mStats.noteStopSensorLocked(uid, sensor);
305         }
306     }
307 
noteVibratorOn(int uid, long durationMillis)308     public void noteVibratorOn(int uid, long durationMillis) {
309         enforceCallingPermission();
310         synchronized (mStats) {
311             mStats.noteVibratorOnLocked(uid, durationMillis);
312         }
313     }
314 
noteVibratorOff(int uid)315     public void noteVibratorOff(int uid) {
316         enforceCallingPermission();
317         synchronized (mStats) {
318             mStats.noteVibratorOffLocked(uid);
319         }
320     }
321 
noteStartGps(int uid)322     public void noteStartGps(int uid) {
323         enforceCallingPermission();
324         synchronized (mStats) {
325             mStats.noteStartGpsLocked(uid);
326         }
327     }
328 
noteStopGps(int uid)329     public void noteStopGps(int uid) {
330         enforceCallingPermission();
331         synchronized (mStats) {
332             mStats.noteStopGpsLocked(uid);
333         }
334     }
335 
noteScreenState(int state)336     public void noteScreenState(int state) {
337         enforceCallingPermission();
338         synchronized (mStats) {
339             mStats.noteScreenStateLocked(state);
340         }
341     }
342 
noteScreenBrightness(int brightness)343     public void noteScreenBrightness(int brightness) {
344         enforceCallingPermission();
345         synchronized (mStats) {
346             mStats.noteScreenBrightnessLocked(brightness);
347         }
348     }
349 
noteUserActivity(int uid, int event)350     public void noteUserActivity(int uid, int event) {
351         enforceCallingPermission();
352         synchronized (mStats) {
353             mStats.noteUserActivityLocked(uid, event);
354         }
355     }
356 
noteInteractive(boolean interactive)357     public void noteInteractive(boolean interactive) {
358         enforceCallingPermission();
359         synchronized (mStats) {
360             mStats.noteInteractiveLocked(interactive);
361         }
362     }
363 
noteConnectivityChanged(int type, String extra)364     public void noteConnectivityChanged(int type, String extra) {
365         enforceCallingPermission();
366         synchronized (mStats) {
367             mStats.noteConnectivityChangedLocked(type, extra);
368         }
369     }
370 
noteMobileRadioPowerState(int powerState, long timestampNs)371     public void noteMobileRadioPowerState(int powerState, long timestampNs) {
372         enforceCallingPermission();
373         synchronized (mStats) {
374             mStats.noteMobileRadioPowerState(powerState, timestampNs);
375         }
376     }
377 
notePhoneOn()378     public void notePhoneOn() {
379         enforceCallingPermission();
380         synchronized (mStats) {
381             mStats.notePhoneOnLocked();
382         }
383     }
384 
notePhoneOff()385     public void notePhoneOff() {
386         enforceCallingPermission();
387         synchronized (mStats) {
388             mStats.notePhoneOffLocked();
389         }
390     }
391 
notePhoneSignalStrength(SignalStrength signalStrength)392     public void notePhoneSignalStrength(SignalStrength signalStrength) {
393         enforceCallingPermission();
394         synchronized (mStats) {
395             mStats.notePhoneSignalStrengthLocked(signalStrength);
396         }
397     }
398 
notePhoneDataConnectionState(int dataType, boolean hasData)399     public void notePhoneDataConnectionState(int dataType, boolean hasData) {
400         enforceCallingPermission();
401         synchronized (mStats) {
402             mStats.notePhoneDataConnectionStateLocked(dataType, hasData);
403         }
404     }
405 
notePhoneState(int state)406     public void notePhoneState(int state) {
407         enforceCallingPermission();
408         int simState = TelephonyManager.getDefault().getSimState();
409         synchronized (mStats) {
410             mStats.notePhoneStateLocked(state, simState);
411         }
412     }
413 
noteWifiOn()414     public void noteWifiOn() {
415         enforceCallingPermission();
416         synchronized (mStats) {
417             mStats.noteWifiOnLocked();
418         }
419     }
420 
noteWifiOff()421     public void noteWifiOff() {
422         enforceCallingPermission();
423         synchronized (mStats) {
424             mStats.noteWifiOffLocked();
425         }
426     }
427 
noteStartAudio(int uid)428     public void noteStartAudio(int uid) {
429         enforceCallingPermission();
430         synchronized (mStats) {
431             mStats.noteAudioOnLocked(uid);
432         }
433     }
434 
noteStopAudio(int uid)435     public void noteStopAudio(int uid) {
436         enforceCallingPermission();
437         synchronized (mStats) {
438             mStats.noteAudioOffLocked(uid);
439         }
440     }
441 
noteStartVideo(int uid)442     public void noteStartVideo(int uid) {
443         enforceCallingPermission();
444         synchronized (mStats) {
445             mStats.noteVideoOnLocked(uid);
446         }
447     }
448 
noteStopVideo(int uid)449     public void noteStopVideo(int uid) {
450         enforceCallingPermission();
451         synchronized (mStats) {
452             mStats.noteVideoOffLocked(uid);
453         }
454     }
455 
noteResetAudio()456     public void noteResetAudio() {
457         enforceCallingPermission();
458         synchronized (mStats) {
459             mStats.noteResetAudioLocked();
460         }
461     }
462 
noteResetVideo()463     public void noteResetVideo() {
464         enforceCallingPermission();
465         synchronized (mStats) {
466             mStats.noteResetVideoLocked();
467         }
468     }
469 
noteFlashlightOn()470     public void noteFlashlightOn() {
471         enforceCallingPermission();
472         synchronized (mStats) {
473             mStats.noteFlashlightOnLocked();
474         }
475     }
476 
noteFlashlightOff()477     public void noteFlashlightOff() {
478         enforceCallingPermission();
479         synchronized (mStats) {
480             mStats.noteFlashlightOffLocked();
481         }
482     }
483 
noteWifiRunning(WorkSource ws)484     public void noteWifiRunning(WorkSource ws) {
485         enforceCallingPermission();
486         synchronized (mStats) {
487             mStats.noteWifiRunningLocked(ws);
488         }
489     }
490 
noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs)491     public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) {
492         enforceCallingPermission();
493         synchronized (mStats) {
494             mStats.noteWifiRunningChangedLocked(oldWs, newWs);
495         }
496     }
497 
noteWifiStopped(WorkSource ws)498     public void noteWifiStopped(WorkSource ws) {
499         enforceCallingPermission();
500         synchronized (mStats) {
501             mStats.noteWifiStoppedLocked(ws);
502         }
503     }
504 
noteWifiState(int wifiState, String accessPoint)505     public void noteWifiState(int wifiState, String accessPoint) {
506         enforceCallingPermission();
507         synchronized (mStats) {
508             mStats.noteWifiStateLocked(wifiState, accessPoint);
509         }
510     }
511 
noteWifiSupplicantStateChanged(int supplState, boolean failedAuth)512     public void noteWifiSupplicantStateChanged(int supplState, boolean failedAuth) {
513         enforceCallingPermission();
514         synchronized (mStats) {
515             mStats.noteWifiSupplicantStateChangedLocked(supplState, failedAuth);
516         }
517     }
518 
noteWifiRssiChanged(int newRssi)519     public void noteWifiRssiChanged(int newRssi) {
520         enforceCallingPermission();
521         synchronized (mStats) {
522             mStats.noteWifiRssiChangedLocked(newRssi);
523         }
524     }
525 
noteBluetoothOn()526     public void noteBluetoothOn() {
527         enforceCallingPermission();
528         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
529         if (adapter != null) {
530             adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
531                                     BluetoothProfile.HEADSET);
532         }
533         synchronized (mStats) {
534             if (mBluetoothHeadset != null) {
535                 mStats.noteBluetoothOnLocked();
536                 mStats.setBtHeadset(mBluetoothHeadset);
537             } else {
538                 mBluetoothPendingStats = true;
539             }
540         }
541     }
542 
543     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
544         new BluetoothProfile.ServiceListener() {
545         public void onServiceConnected(int profile, BluetoothProfile proxy) {
546             mBluetoothHeadset = (BluetoothHeadset) proxy;
547             synchronized (mStats) {
548                 if (mBluetoothPendingStats) {
549                     mStats.noteBluetoothOnLocked();
550                     mStats.setBtHeadset(mBluetoothHeadset);
551                     mBluetoothPendingStats = false;
552                 }
553             }
554         }
555 
556         public void onServiceDisconnected(int profile) {
557             mBluetoothHeadset = null;
558         }
559     };
560 
noteBluetoothOff()561     public void noteBluetoothOff() {
562         enforceCallingPermission();
563         synchronized (mStats) {
564             mBluetoothPendingStats = false;
565             mStats.noteBluetoothOffLocked();
566         }
567     }
568 
noteBluetoothState(int bluetoothState)569     public void noteBluetoothState(int bluetoothState) {
570         enforceCallingPermission();
571         synchronized (mStats) {
572             mStats.noteBluetoothStateLocked(bluetoothState);
573         }
574     }
575 
noteFullWifiLockAcquired(int uid)576     public void noteFullWifiLockAcquired(int uid) {
577         enforceCallingPermission();
578         synchronized (mStats) {
579             mStats.noteFullWifiLockAcquiredLocked(uid);
580         }
581     }
582 
noteFullWifiLockReleased(int uid)583     public void noteFullWifiLockReleased(int uid) {
584         enforceCallingPermission();
585         synchronized (mStats) {
586             mStats.noteFullWifiLockReleasedLocked(uid);
587         }
588     }
589 
noteWifiScanStarted(int uid)590     public void noteWifiScanStarted(int uid) {
591         enforceCallingPermission();
592         synchronized (mStats) {
593             mStats.noteWifiScanStartedLocked(uid);
594         }
595     }
596 
noteWifiScanStopped(int uid)597     public void noteWifiScanStopped(int uid) {
598         enforceCallingPermission();
599         synchronized (mStats) {
600             mStats.noteWifiScanStoppedLocked(uid);
601         }
602     }
603 
noteWifiMulticastEnabled(int uid)604     public void noteWifiMulticastEnabled(int uid) {
605         enforceCallingPermission();
606         synchronized (mStats) {
607             mStats.noteWifiMulticastEnabledLocked(uid);
608         }
609     }
610 
noteWifiMulticastDisabled(int uid)611     public void noteWifiMulticastDisabled(int uid) {
612         enforceCallingPermission();
613         synchronized (mStats) {
614             mStats.noteWifiMulticastDisabledLocked(uid);
615         }
616     }
617 
noteFullWifiLockAcquiredFromSource(WorkSource ws)618     public void noteFullWifiLockAcquiredFromSource(WorkSource ws) {
619         enforceCallingPermission();
620         synchronized (mStats) {
621             mStats.noteFullWifiLockAcquiredFromSourceLocked(ws);
622         }
623     }
624 
noteFullWifiLockReleasedFromSource(WorkSource ws)625     public void noteFullWifiLockReleasedFromSource(WorkSource ws) {
626         enforceCallingPermission();
627         synchronized (mStats) {
628             mStats.noteFullWifiLockReleasedFromSourceLocked(ws);
629         }
630     }
631 
noteWifiScanStartedFromSource(WorkSource ws)632     public void noteWifiScanStartedFromSource(WorkSource ws) {
633         enforceCallingPermission();
634         synchronized (mStats) {
635             mStats.noteWifiScanStartedFromSourceLocked(ws);
636         }
637     }
638 
noteWifiScanStoppedFromSource(WorkSource ws)639     public void noteWifiScanStoppedFromSource(WorkSource ws) {
640         enforceCallingPermission();
641         synchronized (mStats) {
642             mStats.noteWifiScanStoppedFromSourceLocked(ws);
643         }
644     }
645 
noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph)646     public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) {
647         enforceCallingPermission();
648         synchronized (mStats) {
649             mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph);
650         }
651     }
652 
noteWifiBatchedScanStoppedFromSource(WorkSource ws)653     public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) {
654         enforceCallingPermission();
655         synchronized (mStats) {
656             mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws);
657         }
658     }
659 
noteWifiMulticastEnabledFromSource(WorkSource ws)660     public void noteWifiMulticastEnabledFromSource(WorkSource ws) {
661         enforceCallingPermission();
662         synchronized (mStats) {
663             mStats.noteWifiMulticastEnabledFromSourceLocked(ws);
664         }
665     }
666 
noteWifiMulticastDisabledFromSource(WorkSource ws)667     public void noteWifiMulticastDisabledFromSource(WorkSource ws) {
668         enforceCallingPermission();
669         synchronized (mStats) {
670             mStats.noteWifiMulticastDisabledFromSourceLocked(ws);
671         }
672     }
673 
674     @Override
noteNetworkInterfaceType(String iface, int type)675     public void noteNetworkInterfaceType(String iface, int type) {
676         enforceCallingPermission();
677         synchronized (mStats) {
678             mStats.noteNetworkInterfaceTypeLocked(iface, type);
679         }
680     }
681 
682     @Override
noteNetworkStatsEnabled()683     public void noteNetworkStatsEnabled() {
684         enforceCallingPermission();
685         synchronized (mStats) {
686             mStats.noteNetworkStatsEnabledLocked();
687         }
688     }
689 
isOnBattery()690     public boolean isOnBattery() {
691         return mStats.isOnBattery();
692     }
693 
setBatteryState(int status, int health, int plugType, int level, int temp, int volt)694     public void setBatteryState(int status, int health, int plugType, int level,
695             int temp, int volt) {
696         enforceCallingPermission();
697         mStats.setBatteryState(status, health, plugType, level, temp, volt);
698     }
699 
getAwakeTimeBattery()700     public long getAwakeTimeBattery() {
701         mContext.enforceCallingOrSelfPermission(
702                 android.Manifest.permission.BATTERY_STATS, null);
703         return mStats.getAwakeTimeBattery();
704     }
705 
getAwakeTimePlugged()706     public long getAwakeTimePlugged() {
707         mContext.enforceCallingOrSelfPermission(
708                 android.Manifest.permission.BATTERY_STATS, null);
709         return mStats.getAwakeTimePlugged();
710     }
711 
enforceCallingPermission()712     public void enforceCallingPermission() {
713         if (Binder.getCallingPid() == Process.myPid()) {
714             return;
715         }
716         mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
717                 Binder.getCallingPid(), Binder.getCallingUid(), null);
718     }
719 
720     final class WakeupReasonThread extends Thread {
721         final int[] mIrqs = new int[32];
722         final String[] mReasons = new String[32];
723 
WakeupReasonThread()724         WakeupReasonThread() {
725             super("BatteryStats_wakeupReason");
726         }
727 
run()728         public void run() {
729             Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
730 
731             try {
732                 int num;
733                 while ((num=nativeWaitWakeup(mIrqs, mReasons)) >= 0) {
734                     synchronized (mStats) {
735                         if (num > 0) {
736                             for (int i=0; i<num; i++) {
737                                 mStats.noteWakeupReasonLocked(mReasons[i]);
738                             }
739                         } else {
740                             mStats.noteWakeupReasonLocked("unknown");
741                         }
742                     }
743                 }
744             } catch (RuntimeException e) {
745                 Slog.e(TAG, "Failure reading wakeup reasons", e);
746             }
747         }
748     }
749 
nativeWaitWakeup(int[] outIrqs, String[] outReasons)750     private static native int nativeWaitWakeup(int[] outIrqs, String[] outReasons);
751 
dumpHelp(PrintWriter pw)752     private void dumpHelp(PrintWriter pw) {
753         pw.println("Battery stats (batterystats) dump options:");
754         pw.println("  [--checkin] [--history] [--history-start] [--unplugged] [--charged] [-c]");
755         pw.println("  [--reset] [--write] [-h] [<package.name>]");
756         pw.println("  --checkin: format output for a checkin report.");
757         pw.println("  --history: show only history data.");
758         pw.println("  --history-start <num>: show only history data starting at given time offset.");
759         pw.println("  --unplugged: only output data since last unplugged.");
760         pw.println("  --charged: only output data since last charged.");
761         pw.println("  --reset: reset the stats, clearing all current data.");
762         pw.println("  --write: force write current collected stats to disk.");
763         pw.println("  <package.name>: optional name of package to filter output by.");
764         pw.println("  -h: print this help text.");
765         pw.println("Battery stats (batterystats) commands:");
766         pw.println("  enable|disable <option>");
767         pw.println("    Enable or disable a running option.  Option state is not saved across boots.");
768         pw.println("    Options are:");
769         pw.println("      full-history: include additional detailed events in battery history:");
770         pw.println("          wake_lock_in and proc events");
771         pw.println("      no-auto-reset: don't automatically reset stats when unplugged");
772     }
773 
doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable)774     private int doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable) {
775         i++;
776         if (i >= args.length) {
777             pw.println("Missing option argument for " + (enable ? "--enable" : "--disable"));
778             dumpHelp(pw);
779             return -1;
780         }
781         if ("full-wake-history".equals(args[i]) || "full-history".equals(args[i])) {
782             synchronized (mStats) {
783                 mStats.setRecordAllHistoryLocked(enable);
784             }
785         } else if ("no-auto-reset".equals(args[i])) {
786             synchronized (mStats) {
787                 mStats.setNoAutoReset(enable);
788             }
789         } else {
790             pw.println("Unknown enable/disable option: " + args[i]);
791             dumpHelp(pw);
792             return -1;
793         }
794         return i;
795     }
796 
797     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)798     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
799         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
800                 != PackageManager.PERMISSION_GRANTED) {
801             pw.println("Permission Denial: can't dump BatteryStats from from pid="
802                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
803                     + " without permission " + android.Manifest.permission.DUMP);
804             return;
805         }
806 
807         int flags = 0;
808         boolean useCheckinFormat = false;
809         boolean isRealCheckin = false;
810         boolean noOutput = false;
811         boolean writeData = false;
812         long historyStart = -1;
813         int reqUid = -1;
814         if (args != null) {
815             for (int i=0; i<args.length; i++) {
816                 String arg = args[i];
817                 if ("--checkin".equals(arg)) {
818                     useCheckinFormat = true;
819                     isRealCheckin = true;
820                 } else if ("--history".equals(arg)) {
821                     flags |= BatteryStats.DUMP_HISTORY_ONLY;
822                 } else if ("--history-start".equals(arg)) {
823                     flags |= BatteryStats.DUMP_HISTORY_ONLY;
824                     i++;
825                     if (i >= args.length) {
826                         pw.println("Missing time argument for --history-since");
827                         dumpHelp(pw);
828                         return;
829                     }
830                     historyStart = Long.parseLong(args[i]);
831                     writeData = true;
832                 } else if ("-c".equals(arg)) {
833                     useCheckinFormat = true;
834                     flags |= BatteryStats.DUMP_INCLUDE_HISTORY;
835                 } else if ("--unplugged".equals(arg)) {
836                     flags |= BatteryStats.DUMP_UNPLUGGED_ONLY;
837                 } else if ("--charged".equals(arg)) {
838                     flags |= BatteryStats.DUMP_CHARGED_ONLY;
839                 } else if ("--reset".equals(arg)) {
840                     synchronized (mStats) {
841                         mStats.resetAllStatsCmdLocked();
842                         pw.println("Battery stats reset.");
843                         noOutput = true;
844                     }
845                 } else if ("--write".equals(arg)) {
846                     synchronized (mStats) {
847                         mStats.writeSyncLocked();
848                         pw.println("Battery stats written.");
849                         noOutput = true;
850                     }
851                 } else if ("--enable".equals(arg) || "enable".equals(arg)) {
852                     i = doEnableOrDisable(pw, i, args, true);
853                     if (i < 0) {
854                         return;
855                     }
856                     pw.println("Enabled: " + args[i]);
857                     return;
858                 } else if ("--disable".equals(arg) || "disable".equals(arg)) {
859                     i = doEnableOrDisable(pw, i, args, false);
860                     if (i < 0) {
861                         return;
862                     }
863                     pw.println("Disabled: " + args[i]);
864                     return;
865                 } else if ("-h".equals(arg)) {
866                     dumpHelp(pw);
867                     return;
868                 } else if ("-a".equals(arg)) {
869                     flags |= BatteryStats.DUMP_VERBOSE;
870                 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
871                     pw.println("Unknown option: " + arg);
872                     dumpHelp(pw);
873                     return;
874                 } else {
875                     // Not an option, last argument must be a package name.
876                     try {
877                         reqUid = mContext.getPackageManager().getPackageUid(arg,
878                                 UserHandle.getCallingUserId());
879                     } catch (PackageManager.NameNotFoundException e) {
880                         pw.println("Unknown package: " + arg);
881                         dumpHelp(pw);
882                         return;
883                     }
884                 }
885             }
886         }
887         if (noOutput) {
888             return;
889         }
890         if (BatteryStatsHelper.checkWifiOnly(mContext)) {
891             flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY;
892         }
893         if (reqUid >= 0) {
894             // By default, if the caller is only interested in a specific package, then
895             // we only dump the aggregated data since charged.
896             if ((flags&(BatteryStats.DUMP_HISTORY_ONLY|BatteryStats.DUMP_UNPLUGGED_ONLY
897                     |BatteryStats.DUMP_CHARGED_ONLY)) == 0) {
898                 flags |= BatteryStats.DUMP_CHARGED_ONLY;
899                 // Also if they are doing -c, we don't want history.
900                 flags &= ~BatteryStats.DUMP_INCLUDE_HISTORY;
901             }
902         }
903         if (useCheckinFormat) {
904             List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
905             if (isRealCheckin) {
906                 // For a real checkin, first we want to prefer to use the last complete checkin
907                 // file if there is one.
908                 synchronized (mStats.mCheckinFile) {
909                     if (mStats.mCheckinFile.exists()) {
910                         try {
911                             byte[] raw = mStats.mCheckinFile.readFully();
912                             if (raw != null) {
913                                 Parcel in = Parcel.obtain();
914                                 in.unmarshall(raw, 0, raw.length);
915                                 in.setDataPosition(0);
916                                 BatteryStatsImpl checkinStats = new BatteryStatsImpl(
917                                         null, mStats.mHandler);
918                                 checkinStats.readSummaryFromParcel(in);
919                                 in.recycle();
920                                 checkinStats.dumpCheckinLocked(mContext, pw, apps, flags,
921                                         historyStart);
922                                 mStats.mCheckinFile.delete();
923                                 return;
924                             }
925                         } catch (IOException e) {
926                             Slog.w(TAG, "Failure reading checkin file "
927                                     + mStats.mCheckinFile.getBaseFile(), e);
928                         }
929                     }
930                 }
931             }
932             synchronized (mStats) {
933                 mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
934                 if (writeData) {
935                     mStats.writeAsyncLocked();
936                 }
937             }
938         } else {
939             synchronized (mStats) {
940                 mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart);
941                 if (writeData) {
942                     mStats.writeAsyncLocked();
943                 }
944             }
945         }
946     }
947 }
948