这篇文章主要为大家详细介绍了安卓5.1健康d的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
健康d主要是读取电池节点的信息,传给电池服务。或者在关机充电等使用。注意健康d中使用的是核心的日志。
下面先从主要的函数分析
int main(int argc,char **argv) {
内部通道
内部ret
klog _ set _ LEVEL(KLOG _ LEVEL);
healthd _ mode _ ops=android _ ops
如果(!strcmp(basename(argv[0],' charger '){//解析输入参数如果是充电器的使用充电器_ops,这里就不做介绍
healthd _ mode _ ops=charger _ ops
}否则{
while ((ch=getopt(argc,argv,' cr '))!=-1) {//分析输入命令,各个命令对应不同的充电器_操作
开关(通道){
案例“c”:
healthd _ mode _ ops=charger _ ops
打破;
案例“r”:
healthd _ mode _ ops=恢复_ ops
打破;
案子吗?
默认值:
日志_错误(LOG_TAG,'无法识别的健康d选项:%c\n ',
optopt);
出口(1);
}
}
}
ret=healthd _ init();//healthd做初始化
if (ret) {
KLOG _错误('初始化失败,正在退出\ n’);
出口(2);
}
healthd _ main loop();//主函数
KLOG _错误('主循环终止,正在退出\ n’);
返回3;
}
如果是正常开机,不走关机充电等,healthd _ mode _ ops=android _ ops而这里面具体的函数在后面进行详细的介绍。
静态结构healthd_mode_ops android_ops={。init=healthd_mode_android_init。preparetowait=healthd _ mode _ Android _ preparetowait。心跳=healthd_mode_nop_heartbeat。电池_更新=健康d _模式_安卓_电池_更新,
};
下面分析下healthd_init函数,heathd使用了epoll进行超正析象管(图片Orthicon)复用。
静态int healthd_init() {
epollfd=EPOLL _ create(MAX _ EPOLL _ EVENTS);
if (epollfd==-1) {
日志_错误(日志_标签,
epoll_create失败;错误号=%d\n ',
errno);
return-1;
}
healthd _ board _ init(healthd _ config);
healthd _ mode _ ops-init(healthd _ config);
唤醒alarm _ init();
u event _ init()。
gBatteryMonitor=新电池监视器();
gBatteryMonitor-init(healthd _ config);
返回0;
}
这里的healthd_mode_ops-init的函数是android_ops的健康d _模式_安卓_初始化函数,这里主要是将粘合剂通信的软驱也加入epoll,而不像普通粘合剂进程最后使用IPCThreadState:self()-joinThreadPool。这样所有的软驱全在epoll管理,只用了一个线程
int healthd _ mode _ Android _ preparetowait(void){
IPCThreadState:self()-flush commands();
return-1;
}
静态void binder _ event(uint 32 _ t/* epevents */){
IPCThreadState:self()-handlePolledCommands();
}
void healthd _ mode _ Android _ init(struct healthd _ config */* config */){
ProcessState:self()-setThreadPoolMaxThreadCount(0);
IPCThreadState:self()-disableBackgroundScheduling(true);
IPCThreadState:self()-设置轮询(gBinderFd);
if (gBinderFd=0) {
if(healthd _ register _ event(gBinderFd,binder_event))
日志_错误(日志_标签,
注册活页夹事件失败\ n’);
}
gBatteryPropertiesRegistrar=new BatteryPropertiesRegistrar();
gBatteryPropertiesRegistrar-publish();
}
gbatterypropertysregistrar-发布将'电池属性'这个服务加入到服务经理中
void BatteryPropertiesRegistrar:publish(){
defaultServiceManager()-addService(字符串16('电池属性'),this);
}
接下来再来看下唤醒警报_初始化
静态void wakealarm_init(void) {
wake ALARM _ FD=timer FD _ create(CLOCK _ boot time _ ALARM,TFD _ non block);
if (wakealarm_fd==-1) {
日志_错误(LOG_TAG,' wakealarm_init: timerfd_create失败\ n’);
返回;
}
if(healthd _ register _ event(唤醒报警_ FD,唤醒报警_事件))
日志_错误(日志_标签,
注册唤醒警报事件失败\ n’);
唤醒报警设置间隔(healthd _ config。periodic _ feathers _ interval _ fast);
}
唤醒警报_初始化设置警报唤醒的区间,再来看下时间处理函数
静态无效唤醒警报_事件(uint32_t /*epevents*/) {
未签名的长时间唤醒;
if (read(wakealarm_fd,wakeups,sizeof(wakeups))==-1) {//出错结束
日志_错误(LOG_TAG,'唤醒警报_事件:读取唤醒警报软驱失败\ n’);
返回;
}
日志_错误(日志_标记,'唤醒报警_事件\ n’);
periodic _ Java ships();
}
静态空周期_杂务(){
healthd _ battery _ update();
}
void healthd _ battery _ update(void){
//充电时快速唤醒间隔(注意过热);
//使用电池时唤醒时间间隔缓慢(注意电池电量耗尽)。
日志_错误(LOG_TAG,' healthd _ battery _ update enter \ n ');
int new _ wake _ interval=gBatteryMonitor-update()?//调用主要的更新函数,根据返回值,如果当前在充电返回真实的
healthd _ config。periodic _ whaterials _ interval _ fast://时间设置一分钟
healthd _ config。周期_羽毛_间隔_缓慢;
日志_错误(LOG_TAG,' healthd _ battery _ update after \ n ');
if (new_wake_interval!=唤醒警报_唤醒_间隔)
唤醒警报设置间隔(新_唤醒_间隔);
//在清醒期间快速轮询。如果唤醒警报设置为快速
//速率然后只使用报警;如果唤醒警报设置为慢速,则
//唤醒时以快速速率轮询,并在以下情况下让闹钟以慢速唤醒
//睡着了。
if(healthd _ config。periodic _ whaterials _ interval _ fast==-1)
awake _ poll _ interval=-1;
其他
唤醒_轮询_间隔=
新唤醒间隔==健康配置。periodic _ feathers _ interval _ fast?//当前时间是一分钟,epoll为永远阻塞,否则为一分钟
-1:healthd _ config。periodic _ feathers _ interval _ fast * 1000;
}
接下来再来看看uEvent的,
静态void uevent_init(void) {
UE vent _ FD=UE vent _ open _ socket(64 * 1024,true);
if (uevent_fd 0) {
日志_错误(LOG_TAG,' uevent_init: uevent_open_socket失败\ n’);
返回;
}
fcntl(uevent_fd,F_SETFL,O _ non block);
if(healthd _ register _ event(u event _ FD,uevent_event))
日志_错误(日志_标签,
注册uevent事件失败\ n’);
}
看看uevent_event的处理函数,获取uevent后主要判断是否是电源系统的,如果是调用健康d _电池_更新函数
静态void u event _ event(uint 32 _ t/* epevents */){
char MSG[u event _ MSG _ l EN 2];
char * cp
int n;
n=u event _ kernel _多播_ recv(u event _ FD,msg,u event _ MSG _ LEN);
如果(n=0)
返回;
if(n=u event _ MSG _ LEN)/* overflow-discard */
返回;
msg[n]=' \ 0 ';
msg[n 1]=' \ 0 ';
cp=消息
KLOG错误(日志标记,'事件事件\ n’);
while (*cp) {
如果(!strcmp(cp,' SUBSYSTEM=' POWER _ SUPPLY _ SUBSYSTEM)){//是这个子系统的调用健康d _电池_更新函数
healthd _ battery _ update();
打破;
}
/*前进到下一个\0之后*/
while (*cp)
;
}
}
下面分析下健康d _主循环这个主函数,主函数主要是epoll函数监听3个fd,有事件就处理。
静态void healthd_mainloop(void) {
while (1) {
struct epoll _ event events[event CT];
事件;
int time out=awake _ poll _ interval;
int模式_超时
mode _ time out=healthd _ mode _ ops-preparetowait();
如果(超时0 ||(模式超时0模式超时))
超时=模式_超时;
nevents=epoll_wait(epollfd,events,eventct,time out);//epoll_wait等待各个软驱的事件,超时为超时时间
日志_错误(LOG_TAG,'陈康healthd _ main loop epoll _ wait \ n’);
if (nevents==-1) {
if (errno==EINTR)
继续;
日志_错误(LOG_TAG,' healthd_mainloop: epoll_wait失败\ n’);
打破;
}
for(int n=0;neventsn) {
if (events[n].data.ptr)//遍历各个软驱的事件上来,每个处理函数处理
(*(void(*)(int))事件[n]。数据。ptr)(事件[n]).事件);
}
如果(!nevents)//当什么事件没有的时候,是因为epoll超时设置走下来的,这时候也要更新下
periodic _ Java ships();
healthd _ mode _ ops-心跳();
}
返回;
}
初始化函数主要将healthd_config对象传入,并且将里面的成员的一些地址信息去初始化保存起来。主要是保存一些地址信息,以及充电方式。
void电池监控器:init(struct healthd _ config * HC){
字符串8路径;
char pval[PROPERTY _ VALUE _ MAX];
mHealthdConfig=hc//将外面传进来的heathdconfig的指针赋给成员变量
DIR * DIR=opendir(POWER _ SUPPLY _ SYSFS _ PATH);//打开地址/sys/class/power _ support
if (dir==NULL) {
日志_错误(日志_标记,'无法打开%s\n ',电源_系统_路径);
}否则{
结构目录*条目;
while ((entry=readdir(dir))) {
const char * name=entry-d _ name;
如果(!strcmp(名称,'.') || !strcmp(名称,'.'))
继续;
char buf[20];
//在每个子目录中查找"类型"文件
路径。clear();
path.appendFormat('%s/%s/type ',POWER_SUPPLY_SYSFS_PATH,name);
开关(readPowerSupplyType(path)) {//读取各个目录下类型的值,比如/sys/class/电源/电池下类型的值为电池,在readPowerSupplyType读取并且转化为安卓_电源_类型_电池
案例安卓_电源_类型_交流:
if(mHealthdConfig-acchargeheathpath。isempty()){
路径。clear();
路径。附加格式(' % s/% s/health ',电源_系统_路径,
姓名);
if (access(path,R_OK)==0)
mHealthdConfig-acChargeHeathPath=path;//配置路径
}
路径。clear();
路径。追加格式(' % s/% s/online ',电源_系统_路径,名称);
if (access(path.string(),R_OK)==0)
麦克哈尔格名。add(字符串8(名称));//chargername就是当前目录名字:交流
打破;
案例ANDROID _ POWER _ SUPPLY _ TYPE _ USB://USB类似交流电
if(mHealthdConfig-usbchargeheathpath。isempty()){
路径。clear();
路径。附加格式(' % s/% s/health ',电源_系统_路径,
姓名);
if (access(path,R_OK)==0)
mHealthdConfig-usbChargeHeathPath=path;
}
路径。clear();
路径。追加格式(' % s/% s/online ',电源_系统_路径,名称);
if (access(path.string(),R_OK)==0)
麦克哈尔格名。add(字符串8(名称));
打破;
案例ANDROID _ POWER _ support _ TYPE _ WIRELESS://类似
路径。clear();
路径。追加格式(' % s/% s/online ',电源_系统_路径,名称);
if (access(path.string(),R_OK)==0)
麦克哈尔格名。add(字符串8(名称));
打破;
机箱安卓_电源_类型_电池://电池
mBatteryDevicePresent=true
if(mHealthdConfig-batterystatuspath。isempty()){
路径。clear();
路径。附加格式(' % s/% s/status ',电源_系统_路径,
姓名);
if (access(path,R_OK)==0)
mHealthdConfig-batteryStatusPath=path;
}
if(mHealthdConfig-batteryhealthpath。isempty()){
路径。clear();
路径。附加格式(' % s/% s/health ',电源_系统_路径,
姓名);
if (access(path,R_OK)==0)
mHealthdConfig-batteryHealthPath=path;
}
if(mHealthdConfig-battery present path。isempty()){
路径。clear();
路径。附加格式(' % s/% s/present ',电源_系统_路径,
姓名);
if (access(path,R_OK)==0)
mHealthdConfig-batteryPresentPath=path;
}
if(mHealthdConfig-batterycapactypath。isempty()){
路径。clear();
路径。附加格式(' % s/% s/capacity ',电源_系统_路径,
姓名);
if (access(path,R_OK)==0)
mHealthdConfig-batterycapactypath=path;
}
if(mHealthdConfig-batteryvoltagepath。isempty()){
路径。clear();
路径。附加格式(' % s/% s/voltage _ now ',
电源_电源_系统文件系统_路径,名称);
if (access(path,R_OK)==0) {
mHealthdConfig-batteryVoltagePath=path;
}否则{
路径。clear();
路径。附加格式(' % s/% s/batt _ vol ',
电源_电源_系统文件系统_路径,名称);
if (access(path,R_OK)==0)
mHealthdConfig-batteryVoltagePath=path;
}
}
if(mHealthdConfig-batterycurrentnowpath。isempty()){
路径。clear();
路径。附加格式(' % s/% s/current _ now ',
电源_电源_系统文件系统_路径,名称);
if (access(path,R_OK)==0)
mHealthdConfig-batteryCurrentNowPath=path;
}
if(mHealthdConfig-batterycurrentavpath。isempty()){
路径。clear();
路径。附加格式(' % s/% s/current _ avg ',
电源_电源_系统文件系统_路径,名称);
if (access(path,R_OK)==0)
mHealthdConfig-batterycurrentavpath=path;
}
if(mHealthdConfig-batterychargecounterpath。isempty()){
路径。clear();
路径。附加格式(' % s/% s/charge _ counter ',
电源_电源_系统文件系统_路径,名称);
if (access(path,R_OK)==0)
mHealthdConfig-batteryChargeCounterPath=path;
}
if(mHealthdConfig-电池温度路径。isempty()){
路径。clear();
path.appendFormat('%s/%s/temp ',POWER_SUPPLY_SYSFS_PATH,
姓名);
if (access(path,R_OK)==0) {
mHealthdConfig-电池温度path=path
}否则{
路径。clear();
路径。附加格式(' % s/% s/batt _ temp ',
电源_电源_系统文件系统_路径,名称);
if (access(path,R_OK)==0)
mHealthdConfig-电池温度path=path
}
}
if(mHealthdConfig-batterytechnologypath。isempty()){
路径。clear();
路径。附加格式(' % s/% s/technology ',
电源_电源_系统文件系统_路径,名称);
if (access(path,R_OK)==0)
mHealthdConfig-batteryTechnologyPath=path;
}
打破;
案例ANDROID _ POWER _ support _ TYPE _ UNKNOWN:
打破;
}
}
closedir(dir);
}
如果(!mChargerNames.size())
日志_错误(LOG_TAG,'没有找到充电器电源\ n’);
如果(!mBatteryDevicePresent) {//主要由电池该成员变量就为真实的
日志_警告(LOG_TAG,'未找到电池设备\ n’);
HC-periodic _ feathers _ interval _ fast=-1;
HC-periodic _ feathers _ interval _ slow=-1;
}否则{
if(mHealthdConfig-batterystatuspath。isempty())
日志_警告(LOG_TAG,'未找到电池状态路径\ n’);。//这里都是一些警告
}
if(property _ get(' ro。靴子。' fake _ battery ',pval,NULL) 0
strtol(pval,NULL,10)!=0) {
mbatteryfixedpacity=FAKE _ BATTERY _ CAPACITY;
mBatteryFixedTemperature=FAKE _ BATTERY _ TEMPERATURE;
}
}
下面就是更新函数,将数据封装在电池属性中,并且通过健康模式操作电池更新把电池属性发给上层。
布尔电池监控器:更新(无效){
布尔罗吉斯
props.chargerAcOnline=false
props.chargerUsbOnline=false
道具。chargerwirelessonline=false
道具。电池状态=电池状态_未知;
道具。电池健康=电池健康未知;
//都是从之前配置的mHealthd中取地址,读取节点信息,保存到小道具成员变量中
如果(!mHealthdConfig-battery present path。isempty())
道具。电池存在=getBooleanField(mHealthdConfig-电池存在路径);
其他
道具。电池存在=mBatteryDevicePresent
道具。电池电量=mbatteryfixedpacity?
mBatteryFixedCapacity:
getint字段(mHealthdConfig-batterycapactypath);
道具。电池电压=getint字段(mHealthdConfig-电池电压路径)/1000;
道具。电池温度=mBatteryFixedTemperature?
mBatteryFixedTemperature:
getint字段(mHealthdConfig-电池温度路径);
const int SIZE=128
char buf[SIZE];
String8 btech
if(从文件读取(mHealthdConfig-batteryStatusPath,buf,SIZE) 0)
道具。电池状态=get battery status(buf);
if(从文件读取(mHealthdConfig-电池健康路径,buf,SIZE) 0)
道具。电池健康=get battery health(buf);
if(从文件读取(mHealthdConfig-batteryTechnologyPath,buf,SIZE) 0)
道具。电池技术=串8(buf);
if(从文件读取(mHealthdConfig-acChargeHeathPath,buf,SIZE) 0)
道具。acchargeheath=string 8(buf);
if(从文件读取(mHealthdConfig-usbChargeHeathPath,buf,SIZE) 0)
道具。usbchargeheath=string 8(buf);
无符号int I;
for(I=0;我叫麦克哈尔格奈斯。size();i ) {//遍历之前保存的各个充电方式
字符串8路径;
路径。附加格式(' % s/% s/online ',电源_系统_路径,
mChargerNames[i].string());//路径就是每个目录下的在线的字段,比如/sys/class/电源/usb下的在线的
if (readFromFile(path,buf,SIZE) 0) {
if (buf[0]!='0') {//读取在线的里面的内容,如果当前在通用串行总线线上充电,那么通用串行总线下在线的里面的内容为一
路径。clear();
path.appendFormat('%s/%s/type ',POWER_SUPPLY_SYSFS_PATH,
mChargerNames[i].string());//这里看看是哪个类型的
开关(readPowerSupplyType(path)) {
案例安卓_电源_类型_交流:
props.chargerAcOnline=true
打破;
案例ANDROID _ POWER _ SUPPLY _ TYPE _ USB://将其值赋成真实的
props.chargerUsbOnline=true
打破;
案例安卓_电源_类型_无线:
道具。chargerwirelessonline=true
打破;
默认值:
日志_警告(日志标记,' %s:未知的电源类型\n ',
mChargerNames[i].string());
}
}
}
}
logthis=!healthd_board_battery_update(道具);
if (logthis) {
char dmes gline[256];
if (props.batteryPresent) {
snprintf(dmesgline),sizeof(dmesgline),
电池' l=%d v=%d t=%s%d,%d h=%d st=%d ',
道具。电池电平,道具。电池电压,
props.batteryTemperature 0?'-' : '',
abs(道具电池温度/10),
ABS(道具。电池温度% 10),props.batteryHealth,
道具。电池状态);
如果(!mHealthdConfig-batterycurrentnowpath。isempty()){
int c=getint字段(mHealthdConfig-batteryCurrentNowPath);
char b[20];
snprintf(b,sizeof(b),' c=%d ',c/1000);
strl cat(dmesglineb,sizeof(dmesglinea));
}
}否则{
snprintf(dmesgline),sizeof(dmesgline),
电池无');
}
日志_警告(日志标记,' %s更改=%s%s%s\n ',dmesgline,
props.chargerAcOnline?一个":",
props.chargerUsbOnline?u ':',
props.chargerWirelessOnline?w ':);
}
healthd _ mode _ ops-battery _ update(props);//将数据传到上层的电池服务
回归道具。充电器a线|道具。充电器副线|//返回当前是否属于充电
道具。充电器无线在线;
}
接下来看看健康模式操作电池更新是怎么把数据传到上层的
void healthd _ mode _ Android _ battery _ update(
struct Android:电池属性*道具){
if (gBatteryPropertiesRegistrar!=空)
gBatteryPropertiesRegistrar-通知侦听器(* props);
返回;
}
上层会通过粘合剂通信,注册一个回调到电池属性注册器
void BatteryPropertiesRegistrar:register listener(const spIBatteryPropertiesListener listener){
{
if (listener==NULL)
返回;
互斥* Autolock _ l(mregistrionlock);
//检查这是否是重复的
for(size _ t I=0;我是听众。size();i ) {
if(m listeners[I]-as binder()==listener-as binder()){
返回;
}
}
m听众。添加(监听器);
listener-as binder()-linkToDeath(this);
}
healthd _ battery _ update();
}
而更新函数就是调用了通知监听器遍历各个听众传到上层电池服务
void电池属性注册:notify listeners(struct电池属性属性){
互斥* Autolock _ l(mregistrionlock);
for(size _ t I=0;我是听众。size();i ) {
m listeners[I]-电池属性改变(道具);
}
}
再来看看电池服务中,在onStart中通过ServiceManager,和电池属性这个服务通信,将电池监听器这个列表中心注册到电池属性中去
@覆盖
public void onStart() {
服务经理。获取服务(“电池属性”);
最终IBatteryPropertiesRegistrar电池属性注册=
IBatteryPropertiesRegistrar .存根。作为接口(b);
尝试{
batterypropertiesregistrar。注册监听器(新电池监听器());
} catch(远程异常e) {
//永远不应该发生。
}
publishBinderService('电池',new binder service());
publishLocalService(batterymanagerinternal。class,new local service());
}
再来看看电池监听器的电池属性已更改接口,当下面调这个接口,就会调用电池服务的更新函数,然后就是电池服务的一些主要流程就不分析了。
私有最终类电池监听器扩展了IBatteryPropertiesListener .存根{
@覆盖
公共无效电池属性已更改(电池属性属性){
最终长标识=活页夹。clearcallingidentity();
尝试{
电池服务. this.update(道具);
}最后{
粘合剂。restorecallingentity(identity);
}
}
}
电池服务接受健康d的数据都是被动的,健康d穿过来的。有没有主动去健康d查询的。
在电池管理员中就有主动去健康d查询的,代码如下
私有长查询属性(int id){
长浸水使柔软
if(mBatteryPropertiesRegistrar==null){
服务经理。获取服务(“电池属性”);//获取电池属性服务
mBatteryPropertiesRegistrar=
IBatteryPropertiesRegistrar .存根。作为接口(b);//接口转化下
if(mBatteryPropertiesRegistrar==null)
返回龙.最小值;
}
尝试{
电池属性prop=新电池属性();
if(mbatterypropertiesregistrar。getproperty(id,prop)==0)//prop是输出
ret=prop。getlong();
其他
ret=Long .最小值;
} catch(远程异常e) {
ret=Long .最小值;
}
返回浸水使柔软
}
再到
healthd看看对应的接口 status_t BatteryPropertiesRegistrar::getProperty(int id, struct BatteryProperty *val) { return healthd_get_property(id, val); } status_t healthd_get_property(int id, struct BatteryProperty *val) { return gBatteryMonitor->getProperty(id, val); }java的BatteryProperty对象对应到这边是指针
status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) { status_t ret = BAD_VALUE; val->valueInt64 = LONG_MIN; switch(id) { case BATTERY_PROP_CHARGE_COUNTER://根据不同ID,返回不同值 if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) { val->valueInt64 = getIntField(mHealthdConfig->batteryChargeCounterPath); ret = NO_ERROR; } else { ret = NAME_NOT_FOUND; } break; case BATTERY_PROP_CURRENT_NOW: if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) { val->valueInt64 = getIntField(mHealthdConfig->batteryCurrentNowPath); ret = NO_ERROR; } else { ret = NAME_NOT_FOUND; } break; case BATTERY_PROP_CURRENT_AVG: if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) { val->valueInt64 = getIntField(mHealthdConfig->batteryCurrentAvgPath); ret = NO_ERROR; } else { ret = NAME_NOT_FOUND; } break; case BATTERY_PROP_CAPACITY: if (!mHealthdConfig->batteryCapacityPath.isEmpty()) { val->valueInt64 = getIntField(mHealthdConfig->batteryCapacityPath); ret = NO_ERROR; } else { ret = NAME_NOT_FOUND; } break; case BATTERY_PROP_ENERGY_COUNTER: if (mHealthdConfig->energyCounter) { ret = mHealthdConfig->energyCounter(&val->valueInt64); } else { ret = NAME_NOT_FOUND; } break; default: break; } return ret; }以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。