您的位置:首页 > 移动开发 > Android开发

Android中的BatteryService及相关组件

2011-12-16 20:52 369 查看
BatteryService作为电池及充电相关的服务,它的实现非常简单:

o 监听UEvent,读取sysfs里中的状态。

实现了一个UEvent的观察者。uevent是Linux内核用来向用户空间主动上报事件的机制,对于J***A程序来说,只实现UEventObserver的虚函数onUEvent,然后注册即可。

private UEventObserver mUEventObserver = new UEventObserver() {

@Override

public void onUEvent(UEventObserver.UEvent event) {

update();

}

};

这里只关注power_supply的事件:

mUEventObserver.startObserving("SUBSYSTEM=power_supply");

当有power_supply相关的事件上报时,就会调用update函数。

update先调用native_update从sysfs中读取相关状态(com_android_server_BatteryService.cpp):

Linux驱动提供了下列文件,供应用程序获取电源相关状态:

#define AC_ONLINE_PATH "/sys/class/power_supply/ac/online"

#define USB_ONLINE_PATH "/sys/class/power_supply/usb/online"

#define BATTERY_STATUS_PATH "/sys/class/power_supply/battery/status"

#define BATTERY_HEALTH_PATH "/sys/class/power_supply/battery/health"

#define BATTERY_PRESENT_PATH "/sys/class/power_supply/battery/present"

#define BATTERY_CAPACITY_PATH "/sys/class/power_supply/battery/capacity"

#define BATTERY_VOLTAGE_PATH "/sys/class/power_supply/battery/batt_vol"

#define BATTERY_TEMPERATURE_PATH "/sys/class/power_supply/battery/batt_temp"

#define BATTERY_TECHNOLOGY_PATH "/sys/class/power_supply/battery/technology"

在<DA9034驱动程序阅读笔记(6)>一文中,我已经提到drivers/power/micco_power.c里注册了充电器(ac)、 usb和电池(battery)三个power_supply。各个power_supply提供的属性和上述文件是对应的,从这些文件中可以读到充电器 (ac)、usb和电池(battery)三个power_supply的相应状态。

update然后根据读到的状态更新BatteryService的成员变量,并广播一个Intent来通知其它关注电源状态的组件。

private final void sendIntent() {

// Pack up the values and broadcast them to everyone

Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);

intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);

try {

mBatteryStats.setOnBattery(mPlugType == BATTERY_PLUGGED_NONE, mBatteryLevel);

} catch (RemoteException e) {

// Should never happen.

}



int icon = getIcon(mBatteryLevel);



intent.putExtra("status", mBatteryStatus);

intent.putExtra("health", mBatteryHealth);

intent.putExtra("present", mBatteryPresent);

intent.putExtra("level", mBatteryLevel);

intent.putExtra("scale", BATTERY_SCALE);

intent.putExtra("icon-small", icon);

intent.putExtra("plugged", mPlugType);

intent.putExtra("voltage", mBatteryVoltage);

intent.putExtra("temperature", mBatteryTemperature);

intent.putExtra("technology", mBatteryTechnology);



ActivityManagerNative.broadcastStickyIntent(intent, null);

}

关注ACTION_BATTERY_CHANGED的地方有好几个:

o KeyguardUpdateMonitor 这里主要是用来更新锁屏界面下的电池状态。还有低电警告和关机也是在这里做的。

private void handleBatteryUpdate(int pluggedInStatus, int batteryLevel) {

if (DEBUG) Log.d(TAG, "handleBatteryUpdate");

final boolean pluggedIn = isPluggedIn(pluggedInStatus);



if (isBatteryUpdateInteresting(pluggedIn, batteryLevel)) {

mBatteryLevel = batteryLevel;

mDevicePluggedIn = pluggedIn;

for (int i = 0; i < mInfoCallbacks.size(); i++) {

mInfoCallbacks.get(i).onRefreshBatteryInfo(

shouldShowBatteryInfo(), pluggedIn, batteryLevel);

}

}



// shut down gracefully if our battery is critically low and we are not powered

if (batteryLevel == 0 &&

pluggedInStatus != BATTERY_STATUS_CHARGING &&

pluggedInStatus != BATTERY_STATUS_UNKNOWN) {



ShutdownThread.shutdownAfterDisablingRadio(mContext, false);



}

}

o NotificationManagerService 用来更新充电状态(LED)

if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {

boolean batteryCharging = (intent.getIntExtra("plugged", 0) != 0);

int level = intent.getIntExtra("level", -1);

boolean batteryLow = (level >= 0 && level <= Power.LOW_BATTERY_THRESHOLD);

int status = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);

boolean batteryFull = (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90);



if (batteryCharging != mBatteryCharging ||

batteryLow != mBatteryLow ||

batteryFull != mBatteryFull) {

mBatteryCharging = batteryCharging;

mBatteryLow = batteryLow;

mBatteryFull = batteryFull;

updateLights();

}

}

o PowerManagerService 这里主要是做两件事件,先是检查是否在充电时不允许睡眠,并采用相应的行动,其次是触发一个用户行为(会影响下一次睡眠的时间)。

private final class BatteryReceiver extends BroadcastReceiver {

@Override

public void onReceive(Context context, Intent intent) {

synchronized (mLocks) {

boolean wasPowered = mIsPowered;

mIsPowered = mBatteryService.isPowered();



if (mIsPowered != wasPowered) {

// update mStayOnWhilePluggedIn wake lock

updateWakeLockLocked();



// treat plugging and unplugging the devices as a user activity.

// users find it disconcerting when they unplug the device

// and it shuts off right away.

// temporarily set mUserActivityAllowed to true so this will work

// even when the keyguard is on.

synchronized (mLocks) {

boolean savedActivityAllowed = mUserActivityAllowed;

mUserActivityAllowed = true;

userActivity(SystemClock.uptimeMillis(), false);

mUserActivityAllowed = savedActivityAllowed;

}

}

}

}

}

o LocationManagerService 这里似乎没有什么用处,我没找到mCollector赋值的地方。

if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {

log("PowerStateBroadcastReceiver: Battery changed");

synchronized (mLocationListeners) {

int scale = intent.getIntExtra(BATTERY_EXTRA_SCALE, 100);

int level = intent.getIntExtra(BATTERY_EXTRA_LEVEL, 0);

boolean plugged = intent.getIntExtra(BATTERY_EXTRA_PLUGGED, 0) != 0;



// Notify collector battery state

if (mCollector != null) {

mCollector.updateBatteryState(scale, level, plugged);

}

}

}

o WifiService 根据电源状态来决定是否需要定时唤醒(没搞得太明白,看Wifi服务时再研究)。

if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {

/*

* Set a timer to put Wi-Fi to sleep, but only if the screen is off

* AND we are transitioning from a state in which the device was supposed

* to stay awake to a state in which it is not supposed to stay awake.

* If "stay awake" state is not changing, we do nothing, to avoid resetting

* the already-set timer.

*/

int pluggedType = intent.getIntExtra("plugged", 0);

if (mScreenOff && shouldWifiStayAwake(stayAwakeConditions, mPluggedType) &&

!shouldWifiStayAwake(stayAwakeConditions, pluggedType)) {

long triggerTime = System.currentTimeMillis() + idleMillis;

mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);

mPluggedType = pluggedType;

return;

}

mPluggedType = pluggedType;

}

o StatusBarPolicy用来更新状态栏上的充电图标。

if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {

updateBattery(intent);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: