BatteryStatsService.java revision e13c4c0b664dabdc069ca8f9601d96a337eb02f9
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 noteBluetoothOn() {
341        enforceCallingPermission();
342        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
343        if (adapter != null) {
344            adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
345                                    BluetoothProfile.HEADSET);
346        }
347        synchronized (mStats) {
348            if (mBluetoothHeadset != null) {
349                mStats.noteBluetoothOnLocked();
350                mStats.setBtHeadset(mBluetoothHeadset);
351            } else {
352                mBluetoothPendingStats = true;
353            }
354        }
355    }
356
357    private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
358        new BluetoothProfile.ServiceListener() {
359        public void onServiceConnected(int profile, BluetoothProfile proxy) {
360            mBluetoothHeadset = (BluetoothHeadset) proxy;
361            synchronized (mStats) {
362                if (mBluetoothPendingStats) {
363                    mStats.noteBluetoothOnLocked();
364                    mStats.setBtHeadset(mBluetoothHeadset);
365                    mBluetoothPendingStats = false;
366                }
367            }
368        }
369
370        public void onServiceDisconnected(int profile) {
371            mBluetoothHeadset = null;
372        }
373    };
374
375    public void noteBluetoothOff() {
376        enforceCallingPermission();
377        synchronized (mStats) {
378            mBluetoothPendingStats = false;
379            mStats.noteBluetoothOffLocked();
380        }
381    }
382
383    public void noteBluetoothActiveState(int actType) {
384        enforceCallingPermission();
385        synchronized (mStats) {
386            mStats.noteBluetoothActiveStateLocked(actType);
387        }
388    }
389
390    public void noteFullWifiLockAcquired(int uid) {
391        enforceCallingPermission();
392        synchronized (mStats) {
393            mStats.noteFullWifiLockAcquiredLocked(uid);
394        }
395    }
396
397    public void noteFullWifiLockReleased(int uid) {
398        enforceCallingPermission();
399        synchronized (mStats) {
400            mStats.noteFullWifiLockReleasedLocked(uid);
401        }
402    }
403
404    public void noteWifiScanStarted(int uid) {
405        enforceCallingPermission();
406        synchronized (mStats) {
407            mStats.noteWifiScanStartedLocked(uid);
408        }
409    }
410
411    public void noteWifiScanStopped(int uid) {
412        enforceCallingPermission();
413        synchronized (mStats) {
414            mStats.noteWifiScanStoppedLocked(uid);
415        }
416    }
417
418    public void noteWifiMulticastEnabled(int uid) {
419        enforceCallingPermission();
420        synchronized (mStats) {
421            mStats.noteWifiMulticastEnabledLocked(uid);
422        }
423    }
424
425    public void noteWifiMulticastDisabled(int uid) {
426        enforceCallingPermission();
427        synchronized (mStats) {
428            mStats.noteWifiMulticastDisabledLocked(uid);
429        }
430    }
431
432    public void noteFullWifiLockAcquiredFromSource(WorkSource ws) {
433        enforceCallingPermission();
434        synchronized (mStats) {
435            mStats.noteFullWifiLockAcquiredFromSourceLocked(ws);
436        }
437    }
438
439    public void noteFullWifiLockReleasedFromSource(WorkSource ws) {
440        enforceCallingPermission();
441        synchronized (mStats) {
442            mStats.noteFullWifiLockReleasedFromSourceLocked(ws);
443        }
444    }
445
446    public void noteWifiScanStartedFromSource(WorkSource ws) {
447        enforceCallingPermission();
448        synchronized (mStats) {
449            mStats.noteWifiScanStartedFromSourceLocked(ws);
450        }
451    }
452
453    public void noteWifiScanStoppedFromSource(WorkSource ws) {
454        enforceCallingPermission();
455        synchronized (mStats) {
456            mStats.noteWifiScanStoppedFromSourceLocked(ws);
457        }
458    }
459
460    public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) {
461        enforceCallingPermission();
462        synchronized (mStats) {
463            mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph);
464        }
465    }
466
467    public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) {
468        enforceCallingPermission();
469        synchronized (mStats) {
470            mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws);
471        }
472    }
473
474    public void noteWifiMulticastEnabledFromSource(WorkSource ws) {
475        enforceCallingPermission();
476        synchronized (mStats) {
477            mStats.noteWifiMulticastEnabledFromSourceLocked(ws);
478        }
479    }
480
481    public void noteWifiMulticastDisabledFromSource(WorkSource ws) {
482        enforceCallingPermission();
483        synchronized (mStats) {
484            mStats.noteWifiMulticastDisabledFromSourceLocked(ws);
485        }
486    }
487
488    @Override
489    public void noteNetworkInterfaceType(String iface, int type) {
490        enforceCallingPermission();
491        synchronized (mStats) {
492            mStats.noteNetworkInterfaceTypeLocked(iface, type);
493        }
494    }
495
496    @Override
497    public void noteNetworkStatsEnabled() {
498        enforceCallingPermission();
499        synchronized (mStats) {
500            mStats.noteNetworkStatsEnabledLocked();
501        }
502    }
503
504    public boolean isOnBattery() {
505        return mStats.isOnBattery();
506    }
507
508    public void setBatteryState(int status, int health, int plugType, int level,
509            int temp, int volt) {
510        enforceCallingPermission();
511        mStats.setBatteryState(status, health, plugType, level, temp, volt);
512    }
513
514    public long getAwakeTimeBattery() {
515        mContext.enforceCallingOrSelfPermission(
516                android.Manifest.permission.BATTERY_STATS, null);
517        return mStats.getAwakeTimeBattery();
518    }
519
520    public long getAwakeTimePlugged() {
521        mContext.enforceCallingOrSelfPermission(
522                android.Manifest.permission.BATTERY_STATS, null);
523        return mStats.getAwakeTimePlugged();
524    }
525
526    public void enforceCallingPermission() {
527        if (Binder.getCallingPid() == Process.myPid()) {
528            return;
529        }
530        mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
531                Binder.getCallingPid(), Binder.getCallingUid(), null);
532    }
533
534    private void dumpHelp(PrintWriter pw) {
535        pw.println("Battery stats (batterystats) dump options:");
536        pw.println("  [--checkin] [--history] [-c] [--unplugged] [--reset] [--write]");
537        pw.println("  [-h] [<package.name>]");
538        pw.println("  --checkin: format output for a checkin report.");
539        pw.println("  --history: show only history data.");
540        pw.println("  --unplugged: only output data since last unplugged.");
541        pw.println("  --reset: reset the stats, clearing all current data.");
542        pw.println("  --write: force write current collected stats to disk.");
543        pw.println("  -h: print this help text.");
544        pw.println("  <package.name>: optional name of package to filter output by.");
545    }
546
547    @Override
548    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
549        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
550                != PackageManager.PERMISSION_GRANTED) {
551            pw.println("Permission Denial: can't dump BatteryStats from from pid="
552                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
553                    + " without permission " + android.Manifest.permission.DUMP);
554            return;
555        }
556
557        boolean isCheckin = false;
558        boolean includeHistory = false;
559        boolean historyOnly = false;
560        boolean isUnpluggedOnly = false;
561        boolean noOutput = false;
562        int reqUid = -1;
563        if (args != null) {
564            for (String arg : args) {
565                if ("--checkin".equals(arg)) {
566                    isCheckin = true;
567                } else if ("--history".equals(arg)) {
568                    historyOnly = true;
569                } else if ("-c".equals(arg)) {
570                    isCheckin = true;
571                    includeHistory = true;
572                } else if ("--unplugged".equals(arg)) {
573                    isUnpluggedOnly = true;
574                } else if ("--reset".equals(arg)) {
575                    synchronized (mStats) {
576                        mStats.resetAllStatsCmdLocked();
577                        pw.println("Battery stats reset.");
578                        noOutput = true;
579                    }
580                } else if ("--write".equals(arg)) {
581                    synchronized (mStats) {
582                        mStats.writeSyncLocked();
583                        pw.println("Battery stats written.");
584                        noOutput = true;
585                    }
586                } else if ("-h".equals(arg)) {
587                    dumpHelp(pw);
588                    return;
589                } else if ("-a".equals(arg)) {
590                    // fall through
591                } else if (arg.length() > 0 && arg.charAt(0) == '-'){
592                    pw.println("Unknown option: " + arg);
593                    dumpHelp(pw);
594                    return;
595                } else {
596                    // Not an option, last argument must be a package name.
597                    try {
598                        reqUid = mContext.getPackageManager().getPackageUid(arg,
599                                UserHandle.getCallingUserId());
600                    } catch (PackageManager.NameNotFoundException e) {
601                        pw.println("Unknown package: " + arg);
602                        dumpHelp(pw);
603                        return;
604                    }
605                }
606            }
607        }
608        if (noOutput) {
609            return;
610        }
611        if (isCheckin) {
612            List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
613            synchronized (mStats) {
614                mStats.dumpCheckinLocked(mContext, pw, apps, isUnpluggedOnly, includeHistory,
615                        historyOnly);
616            }
617        } else {
618            synchronized (mStats) {
619                mStats.dumpLocked(mContext, pw, isUnpluggedOnly, reqUid, historyOnly);
620            }
621        }
622    }
623}
624