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