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