android uevent机制,android & Linux uevent机制

Linux uevent机制

Uevent是内核通知android有状态变化的一种方法,比如USB线插入、拔出,电池电量变化等等。其本质是内核发送(可以通过socket)一个字符串,应用层(android)接收并解释该字符串,获取相应信息。

一、Kernel侧:

UEVENT的发起在Kernel端,主要是通过函数int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,char *envp_ext[])

该函数的主要功能是根据参数组合一个字符串并发送。一个典型的字符串如下:change@/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, enumkobject_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",

kobject_name(kobj), kobj, __func__);=========================================================这段代码用来查找该kobject所属于的kset,得到 uevent_ops

top_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!", 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!",

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!",

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!", kobject_name(kobj), kobj,

__func__);return 0;

}=========================================================env= kzalloc(sizeof(structkobj_uevent_env), GFP_KERNEL);if (!env)return -ENOMEM;

devpath= kobject_get_path(kobj, GFP_KERNEL);//获取kobject的设备路径

if (!devpath) {

retval= -ENOENT;gotoexit;

}//下面准备要传递的信息数据

retval= add_uevent_var(env, "ACTION=%s", action_string);if(retval)gotoexit;

retval= add_uevent_var(env, "DEVPATH=%s", devpath);if(retval)gotoexit;

retval= add_uevent_var(env, "SUBSYSTEM=%s", subsystem);if(retval)gotoexit;//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)gotoexit;

}

}if (uevent_ops && uevent_ops->uevent) {

retval= uevent_ops->uevent(kset, kobj, env);if(retval) {

pr_debug("kobject: '%s' (%p): %s: uevent() returned"

"%d", kobject_name(kobj), kobj,

__func__, retval);gotoexit;

}

}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)gotoexit;#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,"%s@%s", action_string, devpath);

此时scratch中就增加了change@/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);#endif

if (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)gotoexit;

retval=add_uevent_var(env,"PATH=/sbin:/bin:/usr/sbin:/usr/bin");if(retval)gotoexit;

retval= call_usermodehelper(argv[0], argv,

env->envp, UMH_WAIT_EXEC);

}

exit:

kfree(devpath);

kfree(env);returnretval;

}

二 android 侧private final UEventObserver mUEventObserver = newUEventObserver() {

@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 help

if(DEBUG) Log.w(TAG, "mUEventObserver: onUEvent: state =" +state);//Added for USB Develpment debug, more log for more debuging help

if (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 mObservers = new ArrayList();public voidaddObserver(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 classUEventThread extends Thread {private ArrayList mObservers = new ArrayList();

UEventThread() {

super("UEventObserver");

}public voidrun() {

native_setup();byte[] buffer = new byte[1024];intlen;while (true) {

len=next_event(buffer);if (len > 0) {

String bufferStr= new String(buffer, 0, len); //easier to search a String

synchronized (mObservers) {for (int i = 0; i < mObservers.size(); i += 2) {if (bufferStr.indexOf((String)mObservers.get(i)) != -1) {

((UEventObserver)mObservers.get(i+1))

.onUEvent(newUEvent(bufferStr));

}

}

}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值