Pages

2011年5月18日 星期三

UEvent Simple Introduction

Android 有蠻多服務透過收 UEvent 的方式,取得從底層送上來的訊息,例如:Rotation、Battery、StatusBar 等等,可以在 framework/base/service 看到這些足跡。那麼,它的 code flow 是怎麼跑的,底下咱們來瞧一瞧。

Java Framework
路徑:
framework/base/core/java/android/os/UEventObserver.java
說明:
abstract class UEventObserver
  • UEventObserver 為系統監控是否有 uevent 從 kernel 發出來,它是一個抽象類別,程式設計師可以去繼承它,並且實作
    abstract void onUEvent(UEvent event);
  • 呼叫 startObserving,就會把需要觀察的裝置路徑,儲存在列表中(路徑長得像:"DEVPATH=/devices/...." or "SUBSYSTEM=..."),以便之後和 uevent 字串比對用。
  • 因為 UEventObserver 的運作是透過執行緒不斷地去讀取,所以第二步的 startObserving 就會去檢查執行緒起動了沒。另外,這一條執行緒是系統中僅有的一條執行緒,會透過以下變數判斷執行緒是不是已經生成。
    static boolean sThreadStarted
  • 若執行緒讀到的 uevent 字串,經比對後符合列表中的裝置路徑,就會觸發 onUEvent 這個函式。
class UEvent
  • UEvent 這個類別提供一個 HashMap 資料結構,會把透過 socket 收到的 uevent 字串做拆解,把「=」前當成 key、「=」後當成 value,以便 onUEvent 函式需要的時候使用。uevent 的長相如下:(怪怪的字元應該是結束字元)
    change@/devices/platform/tegra_i2c.1/i2c-1/1-0058/power_supply/battery�� ACTION=change�� DEVPATH=/devices/platform/tegra_i2c.1/i2c-1/1-0058/power_supply/battery�� SUBSYSTEM=power_supply�� POWER_SUPPLY_NAME=battery�� POWER_SUPPLY_TYPE=Battery�� POWER_SUPPLY_STATUS=Unknown��POWER_SUPPLY_HEALTH=Good�� POWER_SUPPLY_PRESENT=0�� POWER_SUPPLY_TECHNOLOGY=Li-ion��POWER_SUPPLY_VOLTAGE_NOW=0�� POWER_SUPPLY_CAPACITY=0�� POWER_SUPPLY_TEMP=-2731�� SEQNUM=721��

private static native void native_setup();
private static native int next_event(byte[] buffer);
  • 這兩個是叫用 JNI 介面,第一個用來做是初始化;第二個是用來讀取 uevent,都在 UEventThread.run() 中使用。


JNI
路徑:
framework/base/core/jni/android_os_UEventObserver.cpp
說明:
android_os_UEventObserver_native_setup
  • 這就是 UEventObserver.java 的 native_setup 所對應的 JNI 接口,這個函式會呼叫 HAL 中的 uevent_init。
android_os_UEventObserver_next_event
  • 這就是 UEventObserver.java 的 next_event 所對應的 JNI 接口,這個函式會呼叫 HAL 中的 uevent_next_event。


HAL(hardware)
路徑:
hardware/libhardware_legacy/uevent/uevent.c
     hardware/libhardware_legacy/include/hardware_legacy/uevent.h
說明:
uevent_init()
  • 這個函式會建立 AF_NETLINK 類型的 socket,然後 bind。

uevent_next_event(char* buffer, int buffer_length)
  • 利用 poll 的方式,對這個 socket fd 作輪詢,如果有資料,就用 recv 去接收,並放在 buffer。poll 的 timeout 等於 -1,代表「Infinitely」。


備註

  • Driver 必須要發出 uevent,語法是 kobject_uevent(&kobj, KOBJ_CHANGE),KOBJ_CHANGE 也可以是 KOBJ_ADD、KOBJ_REMOVE。

參考資料

沒有留言:

 
Blogger Templates