(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");
}
}
};