Android uevent 电池电量上报机制
Android input epoll/inotify机制
power supply是如何上报电池信息的
Android :kernel uevent发送(热插拔)事件到用户空间
源码分析
Kernel space
kernel/msm-4.19/drivers/power/supply/power_supply_core.c
kernel/msm-4.19/drivers/power/supply/power_supply_sysfs.c
power_supply_class_initpower_supply_class->dev_uevent = power_supply_uevent;初始化workqueue,后续用于调度
INIT_WORK(&psy->changed_work, power_supply_changed_work);在驱动中检测到硬件状态发生变化会调用power_supply_changed,进而调取workqueueschedule_work(&psy->changed_work);添加环境变量,回调keset中注册的power_supply_uevent,将msg以socketbuffer的格式进行打包
power_supply_changed_workkobject_uevent(&psy->dev.kobj, KOBJ_CHANGE);kobject_uevent_env(struct kobject *kobj, enum kobject_action action, char *envp_ext[])if(envp_ext != NULL)add_uevnet_var(env, "%s", envp_ext[i]);//测试用例通过这种envp_ext的方式来实现if (uevent_ops && uevent_ops->uevent) //uevent_ops = kset->uevent_ops; uevent_ops->uevent = dev_ueventuevent_ops->uevent(kset, kobj, env); //power_supply_class->dev_uevent = power_supply_uevent; class类ksetpower_supply_ueventadd_uevent_var(env, "ACTION=%s", action_string);add_uevent_var(env, "DEVPATH=%s", devpath);add_uevent_var(env, "SUBSYSTEM=%s", subsystem);kobject_uevent_net_broadcast(kobj, env, action_string, devpath);alloc_uevent_skb // socket buffer的放置有关 header:action@devpath + socket_buffer scratch = skb_put(skb, len); /* add header*/sprintf(scratch, "%s@%s", action_string, devpath) skb_put_data(skb, env->buf, env->buflen);
User space
hardware/interfaces/health/utils/libhealthloop/HealthLoop.cpp
power_supply通过调用kobject_uevent, envp_ext为NULL, 会回调class的dev_uevent并且使用的是默认的add_uevent_var
ACTION=action_string DEVPATH=devpath SUBSYSTEM=subsystem,电池上层接受的时候会通过SUBSYSTEM进行过滤
StartLoopepollfd_.reset(epoll_create1(EPOLL_CLOEXEC)); //进程被替换时会关闭文件描述符uevent_fd_.reset(uevent_open_socket(64 * 1024, true)); // uevent_fd_ev.events = EPOLLIN; //1. 新的请求 2.接收到普通数据(缓冲未满) 3.正常关闭连接ev.events |= EPOLLWAKEUP; //1. 唤醒源,系统会保持唤醒epoll_ctl(epollfd_, EPOLL_CTL_ADD, uevent_fd_, &ev);//ADD表示绑定事件MainLoop -> while(1)epoll_wait(epollfd_, events, eventct, timeout);//epoll等待uevent事件uevent_kernel_multicast_recv //接受uevent事件strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM) //判断subsystem,battery=power_supplyScheduleBatteryUpdate(); //更新上报电池细节(电量,健康状态等) 以'\0'作为间隔,见log
测试用例
Kernel space
Makefile
obj-y += uevent_test.ouevent_test.c
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/semaphore.h>
#include <linux/mutex.h>
#include <linux/syscalls.h>
#include <asm/unistd.h>
#include <asm/uaccess.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/i2c.h>
#include <linux/input.h>struct device *dev = NULL;char * mesg[2];static ssize_t power_supply_changed(struct device *dev,struct device_attribute *attr, const char *buf, size_t count)
{char s_buf[100]={0};mesg[0] =s_buf;mesg[1] = NULL;strcat(s_buf, buf);pr_err( "jerry echo buf=%s s_buf=%s count=%d\n",buf,s_buf,count);kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, mesg);return count;}
static DEVICE_ATTR(capabitlity, S_IRUGO|S_IWUSR, NULL, power_supply_changed);static const struct attribute *kobject_event_attr[] = {&dev_attr_capabitlity.attr,NULL,
};static const struct attribute_group kobject_event_attr_group = {.attrs = (struct attribute **) kobject_event_attr,
};static struct class kobject_event_class = {.name = "uevent_class",.owner = THIS_MODULE,
};static int __init uevent_test_init(void)
{int ret = 0;ret = class_register(&kobject_event_class);if (ret < 0) {pr_err("jerry: class_register fail");return ret;}dev = device_create(&kobject_event_class, NULL, MKDEV(0, 0), NULL, "uevent_test");if (dev) {ret = sysfs_create_group(&dev->kobj, &kobject_event_attr_group);if(ret < 0) {pr_err("uevent_test:sysfs_create_group fail");return ret;}} else {pr_err("uevent_test:device_create fail");ret = -1;return ret;}return 0;
}static __exit void uevent_test_exit(void)
{device_destroy(&kobject_event_class, MKDEV(0,0));class_destroy(&kobject_event_class);sysfs_remove_group(&dev->kobj, &kobject_event_attr_group);
}module_init(uevent_test_init);
module_exit(uevent_test_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("jerry");
User space
#include <fcntl.h>
#include <string.h>
#include <utils/Log.h>
#include <cutils/uevent.h>#define UEVENT_MSG_LEN 2048//hardware/interfaces/health/utils/libhealthloop/HealthLoop.cppint main()
{char msg[UEVENT_MSG_LEN + 2];int n, uevent_fd_;char* cp;uevent_fd_ = uevent_open_socket(64*1024, true);if (uevent_fd_ < 0) {ALOGE( "jerry uevent_init: uevent_open_socket failed\n");return 0;}while(1){n = uevent_kernel_multicast_recv(uevent_fd_, msg, UEVENT_MSG_LEN);if(n < 0 || n >= UEVENT_MSG_LEN ){ALOGE("jerry failed to recevie uevent");return 0;}msg[n] = '\0';msg[n+1] = '\0';cp = msg;ALOGD("jerry get the uevent size n = %d, msg = %s", n, cp);while (*cp) {ALOGD("jerry receive the msg = %s", cp);/* advance to after the next \0 */while (*cp++);}}return 0;
}
Logcat log
cd /sys/devices/virtual/uevent_class/uevent_test or
cd /sys/class/uevent_class/uevent_test
echo "uevent_test" > capabitlityE : jerry echo buf=uevent_test
D uevent_test: jerry get the uevent size n = 161, msg = change@/devices/virtual/uevent_class/uevent_test
D uevent_test: jerry receive the msg = change@/devices/virtual/uevent_class/uevent_test
D uevent_test: jerry receive the msg = ACTION=change
D uevent_test: jerry receive the msg = DEVPATH=/devices/virtual/uevent_class/uevent_test
D uevent_test: jerry receive the msg = SUBSYSTEM=uevent_class
D uevent_test: jerry receive the msg = uevent_test
D uevent_test: jerry receive the msg = SEQNUM=8695power_supply battery
D uevent_test: jerry receive the msg = change@/devices/platform/soc/1c40000.qcom,spmi/spmi-0/spmi0-02/1c40000.qcom,spmi:qcom,pmi632@2:qcom,qpnp-smb5/power_supply/battery
D uevent_test: jerry receive the msg = ACTION=change
D uevent_test: jerry receive the msg = DEVPATH=/devices/platform/soc/1c40000.qcom,spmi/spmi-0/spmi0-02/1c40000.qcom,spmi:qcom,pmi632@2:qcom,qpnp-smb5/power_supply/battery
D uevent_test: jerry receive the msg = SUBSYSTEM=power_supply
D uevent_test: jerry receive the msg = POWER_SUPPLY_NAME=battery
D uevent_test: jerry receive the msg = POWER_SUPPLY_INPUT_SUSPEND=0
D uevent_test: jerry receive the msg = POWER_SUPPLY_STATUS=Full
...D uevent_test: jerry receive the msg = POWER_SUPPLY_FCC_STEPPER_ENABLE=0D uevent_test: jerry receive the msg = SEQNUM=8694
Android uevent 电池电量上报机制相关推荐
- Android 绘制电池电量图标(含充电状态)。
Android 绘制电池电量图标在视频播放等全屏情况下有用到. 先在布局文件中写一个ImageView <?xml version="1.0" encoding=" ...
- android 电池电量广播,Android查看电池电量的方法(基于BroadcastReceiver)
本文实例讲述了Android查看电池电量的方法.分享给大家供大家参考,具体如下: 程序如下: import android.app.Activity; import android.app.Dialo ...
- 安卓修改电池容量教程_安卓(Android)系统电池电量修改图文教程
安卓( Android )系统电池电量修改图文教程 有机友不喜欢新 rom 的电池图标, 想要官方的原版电池 图标,也有机友想更换其他电池图标.为了方便想更换电池 图标的机友,发一个最简易的教程. 在 ...
- Android监控电池电量和充电状态
确定当前充电状态 首先,确定当前充电状态.BatteryManagerBatteryManagerBatteryManager 会在一个包含充电状态的粘性 Intent 中广播所有电池和充电详情. 由 ...
- Android自定义电池电量显示组件(kotlin,java)
最近产品研发需求需要显示在线设备的电池电量状态,然后UI给出的效果的图是这样的 于是就开始了自定义个,因为是项目特定的UI所以很多属性都没有直接抽取到styles里面了,直接上代码(因为项目是使用ko ...
- android adb 电池电量,adb 查看电池状态信息。详解
手机连接上电脑.输入adb命令:adb shell dumpsys battery Current Battery Service state: ####当前电池服务状态 AC powered: ...
- android 电池绘制,Android绘制电池电量图标
Android手动绘制电池图标展示 1.[代码][Java]代码 public class PowerIconView extends View { private int borderColor = ...
- android 显示电池电量
原文引入:http://blog.csdn.net/it_farmer2010/article/details/6334051 没事的时候,记得多学一点,每天进步一点点,好让自己跟上这个每天在变化的技 ...
- Android获取电池电量的三种方法
方法一:注册广播 这个方法网上一搜一大堆,我也贴出部分代码 IntentFilter filter2 = new IntentFilter(); filter2.addAction(Intent.AC ...
最新文章
- 号外号外 你和python大牛的差距有多少?
- C# 连接SQL数据库字符串
- python无法打开_如何解决Windows命令行无法运行python文件?
- 数据结构与算法--最小的k个数
- 漏桶算法与令牌桶算法
- 福师计算机应用基础在线作业二及答,福师《计算机应用基础》在线作业二 下列软件中属于应用软件的是.docx...
- stm32使用stlink烧录后jlik烧不进去_【MCU实战经验】+用stm32单片机做J-Link和ST-Link...
- php 分支排序,php – 基于类别和分支的Mysql排名
- 【免费毕设】课程指导平台的开发(源代码+lunwen)
- Bosh vs Comet vs Long Polling vs Polling
- javascript数据结构之队列
- 【VS2015】 C++实现硬件ID的查询
- word2007显示控件工具箱
- 【Pyautogui学习】屏幕坐标、鼠标滚动
- 闪迪MicroSD卡无法格式化修复经验(不一定管用)
- windows小工具txt转xlsx
- 设置samba密码时提示failed to find entry for user
- c#未能加载程序集oracle.dataaccess,未能加载文件或程序集“Oracle.DataAccess, Version=2.112.1.0...
- springboot利用官方SDK(wechatpay-apache-httpclient)接入微信支付V3
- win7系统msi文件无法安装历程
热门文章
- pandoc把latex转为word
- Javaweb11(三层架构)
- 10行python代码制作笑死人不偿命的倒放gif
- 免费开源的B2B、B2C商城系统(支持PC+小程序+Android+IOS+H5)
- java获取中文的拼音和获取中文的拼音首字母
- USACO2007 捕牛记 /// queue+桶 oj1503
- 封装一个完整版的uniapp图片和视频上传组件,拿来即用,可进行图片视频切换,可自定义上传按钮样式,删除按钮样式,可单独上传图片或者视频,可限制上传数量
- 2021年安全员-B证(广西省)考试技巧及安全员-B证(广西省)实操考试视频
- 标定代码:CPP+OpenCV实现张正友标定法
- 【Qt入门第36篇】 网络(六)UDP