本文共 6024 字,大约阅读时间需要 20 分钟。
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); }转载地址:http://cpwxi.baihongyu.com/