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>&quot;scale&quot; - int, the maximum value for the charge level</p>
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>&quot;level&quot; - int, charge level, from 0 through &quot;scale&quot; inclusive</p>
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>&quot;status&quot; - String, the current charging status.<br />
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>&quot;health&quot; - String, the current battery health.<br />
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>&quot;present&quot; - boolean, true if the battery is present<br />
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>&quot;icon-small&quot; - int, suggested small icon to use for this state</p>
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>&quot;plugged&quot; - 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>&quot;voltage&quot; - int, current battery voltage in millivolts</p>
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>&quot;temperature&quot; - int, current battery temperature in tenths of
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a degree Centigrade</p>
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>&quot;technology&quot; - 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