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