Android中的BatteryService及相关组件

<script type="text/javascript"> document.body.oncopy = function() { if (window.clipboardData) { setTimeout(function() { var text = clipboardData.getData(&quot;text&quot;); if (text &amp;&amp; text.length &gt; 300) { text = text + &quot;\r\n\n本文来自CSDN博客,转载请标明出处:&quot; + location.href; clipboardData.setData(&quot;text&quot;, text); } }, 100); } } </script><script type="text/javascript"> function StorePage() { d = document; t = d.selection ? (d.selection.type != 'None' ? d.selection.createRange().text : '') : (d.getSelection ? d.getSelection() : ''); void (keyit = window.open('http://www.365key.com/storeit.aspx?t=' + escape(d.title) + '&amp;u=' + escape(d.location.href) + '&amp;c=' + escape(t), 'keyit', 'scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes')); keyit.focus(); }</script>

转载时请注明出处和作者联系方式
文章出处:http://www.limodev.cn/blog


BatteryService作为电池及充电相关的服务,它的实现非常简单:

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

实现了一个UEvent的观察者。uevent是Linux内核用来向用户空间主动上报事件的机制,对于JAVA程序来说,只实现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);
}

更多相关文章

  1. Android的状态栏通知(Notification)
  2. Android 学习之- 单选按钮、复选框、状态开关、时钟控件
  3. android media player 状态机
  4. Android 如何才能捕获系统的恢复出厂设置事件
  5. Android onClick事件三种实现方法
  6. Android 沉浸式状态栏 开源 很好用
  7. android状态栏一体化
  8. Android中Preference的使用以及监听事件分析
  9. Android的四种点击事件

随机推荐

  1. 有关XML入门的文章推荐10篇
  2. 关于App.config的9篇文章推荐
  3. 关于处理指令的10篇文章推荐
  4. 有关XHTML的相关推荐10篇
  5. 关于原理及性能的详细介绍
  6. 总结关于百度新闻注意点
  7. 关于添加链接的详细介绍
  8. 有关WSD的详细介绍
  9. 关于XML开发的详细介绍
  10. OpenSearch的汇总分享