Chromium on android:android in the system Chromium in order to implement the main message loop analysis

Source: Internet
Author: User
Tags bit set message queue

Summary: Just start touching a chromium on Android time. It's curious how the Chromium master message loop integrates with Android apps.

For Android program, once started, the main thread will have the Java message layer to cycle through system events, such as user input events, and chromium, there is a set of message loop implementation, this implementation has what characteristics. And how to seamlessly integrate into the Android Java layer of the message loop, it is the topic to be discussed in this article.

Original article series. Reprint please indicate original source is http://blog.csdn.net/hongbomin/article/details/41258469.

message loops and main message loops

The message loop, or event loop, is called. is an important concept in the asynchronous programming model for handling asynchronous events that occur in a single thread. These asynchronous events contain user input events, system events. Timer, asynchronous tasks distributed between threads, and so on.

The Chromium system abstracts the message loop into the Messageloop class, which specifies that each thread can execute at most one Messageloop instance at the same time, Messageloop provides a Posttask series method that agrees to add a new asynchronous task to the task queue. When Messageloop discovers that a new task arrives, it from Samsara queries its own task queue and executes the task from "FIFO" until it receives the MESSAGELOOP::QUIT message. The message loop will not exit.

Chromium divides messageloop into several different types according to the asynchronous events that are required to be handled:

    • type_default: The default message loop. can only handle timer timers and asynchronous tasks.
    • type_ui: Not only can handle timer timer and asynchronous task, but also can handle system UI event. The main thread uses this type of messageloop. i.e. the main message loop;
    • Type_io: Supports asynchronous IO events, chromium all the IO threads that process IPC messages are created with messageloop of that type;
    • Type_java: A message loop type designed for the Android platform, and the backend implementation is the JAVA layer's message processor. Used to run tasks that are added to the messageloop. It behaves almost the same as the type_ui type, but cannot be created using the Messagepump factory method on the main thread.

      Note: This type of messageloop is not related to the message loop discussed in this article.

Messageloop details the implementation of the platform, even on the same platforms, because different event processing libraries are used. In fact, the present way may be different.

Chromium encapsulates platform-related implementations in Messagepump abstract classes, the relationships between classes Messageloop and messagepump such as the following:


The detailed implementation of Messagepump provides platform-related asynchronous event handling. While Messageloop provides the basic framework for polling and dispatching asynchronous tasks, both are associated by Messagepump::D elegate abstract interfaces.

The basic code skeleton for Messagepump::run is as follows:

for (;;) {  bool did_work =dointernalwork ();  if (should_quit_) break    ;   Did_work |= delegate_->dowork ();  if (should_quit_) break    ;   Timeticks Next_time;  Did_work |=delegate_->dodelayedwork (&next_time);  if (should_quit_) break    ;   if (did_work)    continue;   Did_work =delegate_->doidlework ();  if (should_quit_) break    ;   if (did_work)    continue;   Waitforwork ();}
In the code snippet above, three points need to be specifically explained:

    • The Messagepump is responsible for responding to the asynchronous events of the system and also for enough time fragments to dispatch delegate to run the asynchronous task. So the messagepump is to call Dointernalwork,dowork, Dodelayedwork and Doidlework in a mixed interleaved way, to ensure that no matter what kind of task does not have to run because of the "hunger" phenomenon;
    • Both Dointernalwork and Waitforwork are private methods that are messagepump implemented in detail. Dointernalwork is responsible for distributing the next UI event or notifying the next IO complete event, and Waitforwork will block the Messagepump::run method until the current task needs to run;
    • Each of the messagepump has a should_quit_ tag bit set. Once the messagepump::quit is called. Should_quit_ will be set to True to check the should_quit_ tag each time messagepump finishes a class of tasks. To decide whether or not to proceed with the task. When Should_quit_ is found to be true. Jumps directly out of the For loop body.

nested message loops (Nested messageloop)

Suppose that the message loop is likened to a dream that needs to do a lot of things. Then nested message loops are "Inception", from one dream into another.

Simply put, the nested message loop is the current message loop in which a task is run into another message loop, and the current message loop is forced to wait for a nested message loop to exit, and the ability to continue running the following tasks, for example. When the MessageBox dialog box pops up. Means entering a new message loop until the MessageBox's OK or cancelbutton is pressed and the message loop ability exits.

