• Android UEventObserver 使用



    UEventObserver是android Java层利用uevent与获取Kernel层状态变化的机制。

    通过grep发现framework有如下模块使用UEventObserver的功能来提供服务:
    电池状态:services/java/com/android/server/BatteryService.java
    耳机状态:services/java/com/android/server/HeadsetObserver.java
    DOCK状态:services/java/com/android/server/DockObserver.java
    USB状态:services/java/com/android/server/usb/UsbService.java

    它们全部继承自UEventObserver,先看看这个类的构造和原理:
    ./core/java/android/os/UEventObserver.java
                                  |
              [ native_setup(), next_event() ]
                                 |/
    ./core/jni/android_os_UEventObserver.cpp
                                  |
              [ uevent_init(),uevent_next_event() ]
                                 |/
    /hardware/libhardware_legacy/uevent/uevent.c
                                  |                                                                                         [userspace]
    ---------------------[socket]-----------------------------------------------------------------------------
                                  |
                                 |/                                                                                           [kernel]
         socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)

    下面用HeadsetObserver作为例子说明如何使用UEventObserver来监听kernel的uevent。
    继承UEventObserver的类必须实现自己的public abstract void onUEvent(UEvent event):
    1. @Override  
    2. public void onUEvent(UEventObserver.UEvent event) {  
    3.     if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString());  
    4.   
    5.     try {  
    6.         update(event.get("SWITCH_NAME"), Integer.parseInt(event.get("SWITCH_STATE"))); // update中处理事务  
    7.     } catch (NumberFormatException e) {  
    8.         Slog.e(TAG, "Could not parse switch state from event " + event);  
    9.     }  
    10. }  

    这个函数会在UEventObserver接收到event的时候由UEventObserver来回调,HeadsetObserver使用startObserving("DEVPATH=/devices/virtual/switch/h2w")来开始监听,这个API会确保sThread已经运行并且以字串参数作为匹配参数增加一个observer:
        public final synchronized void startObserving(String match) {
            ensureThreadStarted();
            sThread.addObserver(match, this);
        }

    UEventObserver的核心部分就是sThread的run:
    1. public void run() {  
    2.     native_setup(); //调用uevent.c中的API来打开socket  
    3.   
    4.     byte[] buffer = new byte[1024];  
    5.     int len;  
    6.     while (true) {  
    7.         len = next_event(buffer); // 在uevent.c中用poll调用来获取event,会阻塞  
    8.         if (len > 0) {  
    9.             String bufferStr = new String(buffer, 0, len);  // easier to search a String  
    10.             synchronized (mObservers) {  
    11.                 for (int i = 0; i < mObservers.size(); i += 2) {  
    12.                     if (bufferStr.indexOf((String)mObservers.get(i)) != -1) { // 找到匹配的match参数,说明某个observer的监听的event发生了  
    13.                         ((UEventObserver)mObservers.get(i+1))  
    14.                                 .onUEvent(new UEvent(bufferStr)); // 调用这个observer的onUEvent函数  
    15.                     }  
    16.                 }  
    17.             }  
    18.         }  
    19.     }  
    20. }  

    // TODO: 分析kernel层如何上报uevent事件



  • 相关阅读:
    nandflash 分区相关
    android 动态渐变 字符效果
    《Java是如何快速煮成C#的?》(二):数据访问(1)
    01总体分布下的参数假设检验示例一
    《Java是如何快速煮成C#的?》(一):相似的方法(2)
    SQL Server 2008中SQL之WaitFor
    IIS进程经常崩溃的三个解决思路
    Trace.axdasp.net调试的新境界
    ClickOnce发布时报错:Cannot publish because a project failed to build
    《活法》中一个故事--令托尔斯泰也折服的人性寓言
  • 原文地址:https://www.cnblogs.com/liulaolaiu/p/11744625.html
Copyright © 2020-2023  润新知