19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.app.IBatteryStats; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.server.am.BatteryStatsService; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ActivityManagerNative; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.BatteryManager; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 298bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackbornimport android.os.FileUtils; 30605ea69ab16dee2047ea43905a9b443896cde121Jeff Brownimport android.os.Handler; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 3218e939623556928f73fcc7511c85a537929a4a7eDan Egnorimport android.os.DropBoxManager; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.UEventObserver; 375ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.EventLog; 408a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileOutputStream; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>BatteryService monitors the charging status, and charge level of the device 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * battery. When these values change this service broadcasts the new values 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to all {@link android.content.BroadcastReceiver IntentReceivers} that are 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * watching the {@link android.content.Intent#ACTION_BATTERY_CHANGED 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * BATTERY_CHANGED} action.</p> 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The new values are stored in the Intent data and can be retrieved by 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * calling {@link android.content.Intent#getExtra Intent.getExtra} with the 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * following keys:</p> 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>"scale" - int, the maximum value for the charge level</p> 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>"level" - int, charge level, from 0 through "scale" inclusive</p> 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>"status" - String, the current charging status.<br /> 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>"health" - String, the current battery health.<br /> 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>"present" - boolean, true if the battery is present<br /> 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>"icon-small" - int, suggested small icon to use for this state</p> 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>"plugged" - int, 0 if the device is not plugged in; 1 if plugged 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * into an AC power adapter; 2 if plugged in via USB.</p> 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>"voltage" - int, current battery voltage in millivolts</p> 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>"temperature" - int, current battery temperature in tenths of 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a degree Centigrade</p> 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>"technology" - String, the type of battery installed, e.g. "Li-ion"</p> 70605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown * 71605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown * <p> 72605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown * The battery service may be called by the power manager while holding its locks so 73605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown * we take care to post all outcalls into the activity manager to a handler. 74605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown * 75605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown * FIXME: Ideally the power manager would perform all of its calls into the battery 76605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown * service asynchronously itself. 77605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown * </p> 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 79a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brownpublic final class BatteryService extends Binder { 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = BatteryService.class.getSimpleName(); 81ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 82a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private static final boolean DEBUG = false; 83ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 84a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private static final int BATTERY_SCALE = 100; // battery capacity is a percentage 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Used locally for determining when to make a last ditch effort to log 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // discharge stats before the device dies. 884ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato private int mCriticalBatteryLevel; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int DUMP_MAX_LENGTH = 24 * 1024; 916447ca30b8e41c22c7214f201120327057e356dcDianne Hackborn private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "-u" }; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String BATTERY_STATS_SERVICE_NAME = "batteryinfo"; 93ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String DUMPSYS_DATA_PATH = "/data/system/"; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This should probably be exposed in the API, though it's not critical 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int BATTERY_PLUGGED_NONE = 0; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Context mContext; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final IBatteryStats mBatteryStats; 101605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown private final Handler mHandler; 102ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 103a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private final Object mLock = new Object(); 104a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown 105a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown /* Begin native fields: All of these fields are set by native code. */ 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mAcOnline; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mUsbOnline; 10837a37f445cbcd64376af153dd79ea2a123d9405dBrian Muramatsu private boolean mWirelessOnline; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mBatteryStatus; 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mBatteryHealth; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mBatteryPresent; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mBatteryLevel; 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mBatteryVoltage; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mBatteryTemperature; 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mBatteryTechnology; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mBatteryLevelCritical; 117a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown /* End native fields. */ 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mLastBatteryStatus; 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mLastBatteryHealth; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mLastBatteryPresent; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mLastBatteryLevel; 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mLastBatteryVoltage; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mLastBatteryTemperature; 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mLastBatteryLevelCritical; 126a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown 127a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private int mInvalidCharger; 1284ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato private int mLastInvalidCharger; 129d81b1f41e5e7bf0ccd3e4c08838d65eacdc8dda0Mike Lockwood 130d81b1f41e5e7bf0ccd3e4c08838d65eacdc8dda0Mike Lockwood private int mLowBatteryWarningLevel; 131d81b1f41e5e7bf0ccd3e4c08838d65eacdc8dda0Mike Lockwood private int mLowBatteryCloseWarningLevel; 132f3c74f34999337b8eb77e1a5ed0287561b512c21Brian Muramatsu private int mShutdownBatteryTemperature; 133d81b1f41e5e7bf0ccd3e4c08838d65eacdc8dda0Mike Lockwood 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mPlugType; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mLastPlugType = -1; // Extra state so we can detect first run 136ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private long mDischargeStartTime; 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDischargeStartLevel; 139ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 140c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn private boolean mUpdatesStopped; 141c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn 142de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato private Led mLed; 143de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato 1448ec5b83fc8f8aa68805c4d5987f8f75bb28250caDianne Hackborn private boolean mSentLowBatteryBroadcast = false; 145ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 146a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private native void native_update(); 147a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown 148de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato public BatteryService(Context context, LightsService lights) { 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 150605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown mHandler = new Handler(true /*async*/); 151de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato mLed = new Led(context, lights); 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBatteryStats = BatteryStatsService.getService(); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1544ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato mCriticalBatteryLevel = mContext.getResources().getInteger( 1554ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato com.android.internal.R.integer.config_criticalBatteryWarningLevel); 156d81b1f41e5e7bf0ccd3e4c08838d65eacdc8dda0Mike Lockwood mLowBatteryWarningLevel = mContext.getResources().getInteger( 157d81b1f41e5e7bf0ccd3e4c08838d65eacdc8dda0Mike Lockwood com.android.internal.R.integer.config_lowBatteryWarningLevel); 158d81b1f41e5e7bf0ccd3e4c08838d65eacdc8dda0Mike Lockwood mLowBatteryCloseWarningLevel = mContext.getResources().getInteger( 159d81b1f41e5e7bf0ccd3e4c08838d65eacdc8dda0Mike Lockwood com.android.internal.R.integer.config_lowBatteryCloseWarningLevel); 160f3c74f34999337b8eb77e1a5ed0287561b512c21Brian Muramatsu mShutdownBatteryTemperature = mContext.getResources().getInteger( 161f3c74f34999337b8eb77e1a5ed0287561b512c21Brian Muramatsu com.android.internal.R.integer.config_shutdownBatteryTemperature); 162d81b1f41e5e7bf0ccd3e4c08838d65eacdc8dda0Mike Lockwood 163deff9c85ec5c9884d731817e43058589d6fd4631Mike Lockwood mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply"); 164deff9c85ec5c9884d731817e43058589d6fd4631Mike Lockwood 165deff9c85ec5c9884d731817e43058589d6fd4631Mike Lockwood // watch for invalid charger messages if the invalid_charger switch exists 166deff9c85ec5c9884d731817e43058589d6fd4631Mike Lockwood if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) { 167a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown mInvalidChargerObserver.startObserving( 168a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown "DEVPATH=/devices/virtual/switch/invalid_charger"); 169deff9c85ec5c9884d731817e43058589d6fd4631Mike Lockwood } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // set initial status 172a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown synchronized (mLock) { 173a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown updateLocked(); 174a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown } 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 177a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown void systemReady() { 178a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown // check our power situation now that it is safe to display the shutdown dialog. 179a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown synchronized (mLock) { 180a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown shutdownIfNoPowerLocked(); 181a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown shutdownIfOverTempLocked(); 182a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown } 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 185a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown /** 186a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown * Returns true if the device is plugged into any of the specified plug types. 187a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown */ 188a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown public boolean isPowered(int plugTypeSet) { 189a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown synchronized (mLock) { 190a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown return isPoweredLocked(plugTypeSet); 191a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown } 192a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown } 193a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown 194a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private boolean isPoweredLocked(int plugTypeSet) { 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // assume we are powered if battery state is unknown so 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the "stay on while plugged in" option will work. 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) { 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 200a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_AC) != 0 && mAcOnline) { 201a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown return true; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 203a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_USB) != 0 && mUsbOnline) { 204a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown return true; 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 206a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0 && mWirelessOnline) { 207a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown return true; 20837a37f445cbcd64376af153dd79ea2a123d9405dBrian Muramatsu } 209a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown return false; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 212a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown /** 213f3fb895269deadcda0cf497d421e4b89e8ee8f8fJeff Brown * Returns the current plug type. 214f3fb895269deadcda0cf497d421e4b89e8ee8f8fJeff Brown */ 215f3fb895269deadcda0cf497d421e4b89e8ee8f8fJeff Brown public int getPlugType() { 216f3fb895269deadcda0cf497d421e4b89e8ee8f8fJeff Brown synchronized (mLock) { 217f3fb895269deadcda0cf497d421e4b89e8ee8f8fJeff Brown return mPlugType; 218f3fb895269deadcda0cf497d421e4b89e8ee8f8fJeff Brown } 219f3fb895269deadcda0cf497d421e4b89e8ee8f8fJeff Brown } 220f3fb895269deadcda0cf497d421e4b89e8ee8f8fJeff Brown 221f3fb895269deadcda0cf497d421e4b89e8ee8f8fJeff Brown /** 222a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown * Returns battery level as a percentage. 223a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown */ 224a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown public int getBatteryLevel() { 225a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown synchronized (mLock) { 226a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown return mBatteryLevel; 227deff9c85ec5c9884d731817e43058589d6fd4631Mike Lockwood } 22810fb224623eae3a99a4fc68424eb876eb20c3f90John Spurlock } 22910fb224623eae3a99a4fc68424eb876eb20c3f90John Spurlock 230a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown /** 231a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown * Returns true if battery level is below the first warning threshold. 232a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown */ 233a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown public boolean isBatteryLow() { 234a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown synchronized (mLock) { 235a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown return mBatteryPresent && mBatteryLevel <= mLowBatteryWarningLevel; 236a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown } 23707a500f0de2243b832e258ed477652a10cbd2d08Mike Lockwood } 23807a500f0de2243b832e258ed477652a10cbd2d08Mike Lockwood 239a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private void shutdownIfNoPowerLocked() { 24007a500f0de2243b832e258ed477652a10cbd2d08Mike Lockwood // shut down gracefully if our battery is critically low and we are not powered. 24107a500f0de2243b832e258ed477652a10cbd2d08Mike Lockwood // wait until the system has booted before attempting to display the shutdown dialog. 242605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown if (mBatteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) { 243605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown mHandler.post(new Runnable() { 244605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown @Override 245605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown public void run() { 246605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown if (ActivityManagerNative.isSystemReady()) { 247605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN); 248605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false); 249605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 250605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown mContext.startActivityAsUser(intent, UserHandle.CURRENT); 251605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown } 252605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown } 253605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown }); 25407a500f0de2243b832e258ed477652a10cbd2d08Mike Lockwood } 25507a500f0de2243b832e258ed477652a10cbd2d08Mike Lockwood } 25607a500f0de2243b832e258ed477652a10cbd2d08Mike Lockwood 257a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private void shutdownIfOverTempLocked() { 258f3c74f34999337b8eb77e1a5ed0287561b512c21Brian Muramatsu // shut down gracefully if temperature is too high (> 68.0C by default) 259f3c74f34999337b8eb77e1a5ed0287561b512c21Brian Muramatsu // wait until the system has booted before attempting to display the 260f3c74f34999337b8eb77e1a5ed0287561b512c21Brian Muramatsu // shutdown dialog. 261605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown if (mBatteryTemperature > mShutdownBatteryTemperature) { 262605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown mHandler.post(new Runnable() { 263605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown @Override 264605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown public void run() { 265605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown if (ActivityManagerNative.isSystemReady()) { 266605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN); 267605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false); 268605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 269605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown mContext.startActivityAsUser(intent, UserHandle.CURRENT); 270605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown } 271605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown } 272605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown }); 2736a362a97f71cda9eadfb72ce51e664c494cf7a04Eric Olsen } 2746a362a97f71cda9eadfb72ce51e664c494cf7a04Eric Olsen } 2756a362a97f71cda9eadfb72ce51e664c494cf7a04Eric Olsen 276a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private void updateLocked() { 277c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn if (!mUpdatesStopped) { 278c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn // Update the values of mAcOnline, et. all. 279c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn native_update(); 280a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown 281c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn // Process the new values. 282c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn processValuesLocked(); 283c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn } 2844ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato } 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 286a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private void processValuesLocked() { 287105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project boolean logOutlier = false; 288105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project long dischargeDuration = 0; 289a7e4cf9b5c9dd7d733e1ee7109ecb0e58996fe06Joe Onorato 290a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown mBatteryLevelCritical = (mBatteryLevel <= mCriticalBatteryLevel); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAcOnline) { 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPlugType = BatteryManager.BATTERY_PLUGGED_AC; 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mUsbOnline) { 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPlugType = BatteryManager.BATTERY_PLUGGED_USB; 29537a37f445cbcd64376af153dd79ea2a123d9405dBrian Muramatsu } else if (mWirelessOnline) { 29637a37f445cbcd64376af153dd79ea2a123d9405dBrian Muramatsu mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPlugType = BATTERY_PLUGGED_NONE; 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 300f3c74f34999337b8eb77e1a5ed0287561b512c21Brian Muramatsu 301a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown if (DEBUG) { 302a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown Slog.d(TAG, "Processing new values: " 303a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown + "mAcOnline=" + mAcOnline 304a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown + ", mUsbOnline=" + mUsbOnline 305a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown + ", mWirelessOnline=" + mWirelessOnline 306a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown + ", mBatteryStatus=" + mBatteryStatus 307a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown + ", mBatteryHealth=" + mBatteryHealth 308a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown + ", mBatteryPresent=" + mBatteryPresent 309a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown + ", mBatteryLevel=" + mBatteryLevel 310a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown + ", mBatteryTechnology=" + mBatteryTechnology 311a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown + ", mBatteryVoltage=" + mBatteryVoltage 312a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown + ", mBatteryTemperature=" + mBatteryTemperature 313a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown + ", mBatteryLevelCritical=" + mBatteryLevelCritical 314a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown + ", mPlugType=" + mPlugType); 315a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown } 316a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown 3176b7b4845212b3a439c527f2e1eca205b6b45fcebDianne Hackborn // Let the battery stats keep track of the current level. 3186b7b4845212b3a439c527f2e1eca205b6b45fcebDianne Hackborn try { 3196b7b4845212b3a439c527f2e1eca205b6b45fcebDianne Hackborn mBatteryStats.setBatteryState(mBatteryStatus, mBatteryHealth, 3206b7b4845212b3a439c527f2e1eca205b6b45fcebDianne Hackborn mPlugType, mBatteryLevel, mBatteryTemperature, 3216b7b4845212b3a439c527f2e1eca205b6b45fcebDianne Hackborn mBatteryVoltage); 3226b7b4845212b3a439c527f2e1eca205b6b45fcebDianne Hackborn } catch (RemoteException e) { 3236b7b4845212b3a439c527f2e1eca205b6b45fcebDianne Hackborn // Should never happen. 3246b7b4845212b3a439c527f2e1eca205b6b45fcebDianne Hackborn } 325f3c74f34999337b8eb77e1a5ed0287561b512c21Brian Muramatsu 326a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown shutdownIfNoPowerLocked(); 327a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown shutdownIfOverTempLocked(); 3286b7b4845212b3a439c527f2e1eca205b6b45fcebDianne Hackborn 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBatteryStatus != mLastBatteryStatus || 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBatteryHealth != mLastBatteryHealth || 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBatteryPresent != mLastBatteryPresent || 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBatteryLevel != mLastBatteryLevel || 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPlugType != mLastPlugType || 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBatteryVoltage != mLastBatteryVoltage || 335deff9c85ec5c9884d731817e43058589d6fd4631Mike Lockwood mBatteryTemperature != mLastBatteryTemperature || 336deff9c85ec5c9884d731817e43058589d6fd4631Mike Lockwood mInvalidCharger != mLastInvalidCharger) { 337ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mPlugType != mLastPlugType) { 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mLastPlugType == BATTERY_PLUGGED_NONE) { 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // discharging -> charging 341ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // There's no value in this data unless we've discharged at least once and the 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // battery level has changed; so don't log until it does. 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDischargeStartTime != 0 && mDischargeStartLevel != mBatteryLevel) { 345105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime; 346105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project logOutlier = true; 347ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration, 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDischargeStartLevel, mBatteryLevel); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make sure we see a discharge event before logging again 350ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker mDischargeStartTime = 0; 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mPlugType == BATTERY_PLUGGED_NONE) { 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // charging -> discharging or we just powered up 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDischargeStartTime = SystemClock.elapsedRealtime(); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDischargeStartLevel = mBatteryLevel; 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBatteryStatus != mLastBatteryStatus || 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBatteryHealth != mLastBatteryHealth || 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBatteryPresent != mLastBatteryPresent || 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPlugType != mLastPlugType) { 362ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker EventLog.writeEvent(EventLogTags.BATTERY_STATUS, 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBatteryStatus, mBatteryHealth, mBatteryPresent ? 1 : 0, 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPlugType, mBatteryTechnology); 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBatteryLevel != mLastBatteryLevel || 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBatteryVoltage != mLastBatteryVoltage || 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBatteryTemperature != mLastBatteryTemperature) { 369ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker EventLog.writeEvent(EventLogTags.BATTERY_LEVEL, 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBatteryLevel, mBatteryVoltage, mBatteryTemperature); 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBatteryLevelCritical && !mLastBatteryLevelCritical && 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPlugType == BATTERY_PLUGGED_NONE) { 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We want to make sure we log discharge cycle outliers 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if the battery is about to die. 376105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime; 377105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project logOutlier = true; 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 379ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 38099f7eb453cee23e13f3ac8a4fa0632dd28f3a4b8Dianne Hackborn final boolean plugged = mPlugType != BATTERY_PLUGGED_NONE; 38199f7eb453cee23e13f3ac8a4fa0632dd28f3a4b8Dianne Hackborn final boolean oldPlugged = mLastPlugType != BATTERY_PLUGGED_NONE; 38299f7eb453cee23e13f3ac8a4fa0632dd28f3a4b8Dianne Hackborn 38399f7eb453cee23e13f3ac8a4fa0632dd28f3a4b8Dianne Hackborn /* The ACTION_BATTERY_LOW broadcast is sent in these situations: 384d81b1f41e5e7bf0ccd3e4c08838d65eacdc8dda0Mike Lockwood * - is just un-plugged (previously was plugged) and battery level is 385d81b1f41e5e7bf0ccd3e4c08838d65eacdc8dda0Mike Lockwood * less than or equal to WARNING, or 386d81b1f41e5e7bf0ccd3e4c08838d65eacdc8dda0Mike Lockwood * - is not plugged and battery level falls to WARNING boundary 387d81b1f41e5e7bf0ccd3e4c08838d65eacdc8dda0Mike Lockwood * (becomes <= mLowBatteryWarningLevel). 38899f7eb453cee23e13f3ac8a4fa0632dd28f3a4b8Dianne Hackborn */ 38999f7eb453cee23e13f3ac8a4fa0632dd28f3a4b8Dianne Hackborn final boolean sendBatteryLow = !plugged 390de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN 391de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato && mBatteryLevel <= mLowBatteryWarningLevel 392de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel); 393ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 394a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown sendIntentLocked(); 395ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 39606ba55476ee9703c876d223cd41bd73c5f85f42dChristopher Tate // Separate broadcast is sent for power connected / not connected 39706ba55476ee9703c876d223cd41bd73c5f85f42dChristopher Tate // since the standard intent will not wake any applications and some 39806ba55476ee9703c876d223cd41bd73c5f85f42dChristopher Tate // applications may want to have smart behavior based on this. 39906ba55476ee9703c876d223cd41bd73c5f85f42dChristopher Tate if (mPlugType != 0 && mLastPlugType == 0) { 400605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown mHandler.post(new Runnable() { 401605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown @Override 402605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown public void run() { 403605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED); 404605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 405605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); 406605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown } 407605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown }); 40806ba55476ee9703c876d223cd41bd73c5f85f42dChristopher Tate } 40906ba55476ee9703c876d223cd41bd73c5f85f42dChristopher Tate else if (mPlugType == 0 && mLastPlugType != 0) { 410605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown mHandler.post(new Runnable() { 411605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown @Override 412605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown public void run() { 413605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED); 414605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 415605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); 416605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown } 417605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown }); 41806ba55476ee9703c876d223cd41bd73c5f85f42dChristopher Tate } 419a82842f98d64897e92e1012404863f940bd03d26Mihai Preda 420a82842f98d64897e92e1012404863f940bd03d26Mihai Preda if (sendBatteryLow) { 4218ec5b83fc8f8aa68805c4d5987f8f75bb28250caDianne Hackborn mSentLowBatteryBroadcast = true; 422605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown mHandler.post(new Runnable() { 423605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown @Override 424605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown public void run() { 425605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW); 426605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 427605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); 428605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown } 429605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown }); 430d81b1f41e5e7bf0ccd3e4c08838d65eacdc8dda0Mike Lockwood } else if (mSentLowBatteryBroadcast && mLastBatteryLevel >= mLowBatteryCloseWarningLevel) { 4318ec5b83fc8f8aa68805c4d5987f8f75bb28250caDianne Hackborn mSentLowBatteryBroadcast = false; 432605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown mHandler.post(new Runnable() { 433605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown @Override 434605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown public void run() { 435605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY); 436605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 437605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); 438605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown } 439605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown }); 440a82842f98d64897e92e1012404863f940bd03d26Mihai Preda } 441ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 442de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato // Update the battery LED 443de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato mLed.updateLightsLocked(); 444de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato 445105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // This needs to be done after sendIntent() so that we get the lastest battery stats. 446105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (logOutlier && dischargeDuration != 0) { 447a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown logOutlierLocked(dischargeDuration); 448105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 449ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 45099f7eb453cee23e13f3ac8a4fa0632dd28f3a4b8Dianne Hackborn mLastBatteryStatus = mBatteryStatus; 45199f7eb453cee23e13f3ac8a4fa0632dd28f3a4b8Dianne Hackborn mLastBatteryHealth = mBatteryHealth; 45299f7eb453cee23e13f3ac8a4fa0632dd28f3a4b8Dianne Hackborn mLastBatteryPresent = mBatteryPresent; 45399f7eb453cee23e13f3ac8a4fa0632dd28f3a4b8Dianne Hackborn mLastBatteryLevel = mBatteryLevel; 45499f7eb453cee23e13f3ac8a4fa0632dd28f3a4b8Dianne Hackborn mLastPlugType = mPlugType; 45599f7eb453cee23e13f3ac8a4fa0632dd28f3a4b8Dianne Hackborn mLastBatteryVoltage = mBatteryVoltage; 45699f7eb453cee23e13f3ac8a4fa0632dd28f3a4b8Dianne Hackborn mLastBatteryTemperature = mBatteryTemperature; 45799f7eb453cee23e13f3ac8a4fa0632dd28f3a4b8Dianne Hackborn mLastBatteryLevelCritical = mBatteryLevelCritical; 458deff9c85ec5c9884d731817e43058589d6fd4631Mike Lockwood mLastInvalidCharger = mInvalidCharger; 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 462a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private void sendIntentLocked() { 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Pack up the values and broadcast them to everyone 464605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); 4651c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY 4661c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn | Intent.FLAG_RECEIVER_REPLACE_PENDING); 467ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 468a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown int icon = getIconLocked(mBatteryLevel); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 470edd9316ca9b3b24d54e8a2468927da7e813098fcDianne Hackborn intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryStatus); 471edd9316ca9b3b24d54e8a2468927da7e813098fcDianne Hackborn intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryHealth); 472edd9316ca9b3b24d54e8a2468927da7e813098fcDianne Hackborn intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryPresent); 473edd9316ca9b3b24d54e8a2468927da7e813098fcDianne Hackborn intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryLevel); 474edd9316ca9b3b24d54e8a2468927da7e813098fcDianne Hackborn intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE); 475edd9316ca9b3b24d54e8a2468927da7e813098fcDianne Hackborn intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon); 476edd9316ca9b3b24d54e8a2468927da7e813098fcDianne Hackborn intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType); 477edd9316ca9b3b24d54e8a2468927da7e813098fcDianne Hackborn intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryVoltage); 478edd9316ca9b3b24d54e8a2468927da7e813098fcDianne Hackborn intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryTemperature); 479edd9316ca9b3b24d54e8a2468927da7e813098fcDianne Hackborn intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryTechnology); 480deff9c85ec5c9884d731817e43058589d6fd4631Mike Lockwood intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 482a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown if (DEBUG) { 483a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryLevel + 484a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown ", scale:" + BATTERY_SCALE + ", status:" + mBatteryStatus + 485a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown ", health:" + mBatteryHealth + ", present:" + mBatteryPresent + 486a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown ", voltage: " + mBatteryVoltage + 487a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown ", temperature: " + mBatteryTemperature + 488a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown ", technology: " + mBatteryTechnology + 489a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown ", AC powered:" + mAcOnline + ", USB powered:" + mUsbOnline + 490a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown ", Wireless powered:" + mWirelessOnline + 491a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown ", icon:" + icon + ", invalid charger:" + mInvalidCharger); 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 494605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown mHandler.post(new Runnable() { 495605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown @Override 496605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown public void run() { 497605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); 498605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown } 499605ea69ab16dee2047ea43905a9b443896cde121Jeff Brown }); 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 502a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private void logBatteryStatsLocked() { 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder batteryInfoService = ServiceManager.getService(BATTERY_STATS_SERVICE_NAME); 50418e939623556928f73fcc7511c85a537929a4a7eDan Egnor if (batteryInfoService == null) return; 50518e939623556928f73fcc7511c85a537929a4a7eDan Egnor 50618e939623556928f73fcc7511c85a537929a4a7eDan Egnor DropBoxManager db = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE); 50718e939623556928f73fcc7511c85a537929a4a7eDan Egnor if (db == null || !db.isTagEnabled("BATTERY_DISCHARGE_INFO")) return; 50818e939623556928f73fcc7511c85a537929a4a7eDan Egnor 50918e939623556928f73fcc7511c85a537929a4a7eDan Egnor File dumpFile = null; 51018e939623556928f73fcc7511c85a537929a4a7eDan Egnor FileOutputStream dumpStream = null; 51118e939623556928f73fcc7511c85a537929a4a7eDan Egnor try { 51218e939623556928f73fcc7511c85a537929a4a7eDan Egnor // dump the service to a file 51318e939623556928f73fcc7511c85a537929a4a7eDan Egnor dumpFile = new File(DUMPSYS_DATA_PATH + BATTERY_STATS_SERVICE_NAME + ".dump"); 51418e939623556928f73fcc7511c85a537929a4a7eDan Egnor dumpStream = new FileOutputStream(dumpFile); 51518e939623556928f73fcc7511c85a537929a4a7eDan Egnor batteryInfoService.dump(dumpStream.getFD(), DUMPSYS_ARGS); 5168bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn FileUtils.sync(dumpStream); 51718e939623556928f73fcc7511c85a537929a4a7eDan Egnor 51818e939623556928f73fcc7511c85a537929a4a7eDan Egnor // add dump file to drop box 51918e939623556928f73fcc7511c85a537929a4a7eDan Egnor db.addFile("BATTERY_DISCHARGE_INFO", dumpFile, DropBoxManager.IS_TEXT); 52018e939623556928f73fcc7511c85a537929a4a7eDan Egnor } catch (RemoteException e) { 5218a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.e(TAG, "failed to dump battery service", e); 52218e939623556928f73fcc7511c85a537929a4a7eDan Egnor } catch (IOException e) { 5238a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.e(TAG, "failed to write dumpsys file", e); 52418e939623556928f73fcc7511c85a537929a4a7eDan Egnor } finally { 52518e939623556928f73fcc7511c85a537929a4a7eDan Egnor // make sure we clean up 52618e939623556928f73fcc7511c85a537929a4a7eDan Egnor if (dumpStream != null) { 52718e939623556928f73fcc7511c85a537929a4a7eDan Egnor try { 52818e939623556928f73fcc7511c85a537929a4a7eDan Egnor dumpStream.close(); 52918e939623556928f73fcc7511c85a537929a4a7eDan Egnor } catch (IOException e) { 5308a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.e(TAG, "failed to close dumpsys output stream"); 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 53318e939623556928f73fcc7511c85a537929a4a7eDan Egnor if (dumpFile != null && !dumpFile.delete()) { 5348a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.e(TAG, "failed to delete temporary dumpsys file: " 53518e939623556928f73fcc7511c85a537929a4a7eDan Egnor + dumpFile.getAbsolutePath()); 53618e939623556928f73fcc7511c85a537929a4a7eDan Egnor } 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 539ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 540a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private void logOutlierLocked(long duration) { 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentResolver cr = mContext.getContentResolver(); 542625239a05401bbf18b04d9874cea3f82da7c29a1Jeff Sharkey String dischargeThresholdString = Settings.Global.getString(cr, 543625239a05401bbf18b04d9874cea3f82da7c29a1Jeff Sharkey Settings.Global.BATTERY_DISCHARGE_THRESHOLD); 544625239a05401bbf18b04d9874cea3f82da7c29a1Jeff Sharkey String durationThresholdString = Settings.Global.getString(cr, 545625239a05401bbf18b04d9874cea3f82da7c29a1Jeff Sharkey Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD); 546ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dischargeThresholdString != null && durationThresholdString != null) { 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long durationThreshold = Long.parseLong(durationThresholdString); 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dischargeThreshold = Integer.parseInt(dischargeThresholdString); 551ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker if (duration <= durationThreshold && 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDischargeStartLevel - mBatteryLevel >= dischargeThreshold) { 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the discharge cycle is bad enough we want to know about it. 554a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown logBatteryStatsLocked(); 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 556a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown if (DEBUG) Slog.v(TAG, "duration threshold: " + durationThreshold + 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " discharge threshold: " + dischargeThreshold); 558a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown if (DEBUG) Slog.v(TAG, "duration: " + duration + " discharge: " + 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (mDischargeStartLevel - mBatteryLevel)); 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException e) { 5618a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.e(TAG, "Invalid DischargeThresholds GService string: " + 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project durationThresholdString + " or " + dischargeThresholdString); 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 568a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private int getIconLocked(int level) { 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) { 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return com.android.internal.R.drawable.stat_sys_battery_charge; 571794be40f8b62b309004cc3f68ca9567e4ef24c6bJoe Onorato } else if (mBatteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) { 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return com.android.internal.R.drawable.stat_sys_battery; 573794be40f8b62b309004cc3f68ca9567e4ef24c6bJoe Onorato } else if (mBatteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING 574794be40f8b62b309004cc3f68ca9567e4ef24c6bJoe Onorato || mBatteryStatus == BatteryManager.BATTERY_STATUS_FULL) { 575a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown if (isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY) 576a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown && mBatteryLevel >= 100) { 577794be40f8b62b309004cc3f68ca9567e4ef24c6bJoe Onorato return com.android.internal.R.drawable.stat_sys_battery_charge; 578794be40f8b62b309004cc3f68ca9567e4ef24c6bJoe Onorato } else { 579794be40f8b62b309004cc3f68ca9567e4ef24c6bJoe Onorato return com.android.internal.R.drawable.stat_sys_battery; 580794be40f8b62b309004cc3f68ca9567e4ef24c6bJoe Onorato } 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return com.android.internal.R.drawable.stat_sys_battery_unknown; 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 590ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println("Permission Denial: can't dump Battery service from from pid=" 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Binder.getCallingPid() 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", uid=" + Binder.getCallingUid()); 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 597a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown synchronized (mLock) { 598a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown if (args == null || args.length == 0 || "-a".equals(args[0])) { 5994ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato pw.println("Current Battery Service state:"); 600c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn if (mUpdatesStopped) { 601c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn pw.println(" (UPDATES STOPPED -- use 'reset' to restart)"); 602c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn } 6034ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato pw.println(" AC powered: " + mAcOnline); 6044ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato pw.println(" USB powered: " + mUsbOnline); 60537a37f445cbcd64376af153dd79ea2a123d9405dBrian Muramatsu pw.println(" Wireless powered: " + mWirelessOnline); 6064ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato pw.println(" status: " + mBatteryStatus); 6074ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato pw.println(" health: " + mBatteryHealth); 6084ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato pw.println(" present: " + mBatteryPresent); 6094ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato pw.println(" level: " + mBatteryLevel); 6104ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato pw.println(" scale: " + BATTERY_SCALE); 6114ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato pw.println(" voltage:" + mBatteryVoltage); 6124ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato pw.println(" temperature: " + mBatteryTemperature); 6134ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato pw.println(" technology: " + mBatteryTechnology); 614c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn } else if (args.length == 3 && "set".equals(args[0])) { 615c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn String key = args[1]; 616c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn String value = args[2]; 617c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn try { 618c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn boolean update = true; 619c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn if ("ac".equals(key)) { 620c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn mAcOnline = Integer.parseInt(value) != 0; 621c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn } else if ("usb".equals(key)) { 622c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn mUsbOnline = Integer.parseInt(value) != 0; 623c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn } else if ("wireless".equals(key)) { 624c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn mWirelessOnline = Integer.parseInt(value) != 0; 625c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn } else if ("status".equals(key)) { 626c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn mBatteryStatus = Integer.parseInt(value); 627c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn } else if ("level".equals(key)) { 628c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn mBatteryLevel = Integer.parseInt(value); 629c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn } else if ("invalid".equals(key)) { 630c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn mInvalidCharger = Integer.parseInt(value); 631c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn } else { 632c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn pw.println("Unknown set option: " + key); 633c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn update = false; 6344ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato } 635c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn if (update) { 636c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn mUpdatesStopped = true; 637c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn processValuesLocked(); 638c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn } 639c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn } catch (NumberFormatException ex) { 640c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn pw.println("Bad value: " + value); 6414ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato } 642c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn } else if (args.length == 1 && "reset".equals(args[0])) { 643c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn mUpdatesStopped = false; 644c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn updateLocked(); 645c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn } else { 646c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn pw.println("Dump current battery state, or:"); 647c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn pw.println(" set ac|usb|wireless|status|level|invalid <value>"); 648c428aae6429c3fd5e2037c3793af399d9f6e23bfDianne Hackborn pw.println(" reset"); 6494ca7f1e2811dc889e526de6c3d30bac8501c23d2Joe Onorato } 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 652de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato 653a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private final UEventObserver mPowerSupplyObserver = new UEventObserver() { 654a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown @Override 655a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown public void onUEvent(UEventObserver.UEvent event) { 656a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown synchronized (mLock) { 657a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown updateLocked(); 658a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown } 659a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown } 660a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown }; 661a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown 662a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private final UEventObserver mInvalidChargerObserver = new UEventObserver() { 663a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown @Override 664a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown public void onUEvent(UEventObserver.UEvent event) { 665a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown final int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0; 666a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown synchronized (mLock) { 667a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown if (mInvalidCharger != invalidCharger) { 668a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown mInvalidCharger = invalidCharger; 669a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown updateLocked(); 670a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown } 671a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown } 672a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown } 673a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown }; 674de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato 675a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private final class Led { 676a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private final LightsService.Light mBatteryLight; 677de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato 678a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private final int mBatteryLowARGB; 679a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private final int mBatteryMediumARGB; 680a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private final int mBatteryFullARGB; 681a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private final int mBatteryLedOn; 682a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown private final int mBatteryLedOff; 683de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato 684a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown public Led(Context context, LightsService lights) { 685de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato mBatteryLight = lights.getLight(LightsService.LIGHT_ID_BATTERY); 686de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato 687a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown mBatteryLowARGB = context.getResources().getInteger( 688de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato com.android.internal.R.integer.config_notificationsBatteryLowARGB); 689a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown mBatteryMediumARGB = context.getResources().getInteger( 690de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato com.android.internal.R.integer.config_notificationsBatteryMediumARGB); 691a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown mBatteryFullARGB = context.getResources().getInteger( 692de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato com.android.internal.R.integer.config_notificationsBatteryFullARGB); 693a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown mBatteryLedOn = context.getResources().getInteger( 694de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato com.android.internal.R.integer.config_notificationsBatteryLedOn); 695a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown mBatteryLedOff = context.getResources().getInteger( 696de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato com.android.internal.R.integer.config_notificationsBatteryLedOff); 697de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato } 698de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato 699de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato /** 700de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato * Synchronize on BatteryService. 701de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato */ 702a4d8204e3068b9d8d6908d4cf3440e81967867a3Jeff Brown public void updateLightsLocked() { 703de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato final int level = mBatteryLevel; 704de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato final int status = mBatteryStatus; 705de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato if (level < mLowBatteryWarningLevel) { 706de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato if (status == BatteryManager.BATTERY_STATUS_CHARGING) { 707de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato // Solid red when battery is charging 708de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato mBatteryLight.setColor(mBatteryLowARGB); 709de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato } else { 710de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato // Flash red when battery is low and not charging 711de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato mBatteryLight.setFlashing(mBatteryLowARGB, LightsService.LIGHT_FLASH_TIMED, 712de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato mBatteryLedOn, mBatteryLedOff); 713de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato } 714de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato } else if (status == BatteryManager.BATTERY_STATUS_CHARGING 715de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato || status == BatteryManager.BATTERY_STATUS_FULL) { 716de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) { 717de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato // Solid green when full or charging and nearly full 718de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato mBatteryLight.setColor(mBatteryFullARGB); 719de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato } else { 720de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato // Solid orange when charging and halfway full 721de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato mBatteryLight.setColor(mBatteryMediumARGB); 722de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato } 723de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato } else { 724de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato // No lights if not charging and not low 725de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato mBatteryLight.turnOff(); 726de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato } 727de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato } 728de1b359e88ef1dcafdc0c6a724f660ad0b55fc3aJoe Onorato } 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 730