Runloop is a class introduced by chromium in the later code refactoring, primarily for developers to use nested message loops more conveniently, each runloop has a run_depth value that represents the number of nested layers, only when run_ A depth value greater than 1 o'clock indicates that the runloop is nested. Runloop is a special object that is created on the stack when the Messageloop::run function is completed. Runloop to release himself voluntarily:

void Messageloop::run () {  runloop run_loop;  Run_loop. Run ();}

There is a pointer in each of the messageloop. Points to the Runloop instance that is currently executing. When the Runloop::run method is called, the Runloop pointer in the messageloop::current () message loop is also changed to the currently executing runloop. In other words, assuming that messageloop::current ()->posttask is called at this point, the asynchronous task will be executed in a nested message loop.

The basic usage of nested message loops is as seen in the following code:

void Runnestedloop (runloop* run_loop) {   messageloop::scopednestabletaskallower allow (Messageloop::current ());   Run_loop->run ();  }} Create a new Runlooprunloop nested_run_loop on the stack; Asynchronously initiates a nested message loop in the current message loop; Messageloop::current ()->posttask (From_here, Base::bind (&runnestedloop,unretained (&nested_run_loop))); /Once the Runnestedloop is running, the Runloop pointer inside Messageloop::current () points to Nested_run_loop, and Posttask runs the quit operation on the nested runloop Messageloop::current ()->posttask (From_here, Nested_run_loop. Quitclosure ());//When the Task_callback is run asynchronously, the nested runloop is now exited and resumed to the original message queue; Messageloop::current ()->posttask (from_ Here,task_callback);

the message loop mechanism of the Android system

The fundamentals of the message loop mechanism on the Android platform are very similar to the chromium system, but the abstraction of the Android message loop is built on the Java layer.

In the Android system, Android.os.Looper and Android.os.Handler are two important classes in the message loop mechanism.

Looper is similar to Chromium's messageloop (or runloop) concept. Each thread in the Android system can associate a looper for handling asynchronous messages or Runable objects. Android system threads are not associated by default no matter what a looper, developers can explicitly call Looper.prepare and Looper.loop to create and execute looper for threads until they exit Looper. The interaction between Looper needs to be completed through the class handler.

Handler agrees that the developer sends or processes messages and runable objects to the thread's message queue, which has two uses: 1) asynchronously handles Message Queuing in its own thread through the Handlemessage method ; 2) Send messages to other threads ' message queues through the SendMessage or POST method series.

When a thread can have multiple handler,looper polling message queues, it is the responsibility to send the message to the target handler, which is handled by the handlemessage of the target handler.

The relationship between Looper and handler, for example, is seen (image from here):


chromium using the Android message loop mechanism

The main discussion here is the message loop for the main thread. That is, the UI thread, because the IO thread was created at the native layer. Does not involve interactive events with UI elements. And Android is also a POSIX system. There is no need to consider the integration of IO thread message loops.

As mentioned above, the message loop of the Android system is built on the Java layer. Chromium the problem that needs to be solved, how to integrate the C + + layer management and dispatch asynchronous task Messageloop into the control path of the Android system on the main thread. The answer, of course, is to use Android.os.Handler.

First look at the Android platform Messagepumpforui detailed implementation. Unlike other platforms, the Messagepumpforui implementation, which starts the entire message loop processing logic, does not do anything, but instead adds a new start method to enable the Android system's message loop in chromium. For example, the following code sees:

