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