国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開(kāi)通VIP
基于power supply信息傳遞的uevent機(jī)制

參考了 http://blog.sina.com.cn/s/blog_6100a4f101015uwh.html

原文:http://blog.csdn.net/pillarbuaa/article/details/9062115

Linux uevent機(jī)制


Uevent是內(nèi)核通知android有狀態(tài)變化的一種方法,比如USB線插入、拔出,電池電量變化等等。其本質(zhì)是內(nèi)核發(fā)送(可以通過(guò)socket)一個(gè)字符串,應(yīng)用層(android)接收并解釋該字符串,獲取相應(yīng)信息。

一、Kernel側(cè):

 kernel 發(fā)送給battery_logging的uevent格式?
 power_supply_uevent@kernel/drivers/power/power_supply_sysfs.c 該函數(shù)添加發(fā)送的信息到uevent
 ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->name); //psy->name="battery"
 for (j = 0; j < psy->num_properties; j++) {
  attr = &power_supply_attrs[psy->properties[j]]; //得到對(duì)應(yīng)的power supply attr,
  attrname = kstruprdup(attr->attr.name, GFP_KERNEL);//會(huì)把屬性名字轉(zhuǎn)成大寫,比如“status”->"STATUS"
  ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf); //增加該屬性的信息到uevent buffer中
 }
 
  static enum power_supply_property msm_batt_power_props[] = { //對(duì)應(yīng)power_supply_attrs[]@kernel/drivers/power/power_supply_sysfs.c
  POWER_SUPPLY_PROP_CHARGING_ENABLED,       //表示這些屬性是被battery psy所需要的屬性,具體如何得到可查看 
  POWER_SUPPLY_PROP_STATUS,      //qpnp_batt_power_get_property 函數(shù)
  POWER_SUPPLY_PROP_CHARGE_TYPE,  
  POWER_SUPPLY_PROP_HEALTH,  
  POWER_SUPPLY_PROP_PRESENT,  
  POWER_SUPPLY_PROP_TECHNOLOGY,  
  POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
  POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
  POWER_SUPPLY_PROP_VOLTAGE_NOW,  
  POWER_SUPPLY_PROP_CAPACITY,  
  POWER_SUPPLY_PROP_CURRENT_NOW,  
  POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
  POWER_SUPPLY_PROP_TEMP,   
  POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
 };
 
 static struct device_attribute power_supply_attrs[] = {
  /* Properties of type `int' */
  POWER_SUPPLY_ATTR(status),  //表示attr.name = "status"
  POWER_SUPPLY_ATTR(charge_type),
  ...
 }

UEVENT的發(fā)起在Kernel端,主要是通過(guò)函數(shù)

intkobject_uevent_env(struct kobject *kobj, enum kobject_action action,char *envp_ext[])

該函數(shù)的主要功能是根據(jù)參數(shù)組合一個(gè)字符串并發(fā)送。一個(gè)典型的字符串如下:

ACTION=change

DEVPATH=/devices/qpnp-bms-eab17000/power_supply/bms

SUBSYSTEM=power_supply

POWER_SUPPLY_NAME=bms

POWER_SUPPLY_PRESENT=1

POWER_SUPPLY_CAPACITY=42

POWER_SUPPLY_CURRENT_NOW=-426300

POWER_SUPPLY_CURRENT_MAX=6735829

POWER_SUPPLY_CHARGE_FULL_DESIGN=2350

SEQNUM=3488

 

ACTION=change

DEVPATH=/devices/qpnp-charger-eab16c00/power_supply/battery

SUBSYSTEM=power_supply

POWER_SUPPLY_NAME=battery

//和前面的msm_batt_power_props相對(duì)應(yīng)

POWER_SUPPLY_CHARGING_ENABLED=1

POWER_SUPPLY_STATUS=Charging

POWER_SUPPLY_CHARGE_TYPE=Fast

POWER_SUPPLY_HEALTH=Good 

POWER_SUPPLY_PRESENT=1

POWER_SUPPLY_TECHNOLOGY=Li-ion

POWER_SUPPLY_VOLTAGE_MAX_DESIGN=4200000

