Android ueventobserver usage

Source: Internet
Author: User

In the android framework, it is very easy to listen to the underlying uevent event. Just take the following steps and take usbdevicemanager. Java as an example.

First, create a ueventobserver class:

    private final UEventObserver mUEventObserver = new UEventObserver() {                                                                                              @Override        public void onUEvent(UEventObserver.UEvent event) {            if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());            String state = event.get("USB_STATE");            String accessory = event.get("ACCESSORY");            if (state != null) {                mHandler.updateState(state);            } else if ("START".equals(accessory)) {                if (DEBUG) Slog.d(TAG, "got accessory start");                startAccessoryMode();            }        }    };

In this class, you need to override the onuevent method to process the events you get in this method.

Next, call the startobserving method:

                mUEventObserver.startObserving(USB_STATE_MATCH);                                                                                                               mUEventObserver.startObserving(ACCESSORY_START_MATCH);

Here:

    private static final String USB_STATE_MATCH =                                                                                                                          "DEVPATH=/devices/virtual/android_usb/android0";    private static final String ACCESSORY_START_MATCH =                                                                                                                    "DEVPATH=/devices/virtual/misc/usb_accessory";

In this way, you can listen to the uevent event in the above path. Is it easy!

The implementation of the ueventobserver class and the implementation of the JNI layer and the Hal layer have a small amount of code and seem very concise.

First, let's look at the startobserving method:

    public final synchronized void startObserving(String match) {        ensureThreadStarted();        sThread.addObserver(match, this);    }

First, make sure that the thread has been started. If this is the first time you come in, you must start the thread:

    private static final synchronized void ensureThreadStarted() {        if (sThreadStarted == false) {            sThread = new UEventThread();                                                                                                                                  sThread.start();            sThreadStarted = true;        }    }

This thread is in singleton mode, and only one process can be started.

After obtaining the thread instance, call addobserver:

        public void addObserver(String match, UEventObserver observer) {            synchronized(mObservers) {                mObservers.add(match);                mObservers.add(observer);            }        }       

Save the path and ueventobserver instance to arraylist, because a process may have multiple ueventobserver instances.

At this time, the uevent thread is running:

        public void run() {            native_setup();            byte[] buffer = new byte[1024];            int len;            while (true) {                len = next_event(buffer);                if (len > 0) {                    String bufferStr = new String(buffer, 0, len);  // easier to search a String                    synchronized (mObservers) {                        for (int i = 0; i < mObservers.size(); i += 2) {                            if (bufferStr.indexOf((String)mObservers.get(i)) != -1) {                                ((UEventObserver)mObservers.get(i+1))                                        .onUEvent(new UEvent(bufferStr));                            }                        }                    }                }            }        }

Native_setup and next_event are the JNI methods. They call the uevent_init and uevent_next_event methods of the Hal layer respectively:

int uevent_init(){    struct sockaddr_nl addr;    int sz = 64*1024;    int s;    memset(&addr, 0, sizeof(addr));    addr.nl_family = AF_NETLINK;    addr.nl_pid = getpid();    addr.nl_groups = 0xffffffff;    s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);    if(s < 0)        return 0;    setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {        close(s);        return 0;    }    fd = s;                                                                                                                                                        return (fd > 0);}

int uevent_next_event(char* buffer, int buffer_length){    while (1) {        struct pollfd fds;        int nr;        fds.fd = fd;        fds.events = POLLIN;        fds.revents = 0;        nr = poll(&fds, 1, -1);        if(nr > 0 && fds.revents == POLLIN) {            int count = recv(fd, buffer, buffer_length, 0);            if (count > 0) {                struct uevent_handler *h;                pthread_mutex_lock(&uevent_handler_list_lock);                LIST_FOREACH(h, &uevent_handler_list, list)                    h->handler(h->handler_data, buffer, buffer_length);                pthread_mutex_unlock(&uevent_handler_list_lock);                return count;            }        }    }    // won't get here    return 0;}

After listening to the uevent message in the kernel, call Recv and put the data in the buffer. As for the uevent_handler_list queue, It is null because the uevent_add_native_handler function is not called. What is the uevent data format of the kernel, such as the log received when the USB is inserted to the computer:

 ACTION=change DEVPATH=/devices/virtual/android_usb/android0 SUBSYSTEM=android_usb USB_STATE=CONNECTED SEQNUM=1249 change@/devices/virtual/android_usb/android0 ACTION=change DEVPATH=/devices/virtual/android_usb/android0 SUBSYSTEM=android_usb USB_STATE=CONNECTED SEQNUM=1249 change@/devices/virtual/android_usb/android0 ACTION=change DEVPATH=/devices/virtual/android_usb/android0 SUBSYSTEM=android_usb USB_STATE=CONFIGURED SEQNUM=1250 change@/devices/virtual/android_usb/android0 ACTION=change DEVPATH=/devices/virtual/android_usb/android0 SUBSYSTEM=android_usb USB_STATE=CONFIGURED SEQNUM=1250

After the framework thread obtains the buffer data, it uses bufferstr. indexof checks whether the data contains the path you want to monitor. If yes, the onuevent method is called back and a new uevent object is added to parse the data so that onuevent can get data better and faster:

    static public class UEvent {        // collection of key=value pairs parsed from the uevent message        public HashMap<String,String> mMap = new HashMap<String,String>();        public UEvent(String message) {            int offset = 0;            int length = message.length();            while (offset < length) {                int equals = message.indexOf('=', offset);                int at = message.indexOf(0, offset);                if (at < 0) break;                if (equals > offset && equals < at) {                    // key is before the equals sign, and value is after                    mMap.put(message.substring(offset, equals),                            message.substring(equals + 1, at));                }                offset = at + 1;            }        }        public String get(String key) {            return mMap.get(key);        }        public String get(String key, String defaultValue) {            String result = mMap.get(key);            return (result == null ? defaultValue : result);        }                                                                                                                                                                       public String toString() {            return mMap.toString();        }    }

The data format in the hash table is:

ACTION             changeDEVPATH          /devices/virtual/android_usb/android0SUBSYSTEM    android_usbUSB_STATE      CONNECTEDSEQNUM          1249ACTION            changeDEVPATH         /devices/virtual/android_usb/android0SUBSYSTEM    android_usbUSB_STATE     CONFIGURED

In this way, you can easily retrieve the desired data based on the index. For example, in the previous onuevent:

Event. Get ("usb_state") to get connect

Event. Get ("accessory") is empty

End ~

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.