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