POWER_SUPPLY_VOLTAGE_MIN_DESIGN=4200000

POWER_SUPPLY_VOLTAGE_NOW=3833115

POWER_SUPPLY_CAPACITY=42

POWER_SUPPLY_CURRENT_NOW=-395600

POWER_SUPPLY_CHARGE_FULL_DESIGN=2350

POWER_SUPPLY_TEMP=250

POWER_SUPPLY_SYSTEM_TEMP_LEVEL=0

SEQNUM=3489

分析下UEvent如何傳遞給user space?
 a. @kernel/drivers/power/qpnp-charger.c中只要有任何關(guān)于charger的變化,比如charger的各種irq handler
 b. @kernel/drivers/power/qpnp-bms.c中calculate_soc_from_voltage和calculate_state_of_charge
 c. @kernel/arch/arm/boot/dts/msm-pm8226.dtsi中有pm8226_bms的device定義,msm8226-cn3ii.dtsi中有pm8226_bms的定義補(bǔ)充
  其中沒(méi)有 qcom,use-voltage-soc 的定義所以chip->use_voltage_soc=false, 也就是只用calculate_state_of_charge計(jì)算soc
  順便chip->use_external_rsense=true,表示用外部的rsense.
 d. @kernel/driver/power/power_supply_core.c中的power_supply_changed會(huì)被以上內(nèi)容調(diào)用
  schedule_work(&psy->changed_work);
 e.
power_supply_changed_work@kernel/driver/power/power_supply_core.c
  kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE); //action=KOBJ_CHANGE
 f. kobject_uevent_env@kernel/lib/kobject_uevent.c

下面看這個(gè)函數(shù):

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的動(dòng)作

//藍(lán)色為為方便看代碼加入的

static const char *kobject_actions[] = {

[KOBJ_ADD] = "add",

[KOBJ_REMOVE] = "remove",

[KOBJ_CHANGE] = "change",

[KOBJ_MOVE] = "move",

[KOBJ_ONLINE] = "online",

[KOBJ_OFFLINE] = "offline",

};

//以上為kobject標(biāo)準(zhǔn)的動(dòng)作,調(diào)用時(shí)需要傳入相應(yīng)的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_NET

struct uevent_sock *ue_sk;

#endif



pr_debug("kobject: '%s' (%p): %s\n",

kobject_name(kobj), kobj, __func__);

=========================================================

這段代碼用來(lái)查找該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!\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);

else

subsystem = 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的設(shè)備路徑,

if (!devpath) {

retval = -ENOENT;

goto exit;

}

//下面準(zhǔn)備要傳遞的信息數(shù)據(jù)

retval = add_uevent_var(env, "ACTION=%s", action_string); //action_string="change"

if (retval)

goto exit;

retval = add_uevent_var(env, "DEVPATH=%s", devpath);//devpath="/devices/qpnp-charger-eab16c00/power_supply/battery"

if (retval)

goto exit;

retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);//subsystem="power_supply"

if (retval)

goto exit;

//envp_ext[i]是傳進(jìn)來(lái)的參數(shù),為該event時(shí)攜帶的一些自定義的信息,

if (envp_ext) {//對(duì)于power_supply_changed_work->kobject_uevent->kobject_uevent_env(kobj, action, NULL);所以envp_ext=NULL

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);//會(huì)調(diào)用到power_supply_uevent@kernel/drivers/power/power_supply_sysfs.c,回到了前面的分析,

                                                                 //也就是會(huì)添加具體的power battery信息到uevent buffer中了

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的序號(hào)

spin_lock(&sequence_lock);

seq = ++uevent_seqnum;

spin_unlock(&sequence_lock);

retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq); //用cat sys/kernel/uevent_seqnum 可以查看

if (retval)

goto exit;



#if defined(CONFIG_NET)

//下面通過(guò)網(wǎng)絡(luò)socket將數(shù)據(jù)發(fā)送出去

mutex_lock(&uevent_sock_mutex);

