(1)背景概述
众所周知,在安卓系统中有状态栏,在插入外设的时候,会在顶部状态栏显示小图标。
 比如,camera设备,耳机设备,U盘,以及电池等等。这些都需要在状态栏动态显示。

 从上面这张图片可以看出这些设备都有自己的服务一直在跑,并且都是继承了UEventObserver.java这个类去获取kernel的Event事件。下面将着重分析UEventObserver是如何去监听kernel的Event事件。
(2)源码分析
(A)Java层源码分析
//frameworks/base/core/java/android/os/UEventObserver.java
/*
UEventObserver是一个从内核接收UEvents的抽象类。
子类UEventObserver实现onUEvent(UEvent事件),调用startObserving()与匹配字符串匹配,
然后UEvent线程将调用onUEvent()方法,调用stopObserving()停止接收UE事件。
每个进程只有一个UEvent线程,即使该进程具有多个UEventObserver子类实例。
UEvent线程在以下情况下启动:
在该过程中首次调用startObserving()。一旦已启动UEvent线程不会停止(尽管它可以停止通知UEventObserver通过stopObserving())
//hide
*/
public abstract class UEventObserver {
    private static UEventThread sThread;
    private static native void nativeSetup();
    private static native String nativeWaitForNextEvent();
    private static native void nativeAddMatch(String match);
    private static native void nativeRemoveMatch(String match);
	private static UEventThread getThread() {
        synchronized (UEventObserver.class) {
            if (sThread == null) {
                sThread = new UEventThread();
                sThread.start();
            }
            return sThread;
        }
    }
    private static UEventThread peekThread() {
        synchronized (UEventObserver.class) {
            return sThread;
        }
    }
	//注释监听Observer
	public final void startObserving(String match) {
        if (match == null || match.isEmpty()) {
            throw new IllegalArgumentException("match substring must be non-empty");
        }
        final UEventThread t = getThread();
        t.addObserver(match, this);
    }
	//停止监听Observer
    public final void stopObserving() {
        final UEventThread t = peekThread();
        if (t != null) {
            t.removeObserver(this);
        }
    }
    public abstract void onUEvent(UEvent event);
接下来看一下其使用的UEventThread。
private static final class UEventThread extends Thread {
        /** Many to many mapping of string match to observer.
         *  Multimap would be better, but not available in android, so use
         *  an ArrayList where even elements are the String match and odd
         *  elements the corresponding UEventObserver observer */
        private final ArrayList<Object> mKeysAndObservers = new ArrayList<Object>();
        private final ArrayList<UEventObserver> mTempObserversToSignal =
                new ArrayList<UEventObserver>();
        public UEventThread() {
            super("UEventObserver");
        }
        @Override
        public void run() {
            nativeSetup();	//jni调用nativeSetup
            while (true) {
                String message = nativeWaitForNextEvent();	//jni调用nativeWaitForNextEvent
                if (message != null) {
                    if (DEBUG) {
                        Log.d(TAG, message);
                    }
                    sendEvent(message);
                }
            }
        }
        private void sendEvent(String message) {
            synchronized (mKeysAndObservers) {
                final int N = mKeysAndObservers.size();
                for (int i = 0; i < N; i += 2) {
                    final String key = (String)mKeysAndObservers.get(i);
                    if (message.contains(key)) {
                        final UEventObserver observer =
                                (UEventObserver)mKeysAndObservers.get(i + 1);
                        mTempObserversToSignal.add(observer);
                    }
                }
            }
            if (!mTempObserversToSignal.isEmpty()) {
                final UEvent event = new UEvent(message);
                final int N = mTempObserversToSignal.size();
                for (int i = 0; i < N; i++) {
                    final UEventObserver observer = mTempObserversToSignal.get(i);
                    observer.onUEvent(event);
                }
                mTempObserversToSignal.clear();
            }
        }
        public void addObserver(String match, UEventObserver observer) {
            synchronized (mKeysAndObservers) {
                mKeysAndObservers.add(match);
                mKeysAndObservers.add(observer);
                nativeAddMatch(match);
            }
        }
        /** Removes every key/value pair where value=observer from mObservers */
        public void removeObserver(UEventObserver observer) {
            synchronized (mKeysAndObservers) {
                for (int i = 0; i < mKeysAndObservers.size(); ) {
                    if (mKeysAndObservers.get(i + 1) == observer) {
                        mKeysAndObservers.remove(i + 1);
                        final String match = (String)mKeysAndObservers.remove(i);
                        nativeRemoveMatch(match);
                    } else {
                        i += 2;
                    }
                }
            }
        }
    }
当第一次启动这个线程的时候,会调用nativeSetup()方法做初始化,可以看出这个函数是native层来实现的。初始化完之后,进入一个while的死循环,不停的调用native层的nativeWaitForNextEvent()函数来获取Event事件,然后将Event事件转换成message,再通过sendEvent()将message事件传递给外设对应的Observer。
(B)Kernel层源码分析
//frameworks/base/core/jni/android_os_UEventObserver.cpp
static void nativeSetup(JNIEnv *env, jclass clazz) {
    if (!uevent_init()) {	//kernel当中的uevent_init
        jniThrowException(env, "java/lang/RuntimeException",
                "Unable to open socket for UEventObserver");
    }
}
static jstring nativeWaitForNextEvent(JNIEnv *env, jclass clazz) {
    char buffer[1024];
    for (;;) {
        int length = uevent_next_event(buffer, sizeof(buffer) - 1);	//kernel当中的uevent_next_event
        if (length <= 0) {
            return NULL;
        }
        buffer[length] = '\0';
        ALOGV("Received uevent message: %s", buffer);
        if (isMatch(buffer, length)) {
            // Assume the message is ASCII.
            jchar message[length];
            for (int i = 0; i < length; i++) {
                message[i] = buffer[i];
            }
            return env->NewString(message, length);
        }
    }
}
进而调用内核Event相关函数uevent_init()和uevent_next_event()。
//hardware/libhardware_legacy/uevent.c
/* Returns 0 on failure, 1 on success */
int uevent_init()
{
    struct sockaddr_nl addr;
    int sz = 64*1024;
    int s;
    memset(&addr, 0, sizeof(addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_pid = getpid();
    addr.nl_groups = 0xffffffff;
    s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
    if(s < 0)
        return 0;
    setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));
    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
        close(s);
        return 0;
    }
    fd = s;
    return (fd > 0);
}
int uevent_next_event(char* buffer, int buffer_length)
{
    while (1) {
        struct pollfd fds;
        int nr;
    
        fds.fd = fd;
        fds.events = POLLIN;
        fds.revents = 0;
        nr = poll(&fds, 1, -1);
     
        if(nr > 0 && (fds.revents & POLLIN)) {
            int count = recv(fd, buffer, buffer_length, 0);
            if (count > 0) {
                struct uevent_handler *h;
                pthread_mutex_lock(&uevent_handler_list_lock);
                LIST_FOREACH(h, &uevent_handler_list, list)
                    h->handler(h->handler_data, buffer, buffer_length);
                pthread_mutex_unlock(&uevent_handler_list_lock);
                return count;
            } 
        }
    }
    
    // won't get here
    return 0;
}
uevent_init:初始化socket,用来接收来自内核的event事件。
 uevent_next_event:不停的调用poll来等待socket的数据,并将数据存放在buffer中,然后返回。
