1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > android 电量管理机制 电池电量分析---android篇

android 电量管理机制 电池电量分析---android篇

时间:2023-07-18 15:21:09

相关推荐

android 电量管理机制 电池电量分析---android篇

原标题:电池电量分析---android篇

本文将从底层到上层介绍Android系统中电量显示这一块,电池检测采用的是ADC采样,不是使用市场上封装好的电量计芯片;

1.驱动层

Linux内核中提供power_supply_core.c电池管理核心,我们驱动程序主要完成核心给我们提供的接口:battery.get_property,在这个程序中,我们主要获得电池的电压、是否正常、容量、充放电状态等;通过这些值来改变文件系统中/sys/class/power_supply/目录下的文件值,下面主要介绍以上几个参数的获取方法:

1)电池充放电状态gBatChargeStatus:

当DC插入时,会产生一个中断,在这个中断处理程序中,我们主要完成给全局变量gBatChargeStatus赋值,如果DC插入,则gBatChargeStatus=1,否则为0,同事,在中断处理程序中,调用send_wakeup_key()唤醒触摸屏;

2)电池状态

电池状态主要有:充电、放电、电量满三种状态;当DC没插入时,电池处于放电状态,当DC插入时,如果电池电池芯片没有报电量满切电量达到100%则为充电状态,否则为充电状态

3)电压值

电压值采用ADC模块对电池电压的采样,获得电池的电压值,因为系统在使用过程中可能存在跳变,所以,对电池电压的获得最好采取多次采样取平均值的方法。在通过adc读电压值的时候,可以采取同步读或者异步读,区别是异步读在第二次执行这个程序的时候获取第一次执行的结果,这样做的好处就是效率高点;

4)电量值

电量值是用户实际看的的值,是用户最关心的,也是最重要的值,在处理电量值的时候注意,充电状态下电量值不能降低,放电状态下电量值不能升高,而且电量值不能大弧度跨越,基本是按照1%这样的变化;特别要注意的是在低电量和电量接近100%的时候的处理。

电量值主要是根据测得的电压值获取,在开始写驱动前,得获得两组数据,分别是充电和没充电下没10%对应的电压值,切两组数据需要对应上,不如在电量为50%的时候,如果没接DC测得的电压值可能为3700而接着DC测得的电压值可能为3800,所以每一个百分比最好都能对应上。

获取这些值后,驱动里每隔50ms就会调用一次比较函数,确认以上的几个值是否改变,如果改变了,则调用power_supply_changed()->kobject->uevent()上报uevent事件。同事电池管理核心就会调用接口battery.get_property更新/sys/class/power_supply目录下的值拱上层调用。

2.获取电池状态值

BatteryService作为电池及充电相关的服务,它的实现非常简单:监听UEvent,读取sysfs里中的状态。实现了一个UEvent的观察者,uevent是linux内核用来向用户空间主动上报事件的机制,对于Java程序来说,只实现UEventObserver的虚函数onUEvent,然后注册即可。

