用Android UEventObserver监听内核uevent

        很多时候我们在框架需要知道内核中某些事件的状态,用设备的show属性是可以供上层来查询,但是这需要上层设定一个较耗资源的循环。如果用UEventObserver就可以监听内核event,它是android Java层利用uevent获取Kernel层状态变化的机制。

(1)UEventObserver简介

        framework有如下模块使用UEventObserver的功能来提供服务:
电池状态:services/java/com/android/server/BatteryService.java,
耳机状态:services/java/com/android/server/HeadsetObserver.java,
DOCK状态:services/java/com/android/server/DockObserver.java,
USB状态:services/java/com/android/server/usb/UsbService.java。
       它们全部继承自UEventObserver,先看看这个类的构造和原理:
./core/java/android/os/UEventObserver.java
                              |
          [ native_setup(), next_event() ]
                             \|/
./core/jni/android_os_UEventObserver.cpp
                              |
          [ uevent_init(),uevent_next_event() ]
                             \|/
/hardware/libhardware_legacy/uevent/uevent.c
                              |                                                                                         [userspace]
---------------------[socket]-----------------------------------------------------------------------------
                              |
                             \|/                                                                                           [kernel]
     socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)

核心响应函数是:继承UEventObserver的类必须实现自己的public abstract void onUEvent(UEvent event),在这里面进行获取状态后的处理。
(2)实例,在上层服务中监听摄像头的打开和关闭,并作相应处理。需要内核摄像头驱动中也要发出event事件才行,所以改动分为内核和上层两部分。

         A,内核摄像头驱动中的改动:

static atomic_t g_CamHWOpend; 	//camera是否打开成功的标志,其它地方赋值
struct device* sensor_device = NULL;
static void set_camera_status()
{
  char *envp[2];
  int ret = atomic_read(&g_CamHWOpend)? 1 : 0;
	if(ret)
		envp[0] = "STATUS=OPEN";
	else
		envp[0] = "STATUS=CLOSE";
	envp[1] = NULL;
	kobject_uevent_env(&sensor_device->kobj, KOBJ_CHANGE, envp);	//将evnp通过kobject上报
	return;
}

       在打开摄像头和关闭摄像头的函数中,成功打开和成功关闭的位置都要放置set_camera_status函数。

        B,上层某个服务中的改动:

导入类:

import android.os.UEventObserver;

在服务的onCreate函数中启动UEventObserver,启动的路径要根据uevent规则来匹配,具体要去目录下寻找:

m_CameraStatusObserver.startObserving("DEVPATH=/devices/virtual/sensordrv/kd_camera_hw");

UEventObserver型变量的创建:

	private UEventObserver m_CameraStatusObserver = new UEventObserver(){
		public void onUEvent(UEvent event){                       //完成抽象的核心响应函数
			String status = event.get("STATUS");    //没有取特定长度字符串,直接取=前面的子串
			Log.i(TAG,"camera app operation and mCameraOpenInSS is "+mCameraOpenInSS);
			if( "OPEN".equals(status)){
				Log.i(TAG,"camera app open");			
				//如果打开摄像头做。。处理
			}
			else if ("CLOSE".equals(status)){
				Log.i(TAG,"camera app close");
				//如果关闭摄像头做。。处理
			}
		}
	};

在服务的onDestroy函数中加上停止监听:

m_CameraStatusObserver.stopObserving();

 

          这样就完成了上层对底层设备状态的响应处理。

(3)关于udev路径

举一个碰到的例子,misc设备

static struct miscdevice vechile_dev = {
	.minor		= MISC_DYNAMIC_MINOR,
	.name		= "vehicle",
	.fops  		= &vechile_fops,
};
上层监控路径
auxObserver.startObserving("DEVPATH=/devices/virtual/misc/vehicle");




参考原文:http://blog.csdn.net/darkengine/article/details/7442359

uevent是Linux内核实现的一种通信机制,用于内核和用户空间之间的事件通知。而netlink是Linux内核的另一种通信机制,用于内核和用户空间之间的进程通信。 在uevent内核实现中,netlink被广泛用于发送和接收uevent消息。当某个硬件设备的状态发生变化时,比如插入或拔出设备,内核会生成相应的uevent消息,并通过netlink将消息发送给用户空间的进程进行处理。 通过netlink发送uevent消息的过程包括以下几个步骤: 1. 内核生成uevent消息,并构建一个netlink消息。 2. 内核将netlink消息通过系统调用发送给用户空间的进程。这个系统调用通常是nlmsg_multicast函数,用于向所有订阅了uevent的进程广播消息。 3. 用户空间的进程通过netlink的接口监听消息,并接收到uevent消息。 4. 用户空间的进程根据接收到的uevent消息进行相应的处理。 用户空间的程序可以使用socket与内核进行netlink通信。监听uevent消息的程序通常会创建一个netlink socket,并通过bind函数将其绑定到特定的netlink家族和组。然后,程序可以通过recvmsg系统调用从socket接收消息,并通过解析收到的消息以得到uevent相关的信息。 总之,uevent内核实现的netlink是一种用于内核和用户空间之间通信的机制。通过netlink发送和接收uevent消息,内核可以将硬件设备状态变化等信息传递给用户空间的进程,以便进行相应的处理。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值