1,涉及到的文件 frameworks:
frameworks/base/core/java/android/os/UEventObserver.java
frameworks/base/core/jni/android_os_UEventObserver.cpp
要监听kernel层上报的的uevent事件,
首先要做的是自定义一个类继承UEventObserver类并实现其抽象方法onUEvent方法;
public abstract void onUEvent(UEvent event);
其次是调用 mUEventObserver.startObserving(“XXXX”);方法
先看其startObserving方法:
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);
}
通过getThread方法创建了一个单例模式的UEventThread 线程,并调用了start方法。
同时将我们需要监听的event实践添加到观察表中
继续看线程的run方法:
177 @Override
178 public void run() {
179 nativeSetup();
180
181 while (true) {
182 String message = nativeWaitForNextEvent();
183 if (message != null) {
184 if (DEBUG) {
185 Log.d(TAG, message);
186 }
187 sendEvent(message);
188 }
189 }
190 }
在run方法中调用一个nativeSetup()一看名字,就知道这里是跑到Jni中去了
然后就是一个while死循环中无限调用nativeWaitForNextEvent,如果返回的message不为空,调用sendEvent;
来看看nativeSetup具体是做了什么?
frameworks/base/core/jni/android_os_UEventObserver.cpp
37 static void nativeSetup(JNIEnv *env, jclass clazz) {
38 if (!uevent_init()) {
39 jniThrowException(env, "java/lang/RuntimeException",
40 "Unable to open socket for UEventObserver");
41 }
42 }
hardware/libhardware_legacy/uevent.c
43 int uevent_init()
44 {
45 struct sockaddr_nl addr;
46 int sz = 64*1024;
47 int s;
48
49 memset(&addr, 0, sizeof(addr));
50 addr.nl_family = AF_NETLINK;
51 addr.nl_pid = getpid();
52 addr.nl_groups = 0xffffffff;
53
54 s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
55 if(s < 0)
56 return 0;
57
58 setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));
59
60 if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
61 close(s);
62 return 0;
63 }
64
65 fd = s;
66 return (fd > 0);
67 }
使用netlink与底层kernel通信
64 static jstring nativeWaitForNextEvent(JNIEnv *env, jclass clazz) {
65 char buffer[1024];
66
67 for (;;) {
68 int length = uevent_next_event(buffer, sizeof(buffer) - 1);
69 if (length <= 0) {
70 return NULL;
71 }
72 buffer[length] = '\0';
73
74 ALOGV("Received uevent message: %s", buffer);
75
76 if (isMatch(buffer, length)) {
77 // Assume the message is ASCII.
78 jchar message[length];
79 for (int i = 0; i < length; i++) {
80 message[i] = buffer[i];
81 }
82 return env->NewString(message, length);
83 }
84 }
85 }
74 int uevent_next_event(char* buffer, int buffer_length)
75 {
76 while (1) {
77 struct pollfd fds;
78 int nr;
79
80 fds.fd = fd;
81 fds.events = POLLIN;
82 fds.revents = 0;
83 nr = poll(&fds, 1, -1);
84
85 if(nr > 0 && (fds.revents & POLLIN)) {
86 int count = recv(fd, buffer, buffer_length, 0);
87 if (count > 0) {
88 struct uevent_handler *h;
89 pthread_mutex_lock(&uevent_handler_list_lock);
90 LIST_FOREACH(h, &uevent_handler_list, list)
91 h->handler(h->handler_data, buffer, buffer_length);
92 pthread_mutex_unlock(&uevent_handler_list_lock);
93
94 return count;
95 }
96 }
97 }
98
99 // won't get here
100 return 0;
101 }
使用poll机制来监测我们的事件节点
当我们的节点信息发生改变时,在nativeWaitForNextEvent中会收到如下log:
2019-07-24 10:39:02.148 914-988/system_process D/LGY_HAL: Received uevent message: change@/devices/platform/battery/power_supply/battery
2019-07-24 11:31:56.979 914-988/system_process D/LGY_HAL: Received uevent message: change@/devices/virtual/lgy_class/lgy
然后调用isMatch()来判断该类型的事件是否已经注册了,
44 static bool isMatch(const char* buffer, size_t length) {
45 AutoMutex _l(gMatchesMutex);
46
47 for (size_t i = 0; i < gMatches.size(); i++) {
48 const String8& match = gMatches.itemAt(i);
49
50 // Consider all zero-delimited fields of the buffer.
51 const char* field = buffer;
52 const char* end = buffer + length + 1;
53 do {
54 if (strstr(field, match.string())) {
55 ALOGV("Matched uevent message with pattern: %s", match.string());
56 return true;
57 }
58 field += strlen(field) + 1;
59 } while (field != end);
60 }
61 return false;
62 }
我们要监听的事件在startObserving里调用t.addObserver时就已经加上了。
216 public void addObserver(String match, UEventObserver observer) {
217 synchronized (mKeysAndObservers) {
218 mKeysAndObservers.add(match);
219 mKeysAndObservers.add(observer);
220 nativeAddMatch(match);
221 }
222 }
将nativeWaitForNextEvent返回的message 通过sendEvent发送出去:
这里的message是如下类型的字符串:
sendEvent message = change@/devices/virtual/misc/cpu_loading��ACTION=change��DEVPATH=/devices/virtual/misc/cpu_loading��SUBSYSTEM=misc��lower=2��MAJOR=10��MINOR=0��DEVNAME=cpu_loading��SEQNUM=4674��
这里的��乱码其实是'\0';
192 private void sendEvent(String message) {
193 synchronized (mKeysAndObservers) {
194 final int N = mKeysAndObservers.size();
195 for (int i = 0; i < N; i += 2) {
196 final String key = (String)mKeysAndObservers.get(i);
197 if (message.contains(key)) {
198 final UEventObserver observer =
199 (UEventObserver)mKeysAndObservers.get(i + 1);
200 mTempObserversToSignal.add(observer);
201 }
202 }
203 }
204
205 if (!mTempObserversToSignal.isEmpty()) {
206 final UEvent event = new UEvent(message);
207 final int N = mTempObserversToSignal.size();
208 for (int i = 0; i < N; i++) {
209 final UEventObserver observer = mTempObserversToSignal.get(i);
210 observer.onUEvent(event);
211 }
212 mTempObserversToSignal.clear();
213 }
214 }
其中 observer.onUEvent(event);调用各自的onUEvent方法。
所以我们自定义的继承UEventObserver类并实现其抽象方法onUEvent方法,就是在这里触发调用的。
看看系统是在onUEvent中如何处理usb热插拔事件的
frameworks/base/services/usb/java/com/android/server/usb/UsbDeviceManager.java
215 /*
216 * Listens for uevent messages from the kernel to monitor the USB state
217 */
218 private final class UsbUEventObserver extends UEventObserver {
219 @Override
220 public void onUEvent(UEventObserver.UEvent event) {
221 if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());
222
223 String state = event.get("USB_STATE");
224 String accessory = event.get("ACCESSORY");
225 if (state != null) {
226 mHandler.updateState(state);
227 } else if ("START".equals(accessory)) {
228 if (DEBUG) Slog.d(TAG, "got accessory start");
229 startAccessoryMode();
230 }
231 }
232 }
看样子很明确了,在onUEvent中只是通过state和accessory两个String的值判断状态的。
223 String state = event.get("USB_STATE");
224 String accessory = event.get("ACCESSORY");
原理是什么呢?那就要来看UEvent 这个UEventObserver.java中的内部类了
126 public static final class UEvent {
127 // collection of key=value pairs parsed from the uevent message
128 private final HashMap<String,String> mMap = new HashMap<String,String>();
129
130 public UEvent(String message) {
131 int offset = 0;
132 int length = message.length();
133
134 while (offset < length) {
135 int equals = message.indexOf('=', offset);
136 int at = message.indexOf('\0', offset);
137 if (at < 0) break;
138
139 if (equals > offset && equals < at) {
140 // key is before the equals sign, and value is after
141 mMap.put(message.substring(offset, equals),
142 message.substring(equals + 1, at));
143 }
144
145 offset = at + 1;
146 }
147 }
148
149 public String get(String key) {
150 return mMap.get(key);
151 }
152
153 public String get(String key, String defaultValue) {
154 String result = mMap.get(key);
155 return (result == null ? defaultValue : result);
156 }
157
158 public String toString() {
159 return mMap.toString();
160 }
161 }
构造函数很简单,是什么意思呢?
就是将字符串中等于符号'='两边的值,前者为key,后者为value存储在map中。
插拔usb时,通过sendEvent发送出去的message是什么样子的吗?
插入usb:USB_STATE=CONNECTED
sendEvent message = change@/devices/virtual/android_usb/android0??ACTION=change??DEVPATH=/devices/virtual/android_usb/android0??SUBSYSTEM=android_usb??USB_STATE=CONNECTED??SEQNUM=5484??
拔出usb:USB_STATE=DISCONNECTED
sendEvent message = change@/devices/virtual/android_usb/android0??ACTION=change??DEVPATH=/devices/virtual/android_usb/android0??SUBSYSTEM=android_usb??USB_STATE=DISCONNECTED??SEQNUM=5485??
除此之外还有另外一种状态:USB_STATE=CONFIGURED
sendEvent message = change@/devices/virtual/android_usb/android0??ACTION=change??DEVPATH=/devices/virtual/android_usb/android0??SUBSYSTEM=android_usb??USB_STATE=CONFIGURED??SEQNUM=5487??
这一字符串中显示??的地方其实是‘\0’,也在UEvent构造函数中有所处理了哈。
所以String state = event.get("USB_STATE");只会出现三种情况,通过state的值就可以判断usb是处于什么样的状态了。
那么底层kernel是如何传usb的状态的呢?
是通过kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, uevent_envp);传递给用户层的
状态值存在uevent_envp这个二级指针中。kobject_uevent_env的分析在知其然也要知其所以然---Kernel上报电量UEvent事件流程分析一文中有说道。
172 static void android_work(struct work_struct *data)
173 {
174 struct android_dev *dev = container_of(data, struct android_dev, work);
175 struct usb_composite_dev *cdev = dev->cdev;
176 char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL };
177 char *connected[2] = { "USB_STATE=CONNECTED", NULL };
178 char *configured[2] = { "USB_STATE=CONFIGURED", NULL };
179 char **uevent_envp = NULL;
180 unsigned long flags;
181
182 if (!cdev) {
183 pr_notice("android_work, !cdev\n");
184 return;
185 }
186
187 spin_lock_irqsave(&cdev->lock, flags);
188 if (cdev->config)
189 uevent_envp = configured;
190 else if (dev->connected != dev->sw_connected)
191 uevent_envp = dev->connected ? connected : disconnected;
192 dev->sw_connected = dev->connected;
193 spin_unlock_irqrestore(&cdev->lock, flags);
194
195 if (uevent_envp) {
196 kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, uevent_envp);
197 pr_notice("%s: sent uevent %s\n", __func__, uevent_envp[0]);
198 #ifdef CONFIG_MTPROF
199 if (uevent_envp == configured) {
200 static int first_shot = 1;
201
202 if (first_shot) {
203 log_boot("USB configured");
204 first_shot = 0;
205 }
206 }
207 #endif
208 } else {
209 pr_notice("%s: did not send uevent (%d %d %p)\n", __func__,
210 dev->connected, dev->sw_connected, cdev->config);
211 }
212 }