最后附上流程时序图:
 
 (3)简单测试用例
(A)UsbDeviceManager
//frameworks/base/services/usb/java/com/android/server/usb/UsbDeviceManager.java
private static final String USB_STATE_MATCH = "DEVPATH=/devices/virtual/android_usb/android0";
private static final String ACCESSORY_START_MATCH = "DEVPATH=/devices/virtual/misc/usb_accessory";
private final UEventObserver mUEventObserver;
// Watch for USB configuration changes
mUEventObserver = new UsbUEventObserver();
mUEventObserver.startObserving(USB_STATE_MATCH);
mUEventObserver.startObserving(ACCESSORY_START_MATCH);
/*
     * Listens for uevent messages from the kernel to monitor the USB state
     */
    private final class UsbUEventObserver extends UEventObserver {
        @Override
        public void onUEvent(UEventObserver.UEvent event) {
            Slog.v(TAG, "USB UEVENT: " + event.toString());
            String state = event.get("USB_STATE");
            String accessory = event.get("ACCESSORY");
            
            if (state != null) {
                mHandler.updateState(state);
            } else if ("GETPROTOCOL".equals(accessory)) {
                //...
            } else if ("SENDSTRING".equals(accessory)) {
                //...
            } else if ("START".equals(accessory)) {
                //...
            }
        }
    }
(B)监听摄像头的打开和关闭
在上层服务中监听摄像头的打开和关闭,并作相应处理。需要内核摄像头驱动中也要发出event事件才行,所以改动分为内核和上层两部分。
//kernel drv
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);	//将envp通过kobject上报
	return;
}
//上层监听
	m_CameraStatusObserver.startObserving("DEVPATH=/devices/virtual/sensordrv/kd_camera_hw");
	private UEventObserver m_CameraStatusObserver = new UEventObserver(){
		public void onUEvent(UEvent event){
			String status = event.get("STATUS");    //没有取特定长度字符串,直接取=前面的子串
			if( "OPEN".equals(status)){
				Log.i(TAG,"camera app open");			
			}
			else if ("CLOSE".equals(status)){
				Log.i(TAG,"camera app close");
			}
		}
	};











![[附源码]Python计算机毕业设计动物保护资讯推荐网站Django(程序+LW)](https://img-blog.csdnimg.cn/9f0fcde6dd024dc3ae41a1d00bf9ba82.png)
![RabbitMQ[3]-RabbitMQ如何保证消息的可靠性投递与消费?](https://img-blog.csdnimg.cn/img_convert/8f84583ad6db6d0b172b63465d87c3a6.jpeg)





![[附源码]Python计算机毕业设计SSM基于web的学生社团管理系统(程序+LW)](https://img-blog.csdnimg.cn/6cfac408aae840c8ac0d588f27f9b97c.png)
![[附源码]Python计算机毕业设计SSM基于的二手房交易系统(程序+LW)](https://img-blog.csdnimg.cn/9b6f332d5d554f6cbf91b6d60f68e0e0.png)