Android设备中,当电池电量发生变化,USB插入、拔出等等事件发生,或者说是状态变化,是怎么通知到应用层的?

Uevent 是内核通知Android有状态变化的方法之一。其本质是内核发送一个字符串(通过Socket),应用层(Android层)接收并解释该字符串,获取相应的信息。

Android 层

Android 层通过 UEventObserver 来接收和处理 uevent 事件。
关联源码有:

1
2
frameworks/base/core/java/android/os/UEventObserver.java
frameworks/base/core/jni/android_os_UEventObserver.cpp

UEventObserver 是一个从内核接收 UEvent 的抽象类。

使用时,需要继承 UEventObserver,并实现 onUEvent(UEvent event),然后使用匹配字符串调用 startObserving()。然后,UEvent 线程将在包含匹配字符串的 UEvent 发生时调用您的 onUEvent() 方法。

可以通过调用 `stopObserving()`` 停止接收 UEvents。

具体使用如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
final UEventObserver observer = new UEventObserver() {
@Override
public void onUEvent(UEvent event) {
final String value = event.get("WIRELESS_MICROPHONE_CHANNEL");
Log.d(TAG, "onUEvent() event: " + event + ", value: " + value);
if (value != null && !"ff".equals(value)) {
final String[] arr = value.split(" ");
for (int i = 0; i < arr.length; i += 2) {
if (i + 1 < arr.length) {
final GmdChannels.Table table = GmdChannels.resolveTable(null, arr[i] + arr[i + 1]);
Log.d(TAG, "onUEvent() table: " + table);
}
}
}
}
};
observer.startObserving("WIRELESS_MICROPHONE_CHANNEL");

Linux 内核层

电量变化等这些状态改变,内核层检测到之后封装成 uevent 事件,然后向应用层发送事件。

这里用的函数是:int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, char *envp_ext[]),定义在文件 kobject_uevent.c 。源码有点多,我就不贴出来了,函数注释如下:

1
2
3
4
5
6
7
8
9
10
11
12
/**
* kobject_uevent_env - send an uevent with environmental data
*
* @action: action that is happening
* @kobj: struct kobject that the action is happening to
* @envp_ext: pointer to environmental data
*
* Returns 0 if kobject_uevent_env() is completed with success or the
* corresponding error when it fails.
*/
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
char *envp_ext[])

其他uevent相关联的源码有:

1
2
hardware/libhardware_legacy/uevent.c
hardware/libhardware_legacy/include/hardware_legacy/uevent.h