BatteryStatsService.java revision ca1bf21c511dc7d513b631a1af8498b5b08d107a
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, int type,
130            boolean unimportantForLogging) {
131        enforceCallingPermission();
132        synchronized (mStats) {
133            mStats.noteStartWakeLocked(uid, pid, name, 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, int type,
145            boolean unimportantForLogging) {
146        enforceCallingPermission();
147        synchronized (mStats) {
148            mStats.noteStartWakeFromSourceLocked(ws, pid, name, type, unimportantForLogging);
149        }
150    }
151
152    public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, int type) {
153        enforceCallingPermission();
154        synchronized (mStats) {
155            mStats.noteStopWakeFromSourceLocked(ws, pid, name, type);
156        }
157    }
158
159    public void noteStartSensor(int uid, int sensor) {
160        enforceCallingPermission();
161        synchronized (mStats) {
162            mStats.noteStartSensorLocked(uid, sensor);
163        }
164    }
165
166    public void noteStopSensor(int uid, int sensor) {
167        enforceCallingPermission();
168        synchronized (mStats) {
169            mStats.noteStopSensorLocked(uid, sensor);
170        }
171    }
172
173    public void noteVibratorOn(int uid, long durationMillis) {
174        enforceCallingPermission();
175        synchronized (mStats) {
176            mStats.noteVibratorOnLocked(uid, durationMillis);
177        }
178    }
179
180    public void noteVibratorOff(int uid) {
181        enforceCallingPermission();
182        synchronized (mStats) {
183            mStats.noteVibratorOffLocked(uid);
184        }
185    }
186
187    public void noteStartGps(int uid) {
188        enforceCallingPermission();
189        synchronized (mStats) {
190            mStats.noteStartGpsLocked(uid);
191        }
192    }
193
194    public void noteStopGps(int uid) {
195        enforceCallingPermission();
196        synchronized (mStats) {
197            mStats.noteStopGpsLocked(uid);
198        }
199    }
200
201    public void noteScreenOn() {
202        enforceCallingPermission();
203        synchronized (mStats) {
204            mStats.noteScreenOnLocked();
205        }
206    }
207
208    public void noteScreenBrightness(int brightness) {
209        enforceCallingPermission();
210        synchronized (mStats) {
211            mStats.noteScreenBrightnessLocked(brightness);
212        }
213    }
214
215    public void noteScreenOff() {
216        enforceCallingPermission();
217        synchronized (mStats) {
218            mStats.noteScreenOffLocked();
219        }
220    }
221
222    public void noteInputEvent() {
223        enforceCallingPermission();
224        mStats.noteInputEventAtomic();
225    }
226
227    public void noteUserActivity(int uid, int event) {
228        enforceCallingPermission();
229        synchronized (mStats) {
230            mStats.noteUserActivityLocked(uid, event);
231        }
232    }
233
234    public void noteDataConnectionActive(String label, boolean active) {
235        enforceCallingPermission();
236        synchronized (mStats) {
237            mStats.noteDataConnectionActive(label, active);
238        }
239    }
240
241    public void notePhoneOn() {
242        enforceCallingPermission();
243        synchronized (mStats) {
244            mStats.notePhoneOnLocked();
245        }
246    }
247
248    public void notePhoneOff() {
249        enforceCallingPermission();
250        synchronized (mStats) {
251            mStats.notePhoneOffLocked();
252        }
253    }
254
255    public void notePhoneSignalStrength(SignalStrength signalStrength) {
256        enforceCallingPermission();
257        synchronized (mStats) {
258            mStats.notePhoneSignalStrengthLocked(signalStrength);
259        }
260    }
261
262    public void notePhoneDataConnectionState(int dataType, boolean hasData) {
263        enforceCallingPermission();
264        synchronized (mStats) {
265            mStats.notePhoneDataConnectionStateLocked(dataType, hasData);
266        }
267    }
268
269    public void notePhoneState(int state) {
270        enforceCallingPermission();
271        int simState = TelephonyManager.getDefault().getSimState();
272        synchronized (mStats) {
273            mStats.notePhoneStateLocked(state, simState);
274        }
275    }
276
277    public void noteWifiOn() {
278        enforceCallingPermission();
279        synchronized (mStats) {
280            mStats.noteWifiOnLocked();
281        }
282    }
283
284    public void noteWifiOff() {
285        enforceCallingPermission();
286        synchronized (mStats) {
287            mStats.noteWifiOffLocked();
288        }
289    }
290
291    public void noteStartAudio(int uid) {
292        enforceCallingPermission();
293        synchronized (mStats) {
294            mStats.noteAudioOnLocked(uid);
295        }
296    }
297
298    public void noteStopAudio(int uid) {
299        enforceCallingPermission();
300        synchronized (mStats) {
301            mStats.noteAudioOffLocked(uid);
302        }
303    }
304
305    public void noteStartVideo(int uid) {
306        enforceCallingPermission();
307        synchronized (mStats) {
308            mStats.noteVideoOnLocked(uid);
309        }
310    }
311
312    public void noteStopVideo(int uid) {
313        enforceCallingPermission();
314        synchronized (mStats) {
315            mStats.noteVideoOffLocked(uid);
316        }
317    }
318
319    public void noteWifiRunning(WorkSource ws) {
320        enforceCallingPermission();
321        synchronized (mStats) {
322            mStats.noteWifiRunningLocked(ws);
323        }
324    }
325
326    public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) {
327        enforceCallingPermission();
328        synchronized (mStats) {
329            mStats.noteWifiRunningChangedLocked(oldWs, newWs);
330        }
331    }
332
333    public void noteWifiStopped(WorkSource ws) {
334        enforceCallingPermission();
335        synchronized (mStats) {
336            mStats.noteWifiStoppedLocked(ws);
337        }
338    }
339
340    public void noteWifiState(int wifiState, String accessPoint) {
341        enforceCallingPermission();
342        synchronized (mStats) {
343            mStats.noteWifiStateLocked(wifiState, accessPoint);
344        }
345    }
346
347    public void noteBluetoothOn() {
348        enforceCallingPermission();
349        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
350        if (adapter != null) {
351            adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
352                                    BluetoothProfile.HEADSET);
353        }
354        synchronized (mStats) {
355            if (mBluetoothHeadset != null) {
356                mStats.noteBluetoothOnLocked();
357                mStats.setBtHeadset(mBluetoothHeadset);
358            } else {
359                mBluetoothPendingStats = true;
360            }
361        }
362    }
363
364    private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
365        new BluetoothProfile.ServiceListener() {
366        public void onServiceConnected(int profile, BluetoothProfile proxy) {
367            mBluetoothHeadset = (BluetoothHeadset) proxy;
368            synchronized (mStats) {
369                if (mBluetoothPendingStats) {
370                    mStats.noteBluetoothOnLocked();
371                    mStats.setBtHeadset(mBluetoothHeadset);
372                    mBluetoothPendingStats = false;
373                }
374            }
375        }
376
377        public void onServiceDisconnected(int profile) {
378            mBluetoothHeadset = null;
379        }
380    };
381
382    public void noteBluetoothOff() {
383        enforceCallingPermission();
384        synchronized (mStats) {
385            mBluetoothPendingStats = false;
386            mStats.noteBluetoothOffLocked();
387        }
388    }
389
390    public void noteBluetoothState(int bluetoothState) {
391        enforceCallingPermission();
392        synchronized (mStats) {
393            mStats.noteBluetoothStateLocked(bluetoothState);
394        }
395    }
396
397    public void noteFullWifiLockAcquired(int uid) {
398        enforceCallingPermission();
399        synchronized (mStats) {
400            mStats.noteFullWifiLockAcquiredLocked(uid);
401        }
402    }
403
404    public void noteFullWifiLockReleased(int uid) {
405        enforceCallingPermission();
406        synchronized (mStats) {
407            mStats.noteFullWifiLockReleasedLocked(uid);
408        }
409    }
410
411    public void noteWifiScanStarted(int uid) {
412        enforceCallingPermission();
413        synchronized (mStats) {
414            mStats.noteWifiScanStartedLocked(uid);
415        }
416    }
417
418    public void noteWifiScanStopped(int uid) {
419        enforceCallingPermission();
420        synchronized (mStats) {
421            mStats.noteWifiScanStoppedLocked(uid);
422        }
423    }
424
425    public void noteWifiMulticastEnabled(int uid) {
426        enforceCallingPermission();
427        synchronized (mStats) {
428            mStats.noteWifiMulticastEnabledLocked(uid);
429        }
430    }
431
432    public void noteWifiMulticastDisabled(int uid) {
433        enforceCallingPermission();
434        synchronized (mStats) {
435            mStats.noteWifiMulticastDisabledLocked(uid);
436        }
437    }
438
439    public void noteFullWifiLockAcquiredFromSource(WorkSource ws) {
440        enforceCallingPermission();
441        synchronized (mStats) {
442            mStats.noteFullWifiLockAcquiredFromSourceLocked(ws);
443        }
444    }
445
446    public void noteFullWifiLockReleasedFromSource(WorkSource ws) {
447        enforceCallingPermission();
448        synchronized (mStats) {
449            mStats.noteFullWifiLockReleasedFromSourceLocked(ws);
450        }
451    }
452
453    public void noteWifiScanStartedFromSource(WorkSource ws) {
454        enforceCallingPermission();
455        synchronized (mStats) {
456            mStats.noteWifiScanStartedFromSourceLocked(ws);
457        }
458    }
459
460    public void noteWifiScanStoppedFromSource(WorkSource ws) {
461        enforceCallingPermission();
462        synchronized (mStats) {
463            mStats.noteWifiScanStoppedFromSourceLocked(ws);
464        }
465    }
466
467    public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) {
468        enforceCallingPermission();
469        synchronized (mStats) {
470            mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph);
471        }
472    }
473
474    public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) {
475        enforceCallingPermission();
476        synchronized (mStats) {
477            mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws);
478        }
479    }
480
481    public void noteWifiMulticastEnabledFromSource(WorkSource ws) {
482        enforceCallingPermission();
483        synchronized (mStats) {
484            mStats.noteWifiMulticastEnabledFromSourceLocked(ws);
485        }
486    }
487
488    public void noteWifiMulticastDisabledFromSource(WorkSource ws) {
489        enforceCallingPermission();
490        synchronized (mStats) {
491            mStats.noteWifiMulticastDisabledFromSourceLocked(ws);
492        }
493    }
494
495    @Override
496    public void noteNetworkInterfaceType(String iface, int type) {
497        enforceCallingPermission();
498        synchronized (mStats) {
499            mStats.noteNetworkInterfaceTypeLocked(iface, type);
500        }
501    }
502
503    @Override
504    public void noteNetworkStatsEnabled() {
505        enforceCallingPermission();
506        synchronized (mStats) {
507            mStats.noteNetworkStatsEnabledLocked();
508        }
509    }
510
511    public boolean isOnBattery() {
512        return mStats.isOnBattery();
513    }
514
515    public void setBatteryState(int status, int health, int plugType, int level,
516            int temp, int volt) {
517        enforceCallingPermission();
518        mStats.setBatteryState(status, health, plugType, level, temp, volt);
519    }
520
521    public long getAwakeTimeBattery() {
522        mContext.enforceCallingOrSelfPermission(
523                android.Manifest.permission.BATTERY_STATS, null);
524        return mStats.getAwakeTimeBattery();
525    }
526
527    public long getAwakeTimePlugged() {
528        mContext.enforceCallingOrSelfPermission(
529                android.Manifest.permission.BATTERY_STATS, null);
530        return mStats.getAwakeTimePlugged();
531    }
532
533    public void enforceCallingPermission() {
534        if (Binder.getCallingPid() == Process.myPid()) {
535            return;
536        }
537        mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
538                Binder.getCallingPid(), Binder.getCallingUid(), null);
539    }
540
541    private void dumpHelp(PrintWriter pw) {
542        pw.println("Battery stats (batterystats) dump options:");
543        pw.println("  [--checkin] [--history] [-c] [--unplugged] [--reset] [--write]");
544        pw.println("  [-h] [<package.name>]");
545        pw.println("  --checkin: format output for a checkin report.");
546        pw.println("  --history: show only history data.");
547        pw.println("  --unplugged: only output data since last unplugged.");
548        pw.println("  --reset: reset the stats, clearing all current data.");
549        pw.println("  --write: force write current collected stats to disk.");
550        pw.println("  -h: print this help text.");
551        pw.println("  <package.name>: optional name of package to filter output by.");
552    }
553
554    @Override
555    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
556        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
557                != PackageManager.PERMISSION_GRANTED) {
558            pw.println("Permission Denial: can't dump BatteryStats from from pid="
559                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
560                    + " without permission " + android.Manifest.permission.DUMP);
561            return;
562        }
563
564        boolean isCheckin = false;
565        boolean includeHistory = false;
566        boolean historyOnly = false;
567        boolean isUnpluggedOnly = false;
568        boolean noOutput = false;
569        int reqUid = -1;
570        if (args != null) {
571            for (String arg : args) {
572                if ("--checkin".equals(arg)) {
573                    isCheckin = true;
574                } else if ("--history".equals(arg)) {
575                    historyOnly = true;
576                } else if ("-c".equals(arg)) {
577                    isCheckin = true;
578                    includeHistory = true;
579                } else if ("--unplugged".equals(arg)) {
580                    isUnpluggedOnly = true;
581                } else if ("--reset".equals(arg)) {
582                    synchronized (mStats) {
583                        mStats.resetAllStatsCmdLocked();
584                        pw.println("Battery stats reset.");
585                        noOutput = true;
586                    }
587                } else if ("--write".equals(arg)) {
588                    synchronized (mStats) {
589                        mStats.writeSyncLocked();
590                        pw.println("Battery stats written.");
591                        noOutput = true;
592                    }
593                } else if ("-h".equals(arg)) {
594                    dumpHelp(pw);
595                    return;
596                } else if ("-a".equals(arg)) {
597                    // fall through
598                } else if (arg.length() > 0 && arg.charAt(0) == '-'){
599                    pw.println("Unknown option: " + arg);
600                    dumpHelp(pw);
601                    return;
602                } else {
603                    // Not an option, last argument must be a package name.
604                    try {
605                        reqUid = mContext.getPackageManager().getPackageUid(arg,
606                                UserHandle.getCallingUserId());
607                    } catch (PackageManager.NameNotFoundException e) {
608                        pw.println("Unknown package: " + arg);
609                        dumpHelp(pw);
610                        return;
611                    }
612                }
613            }
614        }
615        if (noOutput) {
616            return;
617        }
618        if (isCheckin) {
619            List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
620            synchronized (mStats) {
621                mStats.dumpCheckinLocked(mContext, pw, apps, isUnpluggedOnly, includeHistory,
622                        historyOnly);
623            }
624        } else {
625            synchronized (mStats) {
626                mStats.dumpLocked(mContext, pw, isUnpluggedOnly, reqUid, historyOnly);
627            }
628        }
629    }
630}
631