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