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.BluetoothHeadset;
20import android.content.Context;
21import android.content.pm.ApplicationInfo;
22import android.os.Binder;
23import android.os.IBinder;
24import android.os.Parcel;
25import android.os.Process;
26import android.os.ServiceManager;
27import android.os.WorkSource;
28import android.telephony.SignalStrength;
29import android.telephony.TelephonyManager;
30import android.util.Slog;
31
32import com.android.internal.app.IBatteryStats;
33import com.android.internal.os.BatteryStatsImpl;
34import com.android.internal.os.PowerProfile;
35
36import java.io.FileDescriptor;
37import java.io.PrintWriter;
38import java.util.List;
39
40/**
41 * All information we are collecting about things that can happen that impact
42 * battery life.
43 */
44public final class BatteryStatsService extends IBatteryStats.Stub {
45    static IBatteryStats sService;
46
47    final BatteryStatsImpl mStats;
48    Context mContext;
49
50    BatteryStatsService(String filename) {
51        mStats = new BatteryStatsImpl(filename);
52    }
53
54    public void publish(Context context) {
55        mContext = context;
56        ServiceManager.addService("batteryinfo", asBinder());
57        mStats.setNumSpeedSteps(new PowerProfile(mContext).getNumSpeedSteps());
58        mStats.setRadioScanningTimeout(mContext.getResources().getInteger(
59                com.android.internal.R.integer.config_radioScanningTimeout)
60                * 1000L);
61    }
62
63    public void shutdown() {
64        Slog.w("BatteryStats", "Writing battery stats before shutdown...");
65        synchronized (mStats) {
66            mStats.shutdownLocked();
67        }
68    }
69
70    public static IBatteryStats getService() {
71        if (sService != null) {
72            return sService;
73        }
74        IBinder b = ServiceManager.getService("batteryinfo");
75        sService = asInterface(b);
76        return sService;
77    }
78
79    /**
80     * @return the current statistics object, which may be modified
81     * to reflect events that affect battery usage.  You must lock the
82     * stats object before doing anything with it.
83     */
84    public BatteryStatsImpl getActiveStatistics() {
85        return mStats;
86    }
87
88    public byte[] getStatistics() {
89        mContext.enforceCallingPermission(
90                android.Manifest.permission.BATTERY_STATS, null);
91        //Slog.i("foo", "SENDING BATTERY INFO:");
92        //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
93        Parcel out = Parcel.obtain();
94        mStats.writeToParcel(out, 0);
95        byte[] data = out.marshall();
96        out.recycle();
97        return data;
98    }
99
100    public void noteStartWakelock(int uid, int pid, String name, int type) {
101        enforceCallingPermission();
102        synchronized (mStats) {
103            mStats.noteStartWakeLocked(uid, pid, name, type);
104        }
105    }
106
107    public void noteStopWakelock(int uid, int pid, String name, int type) {
108        enforceCallingPermission();
109        synchronized (mStats) {
110            mStats.noteStopWakeLocked(uid, pid, name, type);
111        }
112    }
113
114    public void noteStartWakelockFromSource(WorkSource ws, int pid, String name, int type) {
115        enforceCallingPermission();
116        synchronized (mStats) {
117            mStats.noteStartWakeFromSourceLocked(ws, pid, name, type);
118        }
119    }
120
121    public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, int type) {
122        enforceCallingPermission();
123        synchronized (mStats) {
124            mStats.noteStopWakeFromSourceLocked(ws, pid, name, type);
125        }
126    }
127
128    public void noteStartSensor(int uid, int sensor) {
129        enforceCallingPermission();
130        synchronized (mStats) {
131            mStats.noteStartSensorLocked(uid, sensor);
132        }
133    }
134
135    public void noteStopSensor(int uid, int sensor) {
136        enforceCallingPermission();
137        synchronized (mStats) {
138            mStats.noteStopSensorLocked(uid, sensor);
139        }
140    }
141
142    public void noteStartGps(int uid) {
143        enforceCallingPermission();
144        synchronized (mStats) {
145            mStats.noteStartGpsLocked(uid);
146        }
147    }
148
149    public void noteStopGps(int uid) {
150        enforceCallingPermission();
151        synchronized (mStats) {
152            mStats.noteStopGpsLocked(uid);
153        }
154    }
155
156    public void noteScreenOn() {
157        enforceCallingPermission();
158        synchronized (mStats) {
159            mStats.noteScreenOnLocked();
160        }
161    }
162
163    public void noteScreenBrightness(int brightness) {
164        enforceCallingPermission();
165        synchronized (mStats) {
166            mStats.noteScreenBrightnessLocked(brightness);
167        }
168    }
169
170    public void noteScreenOff() {
171        enforceCallingPermission();
172        synchronized (mStats) {
173            mStats.noteScreenOffLocked();
174        }
175    }
176
177    public void noteInputEvent() {
178        enforceCallingPermission();
179        mStats.noteInputEventAtomic();
180    }
181
182    public void noteUserActivity(int uid, int event) {
183        enforceCallingPermission();
184        synchronized (mStats) {
185            mStats.noteUserActivityLocked(uid, event);
186        }
187    }
188
189    public void notePhoneOn() {
190        enforceCallingPermission();
191        synchronized (mStats) {
192            mStats.notePhoneOnLocked();
193        }
194    }
195
196    public void notePhoneOff() {
197        enforceCallingPermission();
198        synchronized (mStats) {
199            mStats.notePhoneOffLocked();
200        }
201    }
202
203    public void notePhoneSignalStrength(SignalStrength signalStrength) {
204        enforceCallingPermission();
205        synchronized (mStats) {
206            mStats.notePhoneSignalStrengthLocked(signalStrength);
207        }
208    }
209
210    public void notePhoneDataConnectionState(int dataType, boolean hasData) {
211        enforceCallingPermission();
212        synchronized (mStats) {
213            mStats.notePhoneDataConnectionStateLocked(dataType, hasData);
214        }
215    }
216
217    public void notePhoneState(int state) {
218        enforceCallingPermission();
219        int simState = TelephonyManager.getDefault().getSimState();
220        synchronized (mStats) {
221            mStats.notePhoneStateLocked(state, simState);
222        }
223    }
224
225    public void noteWifiOn() {
226        enforceCallingPermission();
227        synchronized (mStats) {
228            mStats.noteWifiOnLocked();
229        }
230    }
231
232    public void noteWifiOff() {
233        enforceCallingPermission();
234        synchronized (mStats) {
235            mStats.noteWifiOffLocked();
236        }
237    }
238
239    public void noteStartAudio(int uid) {
240        enforceCallingPermission();
241        synchronized (mStats) {
242            mStats.noteAudioOnLocked(uid);
243        }
244    }
245
246    public void noteStopAudio(int uid) {
247        enforceCallingPermission();
248        synchronized (mStats) {
249            mStats.noteAudioOffLocked(uid);
250        }
251    }
252
253    public void noteStartVideo(int uid) {
254        enforceCallingPermission();
255        synchronized (mStats) {
256            mStats.noteVideoOnLocked(uid);
257        }
258    }
259
260    public void noteStopVideo(int uid) {
261        enforceCallingPermission();
262        synchronized (mStats) {
263            mStats.noteVideoOffLocked(uid);
264        }
265    }
266
267    public void noteWifiRunning(WorkSource ws) {
268        enforceCallingPermission();
269        synchronized (mStats) {
270            mStats.noteWifiRunningLocked(ws);
271        }
272    }
273
274    public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) {
275        enforceCallingPermission();
276        synchronized (mStats) {
277            mStats.noteWifiRunningChangedLocked(oldWs, newWs);
278        }
279    }
280
281    public void noteWifiStopped(WorkSource ws) {
282        enforceCallingPermission();
283        synchronized (mStats) {
284            mStats.noteWifiStoppedLocked(ws);
285        }
286    }
287
288    public void noteBluetoothOn() {
289        enforceCallingPermission();
290        BluetoothHeadset headset = new BluetoothHeadset(mContext, null);
291        synchronized (mStats) {
292            mStats.noteBluetoothOnLocked();
293            mStats.setBtHeadset(headset);
294        }
295    }
296
297    public void noteBluetoothOff() {
298        enforceCallingPermission();
299        synchronized (mStats) {
300            mStats.noteBluetoothOffLocked();
301        }
302    }
303
304    public void noteFullWifiLockAcquired(int uid) {
305        enforceCallingPermission();
306        synchronized (mStats) {
307            mStats.noteFullWifiLockAcquiredLocked(uid);
308        }
309    }
310
311    public void noteFullWifiLockReleased(int uid) {
312        enforceCallingPermission();
313        synchronized (mStats) {
314            mStats.noteFullWifiLockReleasedLocked(uid);
315        }
316    }
317
318    public void noteScanWifiLockAcquired(int uid) {
319        enforceCallingPermission();
320        synchronized (mStats) {
321            mStats.noteScanWifiLockAcquiredLocked(uid);
322        }
323    }
324
325    public void noteScanWifiLockReleased(int uid) {
326        enforceCallingPermission();
327        synchronized (mStats) {
328            mStats.noteScanWifiLockReleasedLocked(uid);
329        }
330    }
331
332    public void noteWifiMulticastEnabled(int uid) {
333        enforceCallingPermission();
334        synchronized (mStats) {
335            mStats.noteWifiMulticastEnabledLocked(uid);
336        }
337    }
338
339    public void noteWifiMulticastDisabled(int uid) {
340        enforceCallingPermission();
341        synchronized (mStats) {
342            mStats.noteWifiMulticastDisabledLocked(uid);
343        }
344    }
345
346    public void noteFullWifiLockAcquiredFromSource(WorkSource ws) {
347        enforceCallingPermission();
348        synchronized (mStats) {
349            mStats.noteFullWifiLockAcquiredFromSourceLocked(ws);
350        }
351    }
352
353    public void noteFullWifiLockReleasedFromSource(WorkSource ws) {
354        enforceCallingPermission();
355        synchronized (mStats) {
356            mStats.noteFullWifiLockReleasedFromSourceLocked(ws);
357        }
358    }
359
360    public void noteScanWifiLockAcquiredFromSource(WorkSource ws) {
361        enforceCallingPermission();
362        synchronized (mStats) {
363            mStats.noteScanWifiLockAcquiredFromSourceLocked(ws);
364        }
365    }
366
367    public void noteScanWifiLockReleasedFromSource(WorkSource ws) {
368        enforceCallingPermission();
369        synchronized (mStats) {
370            mStats.noteScanWifiLockReleasedFromSourceLocked(ws);
371        }
372    }
373
374    public void noteWifiMulticastEnabledFromSource(WorkSource ws) {
375        enforceCallingPermission();
376        synchronized (mStats) {
377            mStats.noteWifiMulticastEnabledFromSourceLocked(ws);
378        }
379    }
380
381    public void noteWifiMulticastDisabledFromSource(WorkSource ws) {
382        enforceCallingPermission();
383        synchronized (mStats) {
384            mStats.noteWifiMulticastDisabledFromSourceLocked(ws);
385        }
386    }
387
388    public boolean isOnBattery() {
389        return mStats.isOnBattery();
390    }
391
392    public void setBatteryState(int status, int health, int plugType, int level,
393            int temp, int volt) {
394        enforceCallingPermission();
395        mStats.setBatteryState(status, health, plugType, level, temp, volt);
396    }
397
398    public long getAwakeTimeBattery() {
399        mContext.enforceCallingOrSelfPermission(
400                android.Manifest.permission.BATTERY_STATS, null);
401        return mStats.getAwakeTimeBattery();
402    }
403
404    public long getAwakeTimePlugged() {
405        mContext.enforceCallingOrSelfPermission(
406                android.Manifest.permission.BATTERY_STATS, null);
407        return mStats.getAwakeTimePlugged();
408    }
409
410    public void enforceCallingPermission() {
411        if (Binder.getCallingPid() == Process.myPid()) {
412            return;
413        }
414        mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
415                Binder.getCallingPid(), Binder.getCallingUid(), null);
416    }
417
418    @Override
419    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
420        boolean isCheckin = false;
421        if (args != null) {
422            for (String arg : args) {
423                if ("--checkin".equals(arg)) {
424                    isCheckin = true;
425                } else if ("--reset".equals(arg)) {
426                    synchronized (mStats) {
427                        mStats.resetAllStatsLocked();
428                        pw.println("Battery stats reset.");
429                    }
430                }
431            }
432        }
433        if (isCheckin) {
434            List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
435            synchronized (mStats) {
436                mStats.dumpCheckinLocked(pw, args, apps);
437            }
438        } else {
439            synchronized (mStats) {
440                mStats.dumpLocked(pw);
441            }
442        }
443    }
444}
445