void Messagepumpforui::run (delegate* Delegate) {  notreached () << "unittests should rely on Messagepumpforuistub in  test_stub_android.h ";} void Messagepumpforui::start (delegate* Delegate) {  run_loop_ = Newrunloop ();  Since the Runloopwas just created above, Beforerun should is guaranteed to  //return True (Itonly returns False if The Runloop has been Quit already).  if (!run_loop_->beforerun ())    notreached ();  jnienv* env =base::android::attachcurrentthread (); System_message_handler_obj_. Reset (     java_systemmessagehandler_create (          env,reinterpret_cast<intptr_t> (delegate)));}

The Start method makes a request to the Java layer via JNI to create a systemmessagehandler that inherits from Android.os.Handler, adding a new handler type to the Looper of the current UI thread, which provides its own Handlemessage method:

Class Systemmessagehandler extends Android.os.Handler {    private staticfinal int scheduled_work = 1;    Private staticfinal int delayed_scheduled_work = 2;    Privatesystemmessagehandler (Long messagepumpdelegatenative) {       mmessagepumpdelegatenative = messagepumpdelegatenative;    }    @Override public    voidhandlemessage (Message msg) {        if (msg.what== delayed_scheduled_work) {           mdelayedscheduledtimeticks = 0;        }       Nativedorunlooponce (mmessagepumpdelegatenative,mdelayedscheduledtimeticks);} ...}

So. How does the Chromium system C + + layer take a request to run an asynchronous task to the handler of the Androidjava layer, and how does handler run the asynchronous task at the chromiumc++ layer?

The C + + layer sends asynchronous tasks to the Java layer

Whenever the C + + layer joins a new asynchronous task to the UI thread's Messageloop by calling Messageloop::current ()->posttask*. Messageloop::schedulework all initiate the operation of the dispatch task, while Messageloop::schedulework is requesting messagepump to complete the action. Its invocation chain is:


So Messagepumpforui's schedulework need to send a request from the C + + layer to the Java layer's Systemmessagehandler:

void Messagepumpforui::schedulework () {  jnienv* env =base::android::attachcurrentthread ();  Java_systemmessagehandler_schedulework (env,     system_message_handler_obj_.obj ());}

Correspondingly, the Schedulework implementation code for Systemmessagehandler is as follows:

Class Systemmessagehandler extends Handler {   ...   @CalledByNative    Private Voidschedulework () {       sendemptymessage (scheduled_work);   }   ...}

It is not difficult to see that the only thing systemmessagehandler.schedulework to do is to send a type scheduled_work message to the UI thread's message queue. Now let's look at how the Java layer handles this type of message.

Java Layer handler handles asynchronous tasks from the C + + layer

When the looper of the UI thread receives this scheduled_work asynchronous message, it is correctly distributed to Systemmessagehandler, This message is handled by the Systemmessagehandler.handlemessage overloaded method. As you can see from the code above, Handlemessage runs a native method dorunlooponce defined in Messagepumpforui. In fact the modern codes such as the following:

static void Dorunlooponce (jnienv* env, Jobject obj, Jlong native_delegate, Jlong delayed_scheduled_time_ticks) {  Base::messagepump::D elegate* Delegate =      reinterpret_cast<base::messagepump::D elegate*> (native_delegate );  BOOL Did_work =delegate->dowork ();  Base::timeticksnext_delayed_work_time;  Did_work |=delegate->dodelayedwork (&next_delayed_work_time);   if (!next_delayed_work_time.is_null ()) {    if (delayed_scheduled_time_ticks = = 0 | |       Next_delayed_work_time < Base::timeticks::frominternalvalue (           delayed_scheduled_time_ticks)) {     Java_ Systemmessagehandler_scheduledelayedwork (env, obj,         next_delayed_work_time. Tointernalvalue (),         (Next_delayed_work_time-          base::timeticks::now ()). Inmillisecondsroundedup ());    }  }  if (did_work)    return;   Delegate->doidlework ();}

The Dorunlooponce method gives the C + + layer Messageloop the opportunity to handle its own asynchronous tasks, including deferred tasks and idle tasks.

At this point, through the implementation of Messagepumpforui and Systemmessagehandler, the chromium system has been able to seamlessly integrate into the Android message loop on the main thread,

Summary

The handler class provided by the Android SDK provides considerable convenience for the chromium system to seamlessly integrate its own message loops into the Android system. The chromium Messageloop sends an asynchronous message to the Java layer's handler through JNI. When Looper dispatches this asynchronous message, the Java layer's message handler is called by the native method called by JNI to request Chromium's messageloop to invoke the operation of the asynchronous task. This completes the integration of the Chromium browser with the Android system message loop on the main thread.

Original article series. Reprint please indicate original source is http://blog.csdn.net/hongbomin/article/details/41258469.


Copyright notice: This article blog original article. Blogs, without consent, may not be reproduced.

Chromium on android:android in the system Chromium in order to implement the main message loop analysis

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.