android 4.4 电池电量管理底层分析(C\C++层) (http://blog.csdn.net/daweibalang717/article/details/41446993)
先贴一张类与类之间的关系图:
android开机过程中会加载系统BatteryService ,说一下电池电量相关的,本文主要讲述关于JAVA 层代码。文件路径:\frameworks\base\services\java\com\android\server\BatteryService.java 下面贴出源码。我把注释加上。个人理解,仅参考。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- package com.android.server;
-
- import android.os.BatteryStats;
- import com.android.internal.app.IBatteryStats;
- import com.android.server.am.BatteryStatsService;
-
- import android.app.ActivityManagerNative;
- import android.content.ContentResolver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.pm.PackageManager;
- import android.os.BatteryManager;
- import android.os.BatteryProperties;
- import android.os.Binder;
- import android.os.FileUtils;
- import android.os.Handler;
- import android.os.IBatteryPropertiesListener;
- import android.os.IBatteryPropertiesRegistrar;
- import android.os.IBinder;
- import android.os.DropBoxManager;
- import android.os.RemoteException;
- import android.os.ServiceManager;
- import android.os.SystemClock;
- import android.os.UEventObserver;
- import android.os.UserHandle;
- import android.provider.Settings;
- import android.util.EventLog;
- import android.util.Slog;
-
- import java.io.File;
- import java.io.FileDescriptor;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.PrintWriter;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public final class BatteryService extends Binder {
- private static final String TAG = BatteryService.class.getSimpleName();
-
- private static final boolean DEBUG = false;
-
- private static final int BATTERY_SCALE = 100;
-
-
-
- private int mCriticalBatteryLevel;
-
- private static final int DUMP_MAX_LENGTH = 24 * 1024;
- private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "--unplugged" };
-
- private static final String DUMPSYS_DATA_PATH = "/data/system/";
-
-
- private static final int BATTERY_PLUGGED_NONE = 0;
-
- private final Context mContext;
- private final IBatteryStats mBatteryStats;
- private final Handler mHandler;
-
- private final Object mLock = new Object();
-
- private BatteryProperties mBatteryProps;
- private boolean mBatteryLevelCritical;
- private int mLastBatteryStatus;
- private int mLastBatteryHealth;
- private boolean mLastBatteryPresent;
- private int mLastBatteryLevel;
- private int mLastBatteryVoltage;
- private int mLastBatteryTemperature;
- private boolean mLastBatteryLevelCritical;
-
- private int mInvalidCharger;
- private int mLastInvalidCharger;
-
- private int mLowBatteryWarningLevel;
- private int mLowBatteryCloseWarningLevel;
- private int mShutdownBatteryTemperature;
-
- private int mPlugType;
- private int mLastPlugType = -1;
-
- private long mDischargeStartTime;
- private int mDischargeStartLevel;
-
- private boolean mUpdatesStopped;
-
- private Led mLed;
-
- private boolean mSentLowBatteryBroadcast = false;
-
- private BatteryListener mBatteryPropertiesListener;
- private IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
-
- public BatteryService(Context context, LightsService lights) {
- mContext = context;
- mHandler = new Handler(true );
- mLed = new Led(context, lights);
- mBatteryStats = BatteryStatsService.getService();
-
-
- mCriticalBatteryLevel = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_criticalBatteryWarningLevel);
-
-
- mLowBatteryWarningLevel = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_lowBatteryWarningLevel);
-
-
- mLowBatteryCloseWarningLevel = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_lowBatteryCloseWarningLevel);
-
-
- mShutdownBatteryTemperature = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_shutdownBatteryTemperature);
-
-
- if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
- mInvalidChargerObserver.startObserving(
- "DEVPATH=/devices/virtual/switch/invalid_charger");
- }
-
- mBatteryPropertiesListener = new BatteryListener();
-
- IBinder b = ServiceManager.getService("batterypropreg");
- mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(b);
-
- try {
-
- mBatteryPropertiesRegistrar.registerListener(mBatteryPropertiesListener);
- } catch (RemoteException e) {
-
- }
- }
-
- void systemReady() {
-
- synchronized (mLock) {
- shutdownIfNoPowerLocked();
- shutdownIfOverTempLocked();
- }
- }
-
-
-
-
- public boolean isPowered(int plugTypeSet) {
- synchronized (mLock) {
- return isPoweredLocked(plugTypeSet);
- }
- }
-
- private boolean isPoweredLocked(int plugTypeSet) {
-
-
-
- if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
- return true;
- }
-
- if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_AC) != 0 && mBatteryProps.chargerAcOnline) {
- return true;
- }
-
- if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_USB) != 0 && mBatteryProps.chargerUsbOnline) {
- return true;
- }
-
- if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0 && mBatteryProps.chargerWirelessOnline) {
- return true;
- }
- return false;
- }
-
-
-
-
-
- public int getPlugType() {
- synchronized (mLock) {
- return mPlugType;
- }
- }
-
-
-
-
-
- public int getBatteryLevel() {
- synchronized (mLock) {
- return mBatteryProps.batteryLevel;
- }
- }
-
-
-
-
-
- public boolean isBatteryLow() {
- synchronized (mLock) {
- return mBatteryProps.batteryPresent && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel;
- }
- }
-
-
-
-
-
- public int getInvalidCharger() {
- synchronized (mLock) {
- return mInvalidCharger;
- }
- }
-
-
- private void shutdownIfNoPowerLocked() {
-
-
- if (mBatteryProps.batteryLevel == 0 && (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING)) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (ActivityManagerNative.isSystemReady()) {
- Intent intent = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN_LOWBATTERY");
- intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
- intent.putExtra("cant_be_cancel_by_button", true);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
- }
- }
- });
- }
- }
-
-
- private void shutdownIfOverTempLocked() {
-
-
-
- if (mBatteryProps.batteryTemperature > mShutdownBatteryTemperature) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (ActivityManagerNative.isSystemReady()) {
- Intent intent = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN_LOWBATTERY");
- intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
- }
- }
- });
- }
- }
-
- private void update(BatteryProperties props) {
- synchronized (mLock) {
- if (!mUpdatesStopped) {
- mBatteryProps = props;
-
- processValuesLocked();
- }
- }
- }
-
- private void processValuesLocked() {
- boolean logOutlier = false;
- long dischargeDuration = 0;
-
- mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);
-
- if (mBatteryProps.chargerAcOnline) {
- mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
- } else if (mBatteryProps.chargerUsbOnline) {
- mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
- } else if (mBatteryProps.chargerWirelessOnline) {
- mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
- } else {
- mPlugType = BATTERY_PLUGGED_NONE;
- }
-
- if (DEBUG) {
- Slog.d(TAG, "Processing new values: "
- + "chargerAcOnline=" + mBatteryProps.chargerAcOnline
- + ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline
- + ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline
- + ", batteryStatus=" + mBatteryProps.batteryStatus
- + ", batteryHealth=" + mBatteryProps.batteryHealth
- + ", batteryPresent=" + mBatteryProps.batteryPresent
- + ", batteryLevel=" + mBatteryProps.batteryLevel
- + ", batteryTechnology=" + mBatteryProps.batteryTechnology
- + ", batteryVoltage=" + mBatteryProps.batteryVoltage
- + ", batteryCurrentNow=" + mBatteryProps.batteryCurrentNow
- + ", batteryChargeCounter=" + mBatteryProps.batteryChargeCounter
- + ", batteryTemperature=" + mBatteryProps.batteryTemperature
- + ", mBatteryLevelCritical=" + mBatteryLevelCritical
- + ", mPlugType=" + mPlugType);
- }
-
-
- try {
-
- mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,
- mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,
- mBatteryProps.batteryVoltage);
- } catch (RemoteException e) {
-
- }
-
- shutdownIfNoPowerLocked();
-
- shutdownIfOverTempLocked();
-
- if (mBatteryProps.batteryStatus != mLastBatteryStatus ||
- mBatteryProps.batteryHealth != mLastBatteryHealth ||
- mBatteryProps.batteryPresent != mLastBatteryPresent ||
- mBatteryProps.batteryLevel != mLastBatteryLevel ||
- mPlugType != mLastPlugType ||
- mBatteryProps.batteryVoltage != mLastBatteryVoltage ||
- mBatteryProps.batteryTemperature != mLastBatteryTemperature ||
- mInvalidCharger != mLastInvalidCharger) {
-
- if (mPlugType != mLastPlugType) {
-
- if (mLastPlugType == BATTERY_PLUGGED_NONE) {
-
-
-
-
- if (mDischargeStartTime != 0 && mDischargeStartLevel != mBatteryProps.batteryLevel) {
- dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
- logOutlier = true;
- EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration,
- mDischargeStartLevel, mBatteryProps.batteryLevel);
-
- mDischargeStartTime = 0;
- }
-
- } else if (mPlugType == BATTERY_PLUGGED_NONE) {
-
- mDischargeStartTime = SystemClock.elapsedRealtime();
- mDischargeStartLevel = mBatteryProps.batteryLevel;
- }
- }
- if (mBatteryProps.batteryStatus != mLastBatteryStatus ||
- mBatteryProps.batteryHealth != mLastBatteryHealth ||
- mBatteryProps.batteryPresent != mLastBatteryPresent ||
- mPlugType != mLastPlugType) {
- EventLog.writeEvent(EventLogTags.BATTERY_STATUS,
- mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0,
- mPlugType, mBatteryProps.batteryTechnology);
- }
- if (mBatteryProps.batteryLevel != mLastBatteryLevel) {
-
-
- EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,
- mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.batteryTemperature);
- }
- if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
- mPlugType == BATTERY_PLUGGED_NONE) {
-
-
- dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
- logOutlier = true;
- }
-
- final boolean plugged = mPlugType != BATTERY_PLUGGED_NONE;
-
- final boolean oldPlugged = mLastPlugType != BATTERY_PLUGGED_NONE;
-
-
-
-
-
-
-
-
- final boolean sendBatteryLow = !plugged
- && mBatteryProps.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
- && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel
- && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel);
-
- sendIntentLocked();
-
-
-
-
- if (mPlugType != 0 && mLastPlugType == 0) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
- statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
- }
- });
- }
- else if (mPlugType == 0 && mLastPlugType != 0) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
- statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
- }
- });
- }
-
- if (sendBatteryLow) {
- mSentLowBatteryBroadcast = true;
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
- statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
- }
- });
- } else if (mSentLowBatteryBroadcast && mLastBatteryLevel >= mLowBatteryCloseWarningLevel) {
- mSentLowBatteryBroadcast = false;
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
- statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
- }
- });
- }
-
-
- mLed.updateLightsLocked();
-
-
- if (logOutlier && dischargeDuration != 0) {
- logOutlierLocked(dischargeDuration);
- }
-
- mLastBatteryStatus = mBatteryProps.batteryStatus;
- mLastBatteryHealth = mBatteryProps.batteryHealth;
- mLastBatteryPresent = mBatteryProps.batteryPresent;
- mLastBatteryLevel = mBatteryProps.batteryLevel;
- mLastPlugType = mPlugType;
- mLastBatteryVoltage = mBatteryProps.batteryVoltage;
- mLastBatteryTemperature = mBatteryProps.batteryTemperature;
- mLastBatteryLevelCritical = mBatteryLevelCritical;
- mLastInvalidCharger = mInvalidCharger;
- }
- }
-
- private void sendIntentLocked() {
-
- final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_REPLACE_PENDING);
-
- int icon = getIconLocked(mBatteryProps.batteryLevel);
-
- intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus);
- intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth);
- intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryProps.batteryPresent);
- intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryProps.batteryLevel);
- intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);
- intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon);
- intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
- intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryProps.batteryVoltage);
- intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryProps.batteryTemperature);
- intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryProps.batteryTechnology);
- intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);
-
- if (DEBUG) {
- Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel +
- ", scale:" + BATTERY_SCALE + ", status:" + mBatteryProps.batteryStatus +
- ", health:" + mBatteryProps.batteryHealth + ", present:" + mBatteryProps.batteryPresent +
- ", voltage: " + mBatteryProps.batteryVoltage +
- ", temperature: " + mBatteryProps.batteryTemperature +
- ", technology: " + mBatteryProps.batteryTechnology +
- ", AC powered:" + mBatteryProps.chargerAcOnline + ", USB powered:" + mBatteryProps.chargerUsbOnline +
- ", Wireless powered:" + mBatteryProps.chargerWirelessOnline +
- ", icon:" + icon + ", invalid charger:" + mInvalidCharger);
- }
-
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);
- }
- });
- }
-
- private void logBatteryStatsLocked() {
- IBinder batteryInfoService = ServiceManager.getService(BatteryStats.SERVICE_NAME);
- if (batteryInfoService == null) return;
-
- DropBoxManager db = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
- if (db == null || !db.isTagEnabled("BATTERY_DISCHARGE_INFO")) return;
-
- File dumpFile = null;
- FileOutputStream dumpStream = null;
- try {
-
- dumpFile = new File(DUMPSYS_DATA_PATH + BatteryStats.SERVICE_NAME + ".dump");
- dumpStream = new FileOutputStream(dumpFile);
- batteryInfoService.dump(dumpStream.getFD(), DUMPSYS_ARGS);
- FileUtils.sync(dumpStream);
-
-
- db.addFile("BATTERY_DISCHARGE_INFO", dumpFile, DropBoxManager.IS_TEXT);
- } catch (RemoteException e) {
- Slog.e(TAG, "failed to dump battery service", e);
- } catch (IOException e) {
- Slog.e(TAG, "failed to write dumpsys file", e);
- } finally {
-
- if (dumpStream != null) {
- try {
- dumpStream.close();
- } catch (IOException e) {
- Slog.e(TAG, "failed to close dumpsys output stream");
- }
- }
- if (dumpFile != null && !dumpFile.delete()) {
- Slog.e(TAG, "failed to delete temporary dumpsys file: "
- + dumpFile.getAbsolutePath());
- }
- }
- }
-
- private void logOutlierLocked(long duration) {
- ContentResolver cr = mContext.getContentResolver();
- String dischargeThresholdString = Settings.Global.getString(cr,
- Settings.Global.BATTERY_DISCHARGE_THRESHOLD);
- String durationThresholdString = Settings.Global.getString(cr,
- Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD);
-
- if (dischargeThresholdString != null && durationThresholdString != null) {
- try {
- long durationThreshold = Long.parseLong(durationThresholdString);
- int dischargeThreshold = Integer.parseInt(dischargeThresholdString);
- if (duration <= durationThreshold &&
- mDischargeStartLevel - mBatteryProps.batteryLevel >= dischargeThreshold) {
-
- logBatteryStatsLocked();
- }
- if (DEBUG) Slog.v(TAG, "duration threshold: " + durationThreshold +
- " discharge threshold: " + dischargeThreshold);
- if (DEBUG) Slog.v(TAG, "duration: " + duration + " discharge: " +
- (mDischargeStartLevel - mBatteryProps.batteryLevel));
- } catch (NumberFormatException e) {
- Slog.e(TAG, "Invalid DischargeThresholds GService string: " +
- durationThresholdString + " or " + dischargeThresholdString);
- return;
- }
- }
- }
-
- private int getIconLocked(int level) {
- if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) {
- return com.android.internal.R.drawable.stat_sys_battery_charge;
- } else if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) {
- return com.android.internal.R.drawable.stat_sys_battery;
- } else if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING
- || mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_FULL) {
- if (isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)
- && mBatteryProps.batteryLevel >= 100) {
- return com.android.internal.R.drawable.stat_sys_battery_charge;
- } else {
- return com.android.internal.R.drawable.stat_sys_battery;
- }
- } else {
- return com.android.internal.R.drawable.stat_sys_battery_unknown;
- }
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
-
- pw.println("Permission Denial: can't dump Battery service from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
- synchronized (mLock) {
- if (args == null || args.length == 0 || "-a".equals(args[0])) {
- pw.println("Current Battery Service state:");
- if (mUpdatesStopped) {
- pw.println(" (UPDATES STOPPED -- use 'reset' to restart)");
- }
- pw.println(" AC powered: " + mBatteryProps.chargerAcOnline);
- pw.println(" USB powered: " + mBatteryProps.chargerUsbOnline);
- pw.println(" Wireless powered: " + mBatteryProps.chargerWirelessOnline);
- pw.println(" status: " + mBatteryProps.batteryStatus);
- pw.println(" health: " + mBatteryProps.batteryHealth);
- pw.println(" present: " + mBatteryProps.batteryPresent);
- pw.println(" level: " + mBatteryProps.batteryLevel);
- pw.println(" scale: " + BATTERY_SCALE);
- pw.println(" voltage: " + mBatteryProps.batteryVoltage);
-
- if (mBatteryProps.batteryCurrentNow != Integer.MIN_VALUE) {
- pw.println(" current now: " + mBatteryProps.batteryCurrentNow);
- }
-
- if (mBatteryProps.batteryChargeCounter != Integer.MIN_VALUE) {
- pw.println(" charge counter: " + mBatteryProps.batteryChargeCounter);
- }
-
- pw.println(" temperature: " + mBatteryProps.batteryTemperature);
- pw.println(" technology: " + mBatteryProps.batteryTechnology);
- } else if (args.length == 3 && "set".equals(args[0])) {
- String key = args[1];
- String value = args[2];
- try {
- boolean update = true;
- if ("ac".equals(key)) {
- mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0;
- } else if ("usb".equals(key)) {
- mBatteryProps.chargerUsbOnline = Integer.parseInt(value) != 0;
- } else if ("wireless".equals(key)) {
- mBatteryProps.chargerWirelessOnline = Integer.parseInt(value) != 0;
- } else if ("status".equals(key)) {
- mBatteryProps.batteryStatus = Integer.parseInt(value);
- } else if ("level".equals(key)) {
- mBatteryProps.batteryLevel = Integer.parseInt(value);
- } else if ("invalid".equals(key)) {
- mInvalidCharger = Integer.parseInt(value);
- } else {
- pw.println("Unknown set option: " + key);
- update = false;
- }
- if (update) {
- long ident = Binder.clearCallingIdentity();
- try {
- mUpdatesStopped = true;
- processValuesLocked();
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- } catch (NumberFormatException ex) {
- pw.println("Bad value: " + value);
- }
- } else if (args.length == 1 && "reset".equals(args[0])) {
- long ident = Binder.clearCallingIdentity();
- try {
- mUpdatesStopped = false;
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- } else {
- pw.println("Dump current battery state, or:");
- pw.println(" set ac|usb|wireless|status|level|invalid <value>");
- pw.println(" reset");
- }
- }
- }
-
- private final UEventObserver mInvalidChargerObserver = new UEventObserver() {
- @Override
- public void onUEvent(UEventObserver.UEvent event) {
- final int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
- synchronized (mLock) {
- if (mInvalidCharger != invalidCharger) {
- mInvalidCharger = invalidCharger;
- }
- }
- }
- };
-
- private final class Led {
- private final LightsService.Light mBatteryLight;
-
- private final int mBatteryLowARGB;
- private final int mBatteryMediumARGB;
- private final int mBatteryFullARGB;
- private final int mBatteryLedOn;
- private final int mBatteryLedOff;
-
- public Led(Context context, LightsService lights) {
- mBatteryLight = lights.getLight(LightsService.LIGHT_ID_BATTERY);
-
- mBatteryLowARGB = context.getResources().getInteger(
- com.android.internal.R.integer.config_notificationsBatteryLowARGB);
- mBatteryMediumARGB = context.getResources().getInteger(
- com.android.internal.R.integer.config_notificationsBatteryMediumARGB);
- mBatteryFullARGB = context.getResources().getInteger(
- com.android.internal.R.integer.config_notificationsBatteryFullARGB);
- mBatteryLedOn = context.getResources().getInteger(
- com.android.internal.R.integer.config_notificationsBatteryLedOn);
- mBatteryLedOff = context.getResources().getInteger(
- com.android.internal.R.integer.config_notificationsBatteryLedOff);
- }
-
-
-
-
- public void updateLightsLocked() {
- final int level = mBatteryProps.batteryLevel;
- final int status = mBatteryProps.batteryStatus;
- if (level < mLowBatteryWarningLevel) {
- if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
-
- mBatteryLight.setColor(mBatteryLowARGB);
- } else {
-
- mBatteryLight.setFlashing(mBatteryLowARGB, LightsService.LIGHT_FLASH_TIMED,
- mBatteryLedOn, mBatteryLedOff);
- }
- } else if (status == BatteryManager.BATTERY_STATUS_CHARGING
- || status == BatteryManager.BATTERY_STATUS_FULL) {
- if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) {
-
- mBatteryLight.setColor(mBatteryFullARGB);
- } else {
-
- mBatteryLight.setColor(mBatteryMediumARGB);
- }
- } else {
-
- mBatteryLight.turnOff();
- }
- }
- }
-
- private final class BatteryListener extends IBatteryPropertiesListener.Stub {
- public void batteryPropertiesChanged(BatteryProperties props) {
- BatteryService.this.update(props);
- }
- }
- }
总结如下:
此服务构造时会注册监听到系统JNI层。 当电池电量改变的时候会调用update(BatteryProperties props) -----》processValuesLocked() 。 而processValuesLocked() 函数会把电池状态把广播发送出去。其他类再接收广播进行处理
下一个类就是低电量提醒了,文件目录:\frameworks\base\packages\SystemUI\src\com\android\systemui\power\PowerUI.java
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- package com.android.systemui.power;
-
- import android.app.AlertDialog;
- import android.content.BroadcastReceiver;
- import android.content.ContentResolver;
- import android.content.Context;
- import android.content.DialogInterface;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.media.AudioManager;
- import android.media.Ringtone;
- import android.media.RingtoneManager;
- import android.net.Uri;
- import android.os.BatteryManager;
- import android.os.Handler;
- import android.os.PowerManager;
- import android.os.SystemClock;
- import android.os.UserHandle;
- import android.provider.Settings;
- import android.util.Slog;
- import android.view.View;
- import android.view.WindowManager;
- import android.widget.TextView;
-
- import com.android.systemui.R;
- import com.android.systemui.SystemUI;
-
- import java.io.FileDescriptor;
- import java.io.PrintWriter;
- import java.util.Arrays;
-
- public class PowerUI extends SystemUI {
- static final String TAG = "PowerUI";
-
- static final boolean DEBUG = false;
-
- Handler mHandler = new Handler();
-
- int mBatteryLevel = 100;
- int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
- int mPlugType = 0;
- int mInvalidCharger = 0;
-
- int mLowBatteryAlertCloseLevel;
- int[] mLowBatteryReminderLevels = new int[2];
-
- AlertDialog mInvalidChargerDialog;
- AlertDialog mLowBatteryDialog;
- TextView mBatteryLevelTextView;
-
- private long mScreenOffTime = -1;
-
- public void start() {
-
- mLowBatteryAlertCloseLevel = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_lowBatteryCloseWarningLevel);
- mLowBatteryReminderLevels[0] = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_lowBatteryWarningLevel);
- mLowBatteryReminderLevels[1] = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_criticalBatteryWarningLevel);
-
- final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mScreenOffTime = pm.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
-
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(Intent.ACTION_SCREEN_ON);
- mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
- }
-
-
-
-
-
-
-
-
-
-
-
- private int findBatteryLevelBucket(int level) {
- if (level >= mLowBatteryAlertCloseLevel) {
- return 1;
- }
- if (level >= mLowBatteryReminderLevels[0]) {
- return 0;
- }
- final int N = mLowBatteryReminderLevels.length;
- for (int i=N-1; i>=0; i--) {
- if (level <= mLowBatteryReminderLevels[i]) {
- return -1-i;
- }
- }
- throw new RuntimeException("not possible!");
- }
-
- private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
- final int oldBatteryLevel = mBatteryLevel;
- mBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100); /
- final int oldBatteryStatus = mBatteryStatus;
- mBatteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
- BatteryManager.BATTERY_STATUS_UNKNOWN);
- final int oldPlugType = mPlugType;
- mPlugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 1);
- final int oldInvalidCharger = mInvalidCharger;
- mInvalidCharger = intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER, 0);
-
- final boolean plugged = mPlugType != 0;
- final boolean oldPlugged = oldPlugType != 0;
-
- int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
- int bucket = findBatteryLevelBucket(mBatteryLevel);
-
- if (DEBUG) {
- Slog.d(TAG, "buckets ....." + mLowBatteryAlertCloseLevel
- + " .. " + mLowBatteryReminderLevels[0]
- + " .. " + mLowBatteryReminderLevels[1]);
- Slog.d(TAG, "level " + oldBatteryLevel + " --> " + mBatteryLevel);
- Slog.d(TAG, "status " + oldBatteryStatus + " --> " + mBatteryStatus);
- Slog.d(TAG, "plugType " + oldPlugType + " --> " + mPlugType);
- Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);
- Slog.d(TAG, "bucket " + oldBucket + " --> " + bucket);
- Slog.d(TAG, "plugged " + oldPlugged + " --> " + plugged);
- }
-
- if (oldInvalidCharger == 0 && mInvalidCharger != 0) {
- Slog.d(TAG, "showing invalid charger warning");
- showInvalidChargerDialog();
- return;
- } else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {
- dismissInvalidChargerDialog();
- } else if (mInvalidChargerDialog != null) {
-
- return;
- }
-
- if (!plugged
- && (bucket < oldBucket || oldPlugged)
- && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
- && bucket < 0) {
- showLowBatteryWarning(); <span style="color:#FF0000;">
-
-
- if (bucket != oldBucket || oldPlugged) {
- playLowBatterySound();
- }
- } else if (plugged || (bucket > oldBucket && bucket > 0)) {
- dismissLowBatteryWarning();
- } else if (mBatteryLevelTextView != null) {
- showLowBatteryWarning();
- }
- } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
- mScreenOffTime = SystemClock.elapsedRealtime();
- } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
- mScreenOffTime = -1;
- } else {
- Slog.w(TAG, "unknown intent: " + intent);
- }
- }
- };
-
- void dismissLowBatteryWarning() {
- if (mLowBatteryDialog != null) {
- Slog.i(TAG, "closing low battery warning: level=" + mBatteryLevel);
- mLowBatteryDialog.dismiss();
- }
- }
-
- void showLowBatteryWarning() {
- Slog.i(TAG,
- ((mBatteryLevelTextView == null) ? "showing" : "updating")
- + " low battery warning: level=" + mBatteryLevel
- + " [" + findBatteryLevelBucket(mBatteryLevel) + "]");
-
- CharSequence levelText = mContext.getString(
- R.string.battery_low_percent_format, mBatteryLevel);
-
- if (mBatteryLevelTextView != null) {
- mBatteryLevelTextView.setText(levelText);
- } else {
- View v = View.inflate(mContext, R.layout.battery_low, null);
- mBatteryLevelTextView = (TextView)v.findViewById(R.id.level_percent);
-
- mBatteryLevelTextView.setText(levelText);
-
- AlertDialog.Builder b = new AlertDialog.Builder(mContext);
- b.setCancelable(true);
- b.setTitle(R.string.battery_low_title);
- b.setView(v);
- b.setIconAttribute(android.R.attr.alertDialogIcon);
- b.setPositiveButton(android.R.string.ok, null);
-
- final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_NO_HISTORY);
- if (intent.resolveActivity(mContext.getPackageManager()) != null) {
- b.setNegativeButton(R.string.battery_low_why,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
- dismissLowBatteryWarning();
- }
- });
- }
-
- AlertDialog d = b.create();
- d.setOnDismissListener(new DialogInterface.OnDismissListener() {
- @Override
- public void onDismiss(DialogInterface dialog) {
- mLowBatteryDialog = null;
- mBatteryLevelTextView = null;
- }
- });
- d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- d.getWindow().getAttributes().privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
- d.show();
- mLowBatteryDialog = d;
- }
- }
-
- void playLowBatterySound() {
- final ContentResolver cr = mContext.getContentResolver();
-
- final int silenceAfter = Settings.Global.getInt(cr,
- Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0);
- final long offTime = SystemClock.elapsedRealtime() - mScreenOffTime;
- if (silenceAfter > 0
- && mScreenOffTime > 0
- && offTime > silenceAfter) {
- Slog.i(TAG, "screen off too long (" + offTime + "ms, limit " + silenceAfter
- + "ms): not waking up the user with low battery sound");
- return;
- }
-
- if (DEBUG) {
- Slog.d(TAG, "playing low battery sound. pick-a-doop!");
- }
-
- if (Settings.Global.getInt(cr, Settings.Global.POWER_SOUNDS_ENABLED, 1) == 1) {
- final String soundPath = Settings.Global.getString(cr,
- Settings.Global.LOW_BATTERY_SOUND);
- if (soundPath != null) {
- final Uri soundUri = Uri.parse("file://" + soundPath);
- if (soundUri != null) {
- final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
- if (sfx != null) {
- sfx.setStreamType(AudioManager.STREAM_SYSTEM);
- sfx.play();
- }
- }
- }
- }
- }
-
- void dismissInvalidChargerDialog() {
- if (mInvalidChargerDialog != null) {
- mInvalidChargerDialog.dismiss();
- }
- }
-
- void showInvalidChargerDialog() {
- Slog.d(TAG, "showing invalid charger dialog");
-
- dismissLowBatteryWarning();
-
- AlertDialog.Builder b = new AlertDialog.Builder(mContext);
- b.setCancelable(true);
- b.setMessage(R.string.invalid_charger);
- b.setIconAttribute(android.R.attr.alertDialogIcon);
- b.setPositiveButton(android.R.string.ok, null);
-
- AlertDialog d = b.create();
- d.setOnDismissListener(new DialogInterface.OnDismissListener() {
- public void onDismiss(DialogInterface dialog) {
- mInvalidChargerDialog = null;
- mBatteryLevelTextView = null;
- }
- });
-
- d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- d.show();
- mInvalidChargerDialog = d;
- }
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.print("mLowBatteryAlertCloseLevel=");
- pw.println(mLowBatteryAlertCloseLevel);
- pw.print("mLowBatteryReminderLevels=");
- pw.println(Arrays.toString(mLowBatteryReminderLevels));
- pw.print("mInvalidChargerDialog=");
- pw.println(mInvalidChargerDialog == null ? "null" : mInvalidChargerDialog.toString());
- pw.print("mLowBatteryDialog=");
- pw.println(mLowBatteryDialog == null ? "null" : mLowBatteryDialog.toString());
- pw.print("mBatteryLevel=");
- pw.println(Integer.toString(mBatteryLevel));
- pw.print("mBatteryStatus=");
- pw.println(Integer.toString(mBatteryStatus));
- pw.print("mPlugType=");
- pw.println(Integer.toString(mPlugType));
- pw.print("mInvalidCharger=");
- pw.println(Integer.toString(mInvalidCharger));
- pw.print("mScreenOffTime=");
- pw.print(mScreenOffTime);
- if (mScreenOffTime >= 0) {
- pw.print(" (");
- pw.print(SystemClock.elapsedRealtime() - mScreenOffTime);
- pw.print(" ago)");
- }
- pw.println();
- pw.print("soundTimeout=");
- pw.println(Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0));
- pw.print("bucket: ");
- pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
- }
- }
总结一下:这个类就是接收电池电量改变的广播,然后弹窗提醒。
下一个类就是没电关机界面了,文件目录:\frameworks\base\services\java\com\android\server\ShutdownLowBatteryActivity.java
这个Activity的配置文件是这样的(\frameworks\base\core\res\AndroidManifest.xml):
- <activity android:name="com.android.server.ShutdownLowBatteryActivity"
- android:theme="@android:style/Theme.Translucent.NoTitleBar"
- android:configChanges="orientation|keyboardHidden|screenSize"
- android:windowSoftInputMode="stateHidden"
- android:permission="android.permission.SHUTDOWN"
- android:excludeFromRecents="true">
- <intent-filter>
- <action android:name="android.intent.action.ACTION_REQUEST_SHUTDOWN_LOWBATTERY" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
android:theme="@android:style/Theme.Translucent.NoTitleBar"是API小于11的透明主题。这样弹出的dialog会是老版本的主题。(这个Activity是透明的)
对于Theme,因为是4.4,我更倾向于:android:theme="@android:style/Theme.Holo.Panel"
ShutdownLowBatteryActivity.java:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- package com.android.server;
-
- import android.app.Activity;
- import android.app.AlertDialog;
- import android.app.KeyguardManager;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.DialogInterface;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.os.Bundle;
- import android.os.Handler;
- import android.util.Slog;
- import android.view.Window;
- import android.view.WindowManager;
- import android.view.View;
-
-
-
- import com.android.server.power.ShutdownThread;
-
- import android.telephony.TelephonyManager;
- import android.telephony.PhoneStateListener;
- import android.media.MediaPlayer;
- import android.media.MediaPlayer.OnCompletionListener;
- import android.content.ContentResolver;
- import android.provider.Settings;
-
- import java.io.IOException;
-
- public class ShutdownLowBatteryActivity extends Activity {
-
- private static final String TAG = "ShutdownLowBatteryActivity";
- private boolean mConfirm;
- private int mSeconds = 15;
- private AlertDialog mDialog;
- private Handler myHandler = new Handler();
- private Runnable myRunnable = new Runnable() {
- @Override
- public void run() {
- mSeconds --;
- if(mSeconds <1)
- mSeconds=0;
- mDialog.setMessage(getString(com.android.internal.R.string.low_battery_shutdown_after_seconds,mSeconds));
-
- if(mSeconds <= 1){
- myHandler.removeCallbacks(myRunnable);
- Handler h = new Handler();
- h.post(new Runnable() {
- public void run() {
- ShutdownThread.shutdown(ShutdownLowBatteryActivity.this, mConfirm);
- }
- });
- }
- myHandler.postDelayed(myRunnable,1000);
- }
- };
-
- private BroadcastReceiver mReceiver;
- private MediaPlayer mplayer;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mConfirm = getIntent().getBooleanExtra(Intent.EXTRA_KEY_CONFIRM, false);
- Slog.i(TAG, "onCreate(): confirm=" + mConfirm);
-
-
- mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if(Intent.ACTION_BATTERY_OKAY.equals(intent.getAction())|
- Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())){
- ShutDownWakeLock.releaseCpuLock();
- myHandler.removeCallbacks(myRunnable);
- if(mReceiver != null)
- unregisterReceiver(mReceiver);
- finish();
- }
- }
- };
-
- IntentFilter filter=new IntentFilter(Intent.ACTION_POWER_CONNECTED);
- filter.addAction(Intent.ACTION_BATTERY_OKAY);
- registerReceiver(mReceiver, filter);
-
-
-
- PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
- @Override
- public void onCallStateChanged(int state, String ignored) {
- if (state == TelephonyManager.CALL_STATE_RINGING) {
- ShutDownWakeLock.releaseCpuLock();
- myHandler.removeCallbacks(myRunnable);
- finish();
- }
- }
- };
-
- TelephonyManager mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
- mTelephonyManager.listen(mPhoneStateListener,
- PhoneStateListener.LISTEN_CALL_STATE);
- requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
- Window win = getWindow();
- win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
- | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
- win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
- | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
-
- setContentView(new View(this));
- mDialog=new AlertDialog.Builder(this).create();
- mDialog.setTitle(com.android.internal.R.string.low_battery_shutdown_title);
- mDialog.setMessage(getString(com.android.internal.R.string.low_battery_shutdown_after_seconds,mSeconds));
- if(!getIntent().getBooleanExtra("cant_be_cancel_by_button", false)) {
- mDialog.setButton(DialogInterface.BUTTON_NEUTRAL,getText(com.android.internal.R.string.cancel), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- myHandler.removeCallbacks(myRunnable);
- dialog.cancel();
- if(mReceiver != null)
- unregisterReceiver(mReceiver);
- finish();
- }});
- }
- mDialog.setCancelable(false);
-
- mDialog.show();
- if(mConfirm == false){
- myHandler.postDelayed(myRunnable, 1000);
- }
- myHandler.post(new Runnable(){
- public void run(){
- final ContentResolver cr = getContentResolver();
- String path=Settings.System.getString(cr,Settings.System.NOTIFICATION_SOUND);
-
- mplayer=new MediaPlayer();
- try{
- mplayer.reset();
- mplayer.setDataSource("system/media/audio/ui/LowBattery.ogg");
- mplayer.prepare();
- mplayer.start();
- mplayer.setOnCompletionListener(new OnCompletionListener() {
- @Override
- public void onCompletion(MediaPlayer mp) {
- if(null != mplayer){
- mplayer.stop();
- mplayer.release();
- mplayer = null;
- }
- }
- });
- }
- catch(IOException e){
-
- }
- }
- });
- }
- }
总结如下:这个类就是弹窗计时,提醒不连充电器就要关机了。
最后一个相关的类,文件路径:\frameworks\base\packages\SystemUI\src\com\android\systemui\BatteryMeterView.java
这个类是自定义控件,定义在手机状态栏里:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- package com.android.systemui;
-
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.content.res.Resources;
- import android.content.res.TypedArray;
- import android.graphics.Canvas;
- import android.graphics.Paint;
- import android.graphics.Path;
- import android.graphics.PorterDuff;
- import android.graphics.PorterDuffXfermode;
- import android.graphics.Rect;
- import android.graphics.RectF;
- import android.graphics.Typeface;
- import android.os.BatteryManager;
- import android.os.Bundle;
- import android.provider.Settings;
- import android.util.AttributeSet;
- import android.view.View;
-
- public class BatteryMeterView extends View implements DemoMode {
- public static final String TAG = BatteryMeterView.class.getSimpleName();
- public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
-
- public static final boolean ENABLE_PERCENT = true;
- public static final boolean SINGLE_DIGIT_PERCENT = false;
- public static final boolean SHOW_100_PERCENT = false;
-
- public static final int FULL = 96;
- public static final int EMPTY = 4;
-
- public static final float SUBPIXEL = 0.4f;
-
- int[] mColors;
-
- boolean mShowPercent = true;
- Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint;
- int mButtonHeight;
- private float mTextHeight, mWarningTextHeight;
-
- private int mHeight;
- private int mWidth;
- private String mWarningString;
- private final int mChargeColor;
- private final float[] mBoltPoints;
- private final Path mBoltPath = new Path();
-
- private final RectF mFrame = new RectF();
- private final RectF mButtonFrame = new RectF();
- private final RectF mClipFrame = new RectF();
- private final RectF mBoltFrame = new RectF();
-
- private class BatteryTracker extends BroadcastReceiver {
- public static final int UNKNOWN_LEVEL = -1;
-
-
- int level = UNKNOWN_LEVEL;
- String percentStr;
- int plugType;
- boolean plugged;
- int health;
- int status;
- String technology;
- int voltage;
- int temperature;
- boolean testmode = false;
-
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
- if (testmode && ! intent.getBooleanExtra("testmode", false)) return;
-
- level = (int)(100f
- * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
- / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
-
- plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
- plugged = plugType != 0;
- health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH,
- BatteryManager.BATTERY_HEALTH_UNKNOWN);
- status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
- BatteryManager.BATTERY_STATUS_UNKNOWN);
- technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY);
- voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0);
- temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0);
-
- setContentDescription(
- context.getString(R.string.accessibility_battery_level, level));
- postInvalidate();
- } else if (action.equals(ACTION_LEVEL_TEST)) {
- testmode = true;
- post(new Runnable() {
- int curLevel = 0;
- int incr = 1;
- int saveLevel = level;
- int savePlugged = plugType;
- Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
- @Override
- public void run() {
- if (curLevel < 0) {
- testmode = false;
- dummy.putExtra("level", saveLevel);
- dummy.putExtra("plugged", savePlugged);
- dummy.putExtra("testmode", false);
- } else {
- dummy.putExtra("level", curLevel);
- dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC : 0);
- dummy.putExtra("testmode", true);
- }
- getContext().sendBroadcast(dummy);
-
- if (!testmode) return;
-
- curLevel += incr;
- if (curLevel == 100) {
- incr *= -1;
- }
- postDelayed(this, 200);
- }
- });
- }
- }
- }
-
- BatteryTracker mTracker = new BatteryTracker();
-
- @Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- filter.addAction(ACTION_LEVEL_TEST);
- final Intent sticky = getContext().registerReceiver(mTracker, filter);
- if (sticky != null) {
-
- mTracker.onReceive(getContext(), sticky);
- }
- }
-
- @Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- getContext().unregisterReceiver(mTracker);
-