原标题:电池电量分析---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篇相关推荐

  1. Android系统移除电池电量监测管理功能

    系统优化 - 去除电池电量监测管理功能 去除电池电量监测管理功能,去除电量提示功能. 需要去除电池电量对升级功能的影响,如低电量时无法进行系统升级. 车机平台不需要电池电量监测管理,电池管理模块对界面 ...

  2. Android系统默认显示电池电量百分比

    Android系统默认显示电池电量百分比 整理一下修该需求时候遇到的问题以及进行修改的思路: 需求:Android 11 让系统默认显示电池电量百分比 整理一下修该需求时候遇到的问题以及进行修改的思路 ...

  3. android 自定义View绘制电池电量(电池内带数字显示)

    最新公司需要一个电池内带数字的显示电池电量需求,百度了一下.参考下面这篇文章写的Android自定义View之电池电量显示. 增加了里面电池电量数字显示,还有就是一个屏幕适配.不管屏幕分辨率基本都能适 ...

  4. Android内存管理机制

    好文摘录 原作: https://www.cnblogs.com/nathan909/p/5372981.html 1.基于Linux内存管理 Android系统是基于Linux 2.6内核开发的开源 ...

  5. Android 内存管理机制

    本文主要包括三大部分内容: 内存管理基础:从整个计算机领域简述主要的内存管理技术. Linux的内存管理机制:Android毕竟是基于Linux内核实现的操作系统,因此有必要了解一下Linux的内存管 ...

  6. Android 系统(203)---Android包管理机制(一)PackageInstaller的初始化

    Android包管理机制(一)PackageInstaller的初始化 转自:https://blog.csdn.net/itachi85/article/details/81024903 前言 包管 ...

  7. Android包管理机制(三)PMS处理APK的安装

    本文首发于微信公众号「刘望舒」 关联系列 Android包管理机制系列 前言 在上一篇文章Android包管理机制(二)PackageInstaller安装APK中,我们学习了PackageInsta ...

  8. com.android.packageinstaller,Android包管理机制(二)PackageInstaller安装APK

    前言 在本系列上一篇文章Android包管理机制(一)PackageInstaller的初始化中我们学习了PackageInstaller是如何初始化的,这一篇文章我们接着学习PackageInsta ...

  9. Android内存管理机制官方详解文档

    很早之前写过一篇<Android内存管理机制详解>点击量已7万+,现把Google官方文档整理输出一下,供各位参考. 一.内存管理概览 Android 运行时 (ART) 和 Dalvik ...

最新文章

  1. OC学习笔记之Foundation框架NSNumber、NSValue和NSDate(转)
  2. ElasticSearch大数据分布式弹性搜索引擎使用
  3. Maximum Product Subarray
  4. pythonasyncio在哪个版本好_什么情况下需要使用 Python 的 asyncio 模块?
  5. BBE Sound Sonic Sweet(激励混音效果器)v4.2.0 绿色版
  6. sap中查询字段长度_SAP会计科目编码的层级说明
  7. 扩展卢卡斯定理(Exlucas)
  8. ECNU·AntNLP主页船新上线!
  9. Spark数据分析技术学习笔记(三)——Spark累加器
  10. 台式电脑桌面没有计算机图标,电脑桌面上“我的电脑”的图标没了怎么办
  11. C++ Primer 5th - 1.1 编写一个简单的C++程序
  12. php mysql新闻表模板_新闻列表之创建数据库
  13. ubuntu+网易云安装
  14. 笔记本计算机怎么进入安全模式启动,笔记本怎么进入安全模式,详细教您联想笔记本怎么进入安全模式...
  15. 正则表达式匹配中文及符号、英文及符号数字空格换行符及常用正则表达式
  16. 微信自动加好友可以使用python实现
  17. Mac 系统下java端口占用
  18. Idling along, (or what to do in the idle task)
  19. 机器学习之泰坦尼克号预测生还案例的分析(逻辑回归)
  20. 【IntelliJ IDEA 2019.2】java读取发送pc串口数据

热门文章

  1. 做成功的CIO从反省自己开始
  2. KStar ----BPM应用框架,K2 的新星
  3. animate将flash转换html,【An教程】快速入门Animate(原Adobe Flash)
  4. TeamViewer固定密码远程连接
  5. notebook 实现3d可视化
  6. html5 canvas详解 pdf,html5 canvas教程 pdf
  7. 区块链论文8(ContractGuard分析写作手法)
  8. Java三(运算符 )
  9. CentOS7.6如何配置网桥?|CentOS7.6服务器配置网桥
  10. csv文件 内容转义_保存csv文件时的生僻字处理和格式控制