list_for_each_entry(ue_sk, &uevent_sock_list, list) {//在函數(shù)uevent_net_init會(huì)初始化一個(gè)uevent_sock,也只有一個(gè)

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);//申請(qǐng)網(wǎng)絡(luò)skb數(shù)據(jù)

if (skb) {

char *scratch;


//以下內(nèi)容是發(fā)送內(nèi)容打包

scratch = skb_put(skb, len);

sprintf(scratch, "%s@%s", action_string, devpath);

此時(shí)scratch中就增加了change@/devices/platform/msm-battery/power_supply/usb

//組長(zhǎng)網(wǎng)絡(luò)skb數(shù)據(jù)結(jié)構(gòu)

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;//下面開(kāi)始發(fā)送數(shù)據(jù)

retval = netlink_broadcast_filtered(uevent_sock, skb,  //該函數(shù)很關(guān)鍵后面再具體分析

0, 1, GFP_KERNEL,

kobj_bcast_filter,

kobj);

if (retval == -ENOBUFS || retval == -ESRCH)

retval = 0;

} else

retval = -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)

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;

}

 

基于Netlink的Uevent的具體實(shí)現(xiàn)

參考 http://www.ibm.com/developerworks/cn/linux/l-netlink/?ca=dwcn-newsletter-linux

http://www.chinaunix.net/old_jh/4/822500.html

1. Netlink 機(jī)制

Linux 內(nèi)核模塊的運(yùn)行環(huán)境與傳統(tǒng)進(jìn)程間通信

在一臺(tái)運(yùn)行 Linux 的計(jì)算機(jī)中,CPU 在任何時(shí)候只會(huì)有如下四種狀態(tài):

【1】 在處理一個(gè)硬中斷。

【2】 在處理一個(gè)軟中斷,如 softirq、tasklet 和 bh。

【3】 運(yùn)行于內(nèi)核態(tài),但有進(jìn)程上下文,即與一個(gè)進(jìn)程相關(guān)。

【4】 運(yùn)行一個(gè)用戶態(tài)進(jìn)程。

其中,【1】、【2】和【3】是運(yùn)行于內(nèi)核空間的,而【4】是在用戶空間。其中除了【4】,其他狀態(tài)只可以被在其之上的狀態(tài)搶占。比如,軟中斷只可以被硬中斷搶占。

Linux 內(nèi)核模塊是一段可以動(dòng)態(tài)在內(nèi)核裝載和卸載的代碼,裝載進(jìn)內(nèi)核的代碼便立即在內(nèi)核中工作起來(lái)。Linux 內(nèi)核代碼的運(yùn)行環(huán)境有三種:用戶上下文環(huán)境、硬中斷環(huán)境和軟中斷環(huán)境。但三種環(huán)境的局限性分兩種,因?yàn)檐浿袛喹h(huán)境只是硬中斷環(huán)境的延續(xù)。比較如表【1】。


表【1】

內(nèi)核態(tài)環(huán)境介紹局限性
用戶上下文內(nèi)核態(tài)代碼的運(yùn)行與一用戶空間進(jìn)程相關(guān),如系統(tǒng)調(diào)用中代碼的運(yùn)行環(huán)境。不可直接將本地變量傳遞給用戶態(tài)的內(nèi)存區(qū),因?yàn)閮?nèi)核態(tài)和用戶態(tài)的內(nèi)存映射機(jī)制不同。
硬中斷和軟中斷環(huán)境硬中斷或軟中斷過(guò)程中代碼的運(yùn)行環(huán)境,如 IP 數(shù)據(jù)報(bào)的接收代碼的運(yùn)行環(huán)境,網(wǎng)絡(luò)設(shè)備的驅(qū)動(dòng)程序等。不可直接向用戶態(tài)內(nèi)存區(qū)傳遞數(shù)據(jù);
代碼在運(yùn)行過(guò)程中不可阻塞。

Linux 傳統(tǒng)的進(jìn)程間通信有很多,如各類管道、消息隊(duì)列、內(nèi)存共享、信號(hào)量等等。但它們都無(wú)法介于內(nèi)核態(tài)與用戶態(tài)使用,原因如表【2】。


表【2】

