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.IBinder;
     28 import android.os.Parcel;
     29 import android.os.Process;
     30 import android.os.ServiceManager;
     31 import android.os.UserHandle;
     32 import android.os.WorkSource;
     33 import android.telephony.SignalStrength;
     34 import android.telephony.TelephonyManager;
     35 import android.util.Slog;
     36 
     37 import com.android.internal.app.IBatteryStats;
     38 import com.android.internal.os.BatteryStatsImpl;
     39 import com.android.internal.os.PowerProfile;
     40 
     41 import java.io.FileDescriptor;
     42 import java.io.PrintWriter;
     43 import java.util.List;
     44 
     45 /**
     46  * All information we are collecting about things that can happen that impact
     47  * battery life.
     48  */
     49 public final class BatteryStatsService extends IBatteryStats.Stub {
     50     static IBatteryStats sService;
     51 
     52     final BatteryStatsImpl mStats;
     53     Context mContext;
     54     private boolean mBluetoothPendingStats;
     55     private BluetoothHeadset mBluetoothHeadset;
     56 
     57     BatteryStatsService(String filename) {
     58         mStats = new BatteryStatsImpl(filename);
     59     }
     60 
     61     public void publish(Context context) {
     62         mContext = context;
     63         ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
     64         mStats.setNumSpeedSteps(new PowerProfile(mContext).getNumSpeedSteps());
     65         mStats.setRadioScanningTimeout(mContext.getResources().getInteger(
     66                 com.android.internal.R.integer.config_radioScanningTimeout)
     67                 * 1000L);
     68     }
     69 
     70     public void shutdown() {
     71         Slog.w("BatteryStats", "Writing battery stats before shutdown...");
     72         synchronized (mStats) {
     73             mStats.shutdownLocked();
     74         }
     75     }
     76 
     77     public static IBatteryStats getService() {
     78         if (sService != null) {
     79             return sService;
     80         }
     81         IBinder b = ServiceManager.getService(BatteryStats.SERVICE_NAME);
     82         sService = asInterface(b);
     83         return sService;
     84     }
     85 
     86     /**
     87      * @return the current statistics object, which may be modified
     88      * to reflect events that affect battery usage.  You must lock the
     89      * stats object before doing anything with it.
     90      */
     91     public BatteryStatsImpl getActiveStatistics() {
     92         return mStats;
     93     }
     94 
     95     public byte[] getStatistics() {
     96         mContext.enforceCallingPermission(
     97                 android.Manifest.permission.BATTERY_STATS, null);
     98         //Slog.i("foo", "SENDING BATTERY INFO:");
     99         //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
    100         Parcel out = Parcel.obtain();
    101         mStats.writeToParcel(out, 0);
    102         byte[] data = out.marshall();
    103         out.recycle();
    104         return data;
    105     }
    106 
    107     public void noteStartWakelock(int uid, int pid, String name, int type) {
    108         enforceCallingPermission();
    109         synchronized (mStats) {
    110             mStats.noteStartWakeLocked(uid, pid, name, type);
    111         }
    112     }
    113 
    114     public void noteStopWakelock(int uid, int pid, String name, int type) {
    115         enforceCallingPermission();
    116         synchronized (mStats) {
    117             mStats.noteStopWakeLocked(uid, pid, name, type);
    118         }
    119     }
    120 
    121     public void noteStartWakelockFromSource(WorkSource ws, int pid, String name, int type) {
    122         enforceCallingPermission();
    123         synchronized (mStats) {
    124             mStats.noteStartWakeFromSourceLocked(ws, pid, name, type);
    125         }
    126     }
    127 
    128     public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, int type) {
    129         enforceCallingPermission();
    130         synchronized (mStats) {
    131             mStats.noteStopWakeFromSourceLocked(ws, pid, name, type);
    132         }
    133     }
    134 
    135     public void noteStartSensor(int uid, int sensor) {
    136         enforceCallingPermission();
    137         synchronized (mStats) {
    138             mStats.noteStartSensorLocked(uid, sensor);
    139         }
    140     }
    141 
    142     public void noteStopSensor(int uid, int sensor) {
    143         enforceCallingPermission();
    144         synchronized (mStats) {
    145             mStats.noteStopSensorLocked(uid, sensor);
    146         }
    147     }
    148 
    149     public void noteVibratorOn(int uid, long durationMillis) {
    150         enforceCallingPermission();
    151         synchronized (mStats) {
    152             mStats.noteVibratorOnLocked(uid, durationMillis);
    153         }
    154     }
    155 
    156     public void noteVibratorOff(int uid) {
    157         enforceCallingPermission();
    158         synchronized (mStats) {
    159             mStats.noteVibratorOffLocked(uid);
    160         }
    161     }
    162 
    163     public void noteStartGps(int uid) {
    164         enforceCallingPermission();
    165         synchronized (mStats) {
    166             mStats.noteStartGpsLocked(uid);
    167         }
    168     }
    169 
    170     public void noteStopGps(int uid) {
    171         enforceCallingPermission();
    172         synchronized (mStats) {
    173             mStats.noteStopGpsLocked(uid);
    174         }
    175     }
    176 
    177     public void noteScreenOn() {
    178         enforceCallingPermission();
    179         synchronized (mStats) {
    180             mStats.noteScreenOnLocked();
    181         }
    182     }
    183 
    184     public void noteScreenBrightness(int brightness) {
    185         enforceCallingPermission();
    186         synchronized (mStats) {
    187             mStats.noteScreenBrightnessLocked(brightness);
    188         }
    189     }
    190 
    191     public void noteScreenOff() {
    192         enforceCallingPermission();
    193         synchronized (mStats) {
    194             mStats.noteScreenOffLocked();
    195         }
    196     }
    197 
    198     public void noteInputEvent() {
    199         enforceCallingPermission();
    200         mStats.noteInputEventAtomic();
    201     }
    202 
    203     public void noteUserActivity(int uid, int event) {
    204         enforceCallingPermission();
    205         synchronized (mStats) {
    206             mStats.noteUserActivityLocked(uid, event);
    207         }
    208     }
    209 
    210     public void notePhoneOn() {
    211         enforceCallingPermission();
    212         synchronized (mStats) {
    213             mStats.notePhoneOnLocked();
    214         }
    215     }
    216 
    217     public void notePhoneOff() {
    218         enforceCallingPermission();
    219         synchronized (mStats) {
    220             mStats.notePhoneOffLocked();
    221         }
    222     }
    223 
    224     public void notePhoneSignalStrength(SignalStrength signalStrength) {
    225         enforceCallingPermission();
    226         synchronized (mStats) {
    227             mStats.notePhoneSignalStrengthLocked(signalStrength);
    228         }
    229     }
    230 
    231     public void notePhoneDataConnectionState(int dataType, boolean hasData) {
    232         enforceCallingPermission();
    233         synchronized (mStats) {
    234             mStats.notePhoneDataConnectionStateLocked(dataType, hasData);
    235         }
    236     }
    237 
    238     public void notePhoneState(int state) {
    239         enforceCallingPermission();
    240         int simState = TelephonyManager.getDefault().getSimState();
    241         synchronized (mStats) {
    242             mStats.notePhoneStateLocked(state, simState);
    243         }
    244     }
    245 
    246     public void noteWifiOn() {
    247         enforceCallingPermission();
    248         synchronized (mStats) {
    249             mStats.noteWifiOnLocked();
    250         }
    251     }
    252 
    253     public void noteWifiOff() {
    254         enforceCallingPermission();
    255         synchronized (mStats) {
    256             mStats.noteWifiOffLocked();
    257         }
    258     }
    259 
    260     public void noteStartAudio(int uid) {
    261         enforceCallingPermission();
    262         synchronized (mStats) {
    263             mStats.noteAudioOnLocked(uid);
    264         }
    265     }
    266 
    267     public void noteStopAudio(int uid) {
    268         enforceCallingPermission();
    269         synchronized (mStats) {
    270             mStats.noteAudioOffLocked(uid);
    271         }
    272     }
    273 
    274     public void noteStartVideo(int uid) {
    275         enforceCallingPermission();
    276         synchronized (mStats) {
    277             mStats.noteVideoOnLocked(uid);
    278         }
    279     }
    280 
    281     public void noteStopVideo(int uid) {
    282         enforceCallingPermission();
    283         synchronized (mStats) {
    284             mStats.noteVideoOffLocked(uid);
    285         }
    286     }
    287 
    288     public void noteWifiRunning(WorkSource ws) {
    289         enforceCallingPermission();
    290         synchronized (mStats) {
    291             mStats.noteWifiRunningLocked(ws);
    292         }
    293     }
    294 
    295     public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) {
    296         enforceCallingPermission();
    297         synchronized (mStats) {
    298             mStats.noteWifiRunningChangedLocked(oldWs, newWs);
    299         }
    300     }
    301 
    302     public void noteWifiStopped(WorkSource ws) {
    303         enforceCallingPermission();
    304         synchronized (mStats) {
    305             mStats.noteWifiStoppedLocked(ws);
    306         }
    307     }
    308 
    309     public void noteBluetoothOn() {
    310         enforceCallingPermission();
    311         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    312         if (adapter != null) {
    313             adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
    314                                     BluetoothProfile.HEADSET);
    315         }
    316         synchronized (mStats) {
    317             if (mBluetoothHeadset != null) {
    318                 mStats.noteBluetoothOnLocked();
    319                 mStats.setBtHeadset(mBluetoothHeadset);
    320             } else {
    321                 mBluetoothPendingStats = true;
    322             }
    323         }
    324     }
    325 
    326     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
    327         new BluetoothProfile.ServiceListener() {
    328         public void onServiceConnected(int profile, BluetoothProfile proxy) {
    329             mBluetoothHeadset = (BluetoothHeadset) proxy;
    330             synchronized (mStats) {
    331                 if (mBluetoothPendingStats) {
    332                     mStats.noteBluetoothOnLocked();
    333                     mStats.setBtHeadset(mBluetoothHeadset);
    334                     mBluetoothPendingStats = false;
    335                 }
    336             }
    337         }
    338 
    339         public void onServiceDisconnected(int profile) {
    340             mBluetoothHeadset = null;
    341         }
    342     };
    343 
    344     public void noteBluetoothOff() {
    345         enforceCallingPermission();
    346         synchronized (mStats) {
    347             mBluetoothPendingStats = false;
    348             mStats.noteBluetoothOffLocked();
    349         }
    350     }
    351 
    352     public void noteFullWifiLockAcquired(int uid) {
    353         enforceCallingPermission();
    354         synchronized (mStats) {
    355             mStats.noteFullWifiLockAcquiredLocked(uid);
    356         }
    357     }
    358 
    359     public void noteFullWifiLockReleased(int uid) {
    360         enforceCallingPermission();
    361         synchronized (mStats) {
    362             mStats.noteFullWifiLockReleasedLocked(uid);
    363         }
    364     }
    365 
    366     public void noteWifiScanStarted(int uid) {
    367         enforceCallingPermission();
    368         synchronized (mStats) {
    369             mStats.noteWifiScanStartedLocked(uid);
    370         }
    371     }
    372 
    373     public void noteWifiScanStopped(int uid) {
    374         enforceCallingPermission();
    375         synchronized (mStats) {
    376             mStats.noteWifiScanStoppedLocked(uid);
    377         }
    378     }
    379 
    380     public void noteWifiMulticastEnabled(int uid) {
    381         enforceCallingPermission();
    382         synchronized (mStats) {
    383             mStats.noteWifiMulticastEnabledLocked(uid);
    384         }
    385     }
    386 
    387     public void noteWifiMulticastDisabled(int uid) {
    388         enforceCallingPermission();
    389         synchronized (mStats) {
    390             mStats.noteWifiMulticastDisabledLocked(uid);
    391         }
    392     }
    393 
    394     public void noteFullWifiLockAcquiredFromSource(WorkSource ws) {
    395         enforceCallingPermission();
    396         synchronized (mStats) {
    397             mStats.noteFullWifiLockAcquiredFromSourceLocked(ws);
    398         }
    399     }
    400 
    401     public void noteFullWifiLockReleasedFromSource(WorkSource ws) {
    402         enforceCallingPermission();
    403         synchronized (mStats) {
    404             mStats.noteFullWifiLockReleasedFromSourceLocked(ws);
    405         }
    406     }
    407 
    408     public void noteWifiScanStartedFromSource(WorkSource ws) {
    409         enforceCallingPermission();
    410         synchronized (mStats) {
    411             mStats.noteWifiScanStartedFromSourceLocked(ws);
    412         }
    413     }
    414 
    415     public void noteWifiScanStoppedFromSource(WorkSource ws) {
    416         enforceCallingPermission();
    417         synchronized (mStats) {
    418             mStats.noteWifiScanStoppedFromSourceLocked(ws);
    419         }
    420     }
    421 
    422     public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) {
    423         enforceCallingPermission();
    424         synchronized (mStats) {
    425             mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph);
    426         }
    427     }
    428 
    429     public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) {
    430         enforceCallingPermission();
    431         synchronized (mStats) {
    432             mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws);
    433         }
    434     }
    435 
    436     public void noteWifiMulticastEnabledFromSource(WorkSource ws) {
    437         enforceCallingPermission();
    438         synchronized (mStats) {
    439             mStats.noteWifiMulticastEnabledFromSourceLocked(ws);
    440         }
    441     }
    442 
    443     public void noteWifiMulticastDisabledFromSource(WorkSource ws) {
    444         enforceCallingPermission();
    445         synchronized (mStats) {
    446             mStats.noteWifiMulticastDisabledFromSourceLocked(ws);
    447         }
    448     }
    449 
    450     @Override
    451     public void noteNetworkInterfaceType(String iface, int type) {
    452         enforceCallingPermission();
    453         synchronized (mStats) {
    454             mStats.noteNetworkInterfaceTypeLocked(iface, type);
    455         }
    456     }
    457 
    458     @Override
    459     public void noteNetworkStatsEnabled() {
    460         enforceCallingPermission();
    461         synchronized (mStats) {
    462             mStats.noteNetworkStatsEnabledLocked();
    463         }
    464     }
    465 
    466     public boolean isOnBattery() {
    467         return mStats.isOnBattery();
    468     }
    469 
    470     public void setBatteryState(int status, int health, int plugType, int level,
    471             int temp, int volt) {
    472         enforceCallingPermission();
    473         mStats.setBatteryState(status, health, plugType, level, temp, volt);
    474     }
    475 
    476     public long getAwakeTimeBattery() {
    477         mContext.enforceCallingOrSelfPermission(
    478                 android.Manifest.permission.BATTERY_STATS, null);
    479         return mStats.getAwakeTimeBattery();
    480     }
    481 
    482     public long getAwakeTimePlugged() {
    483         mContext.enforceCallingOrSelfPermission(
    484                 android.Manifest.permission.BATTERY_STATS, null);
    485         return mStats.getAwakeTimePlugged();
    486     }
    487 
    488     public void enforceCallingPermission() {
    489         if (Binder.getCallingPid() == Process.myPid()) {
    490             return;
    491         }
    492         mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
    493                 Binder.getCallingPid(), Binder.getCallingUid(), null);
    494     }
    495 
    496     private void dumpHelp(PrintWriter pw) {
    497         pw.println("Battery stats (batterystats) dump options:");
    498         pw.println("  [--checkin] [-c] [--unplugged] [--reset] [--write] [-h] [<package.name>]");
    499         pw.println("  --checkin: format output for a checkin report.");
    500         pw.println("  --unplugged: only output data since last unplugged.");
    501         pw.println("  --reset: reset the stats, clearing all current data.");
    502         pw.println("  --write: force write current collected stats to disk.");
    503         pw.println("  -h: print this help text.");
    504         pw.println("  <package.name>: optional name of package to filter output by.");
    505     }
    506 
    507     @Override
    508     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    509         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
    510                 != PackageManager.PERMISSION_GRANTED) {
    511             pw.println("Permission Denial: can't dump BatteryStats from from pid="
    512                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
    513                     + " without permission " + android.Manifest.permission.DUMP);
    514             return;
    515         }
    516 
    517         boolean isCheckin = false;
    518         boolean includeHistory = false;
    519         boolean isUnpluggedOnly = false;
    520         boolean noOutput = false;
    521         int reqUid = -1;
    522         if (args != null) {
    523             for (String arg : args) {
    524                 if ("--checkin".equals(arg)) {
    525                     isCheckin = true;
    526                 } else if ("-c".equals(arg)) {
    527                     isCheckin = true;
    528                     includeHistory = true;
    529                 } else if ("--unplugged".equals(arg)) {
    530                     isUnpluggedOnly = true;
    531                 } else if ("--reset".equals(arg)) {
    532                     synchronized (mStats) {
    533                         mStats.resetAllStatsLocked();
    534                         pw.println("Battery stats reset.");
    535                         noOutput = true;
    536                     }
    537                 } else if ("--write".equals(arg)) {
    538                     synchronized (mStats) {
    539                         mStats.writeSyncLocked();
    540                         pw.println("Battery stats written.");
    541                         noOutput = true;
    542                     }
    543                 } else if ("-h".equals(arg)) {
    544                     dumpHelp(pw);
    545                     return;
    546                 } else if ("-a".equals(arg)) {
    547                     // fall through
    548                 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
    549                     pw.println("Unknown option: " + arg);
    550                     dumpHelp(pw);
    551                     return;
    552                 } else {
    553                     // Not an option, last argument must be a package name.
    554                     try {
    555                         reqUid = mContext.getPackageManager().getPackageUid(arg,
    556                                 UserHandle.getCallingUserId());
    557                     } catch (PackageManager.NameNotFoundException e) {
    558                         pw.println("Unknown package: " + arg);
    559                         dumpHelp(pw);
    560                         return;
    561                     }
    562                 }
    563             }
    564         }
    565         if (noOutput) {
    566             return;
    567         }
    568         if (isCheckin) {
    569             List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
    570             synchronized (mStats) {
    571                 mStats.dumpCheckinLocked(pw, apps, isUnpluggedOnly, includeHistory);
    572             }
    573         } else {
    574             synchronized (mStats) {
    575                 mStats.dumpLocked(pw, isUnpluggedOnly, reqUid);
    576             }
    577         }
    578     }
    579 }
    580