BatteryStatsService.java revision 10eaa8574bb220e7dddf9a78057f83dc64ee5687
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.PowerManagerInternal;
31import android.os.Process;
32import android.os.ServiceManager;
33import android.os.SystemClock;
34import android.os.UserHandle;
35import android.os.WorkSource;
36import android.telephony.SignalStrength;
37import android.telephony.TelephonyManager;
38import android.util.Slog;
39
40import com.android.internal.app.IBatteryStats;
41import com.android.internal.os.BatteryStatsImpl;
42import com.android.internal.os.PowerProfile;
43import com.android.server.LocalServices;
44
45import java.io.FileDescriptor;
46import java.io.PrintWriter;
47import java.util.List;
48
49/**
50 * All information we are collecting about things that can happen that impact
51 * battery life.
52 */
53public final class BatteryStatsService extends IBatteryStats.Stub
54        implements PowerManagerInternal.LowPowerModeListener {
55    static final String TAG = "BatteryStatsService";
56
57    static IBatteryStats sService;
58
59    final BatteryStatsImpl mStats;
60    Context mContext;
61    private boolean mBluetoothPendingStats;
62    private BluetoothHeadset mBluetoothHeadset;
63    PowerManagerInternal mPowerManagerInternal;
64
65    BatteryStatsService(String filename, Handler handler) {
66        mStats = new BatteryStatsImpl(filename, handler);
67    }
68
69    public void publish(Context context) {
70        mContext = context;
71        ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
72        mStats.setNumSpeedSteps(new PowerProfile(mContext).getNumSpeedSteps());
73        mStats.setRadioScanningTimeout(mContext.getResources().getInteger(
74                com.android.internal.R.integer.config_radioScanningTimeout)
75                * 1000L);
76    }
77
78    /**
79     * At the time when the constructor runs, the power manager has not yet been
80     * initialized.  So we initialize the low power observer later.
81     */
82    public void initPowerManagement() {
83        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
84        mPowerManagerInternal.registerLowPowerModeObserver(this);
85        mStats.noteLowPowerMode(mPowerManagerInternal.getLowPowerModeEnabled());
86        (new WakeupReasonThread()).start();
87    }
88
89    public void shutdown() {
90        Slog.w("BatteryStats", "Writing battery stats before shutdown...");
91        synchronized (mStats) {
92            mStats.shutdownLocked();
93        }
94    }
95
96    public static IBatteryStats getService() {
97        if (sService != null) {
98            return sService;
99        }
100        IBinder b = ServiceManager.getService(BatteryStats.SERVICE_NAME);
101        sService = asInterface(b);
102        return sService;
103    }
104
105    @Override
106    public void onLowPowerModeChanged(boolean enabled) {
107        synchronized (mStats) {
108            mStats.noteLowPowerMode(enabled);
109        }
110    }
111
112    /**
113     * @return the current statistics object, which may be modified
114     * to reflect events that affect battery usage.  You must lock the
115     * stats object before doing anything with it.
116     */
117    public BatteryStatsImpl getActiveStatistics() {
118        return mStats;
119    }
120
121    public byte[] getStatistics() {
122        mContext.enforceCallingPermission(
123                android.Manifest.permission.BATTERY_STATS, null);
124        //Slog.i("foo", "SENDING BATTERY INFO:");
125        //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
126        Parcel out = Parcel.obtain();
127        mStats.writeToParcel(out, 0);
128        byte[] data = out.marshall();
129        out.recycle();
130        return data;
131    }
132
133    public long computeBatteryTimeRemaining() {
134        synchronized (mStats) {
135            long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
136            return time >= 0 ? (time/1000) : time;
137        }
138    }
139
140    public long computeChargeTimeRemaining() {
141        synchronized (mStats) {
142            long time = mStats.computeChargeTimeRemaining(SystemClock.elapsedRealtime());
143            return time >= 0 ? (time/1000) : time;
144        }
145    }
146
147    public void addIsolatedUid(int isolatedUid, int appUid) {
148        enforceCallingPermission();
149        synchronized (mStats) {
150            mStats.addIsolatedUidLocked(isolatedUid, appUid);
151        }
152    }
153
154    public void removeIsolatedUid(int isolatedUid, int appUid) {
155        enforceCallingPermission();
156        synchronized (mStats) {
157            mStats.removeIsolatedUidLocked(isolatedUid, appUid);
158        }
159    }
160
161    public void noteEvent(int code, String name, int uid) {
162        enforceCallingPermission();
163        synchronized (mStats) {
164            mStats.noteEventLocked(code, name, uid);
165        }
166    }
167
168    public void noteProcessStart(String name, int uid) {
169        enforceCallingPermission();
170        synchronized (mStats) {
171            mStats.noteProcessStartLocked(name, uid);
172        }
173    }
174
175    public void noteProcessState(String name, int uid, int state) {
176        enforceCallingPermission();
177        synchronized (mStats) {
178            mStats.noteProcessStateLocked(name, uid, state);
179        }
180    }
181
182    public void noteProcessFinish(String name, int uid) {
183        enforceCallingPermission();
184        synchronized (mStats) {
185            mStats.noteProcessFinishLocked(name, uid);
186        }
187    }
188
189    public void noteSyncStart(String name, int uid) {
190        enforceCallingPermission();
191        synchronized (mStats) {
192            mStats.noteSyncStartLocked(name, uid);
193        }
194    }
195
196    public void noteSyncFinish(String name, int uid) {
197        enforceCallingPermission();
198        synchronized (mStats) {
199            mStats.noteSyncFinishLocked(name, uid);
200        }
201    }
202
203    public void noteJobStart(String name, int uid) {
204        enforceCallingPermission();
205        synchronized (mStats) {
206            mStats.noteJobStartLocked(name, uid);
207        }
208    }
209
210    public void noteJobFinish(String name, int uid) {
211        enforceCallingPermission();
212        synchronized (mStats) {
213            mStats.noteJobFinishLocked(name, uid);
214        }
215    }
216
217    public void noteStartWakelock(int uid, int pid, String name, String historyName, int type,
218            boolean unimportantForLogging) {
219        enforceCallingPermission();
220        synchronized (mStats) {
221            mStats.noteStartWakeLocked(uid, pid, name, historyName, type, unimportantForLogging,
222                    SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
223        }
224    }
225
226    public void noteStopWakelock(int uid, int pid, String name, String historyName, int type) {
227        enforceCallingPermission();
228        synchronized (mStats) {
229            mStats.noteStopWakeLocked(uid, pid, name, historyName, type,
230                    SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
231        }
232    }
233
234    public void noteStartWakelockFromSource(WorkSource ws, int pid, String name,
235            String historyName, int type, boolean unimportantForLogging) {
236        enforceCallingPermission();
237        synchronized (mStats) {
238            mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName,
239                    type, unimportantForLogging);
240        }
241    }
242
243    public void noteChangeWakelockFromSource(WorkSource ws, int pid, String name,
244            String historyName, int type, WorkSource newWs, int newPid, String newName,
245            String newHistoryName, int newType, boolean newUnimportantForLogging) {
246        enforceCallingPermission();
247        synchronized (mStats) {
248            mStats.noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type,
249                    newWs, newPid, newName, newHistoryName, newType, newUnimportantForLogging);
250        }
251    }
252
253    public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, String historyName,
254            int type) {
255        enforceCallingPermission();
256        synchronized (mStats) {
257            mStats.noteStopWakeFromSourceLocked(ws, pid, name, historyName, type);
258        }
259    }
260
261    public void noteStartSensor(int uid, int sensor) {
262        enforceCallingPermission();
263        synchronized (mStats) {
264            mStats.noteStartSensorLocked(uid, sensor);
265        }
266    }
267
268    public void noteStopSensor(int uid, int sensor) {
269        enforceCallingPermission();
270        synchronized (mStats) {
271            mStats.noteStopSensorLocked(uid, sensor);
272        }
273    }
274
275    public void noteVibratorOn(int uid, long durationMillis) {
276        enforceCallingPermission();
277        synchronized (mStats) {
278            mStats.noteVibratorOnLocked(uid, durationMillis);
279        }
280    }
281
282    public void noteVibratorOff(int uid) {
283        enforceCallingPermission();
284        synchronized (mStats) {
285            mStats.noteVibratorOffLocked(uid);
286        }
287    }
288
289    public void noteStartGps(int uid) {
290        enforceCallingPermission();
291        synchronized (mStats) {
292            mStats.noteStartGpsLocked(uid);
293        }
294    }
295
296    public void noteStopGps(int uid) {
297        enforceCallingPermission();
298        synchronized (mStats) {
299            mStats.noteStopGpsLocked(uid);
300        }
301    }
302
303    public void noteScreenState(int state) {
304        enforceCallingPermission();
305        synchronized (mStats) {
306            mStats.noteScreenStateLocked(state);
307        }
308    }
309
310    public void noteScreenBrightness(int brightness) {
311        enforceCallingPermission();
312        synchronized (mStats) {
313            mStats.noteScreenBrightnessLocked(brightness);
314        }
315    }
316
317    public void noteUserActivity(int uid, int event) {
318        enforceCallingPermission();
319        synchronized (mStats) {
320            mStats.noteUserActivityLocked(uid, event);
321        }
322    }
323
324    public void noteInteractive(boolean interactive) {
325        enforceCallingPermission();
326        synchronized (mStats) {
327            mStats.noteInteractiveLocked(interactive);
328        }
329    }
330
331    public void noteMobileRadioPowerState(int powerState, long timestampNs) {
332        enforceCallingPermission();
333        synchronized (mStats) {
334            mStats.noteMobileRadioPowerState(powerState, timestampNs);
335        }
336    }
337
338    public void notePhoneOn() {
339        enforceCallingPermission();
340        synchronized (mStats) {
341            mStats.notePhoneOnLocked();
342        }
343    }
344
345    public void notePhoneOff() {
346        enforceCallingPermission();
347        synchronized (mStats) {
348            mStats.notePhoneOffLocked();
349        }
350    }
351
352    public void notePhoneSignalStrength(SignalStrength signalStrength) {
353        enforceCallingPermission();
354        synchronized (mStats) {
355            mStats.notePhoneSignalStrengthLocked(signalStrength);
356        }
357    }
358
359    public void notePhoneDataConnectionState(int dataType, boolean hasData) {
360        enforceCallingPermission();
361        synchronized (mStats) {
362            mStats.notePhoneDataConnectionStateLocked(dataType, hasData);
363        }
364    }
365
366    public void notePhoneState(int state) {
367        enforceCallingPermission();
368        int simState = TelephonyManager.getDefault().getSimState();
369        synchronized (mStats) {
370            mStats.notePhoneStateLocked(state, simState);
371        }
372    }
373
374    public void noteWifiOn() {
375        enforceCallingPermission();
376        synchronized (mStats) {
377            mStats.noteWifiOnLocked();
378        }
379    }
380
381    public void noteWifiOff() {
382        enforceCallingPermission();
383        synchronized (mStats) {
384            mStats.noteWifiOffLocked();
385        }
386    }
387
388    public void noteStartAudio(int uid) {
389        enforceCallingPermission();
390        synchronized (mStats) {
391            mStats.noteAudioOnLocked(uid);
392        }
393    }
394
395    public void noteStopAudio(int uid) {
396        enforceCallingPermission();
397        synchronized (mStats) {
398            mStats.noteAudioOffLocked(uid);
399        }
400    }
401
402    public void noteStartVideo(int uid) {
403        enforceCallingPermission();
404        synchronized (mStats) {
405            mStats.noteVideoOnLocked(uid);
406        }
407    }
408
409    public void noteStopVideo(int uid) {
410        enforceCallingPermission();
411        synchronized (mStats) {
412            mStats.noteVideoOffLocked(uid);
413        }
414    }
415
416    public void noteResetAudio() {
417        enforceCallingPermission();
418        synchronized (mStats) {
419            mStats.noteResetAudioLocked();
420        }
421    }
422
423    public void noteResetVideo() {
424        enforceCallingPermission();
425        synchronized (mStats) {
426            mStats.noteResetVideoLocked();
427        }
428    }
429
430    public void noteFlashlightOn() {
431        enforceCallingPermission();
432        synchronized (mStats) {
433            mStats.noteFlashlightOnLocked();
434        }
435    }
436
437    public void noteFlashlightOff() {
438        enforceCallingPermission();
439        synchronized (mStats) {
440            mStats.noteFlashlightOffLocked();
441        }
442    }
443
444    public void noteWifiRunning(WorkSource ws) {
445        enforceCallingPermission();
446        synchronized (mStats) {
447            mStats.noteWifiRunningLocked(ws);
448        }
449    }
450
451    public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) {
452        enforceCallingPermission();
453        synchronized (mStats) {
454            mStats.noteWifiRunningChangedLocked(oldWs, newWs);
455        }
456    }
457
458    public void noteWifiStopped(WorkSource ws) {
459        enforceCallingPermission();
460        synchronized (mStats) {
461            mStats.noteWifiStoppedLocked(ws);
462        }
463    }
464
465    public void noteWifiState(int wifiState, String accessPoint) {
466        enforceCallingPermission();
467        synchronized (mStats) {
468            mStats.noteWifiStateLocked(wifiState, accessPoint);
469        }
470    }
471
472    public void noteWifiSupplicantStateChanged(int supplState, boolean failedAuth) {
473        enforceCallingPermission();
474        synchronized (mStats) {
475            mStats.noteWifiSupplicantStateChangedLocked(supplState, failedAuth);
476        }
477    }
478
479    public void noteWifiRssiChanged(int newRssi) {
480        enforceCallingPermission();
481        synchronized (mStats) {
482            mStats.noteWifiRssiChangedLocked(newRssi);
483        }
484    }
485
486    public void noteBluetoothOn() {
487        enforceCallingPermission();
488        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
489        if (adapter != null) {
490            adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
491                                    BluetoothProfile.HEADSET);
492        }
493        synchronized (mStats) {
494            if (mBluetoothHeadset != null) {
495                mStats.noteBluetoothOnLocked();
496                mStats.setBtHeadset(mBluetoothHeadset);
497            } else {
498                mBluetoothPendingStats = true;
499            }
500        }
501    }
502
503    private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
504        new BluetoothProfile.ServiceListener() {
505        public void onServiceConnected(int profile, BluetoothProfile proxy) {
506            mBluetoothHeadset = (BluetoothHeadset) proxy;
507            synchronized (mStats) {
508                if (mBluetoothPendingStats) {
509                    mStats.noteBluetoothOnLocked();
510                    mStats.setBtHeadset(mBluetoothHeadset);
511                    mBluetoothPendingStats = false;
512                }
513            }
514        }
515
516        public void onServiceDisconnected(int profile) {
517            mBluetoothHeadset = null;
518        }
519    };
520
521    public void noteBluetoothOff() {
522        enforceCallingPermission();
523        synchronized (mStats) {
524            mBluetoothPendingStats = false;
525            mStats.noteBluetoothOffLocked();
526        }
527    }
528
529    public void noteBluetoothState(int bluetoothState) {
530        enforceCallingPermission();
531        synchronized (mStats) {
532            mStats.noteBluetoothStateLocked(bluetoothState);
533        }
534    }
535
536    public void noteFullWifiLockAcquired(int uid) {
537        enforceCallingPermission();
538        synchronized (mStats) {
539            mStats.noteFullWifiLockAcquiredLocked(uid);
540        }
541    }
542
543    public void noteFullWifiLockReleased(int uid) {
544        enforceCallingPermission();
545        synchronized (mStats) {
546            mStats.noteFullWifiLockReleasedLocked(uid);
547        }
548    }
549
550    public void noteWifiScanStarted(int uid) {
551        enforceCallingPermission();
552        synchronized (mStats) {
553            mStats.noteWifiScanStartedLocked(uid);
554        }
555    }
556
557    public void noteWifiScanStopped(int uid) {
558        enforceCallingPermission();
559        synchronized (mStats) {
560            mStats.noteWifiScanStoppedLocked(uid);
561        }
562    }
563
564    public void noteWifiMulticastEnabled(int uid) {
565        enforceCallingPermission();
566        synchronized (mStats) {
567            mStats.noteWifiMulticastEnabledLocked(uid);
568        }
569    }
570
571    public void noteWifiMulticastDisabled(int uid) {
572        enforceCallingPermission();
573        synchronized (mStats) {
574            mStats.noteWifiMulticastDisabledLocked(uid);
575        }
576    }
577
578    public void noteFullWifiLockAcquiredFromSource(WorkSource ws) {
579        enforceCallingPermission();
580        synchronized (mStats) {
581            mStats.noteFullWifiLockAcquiredFromSourceLocked(ws);
582        }
583    }
584
585    public void noteFullWifiLockReleasedFromSource(WorkSource ws) {
586        enforceCallingPermission();
587        synchronized (mStats) {
588            mStats.noteFullWifiLockReleasedFromSourceLocked(ws);
589        }
590    }
591
592    public void noteWifiScanStartedFromSource(WorkSource ws) {
593        enforceCallingPermission();
594        synchronized (mStats) {
595            mStats.noteWifiScanStartedFromSourceLocked(ws);
596        }
597    }
598
599    public void noteWifiScanStoppedFromSource(WorkSource ws) {
600        enforceCallingPermission();
601        synchronized (mStats) {
602            mStats.noteWifiScanStoppedFromSourceLocked(ws);
603        }
604    }
605
606    public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) {
607        enforceCallingPermission();
608        synchronized (mStats) {
609            mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph);
610        }
611    }
612
613    public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) {
614        enforceCallingPermission();
615        synchronized (mStats) {
616            mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws);
617        }
618    }
619
620    public void noteWifiMulticastEnabledFromSource(WorkSource ws) {
621        enforceCallingPermission();
622        synchronized (mStats) {
623            mStats.noteWifiMulticastEnabledFromSourceLocked(ws);
624        }
625    }
626
627    public void noteWifiMulticastDisabledFromSource(WorkSource ws) {
628        enforceCallingPermission();
629        synchronized (mStats) {
630            mStats.noteWifiMulticastDisabledFromSourceLocked(ws);
631        }
632    }
633
634    @Override
635    public void noteNetworkInterfaceType(String iface, int type) {
636        enforceCallingPermission();
637        synchronized (mStats) {
638            mStats.noteNetworkInterfaceTypeLocked(iface, type);
639        }
640    }
641
642    @Override
643    public void noteNetworkStatsEnabled() {
644        enforceCallingPermission();
645        synchronized (mStats) {
646            mStats.noteNetworkStatsEnabledLocked();
647        }
648    }
649
650    public boolean isOnBattery() {
651        return mStats.isOnBattery();
652    }
653
654    public void setBatteryState(int status, int health, int plugType, int level,
655            int temp, int volt) {
656        enforceCallingPermission();
657        mStats.setBatteryState(status, health, plugType, level, temp, volt);
658    }
659
660    public long getAwakeTimeBattery() {
661        mContext.enforceCallingOrSelfPermission(
662                android.Manifest.permission.BATTERY_STATS, null);
663        return mStats.getAwakeTimeBattery();
664    }
665
666    public long getAwakeTimePlugged() {
667        mContext.enforceCallingOrSelfPermission(
668                android.Manifest.permission.BATTERY_STATS, null);
669        return mStats.getAwakeTimePlugged();
670    }
671
672    public void enforceCallingPermission() {
673        if (Binder.getCallingPid() == Process.myPid()) {
674            return;
675        }
676        mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
677                Binder.getCallingPid(), Binder.getCallingUid(), null);
678    }
679
680    final class WakeupReasonThread extends Thread {
681        final int[] mIrqs = new int[32];
682        final String[] mReasons = new String[32];
683
684        WakeupReasonThread() {
685            super("BatteryStats_wakeupReason");
686        }
687
688        public void run() {
689            Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
690
691            try {
692                int num;
693                while ((num=nativeWaitWakeup(mIrqs, mReasons)) >= 0) {
694                    synchronized (mStats) {
695                        if (num > 0) {
696                            for (int i=0; i<num; i++) {
697                                mStats.noteWakeupReasonLocked(mReasons[i]);
698                            }
699                        } else {
700                            mStats.noteWakeupReasonLocked("unknown");
701                        }
702                    }
703                }
704            } catch (RuntimeException e) {
705                Slog.e(TAG, "Failure reading wakeup reasons", e);
706            }
707        }
708    }
709
710    private static native int nativeWaitWakeup(int[] outIrqs, String[] outReasons);
711
712    private void dumpHelp(PrintWriter pw) {
713        pw.println("Battery stats (batterystats) dump options:");
714        pw.println("  [--checkin] [--history] [--history-start] [--unplugged] [--charged] [-c]");
715        pw.println("  [--reset] [--write] [-h] [<package.name>]");
716        pw.println("  --checkin: format output for a checkin report.");
717        pw.println("  --history: show only history data.");
718        pw.println("  --history-start <num>: show only history data starting at given time offset.");
719        pw.println("  --unplugged: only output data since last unplugged.");
720        pw.println("  --charged: only output data since last charged.");
721        pw.println("  --reset: reset the stats, clearing all current data.");
722        pw.println("  --write: force write current collected stats to disk.");
723        pw.println("  <package.name>: optional name of package to filter output by.");
724        pw.println("  -h: print this help text.");
725        pw.println("Battery stats (batterystats) commands:");
726        pw.println("  enable|disable <option>");
727        pw.println("    Enable or disable a running option.  Option state is not saved across boots.");
728        pw.println("    Options are:");
729        pw.println("      full-wake-history: include wake_lock_in battery history, full wake details.");
730        pw.println("      no-auto-reset: don't automatically reset stats when unplugged");
731    }
732
733    private int doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable) {
734        i++;
735        if (i >= args.length) {
736            pw.println("Missing option argument for " + (enable ? "--enable" : "--disable"));
737            dumpHelp(pw);
738            return -1;
739        }
740        if ("full-wake-history".equals(args[i])) {
741            synchronized (mStats) {
742                mStats.setRecordAllWakeLocksLocked(enable);
743            }
744        } else if ("no-auto-reset".equals(args[i])) {
745            synchronized (mStats) {
746                mStats.setNoAutoReset(enable);
747            }
748        } else {
749            pw.println("Unknown enable/disable option: " + args[i]);
750            dumpHelp(pw);
751            return -1;
752        }
753        return i;
754    }
755
756    @Override
757    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
758        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
759                != PackageManager.PERMISSION_GRANTED) {
760            pw.println("Permission Denial: can't dump BatteryStats from from pid="
761                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
762                    + " without permission " + android.Manifest.permission.DUMP);
763            return;
764        }
765
766        int flags = 0;
767        boolean isCheckin = false;
768        boolean noOutput = false;
769        boolean writeData = false;
770        long historyStart = -1;
771        int reqUid = -1;
772        if (args != null) {
773            for (int i=0; i<args.length; i++) {
774                String arg = args[i];
775                if ("--checkin".equals(arg)) {
776                    isCheckin = true;
777                } else if ("--history".equals(arg)) {
778                    flags |= BatteryStats.DUMP_HISTORY_ONLY;
779                } else if ("--history-start".equals(arg)) {
780                    flags |= BatteryStats.DUMP_HISTORY_ONLY;
781                    i++;
782                    if (i >= args.length) {
783                        pw.println("Missing time argument for --history-since");
784                        dumpHelp(pw);
785                        return;
786                    }
787                    historyStart = Long.parseLong(args[i]);
788                    writeData = true;
789                } else if ("-c".equals(arg)) {
790                    isCheckin = true;
791                    flags |= BatteryStats.DUMP_INCLUDE_HISTORY;
792                } else if ("--unplugged".equals(arg)) {
793                    flags |= BatteryStats.DUMP_UNPLUGGED_ONLY;
794                } else if ("--charged".equals(arg)) {
795                    flags |= BatteryStats.DUMP_CHARGED_ONLY;
796                } else if ("--reset".equals(arg)) {
797                    synchronized (mStats) {
798                        mStats.resetAllStatsCmdLocked();
799                        pw.println("Battery stats reset.");
800                        noOutput = true;
801                    }
802                } else if ("--write".equals(arg)) {
803                    synchronized (mStats) {
804                        mStats.writeSyncLocked();
805                        pw.println("Battery stats written.");
806                        noOutput = true;
807                    }
808                } else if ("--enable".equals(arg) || "enable".equals(arg)) {
809                    i = doEnableOrDisable(pw, i, args, true);
810                    if (i < 0) {
811                        return;
812                    }
813                    pw.println("Enabled: " + args[i]);
814                    return;
815                } else if ("--disable".equals(arg) || "disable".equals(arg)) {
816                    i = doEnableOrDisable(pw, i, args, false);
817                    if (i < 0) {
818                        return;
819                    }
820                    pw.println("Disabled: " + args[i]);
821                    return;
822                } else if ("-h".equals(arg)) {
823                    dumpHelp(pw);
824                    return;
825                } else if ("-a".equals(arg)) {
826                    flags |= BatteryStats.DUMP_VERBOSE;
827                } else if (arg.length() > 0 && arg.charAt(0) == '-'){
828                    pw.println("Unknown option: " + arg);
829                    dumpHelp(pw);
830                    return;
831                } else {
832                    // Not an option, last argument must be a package name.
833                    try {
834                        reqUid = mContext.getPackageManager().getPackageUid(arg,
835                                UserHandle.getCallingUserId());
836                    } catch (PackageManager.NameNotFoundException e) {
837                        pw.println("Unknown package: " + arg);
838                        dumpHelp(pw);
839                        return;
840                    }
841                }
842            }
843        }
844        if (noOutput) {
845            return;
846        }
847        if (isCheckin) {
848            List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
849            synchronized (mStats) {
850                mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
851                if (writeData) {
852                    mStats.writeAsyncLocked();
853                }
854            }
855        } else {
856            synchronized (mStats) {
857                mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart);
858                if (writeData) {
859                    mStats.writeAsyncLocked();
860                }
861            }
862        }
863    }
864}
865