通信方法無(wú)法介于內(nèi)核態(tài)與用戶態(tài)的原因
管道(不包括命名管道)局限于父子進(jìn)程間的通信。
消息隊(duì)列在硬、軟中斷中無(wú)法無(wú)阻塞地接收數(shù)據(jù)。
信號(hào)量無(wú)法介于內(nèi)核態(tài)和用戶態(tài)使用。
內(nèi)存共享需要信號(hào)量輔助,而信號(hào)量又無(wú)法使用。
套接字在硬、軟中斷中無(wú)法無(wú)阻塞地接收數(shù)據(jù)。


Linux內(nèi)核態(tài)與用戶態(tài)進(jìn)程通信方法的提出與實(shí)現(xiàn)

 

運(yùn)行在用戶上下文環(huán)境中的代碼是可以阻塞的,這樣,便可以使用消息隊(duì)列和 UNIX 域套接字來(lái)實(shí)現(xiàn)內(nèi)核態(tài)與用戶態(tài)的通信。但這些方法的數(shù)據(jù)傳輸效率較低,Linux 內(nèi)核提供 copy_from_user()/copy_to_user() 函數(shù)來(lái)實(shí)現(xiàn)內(nèi)核態(tài)與用戶態(tài)數(shù)據(jù)的拷貝,但這兩個(gè)函數(shù)會(huì)引發(fā)阻塞,所以不能用在硬、軟中斷中。一般將這兩個(gè)特殊拷貝函數(shù)用在類似于系統(tǒng)調(diào)用一類的函數(shù)中,此類函數(shù)在使用中往往"穿梭"于內(nèi)核態(tài)與用戶態(tài)。此類方法的工作原理路如圖【1】。


圖【1】


其中相關(guān)的系統(tǒng)調(diào)用是需要用戶自行編寫并載入內(nèi)核。 imp1.tar.gz是一個(gè)示例,內(nèi)核模塊注冊(cè)了一組設(shè)置套接字選項(xiàng)的函數(shù)使得用戶空間進(jìn)程可以調(diào)用此組函數(shù)對(duì)內(nèi)核態(tài)數(shù)據(jù)進(jìn)行讀寫。源碼包含三個(gè)文件,imp1.h 是通用頭文件,定義了用戶態(tài)和內(nèi)核態(tài)都要用到的宏。imp1_k.c 是內(nèi)核模塊的源代碼。imp1_u.c 是用戶態(tài)進(jìn)程的源代碼。整個(gè)示例演示了由一個(gè)用戶態(tài)進(jìn)程向用戶上下文環(huán)境發(fā)送一個(gè)字符串,內(nèi)容為"a message from userspace\n"。然后再由用戶上下文環(huán)境向用戶態(tài)進(jìn)程發(fā)送一個(gè)字符串,內(nèi)容為"a message from kernel\n"。

 

硬、軟中斷環(huán)境

比起用戶上下文環(huán)境,硬中斷和軟中斷環(huán)境與用戶態(tài)進(jìn)程無(wú)絲毫關(guān)系,而且運(yùn)行過(guò)程不能阻塞。

1 使用一般進(jìn)程間通信的方法

我們無(wú)法直接使用傳統(tǒng)的進(jìn)程間通信的方法實(shí)現(xiàn)。但硬、軟中斷中也有一套同步機(jī)制--自旋鎖(spinlock),可以通過(guò)自旋鎖來(lái)實(shí)現(xiàn)中斷環(huán)境與中斷環(huán)境,中斷環(huán)境與內(nèi)核線程的同步,而內(nèi)核線程是運(yùn)行在有進(jìn)程上下文環(huán)境中的,這樣便可以在內(nèi)核線程中使用套接字或消息隊(duì)列來(lái)取得用戶空間的數(shù)據(jù),然后再將數(shù)據(jù)通過(guò)臨界區(qū)傳遞給中斷過(guò)程?;舅悸啡鐖D【2】。


圖【2】


