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 电池电量上报机制相关推荐

  1. Android 绘制电池电量图标(含充电状态)。

    Android 绘制电池电量图标在视频播放等全屏情况下有用到. 先在布局文件中写一个ImageView <?xml version="1.0" encoding=" ...

  2. android 电池电量广播,Android查看电池电量的方法(基于BroadcastReceiver)

    本文实例讲述了Android查看电池电量的方法.分享给大家供大家参考,具体如下: 程序如下: import android.app.Activity; import android.app.Dialo ...

  3. 安卓修改电池容量教程_安卓(Android)系统电池电量修改图文教程

    安卓( Android )系统电池电量修改图文教程 有机友不喜欢新 rom 的电池图标, 想要官方的原版电池 图标,也有机友想更换其他电池图标.为了方便想更换电池 图标的机友,发一个最简易的教程. 在 ...

  4. Android监控电池电量和充电状态

    确定当前充电状态 首先,确定当前充电状态.BatteryManagerBatteryManagerBatteryManager 会在一个包含充电状态的粘性 Intent 中广播所有电池和充电详情. 由 ...

  5. Android自定义电池电量显示组件(kotlin,java)

    最近产品研发需求需要显示在线设备的电池电量状态,然后UI给出的效果的图是这样的 于是就开始了自定义个,因为是项目特定的UI所以很多属性都没有直接抽取到styles里面了,直接上代码(因为项目是使用ko ...

  6. android adb 电池电量,adb 查看电池状态信息。详解

    手机连接上电脑.输入adb命令:adb shell dumpsys battery Current Battery Service state:   ####当前电池服务状态 AC powered: ...

  7. android 电池绘制,Android绘制电池电量图标

    Android手动绘制电池图标展示 1.[代码][Java]代码 public class PowerIconView extends View { private int borderColor = ...

  8. android 显示电池电量

    原文引入:http://blog.csdn.net/it_farmer2010/article/details/6334051 没事的时候,记得多学一点,每天进步一点点,好让自己跟上这个每天在变化的技 ...

  9. Android获取电池电量的三种方法

    方法一:注册广播 这个方法网上一搜一大堆,我也贴出部分代码 IntentFilter filter2 = new IntentFilter(); filter2.addAction(Intent.AC ...

最新文章

  1. 号外号外 你和python大牛的差距有多少?
  2. C# 连接SQL数据库字符串
  3. python无法打开_如何解决Windows命令行无法运行python文件?
  4. 数据结构与算法--最小的k个数
  5. 漏桶算法与令牌桶算法
  6. 福师计算机应用基础在线作业二及答,福师《计算机应用基础》在线作业二 下列软件中属于应用软件的是.docx...
  7. stm32使用stlink烧录后jlik烧不进去_【MCU实战经验】+用stm32单片机做J-Link和ST-Link...
  8. php 分支排序,php – 基于类别和分支的Mysql排名
  9. 【免费毕设】课程指导平台的开发(源代码+lunwen)
  10. Bosh vs Comet vs Long Polling vs Polling
  11. javascript数据结构之队列
  12. 【VS2015】 C++实现硬件ID的查询
  13. word2007显示控件工具箱
  14. 【Pyautogui学习】屏幕坐标、鼠标滚动
  15. 闪迪MicroSD卡无法格式化修复经验(不一定管用)
  16. windows小工具txt转xlsx
  17. 设置samba密码时提示failed to find entry for user
  18. c#未能加载程序集oracle.dataaccess,未能加载文件或程序集“Oracle.DataAccess, Version=2.112.1.0...
  19. springboot利用官方SDK(wechatpay-apache-httpclient)接入微信支付V3
  20. win7系统msi文件无法安装历程

热门文章

  1. pandoc把latex转为word
  2. Javaweb11(三层架构)
  3. 10行python代码制作笑死人不偿命的倒放gif
  4. 免费开源的B2B、B2C商城系统(支持PC+小程序+Android+IOS+H5)
  5. java获取中文的拼音和获取中文的拼音首字母
  6. USACO2007 捕牛记 /// queue+桶 oj1503
  7. 封装一个完整版的uniapp图片和视频上传组件,拿来即用,可进行图片视频切换,可自定义上传按钮样式,删除按钮样式,可单独上传图片或者视频,可限制上传数量
  8. 2021年安全员-B证(广西省)考试技巧及安全员-B证(广西省)实操考试视频
  9. 标定代码:CPP+OpenCV实现张正友标定法
  10. 【Qt入门第36篇】 网络(六)UDP