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