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