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