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 noteStartGps(int uid) {
    148         enforceCallingPermission();
    149         synchronized (mStats) {
    150             mStats.noteStartGpsLocked(uid);
    151         }
    152     }
    153 
    154     public void noteStopGps(int uid) {
    155         enforceCallingPermission();
    156         synchronized (mStats) {
    157             mStats.noteStopGpsLocked(uid);
    158         }
    159     }
    160 
    161     public void noteScreenOn() {
    162         enforceCallingPermission();
    163         synchronized (mStats) {
    164             mStats.noteScreenOnLocked();
    165         }
    166     }
    167 
    168     public void noteScreenBrightness(int brightness) {
    169         enforceCallingPermission();
    170         synchronized (mStats) {
    171             mStats.noteScreenBrightnessLocked(brightness);
    172         }
    173     }
    174 
    175     public void noteScreenOff() {
    176         enforceCallingPermission();
    177         synchronized (mStats) {
    178             mStats.noteScreenOffLocked();
    179         }
    180     }
    181 
    182     public void noteInputEvent() {
    183         enforceCallingPermission();
    184         mStats.noteInputEventAtomic();
    185     }
    186 
    187     public void noteUserActivity(int uid, int event) {
    188         enforceCallingPermission();
    189         synchronized (mStats) {
    190             mStats.noteUserActivityLocked(uid, event);
    191         }
    192     }
    193 
    194     public void notePhoneOn() {
    195         enforceCallingPermission();
    196         synchronized (mStats) {
    197             mStats.notePhoneOnLocked();
    198         }
    199     }
    200 
    201     public void notePhoneOff() {
    202         enforceCallingPermission();
    203         synchronized (mStats) {
    204             mStats.notePhoneOffLocked();
    205         }
    206     }
    207 
    208     public void notePhoneSignalStrength(SignalStrength signalStrength) {
    209         enforceCallingPermission();
    210         synchronized (mStats) {
    211             mStats.notePhoneSignalStrengthLocked(signalStrength);
    212         }
    213     }
    214 
    215     public void notePhoneDataConnectionState(int dataType, boolean hasData) {
    216         enforceCallingPermission();
    217         synchronized (mStats) {
    218             mStats.notePhoneDataConnectionStateLocked(dataType, hasData);
    219         }
    220     }
    221 
    222     public void notePhoneState(int state) {
    223         enforceCallingPermission();
    224         int simState = TelephonyManager.getDefault().getSimState();
    225         synchronized (mStats) {
    226             mStats.notePhoneStateLocked(state, simState);
    227         }
    228     }
    229 
    230     public void noteWifiOn() {
    231         enforceCallingPermission();
    232         synchronized (mStats) {
    233             mStats.noteWifiOnLocked();
    234         }
    235     }
    236 
    237     public void noteWifiOff() {
    238         enforceCallingPermission();
    239         synchronized (mStats) {
    240             mStats.noteWifiOffLocked();
    241         }
    242     }
    243 
    244     public void noteStartAudio(int uid) {
    245         enforceCallingPermission();
    246         synchronized (mStats) {
    247             mStats.noteAudioOnLocked(uid);
    248         }
    249     }
    250 
    251     public void noteStopAudio(int uid) {
    252         enforceCallingPermission();
    253         synchronized (mStats) {
    254             mStats.noteAudioOffLocked(uid);
    255         }
    256     }
    257 
    258     public void noteStartVideo(int uid) {
    259         enforceCallingPermission();
    260         synchronized (mStats) {
    261             mStats.noteVideoOnLocked(uid);
    262         }
    263     }
    264 
    265     public void noteStopVideo(int uid) {
    266         enforceCallingPermission();
    267         synchronized (mStats) {
    268             mStats.noteVideoOffLocked(uid);
    269         }
    270     }
    271 
    272     public void noteWifiRunning(WorkSource ws) {
    273         enforceCallingPermission();
    274         synchronized (mStats) {
    275             mStats.noteWifiRunningLocked(ws);
    276         }
    277     }
    278 
    279     public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) {
    280         enforceCallingPermission();
    281         synchronized (mStats) {
    282             mStats.noteWifiRunningChangedLocked(oldWs, newWs);
    283         }
    284     }
    285 
    286     public void noteWifiStopped(WorkSource ws) {
    287         enforceCallingPermission();
    288         synchronized (mStats) {
    289             mStats.noteWifiStoppedLocked(ws);
    290         }
    291     }
    292 
    293     public void noteBluetoothOn() {
    294         enforceCallingPermission();
    295         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    296         if (adapter != null) {
    297             adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
    298                                     BluetoothProfile.HEADSET);
    299         }
    300         synchronized (mStats) {
    301             if (mBluetoothHeadset != null) {
    302                 mStats.noteBluetoothOnLocked();
    303                 mStats.setBtHeadset(mBluetoothHeadset);
    304             } else {
    305                 mBluetoothPendingStats = true;
    306             }
    307         }
    308     }
    309 
    310     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
    311         new BluetoothProfile.ServiceListener() {
    312         public void onServiceConnected(int profile, BluetoothProfile proxy) {
    313             mBluetoothHeadset = (BluetoothHeadset) proxy;
    314             synchronized (mStats) {
    315                 if (mBluetoothPendingStats) {
    316                     mStats.noteBluetoothOnLocked();
    317                     mStats.setBtHeadset(mBluetoothHeadset);
    318                     mBluetoothPendingStats = false;
    319                 }
    320             }
    321         }
    322 
    323         public void onServiceDisconnected(int profile) {
    324             mBluetoothHeadset = null;
    325         }
    326     };
    327 
    328     public void noteBluetoothOff() {
    329         enforceCallingPermission();
    330         synchronized (mStats) {
    331             mBluetoothPendingStats = false;
    332             mStats.noteBluetoothOffLocked();
    333         }
    334     }
    335 
    336     public void noteFullWifiLockAcquired(int uid) {
    337         enforceCallingPermission();
    338         synchronized (mStats) {
    339             mStats.noteFullWifiLockAcquiredLocked(uid);
    340         }
    341     }
    342 
    343     public void noteFullWifiLockReleased(int uid) {
    344         enforceCallingPermission();
    345         synchronized (mStats) {
    346             mStats.noteFullWifiLockReleasedLocked(uid);
    347         }
    348     }
    349 
    350     public void noteScanWifiLockAcquired(int uid) {
    351         enforceCallingPermission();
    352         synchronized (mStats) {
    353             mStats.noteScanWifiLockAcquiredLocked(uid);
    354         }
    355     }
    356 
    357     public void noteScanWifiLockReleased(int uid) {
    358         enforceCallingPermission();
    359         synchronized (mStats) {
    360             mStats.noteScanWifiLockReleasedLocked(uid);
    361         }
    362     }
    363 
    364     public void noteWifiMulticastEnabled(int uid) {
    365         enforceCallingPermission();
    366         synchronized (mStats) {
    367             mStats.noteWifiMulticastEnabledLocked(uid);
    368         }
    369     }
    370 
    371     public void noteWifiMulticastDisabled(int uid) {
    372         enforceCallingPermission();
    373         synchronized (mStats) {
    374             mStats.noteWifiMulticastDisabledLocked(uid);
    375         }
    376     }
    377 
    378     public void noteFullWifiLockAcquiredFromSource(WorkSource ws) {
    379         enforceCallingPermission();
    380         synchronized (mStats) {
    381             mStats.noteFullWifiLockAcquiredFromSourceLocked(ws);
    382         }
    383     }
    384 
    385     public void noteFullWifiLockReleasedFromSource(WorkSource ws) {
    386         enforceCallingPermission();
    387         synchronized (mStats) {
    388             mStats.noteFullWifiLockReleasedFromSourceLocked(ws);
    389         }
    390     }
    391 
    392     public void noteScanWifiLockAcquiredFromSource(WorkSource ws) {
    393         enforceCallingPermission();
    394         synchronized (mStats) {
    395             mStats.noteScanWifiLockAcquiredFromSourceLocked(ws);
    396         }
    397     }
    398 
    399     public void noteScanWifiLockReleasedFromSource(WorkSource ws) {
    400         enforceCallingPermission();
    401         synchronized (mStats) {
    402             mStats.noteScanWifiLockReleasedFromSourceLocked(ws);
    403         }
    404     }
    405 
    406     public void noteWifiMulticastEnabledFromSource(WorkSource ws) {
    407         enforceCallingPermission();
    408         synchronized (mStats) {
    409             mStats.noteWifiMulticastEnabledFromSourceLocked(ws);
    410         }
    411     }
    412 
    413     public void noteWifiMulticastDisabledFromSource(WorkSource ws) {
    414         enforceCallingPermission();
    415         synchronized (mStats) {
    416             mStats.noteWifiMulticastDisabledFromSourceLocked(ws);
    417         }
    418     }
    419 
    420     public void noteNetworkInterfaceType(String iface, int type) {
    421         enforceCallingPermission();
    422         synchronized (mStats) {
    423             mStats.noteNetworkInterfaceTypeLocked(iface, type);
    424         }
    425     }
    426 
    427     public boolean isOnBattery() {
    428         return mStats.isOnBattery();
    429     }
    430 
    431     public void setBatteryState(int status, int health, int plugType, int level,
    432             int temp, int volt) {
    433         enforceCallingPermission();
    434         mStats.setBatteryState(status, health, plugType, level, temp, volt);
    435     }
    436 
    437     public long getAwakeTimeBattery() {
    438         mContext.enforceCallingOrSelfPermission(
    439                 android.Manifest.permission.BATTERY_STATS, null);
    440         return mStats.getAwakeTimeBattery();
    441     }
    442 
    443     public long getAwakeTimePlugged() {
    444         mContext.enforceCallingOrSelfPermission(
    445                 android.Manifest.permission.BATTERY_STATS, null);
    446         return mStats.getAwakeTimePlugged();
    447     }
    448 
    449     public void enforceCallingPermission() {
    450         if (Binder.getCallingPid() == Process.myPid()) {
    451             return;
    452         }
    453         mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
    454                 Binder.getCallingPid(), Binder.getCallingUid(), null);
    455     }
    456 
    457     private void dumpHelp(PrintWriter pw) {
    458         pw.println("Battery stats (batteryinfo) dump options:");
    459         pw.println("  [--checkin] [--reset] [--write] [-h]");
    460         pw.println("  --checkin: format output for a checkin report.");
    461         pw.println("  --reset: reset the stats, clearing all current data.");
    462         pw.println("  --write: force write current collected stats to disk.");
    463         pw.println("  -h: print this help text.");
    464     }
    465 
    466     @Override
    467     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    468         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
    469                 != PackageManager.PERMISSION_GRANTED) {
    470             pw.println("Permission Denial: can't dump BatteryStats from from pid="
    471                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
    472                     + " without permission " + android.Manifest.permission.DUMP);
    473             return;
    474         }
    475 
    476         boolean isCheckin = false;
    477         boolean noOutput = false;
    478         if (args != null) {
    479             for (String arg : args) {
    480                 if ("--checkin".equals(arg)) {
    481                     isCheckin = true;
    482                 } else if ("--reset".equals(arg)) {
    483                     synchronized (mStats) {
    484                         mStats.resetAllStatsLocked();
    485                         pw.println("Battery stats reset.");
    486                         noOutput = true;
    487                     }
    488                 } else if ("--write".equals(arg)) {
    489                     synchronized (mStats) {
    490                         mStats.writeSyncLocked();
    491                         pw.println("Battery stats written.");
    492                         noOutput = true;
    493                     }
    494                 } else if ("-h".equals(arg)) {
    495                     dumpHelp(pw);
    496                     return;
    497                 } else if ("-a".equals(arg)) {
    498                     // fall through
    499                 } else {
    500                     pw.println("Unknown option: " + arg);
    501                     dumpHelp(pw);
    502                 }
    503             }
    504         }
    505         if (noOutput) {
    506             return;
    507         }
    508         if (isCheckin) {
    509             List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
    510             synchronized (mStats) {
    511                 mStats.dumpCheckinLocked(pw, args, apps);
    512             }
    513         } else {
    514             synchronized (mStats) {
    515                 mStats.dumpLocked(pw);
    516             }
    517         }
    518     }
    519 }
    520