Linux uevent机制Uevent是内核通知android有状态变化的一种方法,比如USB线插入、拔出,电池电量变化等等。其本质是内核发送(可以通过socket)一个字符串,应用层(android)接收并解释该字符串,获取相应信息。一、Kernel侧:UEVENT的发起在Kernel端,主要是通过函数int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,char *envp_ext[])该函数的主要功能是根据参数组合一个字符串并发送。一个典型的字符串如下:[email protected]/devices/platform/msm-battery/power_supply/usb纮ACTION=change纮DEVPATH=/devices/platform/msm-battery/power_supply/usb纮SUBSYSTEM=power_supply纮POWER_SUPPLY_NAME=usb纮POWER_SUPPLY_ONLINE=0纮SEQNUM=1486纮上面这块来自网上,这段内容是否有问题,待考究。下面看这个函数:int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,char *envp_ext[]){struct kobj_uevent_env *env;const char *action_string = kobject_actions[action];//获取object的动作//蓝色为为方便看代码加入的static const char *kobject_actions[] = {[KOBJ_ADD] = "add",[KOBJ_REMOVE] = "remove",[KOBJ_CHANGE] = "change",[KOBJ_MOVE] = "move",[KOBJ_ONLINE] = "online",[KOBJ_OFFLINE] = "offline",};//以上为kobject标准的动作,调用时需要传入相应的enum值const char *devpath = NULL;const char *subsystem;struct kobject *top_kobj;struct kset *kset;const struct kset_uevent_ops *uevent_ops;u64 seq;int i = 0;int retval = 0;#ifdef CONFIG_NETstruct uevent_sock *ue_sk;#endifpr_debug("kobject: '%s' (%p): %s\n",kobject_name(kobj), kobj, __func__);=========================================================这段代码用来查找该kobject所属于的kset,得到 uevent_opstop_kobj = kobj;while (!top_kobj->kset && top_kobj->parent)top_kobj = top_kobj->parent;if (!top_kobj->kset) {pr_debug("kobject: '%s' (%p): %s: attempted to send uevent ""without kset!\n", kobject_name(kobj), kobj,__func__);return -EINVAL;}kset = top_kobj->kset;uevent_ops = kset->uevent_ops;=========================================================if (kobj->uevent_suppress) {pr_debug("kobject: '%s' (%p): %s: uevent_suppress ""caused the event to drop!\n",kobject_name(kobj), kobj, __func__);return 0;}if (uevent_ops && uevent_ops->filter)if (!uevent_ops->filter(kset, kobj)) {pr_debug("kobject: '%s' (%p): %s: filter function ""caused the event to drop!\n",kobject_name(kobj), kobj, __func__);return 0;}====================================================获取subsystem信息if (uevent_ops && uevent_ops->name)subsystem = uevent_ops->name(kset, kobj);elsesubsystem = kobject_name(&kset->kobj);if (!subsystem) {pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the ""event to drop!\n", kobject_name(kobj), kobj,__func__);return 0;}=========================================================env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);if (!env)return -ENOMEM;devpath = kobject_get_path(kobj, GFP_KERNEL);//获取kobject的设备路径if (!devpath) {retval = -ENOENT;goto exit;}//下面准备要传递的信息数据retval = add_uevent_var(env, "ACTION=%s", action_string);if (retval)goto exit;retval = add_uevent_var(env, "DEVPATH=%s", devpath);if (retval)goto exit;retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);if (retval)goto exit;//envp_ext[i]是传进来的参数,为该event时携带的一些自定义的信息if (envp_ext) {for (i = 0; envp_ext[i]; i++) {retval = add_uevent_var(env, "%s", envp_ext[i]);if (retval)goto exit;}}if (uevent_ops && uevent_ops->uevent) {retval = uevent_ops->uevent(kset, kobj, env);if (retval) {pr_debug("kobject: '%s' (%p): %s: uevent() returned ""%d\n", kobject_name(kobj), kobj,__func__, retval);goto exit;}}if (action == KOBJ_ADD)kobj->state_add_uevent_sent = 1;else if (action == KOBJ_REMOVE)kobj->state_remove_uevent_sent = 1;//加入该event的序号spin_lock(&sequence_lock);seq = ++uevent_seqnum;spin_unlock(&sequence_lock);retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);if (retval)goto exit;#if defined(CONFIG_NET)//下面通过网络socket将数据发送出去mutex_lock(&uevent_sock_mutex);list_for_each_entry(ue_sk, &uevent_sock_list, list) {struct sock *uevent_sock = ue_sk->sk;struct sk_buff *skb;size_t len;len = strlen(action_string) + strlen(devpath) + 2;skb = alloc_skb(len + env->buflen, GFP_KERNEL);//申请网络skb数据if (skb) {char *scratch;scratch = skb_put(skb, len);sprintf(scratch, "%[email protected]%s", action_string, devpath);此时scratch中就增加了[email protected]/devices/platform/msm-battery/power_supply/usb的//组长网络skb数据结构for (i = 0; i < env->envp_idx; i++) {len = strlen(env->envp[i]) + 1;scratch = skb_put(skb, len);strcpy(scratch, env->envp[i]);}NETLINK_CB(skb).dst_group = 1;//下面开始发送数据retval = netlink_broadcast_filtered(uevent_sock, skb,0, 1, GFP_KERNEL,kobj_bcast_filter,kobj);if (retval == -ENOBUFS || retval == -ESRCH)retval = 0;} elseretval = -ENOMEM;}mutex_unlock(&uevent_sock_mutex);#endifif (uevent_helper[0] && !kobj_usermode_filter(kobj)) {char *argv [3];argv [0] = uevent_helper;argv [1] = (char *)subsystem;argv [2] = NULL;retval = add_uevent_var(env, "HOME=/");if (retval)goto exit;retval = add_uevent_var(env,"PATH=/sbin:/bin:/usr/sbin:/usr/bin");if (retval)goto exit;retval = call_usermodehelper(argv[0], argv,env->envp, UMH_WAIT_EXEC);}exit:kfree(devpath);kfree(env);return retval;}二 android 侧 private final UEventObserver mUEventObserver = new UEventObserver() {@Overridepublic void onUEvent(UEventObserver.UEvent event) {if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());String state = event.get("USB_STATE");String accessory = event.get("ACCESSORY");//Added for USB Develpment debug, more log for more debuging helpif(DEBUG) Log.w(TAG, "mUEventObserver: onUEvent: state = " + state);//Added for USB Develpment debug, more log for more debuging helpif (state != null) {mHandler.updateState(state);} else if ("START".equals(accessory)) {if (DEBUG) Slog.d(TAG, "got accessory start");setCurrentFunction(UsbManager.USB_FUNCTION_ACCESSORY, false);}}};在类初始化时会调用下面的动作,启动监听动作。mUEventObserver.startObserving(USB_STATE_MATCH);最终会调用到UEventObserver的addObserver:private ArrayList<Object> mObservers = new ArrayList<Object>();public void addObserver(String match, UEventObserver observer) {synchronized(mObservers) {mObservers.add(match);mObservers.add(observer);}}private static final String USB_STATE_MATCH ="DEVPATH=/devices/virtual/android_usb/android0";该函数最终会将”DEVPATH=/devices/virtual/android_usb/android0”增加到匹配序列中,当kernel发送具有该字符串的数据时,就返回匹配成功,然后调用mUEventObserver 的onUEvent函数;UeventObserver.javaprivate static class UEventThread extends Thread { private ArrayList<Object> mObservers = new ArrayList<Object>(); UEventThread() {super("UEventObserver");} public void run() {native_setup();byte[] buffer = new byte[1024];int len;while (true) {len = next_event(buffer);if (len > 0) {String bufferStr = new String(buffer, 0, len); // easier to search a Stringsynchronized (mObservers) {for (int i = 0; i < mObservers.size(); i += 2) {if (bufferStr.indexOf((String)mObservers.get(i)) != -1) {((UEventObserver)mObservers.get(i+1)).onUEvent(new UEvent(bufferStr));}}}}}}

更多相关文章

  1. Android 从properties配置文件读取数据
  2. 10天学通Android开发(7)-数据存储
  3. 我的android 第16天 - SQLite数据库
  4. android 数据话持久化——SQLite
  5. Android数据持久化之SQLite数据库用法分析
  6. android SQLite数据库的基本操作
  7. android 字符串、颜色和尺寸

随机推荐

  1. 将一个图片以二进制值的形式存入Xml文件
  2. 新兴XML处理方法VTD-XML介绍
  3. 将图片读入到Dom中,并将其存为xml文件
  4. 利用XMLSerializer将对象串行化到XML
  5. 利用XML实现通用WEB报表打印实际使用中的
  6. 广告控件中xml文件的写法
  7. 在 XSL/XSLT 中实现随机排序
  8. 读取XML为行记录
  9. WML初级教程之从实际应用中了解WML
  10. 从XML中读取数据到内存的实例