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