In depth analysis of event delivery in Android

preface

Some time ago, I encountered a problem in my work, that is, I want to listen to the back event after the soft keyboard pops up, but I can't listen after rewriting the corresponding onkeydown function in the activity. After a while of Google, I found that I need to rewrite the dispatchkeyeventpreime function of view. At that time, I felt that the name of this function was very familiar. After careful thinking, I suddenly realized that I had this understanding when I looked at the WMS source code, but now I forgot it. So I decided to write this article and keep it as a record.

InputManagerService

First of all, we know that both "keyboard events" and "click events" are transmitted to us from the bottom of the system. Of course, we won't discuss the Linux kernel at the bottom here. Our starting point starts from the framework layer. Students who have seen the source code of Android framework layer have made it clear that there are many xxxmanagerservices running in system_ Server process, such as AMS (activity manager service) and WMS (window manager service). The service related to Android events here is inputmanagerservice, so let's see how it works first.

When you see this nativestart, do you take a breath back? Yes, it's a nativestart method. But there's no way. After all, the bottom layer has to deal with C ~

As you can see, the start method of inputmanager is called.

Two threads are initialized -- readerthread and dispatcher thread. The role of these two threads is very important. The former accepts events from the device and encapsulates them into information that can be understood by the upper layer, and the latter is responsible for distributing events. It can be said that the events of our upper activity or view come from these two threads. I won't talk about it here. Interested students can analyze it according to the source code. Interestingly, in the process of polling click events, dispatcher thread adopts the form of looper. It can be seen that the source code in Android is really related everywhere, so don't think that some of the source code is useless. Maybe you will use it in the future.

ViewRootImpl

We learned from the previous section that the click event of the device is transmitted through inputmanagerservice. There are two threads, one for processing and the other for distribution. Where are the events distributed? Send directly to activity or view? This is obviously unreasonable, so there is a viewrootimpl class in the framework layer as a bridge between the two. It should be noted that this class is called viewroot in the source code of the old version.

The viewrootimpl class is initialized in the resume life cycle of the activity and calls the viewrootimpl.setview function. Let's see what this function does.

This method is very long. First, I intercepted a short section, looked at [attention here] I marked, created an instance of inputchannel, and added it to mwindowsession through mwindowsession.addtodisplay method.

What is mwindowsession? From the above code, we can know that mwindowsession is an internal instance in windowmanagerservice. Getwindowmanagerservice gets the proxy object of windowmanagernative, so we can know that mwindowsession is also used for IPC.

If you don't know much about the above paragraph, in other words, if you don't know the binder mechanism of Android, you can settle it yourself first.

Returning to the setview function above, the mwindowsession.addtodisplay method must call the addtodisplay method corresponding to remote, in which the windowmanagerservice:: addwindow method will be called to register the inputchannel with WMS.

After seeing this, you may have questions. The first section is about the events of inputmanagerservice managing devices. How can you deal with windowmanagerservice in this section? The secret is actually in the mwindowsession.addtodisplay method.

WindowManagerService

You can see that in the addwindow method, an array of inputchannels is created. There are two inputchannels in the array. The first is remote, and it is registered in the inputmanager through the minputmanager.registerinputchannel method; The second is on the native side. It points to the outinputchannel through the inputchannels [1]. Transferto (outinputchannel) method, and the outinputchannel is the inputchannel passed from the previous setview, that is, in viewrootimpl.

Through this code, we know that when the activity is initialized, we will register two inputchannels in WMS. The inputchannel on the remote side is registered in the inputmanager to accept the information transmitted from the readerthread and dispatcherthread. The inputchannel on the native side points to the inputchannel in viewrootimpl, It is used to accept the information transmitted from the inputchannel on the remote side.

Finally, back to the setview method of viewrootimpl, there is this sentence:

Windowinputeventreceiver is the receiver that we finally accept events.

Keyboard event delivery

Let's take a look at what windowinputeventreceiver does.

Very simply, when callback to oninputevent function, enqueueinputevent function of viewrootimpl will be called.

You can see that if you need to process the event immediately, you can directly call the doprocessinputevents function. Otherwise, you can call the scheduleprocessinputevents function to join the scheduling.

Let's simplify everything here and look directly at the doprocessinputevents function.

You can see that there is an interesting thing called inputstage in the deliverinputevent function. You can use some marker bits to determine which inputstage is used for processing.

Where are these inputstages initialized? The display is in the setview function.

You can see that so many inputstages have been initialized. The calling order of these stages is strictly controlled. Ime means input method, so you should understand what these preime and postime mean?

From the above, we can see that the inputstage's deliver function will eventually be called:

The apply method is overridden by various subclasses. Let's take viewpreimeinputstage as an example:

As you can see, the dispatchkeyeventpreime method of view will be called. Here, the problem at the beginning of the article is solved. Why is it useless to listen to onkeydown of activity when the input method pops up? Because this event is consumed by the input method, it corresponds to the input stage of imestage; Then why override the dispatchkeyeventpreime method of view? Because it is called in viewpreimeinputstage, it's not imestage's turn yet

summary

Through such an analysis, I believe you have a certain understanding of event distribution in Android. I hope the content of this article can bring some help to your study or work. Thank you for your support for programming tips.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>