private UEventObserver mUEventObserver = newUEventObserver() { @Override public voidonUEvent(UEventObserver.UEvent event) { String strOnline =event.get("POWER_SUPPLY_ONLINE"); //电源连接状态 String strBatteryState =event.get("POWER_SUPPLY_STATUS");

//电池状态,"Discharging","Charging","Notcharging","Full","Unknown" String strBatteryLevel =event.get("POWER_SUPPLY_CAPACITY");//电池容量 ... } } 1).BatteryService通过JNI(com_android_server_BatteryService.cpp)读取数据。BatteryService通过JNI注册的不仅有函数,还有变量。 如下: //##############在BatteryService.java中声明的变量################ private boolean mAcOnline; private boolean mUsbOnline; private int mBatteryStatus; private int mBatteryHealth; private boolean mBatteryPresent; private int mBatteryLevel; private int mBatteryVoltage; private int mBatteryTemperature; private String mBatteryTechnology; 2).在BatteryService.java中声明的变量,在com_android_server_BatteryService.cpp中共用,即在com_android_server_BatteryService.cpp中其实操作的也是BatteryService.java中声明的变量 gFieldIds.mAcOnline = env->GetFieldID(clazz,"mAcOnline", "Z"); gFieldIds.mUsbOnline = env->GetFieldID(clazz,"mUsbOnline", "Z"); gFieldIds.mBatteryStatus = env->GetFieldID(clazz,"mBatteryStatus", "I"); gFieldIds.mBatteryHealth = env->GetFieldID(clazz,"mBatteryHealth", "I"); gFieldIds.mBatteryPresent = env->GetFieldID(clazz,"mBatteryPresent", "Z"); gFieldIds.mBatteryLevel = env->GetFieldID(clazz, "mBatteryLevel","I"); gFieldIds.mBatteryTechnology = env->GetFieldID(clazz,"mBatteryTechnology", "Ljava/lang/String;"); gFieldIds.mBatteryVoltage = env->GetFieldID(clazz,"mBatteryVoltage", "I"); gFieldIds.mBatteryTemperature=env->GetFieldID(clazz, "mBatteryTemperature", "I"); 3).上面这些变量的值,对应是从下面的文件中读取的,一个文件存储一个数值。 #define AC_ONLINE_PATH"/sys/class/power_supply/ac/online" AC电源连接状态

#defineUSB_ONLINE_PATH "/sys/class/power_supply/usb/online"USB电源连接状 #defineBATTERY_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" 电池电压 #defineBATTERY_TEMPERATURE_PATH"/sys/class/power_supply/battery/batt_temp" 电池温度 #defineBATTERY_TECHNOLOGY_PATH "/sys/class/power_supply/battery/technology" 电池技术update然后根据读到的状态更新BatteryService的成员变量,并广播一个Intent来通知其它关注电源状态的组件。

private final void sendIntent() { // Pack up the values and broadcast them to everyone Intent intent = newIntent(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);

........... ActivityManagerNative.broadcastStickyIntent(intent,null); }

3.根据电池状态值改变UI

关注ACTION_BATTERY_CHANGED的地方有好几个:1) KeyguardUpdateMonitor 这里主要是用来更新锁屏界面下的电池状态和低电关机

private void handleBatteryUpdate(intpluggedInStatus, 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 batteryis critically low and we are not powered if (batteryLevel == 0 && pluggedInStatus !=BATTERY_STATUS_CHARGING && pluggedInStatus !=BATTERY_STATUS_UNKNOWN) { ShutdownThread.shutdownAfterDisablingRadio(mContext, false); } } 2 )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(); } } 3 )PowerManagerService 这里主要是做两件事件,先是检查是否在充电时不允许睡眠,并采用相应的行动,其次是触发一个用户行为(会影响下一次睡眠的时间)。 private final class BatteryReceiver extendsBroadcastReceiver { @Override public void onReceive(Context context,Intent intent) { synchronized (mLocks) { boolean wasPowered =mIsPowered; mIsPowered = mBatteryService.isPowered(); if (mIsPowered != wasPowered) { updateWakeLockLocked();. synchronized (mLocks) { booleansavedActivityAllowed = mUserActivityAllowed; mUserActivityAllowed =true; userActivity(SystemClock.uptimeMillis(), false); mUserActivityAllowed =savedActivityAllowed; } } } } } 4 )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; if (mCollector != null) { mCollector.updateBatteryState(scale, level, plugged); } } } 5 )WifiService 根据电源状态来决定是否需要定时唤醒if(action.equals(Intent.ACTION_BATTERY_CHANGED)) { 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; }6 )StatusBarPolicy用来更新状态栏上的充电图标。 if (action.equals(Intent.ACTION_BATTERY_CHANGED)){ updateBattery(intent); }7)发送低电警报首先需要判断是否需要发送低电量信息:Intent.ACTION_BATTERY_LOW

final boolean sendBatteryLow = !plugged && mBatteryStatus !=BatteryManager.BATTERY_STATUS_UNKNOWN

&&mBatteryLevel <= mLowBatteryWarningLevel

&&(oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel);

可以看到发送低电量信息会有两个条件,

1)当前不在充电状态,上次update时处于充电状态,并且电池电量小于等于mLowBatteryWarningLevel(低电量警告值)

2)当前不在充电状态,电池电量小于等于mLowBatteryWarningLevel(低电量警告值),并且上次update时,电量大于mLowBatteryWarningLevel(低电量警告值)

下面代码是具体发送

if(sendBatteryLow) {

mSentLowBatteryBroadcast = true;

statusIntent.setAction(Intent.ACTION_BATTERY_LOW);

mContext.sendBroadcast(statusIntent);

}else if(mSentLowBatteryBroadcast && mLastBatteryLevel >=mLowBatteryCloseWarningLevel) {

mSentLowBatteryBroadcast = false;

statusIntent.setAction(Intent.ACTION_BATTERY_OKAY);

mContext.sendBroadcast(statusIntent);

责任编辑:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。