Android system-thread-message processing mechanism

introduction:

What is the Android application message processing mechanism?
What is the relationship with Native and the bottom layer of Linux?

Concept and understanding:

Android applications are driven by messages.

1) When each thread of the application starts, it can first create a message queue internally,

2) Then enter the message loop, and constantly check whether his message queue needs to be processed again.
        If there is: then the thread will take it out of the message queue and process it.
        If not: the thread will enter the sleep waiting state until there are new messages that need to be processed.
This is called: driving the execution of the application through the message.

The message processing mechanism of the Android application is implemented around the message queue.

After a thread has a message queue, it can enter a message loop, and at the same time other threads and the thread itself can send messages to the message queue. so that a specific action can be performed while the message is being processed independently. In this way, we can divide the message mechanism into two stages: the creation of the message queue and the cycle of the message queue. The message queue cycle can be divided into: message sending and message processing.

1. Create a message queue

MessageQueue: This object is used to describe the message queue of the Android application thread.

Looper: This object is used to implement loops.

These two objects are implemented in both the Java layer and the Native layer. So Android's message loop mechanism can be used not only in Java code, but also in C++ code. First look at a map:

1) The Java layer has the MessageQueue class and the Looper class, and the Native layer has the NativeMessageQueue class and the Looper class

 2) In Java, each Looper object has a member variable mQueue of MessageQueue type, pointing to a MessageQueue;

3) In Native, each NativeMessageQueue object has a member variable mLooper of type Looper inside, pointing to the Looper object of the Native layer.

This allows the Java layer and the Native layer to associate MessageQueue and Looper together. How are the Java layer and the Native layer related? The answer is mPtr, which is a member variable of type int of the MessageQueue object, which points to NativeMessageQueue.

MessageQueue and Looper constitute the basic framework of a message loop, so where to put the message?

The message is described by a member variable mMessage called Message. This mMessage belongs to the MessageQueue object. MessageQueue, Looper, and Message constitute all the elements of the message loop.

How is the message queue created? How is the message added to the message queue?

Looper can create a message queue through two static member functions:

1) prepareMainLooper: The main thread of the application creates a message queue

2) prepare: the child thread creates a message queue

When these two static member functions are called to create a message queue, the Looper class of the Java layer will create a Looper object and a MessageQueue object in this thread. In the process of creating the MessageQueue object of the Java layer, nativeInit is called to create a NativeMessageQueue object and a Looper object in the C++ layer. The above has explained how the Java layer and the Native layer are associated together. When creating a NativeMessageQueue object, a pipeline is also created. What is the function of this pipeline?

When a thread message queue has no messages to process, it will sleep and wait on the read-end file descriptor of the pipeline until other threads wake it up through the write-end file descriptor of the pipeline. That is, the read-end descriptor can sleep, and the write-end descriptor can wake up

These two descriptors are static member variables belonging to Looper:

mWakeReadPipeFd
mWakeWritePipeFd

How to support the sleep and wake-up of the pipeline?

system/core/libutils/Looper.cpp

It is mainly based on the Epoll message mechanism of Linux. If an epoll instance listens to a large number of file descriptor IO read and write events, but only a small number of file descriptors are active, that is, a small number of file descriptors will have IO read and write events, then this epoll instance can be reduced CPU usage, thereby improving the concurrent processing capability of the system performance.

frameworks/base/core/java/android/os/Looper.java

Guess you like

Origin blog.csdn.net/haigand/article/details/132331338