BatteryStatsService.java revision a1f1a3c573acd91024fda0ceb3b921c73b186963
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
17package com.android.server.am;
18
19import android.bluetooth.BluetoothAdapter;
20import android.bluetooth.BluetoothHeadset;
21import android.bluetooth.BluetoothProfile;
22import android.content.Context;
23import android.content.pm.ApplicationInfo;
24import android.content.pm.PackageManager;
25import android.os.BatteryStats;
26import android.os.Binder;
27import android.os.Handler;
28import android.os.IBinder;
29import android.os.Parcel;
30import android.os.Process;
31import android.os.ServiceManager;
32import android.os.UserHandle;
33import android.os.WorkSource;
34import android.telephony.SignalStrength;
35import android.telephony.TelephonyManager;
36import android.util.Slog;
37
38import com.android.internal.app.IBatteryStats;
39import com.android.internal.os.BatteryStatsImpl;
40import com.android.internal.os.PowerProfile;
41
42import java.io.FileDescriptor;
43import java.io.PrintWriter;
44import java.util.List;
45
46/**
47 * All information we are collecting about things that can happen that impact
48 * battery life.
49 */
50public final class BatteryStatsService extends IBatteryStats.Stub {
51    static IBatteryStats sService;
52
53    final BatteryStatsImpl mStats;
54    Context mContext;
55    private boolean mBluetoothPendingStats;
56    private BluetoothHeadset mBluetoothHeadset;
57
58    BatteryStatsService(String filename, Handler handler) {
59        mStats = new BatteryStatsImpl(filename, handler);
60    }
61
62    public void publish(Context context) {
63        mContext = context;
64        ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
65        mStats.setNumSpeedSteps(new PowerProfile(mContext).getNumSpeedSteps());
66        mStats.setRadioScanningTimeout(mContext.getResources().getInteger(
67                com.android.internal.R.integer.config_radioScanningTimeout)
68                * 1000L);
69    }
70
71    public void shutdown() {
72        Slog.w("BatteryStats", "Writing battery stats before shutdown...");
73        synchronized (mStats) {
74            mStats.shutdownLocked();
75        }
76    }
77
78    public static IBatteryStats getService() {
79        if (sService != null) {
80            return sService;
81        }
82        IBinder b = ServiceManager.getService(BatteryStats.SERVICE_NAME);
83        sService = asInterface(b);
84        return sService;
85    }
86
87    /**
88     * @return the current statistics object, which may be modified
89     * to reflect events that affect battery usage.  You must lock the
90     * stats object before doing anything with it.
91     */
92    public BatteryStatsImpl getActiveStatistics() {
93        return mStats;
94    }
95
96    public byte[] getStatistics() {
97        mContext.enforceCallingPermission(
98                android.Manifest.permission.BATTERY_STATS, null);
99        //Slog.i("foo", "SENDING BATTERY INFO:");
100        //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
101        Parcel out = Parcel.obtain();
102        mStats.writeToParcel(out, 0);
103        byte[] data = out.marshall();
104        out.recycle();
105        return data;
106    }
107
108    public void addIsolatedUid(int isolatedUid, int appUid) {
109        enforceCallingPermission();
110        synchronized (mStats) {
111            mStats.addIsolatedUidLocked(isolatedUid, appUid);
112        }
113    }
114
115    public void removeIsolatedUid(int isolatedUid, int appUid) {
116        enforceCallingPermission();
117        synchronized (mStats) {
118            mStats.removeIsolatedUidLocked(isolatedUid, appUid);
119        }
120    }
121
122    public void noteEvent(int code, String name, int uid) {
123        enforceCallingPermission();
124        synchronized (mStats) {
125            mStats.noteEventLocked(code, name, uid);
126        }
127    }
128
129    public void noteStartWakelock(int uid, int pid, String name, String historyName, int type,
130            boolean unimportantForLogging) {
131        enforceCallingPermission();
132        synchronized (mStats) {
133            mStats.noteStartWakeLocked(uid, pid, name, historyName, type, unimportantForLogging);
134        }
135    }
136
137    public void noteStopWakelock(int uid, int pid, String name, int type) {
138        enforceCallingPermission();
139        synchronized (mStats) {
140            mStats.noteStopWakeLocked(uid, pid, name, type);
141        }
142    }
143
144    public void noteStartWakelockFromSource(WorkSource ws, int pid, String name,
145            String historyName, int type, boolean unimportantForLogging) {
146        enforceCallingPermission();
147        synchronized (mStats) {
148            mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName,
149                    type, unimportantForLogging);
150        }
151    }
152
153    public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, int type) {
154        enforceCallingPermission();
155        synchronized (mStats) {
156            mStats.noteStopWakeFromSourceLocked(ws, pid, name, type);
157        }
158    }
159
160    public void noteStartSensor(int uid, int sensor) {
161        enforceCallingPermission();
162        synchronized (mStats) {
163            mStats.noteStartSensorLocked(uid, sensor);
164        }
165    }
166
167    public void noteStopSensor(int uid, int sensor) {
168        enforceCallingPermission();
169        synchronized (mStats) {
170            mStats.noteStopSensorLocked(uid, sensor);
171        }
172    }
173
174    public void noteVibratorOn(int uid, long durationMillis) {
175        enforceCallingPermission();
176        synchronized (mStats) {
177            mStats.noteVibratorOnLocked(uid, durationMillis);
178        }
179    }
180
181    public void noteVibratorOff(int uid) {
182        enforceCallingPermission();
183        synchronized (mStats) {
184            mStats.noteVibratorOffLocked(uid);
185        }
186    }
187
188    public void noteStartGps(int uid) {
189        enforceCallingPermission();
190        synchronized (mStats) {
191            mStats.noteStartGpsLocked(uid);
192        }
193    }
194
195    public void noteStopGps(int uid) {
196        enforceCallingPermission();
197        synchronized (mStats) {
198            mStats.noteStopGpsLocked(uid);
199        }
200    }
201
202    public void noteScreenOn() {
203        enforceCallingPermission();
204        synchronized (mStats) {
205            mStats.noteScreenOnLocked();
206        }
207    }
208
209    public void noteScreenBrightness(int brightness) {
210        enforceCallingPermission();
211        synchronized (mStats) {
212            mStats.noteScreenBrightnessLocked(brightness);
213        }
214    }
215
216    public void noteScreenOff() {
217        enforceCallingPermission();
218        synchronized (mStats) {
219            mStats.noteScreenOffLocked();
220        }
221    }
222
223    public void noteInputEvent() {
224        enforceCallingPermission();
225        mStats.noteInputEventAtomic();
226    }
227
228    public void noteUserActivity(int uid, int event) {
229        enforceCallingPermission();
230        synchronized (mStats) {
231            mStats.noteUserActivityLocked(uid, event);
232        }
233    }
234
235    public void noteDataConnectionActive(String label, boolean active) {
236        enforceCallingPermission();
237        synchronized (mStats) {
238            mStats.noteDataConnectionActive(label, active);
239        }
240    }
241
242    public void notePhoneOn() {
243        enforceCallingPermission();
244        synchronized (mStats) {
245            mStats.notePhoneOnLocked();
246        }
247    }
248
249    public void notePhoneOff() {
250        enforceCallingPermission();
251        synchronized (mStats) {
252            mStats.notePhoneOffLocked();
253        }
254    }
255
256    public void notePhoneSignalStrength(SignalStrength signalStrength) {
257        enforceCallingPermission();
258        synchronized (mStats) {
259            mStats.notePhoneSignalStrengthLocked(signalStrength);
260        }
261    }
262
263    public void notePhoneDataConnectionState(int dataType, boolean hasData) {
264        enforceCallingPermission();
265        synchronized (mStats) {
266            mStats.notePhoneDataConnectionStateLocked(dataType, hasData);
267        }
268    }
269
270    public void notePhoneState(int state) {
271        enforceCallingPermission();
272        int simState = TelephonyManager.getDefault().getSimState();
273        synchronized (mStats) {
274            mStats.notePhoneStateLocked(state, simState);
275        }
276    }
277
278    public void noteWifiOn() {
279        enforceCallingPermission();
280        synchronized (mStats) {
281            mStats.noteWifiOnLocked();
282        }
283    }
284
285    public void noteWifiOff() {
286        enforceCallingPermission();
287        synchronized (mStats) {
288            mStats.noteWifiOffLocked();
289        }
290    }
291
292    public void noteStartAudio(int uid) {
293        enforceCallingPermission();
294        synchronized (mStats) {
295            mStats.noteAudioOnLocked(uid);
296        }
297    }
298
299    public void noteStopAudio(int uid) {
300        enforceCallingPermission();
301        synchronized (mStats) {
302            mStats.noteAudioOffLocked(uid);
303        }
304    }
305
306    public void noteStartVideo(int uid) {
307        enforceCallingPermission();
308        synchronized (mStats) {
309            mStats.noteVideoOnLocked(uid);
310        }
311    }
312
313    public void noteStopVideo(int uid) {
314        enforceCallingPermission();
315        synchronized (mStats) {
316            mStats.noteVideoOffLocked(uid);
317        }
318    }
319
320    public void noteWifiRunning(WorkSource ws) {
321        enforceCallingPermission();
322        synchronized (mStats) {
323            mStats.noteWifiRunningLocked(ws);
324        }
325    }
326
327    public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) {
328        enforceCallingPermission();
329        synchronized (mStats) {
330            mStats.noteWifiRunningChangedLocked(oldWs, newWs);
331        }
332    }
333
334    public void noteWifiStopped(WorkSource ws) {
335        enforceCallingPermission();
336        synchronized (mStats) {
337            mStats.noteWifiStoppedLocked(ws);
338        }
339    }
340
341    public void noteWifiState(int wifiState, String accessPoint) {
342        enforceCallingPermission();
343        synchronized (mStats) {
344            mStats.noteWifiStateLocked(wifiState, accessPoint);
345        }
346    }
347
348    public void noteBluetoothOn() {
349        enforceCallingPermission();
350        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
351        if (adapter != null) {
352            adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
353                                    BluetoothProfile.HEADSET);
354        }
355        synchronized (mStats) {
356            if (mBluetoothHeadset != null) {
357                mStats.noteBluetoothOnLocked();
358                mStats.setBtHeadset(mBluetoothHeadset);
359            } else {
360                mBluetoothPendingStats = true;
361            }
362        }
363    }
364
365    private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
366        new BluetoothProfile.ServiceListener() {
367        public void onServiceConnected(int profile, BluetoothProfile proxy) {
368            mBluetoothHeadset = (BluetoothHeadset) proxy;
369            synchronized (mStats) {
370                if (mBluetoothPendingStats) {
371                    mStats.noteBluetoothOnLocked();
372                    mStats.setBtHeadset(mBluetoothHeadset);
373                    mBluetoothPendingStats = false;
374                }
375            }
376        }
377
378        public void onServiceDisconnected(int profile) {
379            mBluetoothHeadset = null;
380        }
381    };
382
383    public void noteBluetoothOff() {
384        enforceCallingPermission();
385        synchronized (mStats) {
386            mBluetoothPendingStats = false;
387            mStats.noteBluetoothOffLocked();
388        }
389    }
390
391    public void noteBluetoothState(int bluetoothState) {
392        enforceCallingPermission();
393        synchronized (mStats) {
394            mStats.noteBluetoothStateLocked(bluetoothState);
395        }
396    }
397
398    public void noteFullWifiLockAcquired(int uid) {
399        enforceCallingPermission();
400        synchronized (mStats) {
401            mStats.noteFullWifiLockAcquiredLocked(uid);
402        }
403    }
404
405    public void noteFullWifiLockReleased(int uid) {
406        enforceCallingPermission();
407        synchronized (mStats) {
408            mStats.noteFullWifiLockReleasedLocked(uid);
409        }
410    }
411
412    public void noteWifiScanStarted(int uid) {
413        enforceCallingPermission();
414        synchronized (mStats) {
415            mStats.noteWifiScanStartedLocked(uid);
416        }
417    }
418
419    public void noteWifiScanStopped(int uid) {
420        enforceCallingPermission();
421        synchronized (mStats) {
422            mStats.noteWifiScanStoppedLocked(uid);
423        }
424    }
425
426    public void noteWifiMulticastEnabled(int uid) {
427        enforceCallingPermission();
428        synchronized (mStats) {
429            mStats.noteWifiMulticastEnabledLocked(uid);
430        }
431    }
432
433    public void noteWifiMulticastDisabled(int uid) {
434        enforceCallingPermission();
435        synchronized (mStats) {
436            mStats.noteWifiMulticastDisabledLocked(uid);
437        }
438    }
439
440    public void noteFullWifiLockAcquiredFromSource(WorkSource ws) {
441        enforceCallingPermission();
442        synchronized (mStats) {
443            mStats.noteFullWifiLockAcquiredFromSourceLocked(ws);
444        }
445    }
446
447    public void noteFullWifiLockReleasedFromSource(WorkSource ws) {
448        enforceCallingPermission();
449        synchronized (mStats) {
450            mStats.noteFullWifiLockReleasedFromSourceLocked(ws);
451        }
452    }
453
454    public void noteWifiScanStartedFromSource(WorkSource ws) {
455        enforceCallingPermission();
456        synchronized (mStats) {
457            mStats.noteWifiScanStartedFromSourceLocked(ws);
458        }
459    }
460
461    public void noteWifiScanStoppedFromSource(WorkSource ws) {
462        enforceCallingPermission();
463        synchronized (mStats) {
464            mStats.noteWifiScanStoppedFromSourceLocked(ws);
465        }
466    }
467
468    public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) {
469        enforceCallingPermission();
470        synchronized (mStats) {
471            mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph);
472        }
473    }
474
475    public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) {
476        enforceCallingPermission();
477        synchronized (mStats) {
478            mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws);
479        }
480    }
481
482    public void noteWifiMulticastEnabledFromSource(WorkSource ws) {
483        enforceCallingPermission();
484        synchronized (mStats) {
485            mStats.noteWifiMulticastEnabledFromSourceLocked(ws);
486        }
487    }
488
489    public void noteWifiMulticastDisabledFromSource(WorkSource ws) {
490        enforceCallingPermission();
491        synchronized (mStats) {
492            mStats.noteWifiMulticastDisabledFromSourceLocked(ws);
493        }
494    }
495
496    @Override
497    public void noteNetworkInterfaceType(String iface, int type) {
498        enforceCallingPermission();
499        synchronized (mStats) {
500            mStats.noteNetworkInterfaceTypeLocked(iface, type);
501        }
502    }
503
504    @Override
505    public void noteNetworkStatsEnabled() {
506        enforceCallingPermission();
507        synchronized (mStats) {
508            mStats.noteNetworkStatsEnabledLocked();
509        }
510    }
511
512    public boolean isOnBattery() {
513        return mStats.isOnBattery();
514    }
515
516    public void setBatteryState(int status, int health, int plugType, int level,
517            int temp, int volt) {
518        enforceCallingPermission();
519        mStats.setBatteryState(status, health, plugType, level, temp, volt);
520    }
521
522    public long getAwakeTimeBattery() {
523        mContext.enforceCallingOrSelfPermission(
524                android.Manifest.permission.BATTERY_STATS, null);
525        return mStats.getAwakeTimeBattery();
526    }
527
528    public long getAwakeTimePlugged() {
529        mContext.enforceCallingOrSelfPermission(
530                android.Manifest.permission.BATTERY_STATS, null);
531        return mStats.getAwakeTimePlugged();
532    }
533
534    public void enforceCallingPermission() {
535        if (Binder.getCallingPid() == Process.myPid()) {
536            return;
537        }
538        mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
539                Binder.getCallingPid(), Binder.getCallingUid(), null);
540    }
541
542    private void dumpHelp(PrintWriter pw) {
543        pw.println("Battery stats (batterystats) dump options:");
544        pw.println("  [--checkin] [--history] [-c] [--unplugged] [--reset] [--write]");
545        pw.println("  [-h] [<package.name>]");
546        pw.println("  --checkin: format output for a checkin report.");
547        pw.println("  --history: show only history data.");
548        pw.println("  --unplugged: only output data since last unplugged.");
549        pw.println("  --reset: reset the stats, clearing all current data.");
550        pw.println("  --write: force write current collected stats to disk.");
551        pw.println("  -h: print this help text.");
552        pw.println("  <package.name>: optional name of package to filter output by.");
553    }
554
555    @Override
556    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
557        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
558                != PackageManager.PERMISSION_GRANTED) {
559            pw.println("Permission Denial: can't dump BatteryStats from from pid="
560                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
561                    + " without permission " + android.Manifest.permission.DUMP);
562            return;
563        }
564
565        boolean isCheckin = false;
566        boolean includeHistory = false;
567        boolean historyOnly = false;
568        boolean isUnpluggedOnly = false;
569        boolean noOutput = false;
570        int reqUid = -1;
571        if (args != null) {
572            for (String arg : args) {
573                if ("--checkin".equals(arg)) {
574                    isCheckin = true;
575                } else if ("--history".equals(arg)) {
576                    historyOnly = true;
577                } else if ("-c".equals(arg)) {
578                    isCheckin = true;
579                    includeHistory = true;
580                } else if ("--unplugged".equals(arg)) {
581                    isUnpluggedOnly = true;
582                } else if ("--reset".equals(arg)) {
583                    synchronized (mStats) {
584                        mStats.resetAllStatsCmdLocked();
585                        pw.println("Battery stats reset.");
586                        noOutput = true;
587                    }
588                } else if ("--write".equals(arg)) {
589                    synchronized (mStats) {
590                        mStats.writeSyncLocked();
591                        pw.println("Battery stats written.");
592                        noOutput = true;
593                    }
594                } else if ("-h".equals(arg)) {
595                    dumpHelp(pw);
596                    return;
597                } else if ("-a".equals(arg)) {
598                    // fall through
599                } else if (arg.length() > 0 && arg.charAt(0) == '-'){
600                    pw.println("Unknown option: " + arg);
601                    dumpHelp(pw);
602                    return;
603                } else {
604                    // Not an option, last argument must be a package name.
605                    try {
606                        reqUid = mContext.getPackageManager().getPackageUid(arg,
607                                UserHandle.getCallingUserId());
608                    } catch (PackageManager.NameNotFoundException e) {
609                        pw.println("Unknown package: " + arg);
610                        dumpHelp(pw);
611                        return;
612                    }
613                }
614            }
615        }
616        if (noOutput) {
617            return;
618        }
619        if (isCheckin) {
620            List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
621            synchronized (mStats) {
622                mStats.dumpCheckinLocked(mContext, pw, apps, isUnpluggedOnly, includeHistory,
623                        historyOnly);
624            }
625        } else {
626            synchronized (mStats) {
627                mStats.dumpLocked(mContext, pw, isUnpluggedOnly, reqUid, historyOnly);
628            }
629        }
630    }
631}
632