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);
责任编辑:
android 电量管理机制,电池电量分析---android篇相关推荐
- Android系统移除电池电量监测管理功能
系统优化 - 去除电池电量监测管理功能 去除电池电量监测管理功能,去除电量提示功能. 需要去除电池电量对升级功能的影响,如低电量时无法进行系统升级. 车机平台不需要电池电量监测管理,电池管理模块对界面 ...
- Android系统默认显示电池电量百分比
Android系统默认显示电池电量百分比 整理一下修该需求时候遇到的问题以及进行修改的思路: 需求:Android 11 让系统默认显示电池电量百分比 整理一下修该需求时候遇到的问题以及进行修改的思路 ...
- android 自定义View绘制电池电量(电池内带数字显示)
最新公司需要一个电池内带数字的显示电池电量需求,百度了一下.参考下面这篇文章写的Android自定义View之电池电量显示. 增加了里面电池电量数字显示,还有就是一个屏幕适配.不管屏幕分辨率基本都能适 ...
- Android内存管理机制
好文摘录 原作: https://www.cnblogs.com/nathan909/p/5372981.html 1.基于Linux内存管理 Android系统是基于Linux 2.6内核开发的开源 ...
- Android 内存管理机制
本文主要包括三大部分内容: 内存管理基础:从整个计算机领域简述主要的内存管理技术. Linux的内存管理机制:Android毕竟是基于Linux内核实现的操作系统,因此有必要了解一下Linux的内存管 ...
- Android 系统(203)---Android包管理机制(一)PackageInstaller的初始化
Android包管理机制(一)PackageInstaller的初始化 转自:https://blog.csdn.net/itachi85/article/details/81024903 前言 包管 ...
- Android包管理机制(三)PMS处理APK的安装
本文首发于微信公众号「刘望舒」 关联系列 Android包管理机制系列 前言 在上一篇文章Android包管理机制(二)PackageInstaller安装APK中,我们学习了PackageInsta ...
- com.android.packageinstaller,Android包管理机制(二)PackageInstaller安装APK
前言 在本系列上一篇文章Android包管理机制(一)PackageInstaller的初始化中我们学习了PackageInstaller是如何初始化的,这一篇文章我们接着学习PackageInsta ...
- Android内存管理机制官方详解文档
很早之前写过一篇<Android内存管理机制详解>点击量已7万+,现把Google官方文档整理输出一下,供各位参考. 一.内存管理概览 Android 运行时 (ART) 和 Dalvik ...
最新文章
- OC学习笔记之Foundation框架NSNumber、NSValue和NSDate(转)
- ElasticSearch大数据分布式弹性搜索引擎使用
- Maximum Product Subarray
- pythonasyncio在哪个版本好_什么情况下需要使用 Python 的 asyncio 模块?
- BBE Sound Sonic Sweet(激励混音效果器)v4.2.0 绿色版
- sap中查询字段长度_SAP会计科目编码的层级说明
- 扩展卢卡斯定理(Exlucas)
- ECNU·AntNLP主页船新上线!
- Spark数据分析技术学习笔记(三)——Spark累加器
- 台式电脑桌面没有计算机图标,电脑桌面上“我的电脑”的图标没了怎么办
- C++ Primer 5th - 1.1 编写一个简单的C++程序
- php mysql新闻表模板_新闻列表之创建数据库
- ubuntu+网易云安装
- 笔记本计算机怎么进入安全模式启动,笔记本怎么进入安全模式,详细教您联想笔记本怎么进入安全模式...
- 正则表达式匹配中文及符号、英文及符号数字空格换行符及常用正则表达式
- 微信自动加好友可以使用python实现
- Mac 系统下java端口占用
- Idling along, (or what to do in the idle task)
- 机器学习之泰坦尼克号预测生还案例的分析(逻辑回归)
- 【IntelliJ IDEA 2019.2】java读取发送pc串口数据
热门文章
- 做成功的CIO从反省自己开始
- KStar ----BPM应用框架,K2 的新星
- animate将flash转换html,【An教程】快速入门Animate(原Adobe Flash)
- TeamViewer固定密码远程连接
- notebook 实现3d可视化
- html5 canvas详解 pdf,html5 canvas教程 pdf
- 区块链论文8(ContractGuard分析写作手法)
- Java三(运算符 )
- CentOS7.6如何配置网桥?|CentOS7.6服务器配置网桥
- csv文件 内容转义_保存csv文件时的生僻字处理和格式控制