因?yàn)橹袛噙^(guò)程不可能無(wú)休止地等待用戶態(tài)進(jìn)程發(fā)送數(shù)據(jù),所以要通過(guò)一個(gè)內(nèi)核線程來(lái)接收用戶空間的數(shù)據(jù),再通過(guò)臨界區(qū)傳給中斷過(guò)程。中斷過(guò)程向用戶空間的數(shù)據(jù)發(fā)送必須是無(wú)阻塞的。這樣的通信模型并不令人滿意,因?yàn)閮?nèi)核線程是和其他用戶態(tài)進(jìn)程競(jìng)爭(zhēng)CPU接收數(shù)據(jù)的,效率很低,這樣中斷過(guò)程便不能實(shí)時(shí)地接收來(lái)自用戶空間的數(shù)據(jù)。

2 netlink 套接字

在 Linux 2.4 版以后版本的內(nèi)核中,幾乎全部的中斷過(guò)程與用戶態(tài)進(jìn)程的通信都是使用 netlink 套接字實(shí)現(xiàn)的,同時(shí)還使用 netlink 實(shí)現(xiàn)了 ip queue 工具,但 ip queue 的使用有其局限性,不能自由地用于各種中斷過(guò)程。內(nèi)核的幫助文檔和其他一些 Linux 相關(guān)文章都沒(méi)有對(duì) netlink 套接字在中斷過(guò)程和用戶空間通信的應(yīng)用上作詳細(xì)的說(shuō)明,使得很多用戶對(duì)此只有一個(gè)模糊的概念。

netlink 套接字的通信依據(jù)是一個(gè)對(duì)應(yīng)于進(jìn)程的標(biāo)識(shí),一般定為該進(jìn)程的 ID。當(dāng)通信的一端處于中斷過(guò)程時(shí),該標(biāo)識(shí)為 0。當(dāng)使用 netlink 套接字進(jìn)行通信,通信的雙方都是用戶態(tài)進(jìn)程,則使用方法類似于消息隊(duì)列。但通信雙方有一端是中斷過(guò)程,使用方法則不同。netlink 套接字的最大特點(diǎn)是對(duì)中斷過(guò)程的支持,它在內(nèi)核空間接收用戶空間數(shù)據(jù)時(shí)不再需要用戶自行啟動(dòng)一個(gè)內(nèi)核線程,而是通過(guò)另一個(gè)軟中斷調(diào)用用戶事先指定的接收函數(shù)。工作原理如圖【3】。


圖【3】


很明顯,這里使用了軟中斷而不是內(nèi)核線程來(lái)接收數(shù)據(jù),這樣就可以保證數(shù)據(jù)接收的實(shí)時(shí)性。

當(dāng) netlink 套接字用于內(nèi)核空間與用戶空間的通信時(shí),在用戶空間的創(chuàng)建方法和一般套接字使用類似,但內(nèi)核空間的創(chuàng)建方法則不同。圖【4】是 netlink 套接字實(shí)現(xiàn)此類通信時(shí)創(chuàng)建的過(guò)程。


圖【4】


 

 

 

android側(cè)


 

private finalUEventObserver mUEventObserver = newUEventObserver() {

@Override

public 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);

}

}

};


在類初始化時(shí)會(huì)調(diào)用下面的動(dòng)作,啟動(dòng)監(jiān)聽(tīng)動(dòng)作。

mUEventObserver.startObserving(USB_STATE_MATCH);


最終會(huì)調(diào)用到UEventObserveraddObserver

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";

該函數(shù)最終會(huì)將”DEVPATH=/devices/virtual/android_usb/android0”增加到匹配序列中,當(dāng)kernel發(fā)送具有該字符串的數(shù)據(jù)時(shí),就返回匹配成功,然后調(diào)用mUEventObserveronUEvent函數(shù);



UeventObserver.java

private 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 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(new UEvent(bufferStr));

}

}

}

}

}

}

 

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Linux內(nèi)核模塊自動(dòng)加載機(jī)制 .
Android Uevent 分析,從kernel到framework
Linux設(shè)備驅(qū)動(dòng)模型中的熱插拔機(jī)制及實(shí)驗(yàn)
我對(duì)linux理解之driver_register
Kobject模型
Linux設(shè)備模型(3)_Uevent
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服