SystemServer在启动BatteryService时,一次会调用它的构造函数,onStart,onBootPhase方法;解析来我们分析一下这些方法:
1.Constructor方法:
public BatteryService(Context context) {
super(context);
mContext = context;
mHandler = new Handler(true );
mLed = new Led(context, getLocalService(LightsManager.class));
mBatteryStats = BatteryStatsService.getService();
mActivityManagerInternal =
LocalServices.getService(ActivityManagerInternal.class);
mCriticalBatteryLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
mLowBatteryWarningLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryWarningLevel);
mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel +
mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
mShutdownBatteryTemperature = mContext.getResources().getInteger(
com.android.internal.R.integer.config_shutdownBatteryTemperature);
if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
UEventObserver invalidChargerObserver = new UEventObserver() {
@Override
public void onUEvent(UEvent event) {
final int invalidCharger = "1".equals(
event.get("SWITCH_STATE")) ? 1 : 0;
synchronized (mLock) {
if (mInvalidCharger != invalidCharger) {
mInvalidCharger = invalidCharger;
}
}
}
};
invalidChargerObserver.startObserving(
"DEVPATH=/devices/virtual/switch/invalid_charger");
}
}
UEvent机制:UEvent机制时kernel通知用户空间的一种机制,很多地方都用到了UEvent机制,入USB插拔/充电等,其本质是内核发送一个字符串(可通过Socket), 应用层接收解释该字符串,获取相应的信息,如果信息有变化,onUEvent方法触发,做出改变;
使用UEvent机制时,需要一个UEventObserver对象,并重写onUEvent(UEvent e)方法,然后调用startObserving方法进行监听,当一个uevent匹配startObserving方法中指定的字符串时触发onUEvent方法;
2.onStart方法:
public void onStart() {
IBinder b = ServiceManager.getService("batteryproperties");
final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
IBatteryPropertiesRegistrar.Stub.asInterface(b);
try {
batteryPropertiesRegistrar.registerListener(new BatteryListener());
} catch (RemoteException e) {
}
mBinderService = new BinderService();
publishBinderService("battery", mBinderService);
publishLocalService(BatteryManagerInternal.class, new LocalService());
}
首先获取一个"batteryproperties"的Binder,也即BatteryPropertiesRegistrar,这个服务由healthd层进行注册,底层间隔1分钟,会通过这个服务将电量状态信息更新给BatteryService;
然后,实例化内部类BinderService,该类继承自Binder,然后将这个Binder通过PublishBinderService方法发布到系统服务中;
publishLocalService方法中将BatterySevice的内部类LocalService注册到本地服务;LocalService中提供了一些获取电池相关的方法,且仅限于SystemServer进程内使用;
onBootPhase方法:
public void onBootPhase(int phase) {
if (phase == PHASE_ACTIVITY_MANAGER_READY) {
synchronized (mLock) {
ContentObserver obs = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
synchronized (mLock) {
updateBatteryWarningLevelLocked();
}
}
};
final ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
false, obs, UserHandle.USER_ALL);
updateBatteryWarningLevelLocked();
}
}
}
这个方法中设置了ContentObserver观察者,当Settings.Global中低电量触发值改变时,就会触发onChange方法,根据上面分析;
接下来分析updateBatteryWarningLevelLocked方法:
private void updateBatteryWarningLevelLocked() {
final ContentResolver resolver = mContext.getContentResolver();
int defWarnLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryWarningLevel);
mLowBatteryWarningLevel = Settings.Global.getInt(resolver,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, defWarnLevel);
if (mLowBatteryWarningLevel == 0) {
mLowBatteryWarningLevel = defWarnLevel;
}
if (mLowBatteryWarningLevel < mCriticalBatteryLevel) {
mLowBatteryWarningLevel = mCriticalBatteryLevel;
}
mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
processValuesLocked(true);
}
调用更新电池状态信息的核心方法processValuesLocked(): 这个是BatteryService最核心的方法,当healthd从kernel层获取电池信息后,会上报给BatteryService,BatteryService中通过这个方法进行处理从而完成更新; 再BatteryService中,有三个地方调用了processValuesLocked方法 1.启动BatteryService时,在onBootPhase方法中的updateBatteryWainingLock方法中; 2.在healthd层向BatteryService更新电池状态信息的update方法中,这里每分钟调用一次; 3.通过adb shell命令dump时在processValuesFromShellLocked方法中;
由于该方法体量较大,我们将分段分析:
1.获取充电类型:
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;
}
2.更新统计电池状态信息:
try {
mBatteryStats.setBatteryState(mBatteryProps.batteryStatus,
mBatteryProps.batteryHealth,
mPlugType, mBatteryProps.batteryLevel,
mBatteryProps.batteryTemperature,
mBatteryProps.batteryVoltage, mBatteryProps.batteryChargeCounter,
mBatteryProps.batteryFullCharge);
} catch (RemoteException e) {
}
这里将BatteryProperties中更新的电池信息更新到BatteryStatesService中进行统计;
BatteryProperties是由healthd中传入,实现了Parcelable接口,里面存储了healthd从节点文件中读取的电池信息;
3.进行低电量时和高温时的关机:
shutdownIfNoPowerLocked();
shutdownIfOverTempLocked();
在电量为0并且没有充电时,会自动关机,当温度高于68时,也会进行自动关机;
4.充电类型改变时获取放电时长和放电量:
if (mPlugType != mLastPlugType) {
if (mLastPlugType == BATTERY_PLUGGED_NONE) {
if (mDischargeStartTime != 0 && mDischargeStartLevel !=
mBatteryProps.batteryLevel) {
dischargeDuration = SystemClock.elapsedRealtime() -
mDischargeStartTime;
mDischargeStartTime = 0;
}
} else if (mPlugType == BATTERY_PLUGGED_NONE) {
mDischargeStartTime = SystemClock.elapsedRealtime();
mDischargeStartLevel = mBatteryProps.batteryLevel;
}
}
5.更新低电量临界值:
if (!mBatteryLevelLow) {
if (mPlugType == BATTERY_PLUGGED_NONE
&& mBatteryProps.batteryLevel <= mLowBatteryWarningLevel) {
mBatteryLevelLow = true;
}
} else {
if (mPlugType != BATTERY_PLUGGED_NONE) {
mBatteryLevelLow = false;
} else if (mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel) {
mBatteryLevelLow = false;
} else if (force && mBatteryProps.batteryLevel >= mLowBatteryWarningLevel) {
mBatteryLevelLow = false;
}
}
mBatteryLevelLow是一个用于判断当前电量是否小于低电量警告值得boolean值,和低电量模式有关,在PMS中设置低电量模式时,都会通过LocalService获取到这个值;
6.发送充电/放电模式和到达低电量/退出低电量广播:
if (mPlugType != 0 && mLastPlugType == 0) {
final Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_
ONLY_BEFORE_BOOT);
statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
}
else if (mPlugType == 0 && mLastPlugType != 0) {
final Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_
BEFORE_BOOT);
statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
}
if (shouldSendBatteryLowLocked()) {
mSentLowBatteryBroadcast = true;
final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
statusIntent.setFlags(Intent.
FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
} else if (mSentLowBatteryBroadcast &&
mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel) {
mSentLowBatteryBroadcast = false;
final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
statusIntent.setFlags(Intent.
FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
}
7.调用sendIntentLocked方法发送粘性广播:该广播持续性的发送电池电量的变化
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_SEQUENCE, mSequence);
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);
intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_CURRENT,
mBatteryProps.maxChargingCurrent);
intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE,
mBatteryProps.maxChargingVoltage);
intent.putExtra(BatteryManager.EXTRA_CHARGE_COUNTER,
mBatteryProps.batteryChargeCounter);
mHandler.post(new Runnable() {
@Override
public void run() {
ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
}
});
}
8.更新LED灯状态:
mLed.updateLightsLocked();
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, Light.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();
}
}
9.更新电池信息:
mLastBatteryStatus = mBatteryProps.batteryStatus;
mLastBatteryHealth = mBatteryProps.batteryHealth;
mLastBatteryPresent = mBatteryProps.batteryPresent;
mLastBatteryLevel = mBatteryProps.batteryLevel;
mLastPlugType = mPlugType;
mLastBatteryVoltage = mBatteryProps.batteryVoltage;
mLastBatteryTemperature = mBatteryProps.batteryTemperature;
mLastMaxChargingCurrent = mBatteryProps.maxChargingCurrent;
mLastMaxChargingVoltage = mBatteryProps.maxChargingVoltage;
mLastChargeCounter = mBatteryProps.batteryChargeCounter;
mLastBatteryLevelCritical = mBatteryLevelCritical;
mLastInvalidCharger = mInvalidCharger;
至此,BatteryService得启动流程和和核心方法就分析完比了,现在剩余内部类BatteryListener了;
BatteryService.BatteryListener: 在分析batteryService得启动过程时,对onStart方法中得IBatteryPropertiesRegistrar和BatteryListener没有深入得分析说明,现在主要研究它们之间的关系和作用;
回到onStart方法中:
public void onStart() {
IBinder b = ServiceManager.getService("batteryproperties");
final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
IBatteryPropertiesRegistrar.Stub.asInterface(b);
try {
batteryPropertiesRegistrar.registerListener(new BatteryListener());
} catch (RemoteException e) {
}
......
}
首先,在系统服务中获取batteryproperties注册的服务,获取到的对象为Binder,那么这个名为batteryProperties的系统服务,它是在何处注册的呢?
在C++的代码中,找到了batteryProperties注册位置:
\system\core\healthd\BatteryPropertiesRegistrar.cpp
void BatteryPropertiesRegistrar::publish(
const sp<BatteryPropertiesRegistrar>& service) {
defaultServiceManager()->addService(String16("batteryproperties"), service);
}
之后对IBatteryPropertiesRegistrar注册一个监听事件,当监听内容改变时回调对应的方法,监听器如下:
private final class BatteryListener extends IBatteryPropertiesListener.Stub {
@Override public void batteryPropertiesChanged(BatteryProperties props) {
final long identity = Binder.clearCallingIdentity();
try {
BatteryService.this.update(props);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
可以看到,BatteryListener继承于IBatteryPropertiesListener.Stub,因此也是一个Binder对象,当监听内容发生变化时,回调方法batteryPropertiesChanged方法中调用update方法:
private void update(BatteryProperties props) {
synchronized (mLock) {
if (!mUpdatesStopped) {
mBatteryProps = props;
processValuesLocked(false);
} else {
mLastBatteryProps.set(props);
}
}
}
在这个方法中,通过监听器传入到BatteryProperties初始化成员变量mBatteryProps;BatteryProperties中带有电池状态信息,通过该方法最终调用processValuesLocked方法,从而完成电池状态信息的更新;
参考文档: 电池服务管理-详解
|