Android thread Management (ii)--activitythread

Source: Internet
Author: User

Thread communication, Activitythread, and thread classes are key to understanding Android threading management.

threads, as the basic unit of CPU scheduling resources, have a very important and fundamental role in the operating system for embedded devices such as Android. This section is mainly from the following three aspects of analysis:

    1. "Android thread Management (i)--thread communication"
    2. "Android Threading Management (ii)--activitythread"
    3. Android Threading Management (iii) Internal principles, sleep and wake of the--thread class

Second, the main work of activitythread and the realization mechanism

Activitythread is the main thread of the Android app (UI thread), speaking of Activitythread, has to mention the activity's creation, startup process, and Activitymanagerservice, However, this article will analyze Activitythread only from the perspective of thread management. Activitymanagerservice, Activitystack, Applicationthread, etc. will be detailed analysis in the following articles, please look forward to Oh ~ ~ But in order to clarify the origin of activitythread, or need a brief introduction.

The following references are from the blog of the Luo Shenyang Master: A brief introduction to the activity initiation process of the Android app and a learning Plan

Step 1. Start a new activity either through launcher, or by invoking the StartActivity interface inside the activity. All through the binder interprocess communication into the activitymanagerservice process, and call the Activitymanagerservice.startactivity interface;

Step 2. Activitymanagerservice calls Activitystack.startactivitymaywait to prepare information about the activity to be started;

Step 3. Activitystack notify Applicationthread To do activity start scheduling, The Applicationthread here represents the process of invoking the Activitymanagerservice.startactivity interface, which is launcher for the scenario by clicking on the application icon, and for invoking s within the activity Tartactivity scenario, this process is the process of the activity;

Step 4. Applicationthread does not perform a real boot operation, It enters into the activitymanagerservice process by calling the Activitymanagerservice.activitypaused interface to see if a new process needs to be created to start the activity;

Step 5. For a story that launches an activity by tapping the application icon, Activitymanagerservice in this step calls startprocesslocked to create a new process, This step is not required to start a new activity by invoking startactivity within the activity, as the new activity is started in the same process as the original activity;

Step 6. Activitymanagerservic calls the Applicationthread.schedulelaunchactivity interface to notify the appropriate process to perform the activity operation;

Step 7. Applicationthread the action that initiates the activity to Activitythread,activitythread to import the corresponding activity class through ClassLoader, and then start it up.

This description of the master tells the Activitymanagerservice, Activitystack, Applicationthread, and Activitythread of the call relationship very clearly, This paper begins with the main () method of Activitythread and analyzes its primary work and implementation mechanism.

Activitythread Source from: https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/ Activitythread.java

public static void Main (string[] args) {Trace.tracebegin (Trace.trace_tag_activity_manager, "Activitythreadmain");        Samplingprofilerintegration.start ();  Closeguard defaults to True and can is quite spammy. We//Disable it here, but selectively enable it later (via/strictmode) on debug builds, but using DROPBO        x, not logs.        Closeguard.setenabled (FALSE);        Environment.initforcurrentuser ();        Set The reporter for event logging in Libcore eventlogger.setreporter (New Eventloggingreporter ());        Androidkeystoreprovider.install (); Make sure Trustedcertificatestore looks in the right place for CA certificates final File Configdir = environmen        T.getuserconfigdirectory (Userhandle.myuserid ());        Trustedcertificatestore.setdefaultuserdirectory (Configdir);         Process.setargv0 ("<pre-initialized>");Looper.preparemainlooper (); Activitythread Thread= new Activitythread (); Thread.attach (false); if (Smainthreadhandler = =null) {Smainthreadhandler =Thread.gethandler (); } if (false) {Looper.mylooper (). setmessagelogging (New Logprinter (Log.debug, "Activitythread")); }//End of event Activitythreadmain.trace.traceend (Trace.trace_tag_activity_manager); Looper.loop ();throw new RuntimeException ("Main thread loop unexpectedly exited"); }

In the above code, the red part of the code before the main use for the environment initialization, androidkeystoreprovider installation, etc., here do not focus on the description. The code in the Red section is divided into two function blocks: 1) The main thread of the binding application process to ACTIVITYMANAGERSERVICE;2) handler message processing.

For the thread communication mechanism, Handler, MessageQueue, message and Looper, please refer to the previous article "Android Thread management-thread communication".

2.1 Apply Process Bindings

The main () method binds the application process through Thread.attach (false). Activitymanagernative returns an instance of Activitymanagerservice through the Getdefault () method, Activitymanagerservice binds Applicationthread objects to activitymanagerservice through Attachapplication, Applicationthread, as binder, implements Activitymanagerservice communication and control of the application process.

private void Attach (Boolean system) {        scurrentactivitythread = this;        Msystemthread = System;        if (!system) {            ...
            Runtimeinit.setapplicationobject (Mappthread.asbinder ());            Final Iactivitymanager mgr = Activitymanagernative.getdefault ();            try {                mgr.attachapplication (mappthread);            } catch (RemoteException ex) {                //Ignore            }            ...
        } else {    ...    }}

Inside the Activitymanagerservice, Attachapplication is actually implemented by calling Attachapplicationlocked, where the synchronized keyword is used to ensure synchronization.

@Overridepublic final void attachapplication (Iapplicationthread thread) {    synchronized (this) {        int Callingpid = Binder.getcallingpid ();        Final Long Origid = Binder.clearcallingidentity ();        attachapplicationlocked (thread, callingpid);        Binder.restorecallingidentity (Origid);    }}

The implementation of attachapplicationlocked is more complex and its main functions are divided into two parts:

    • Thread.bindapplication

    • Mstacksupervisor.attachapplicationlocked (APP)

Private Final Boolean attachapplicationlocked (iapplicationthread thread, int pid) {//Find the Applicat Ion record that is being attached ... either via//the PID if we are running in multiple processes, or just pull t        He//Next app record if we is emulating process with anonymous threads.        Processrecord app; if (pid! = my_pid && pid >= 0) {synchronized (mpidsselflocked) {app = Mpidsselflock            Ed.get (PID);        }} else {app = null; }//... try {//.....thread.bindapplication (ProcessName, AppInfo, providers, App.instrumentationclass, Profilerinfo, app . instrumentationarguments, App.instrumentationwatcher, App.instrumentationuiautomationconnection, TestM Ode, Enableopengltrace, Enabletrackallocation, Isrestrictedbackupmode|| !Normalmode, app.persistent, newConfiguration (mconfiguration), App.compat, getcommonserviceslocked (app.isolated), Mcoresettingsobserver.getcoresettingslocked ());Updatelruprocesslocked (app, false, NULL);        APP.LASTREQUESTEDGC = App.lastlowmemory = Systemclock.uptimemillis ();  } catch (Exception e) {//todo:yikes!  What should we do?  For now we'll try to//start another process, but this could easily get us in//an infinite loop            of restarting processes ...            SLOG.WTF (TAG, "Exception thrown during bind of" + app, E);            App.resetpackagelist (Mprocessstats);            App.unlinkdeathrecipient ();            startprocesslocked (app, "Bind fail", processName);        return false;                 }//See if the top visible activity was waiting to run with this process ... if (Normalmode) {try { if (mstacksupervisor.attachapplicationlocked (APP)) {didsomething = true;                }} catch (Exception e) {slog.wtf (TAG, "Exception thrown launching activities in" + app, E);            Badapp = true; } } // ...... }

The thread object is actually a proxy object in the Activitythread Applicationthread object in Activitymanagerservice, So executing thread.bindapplication will eventually call the Applicationthread Bindapplication method. The essence of the Bindapplication method is to call the Handlebindapplication method by sending a bind_application message to Activitythread message queue, The important thing about the Handlebindapplication method is that it calls the following methods:

Minstrumentation.callapplicationoncreate (APP);

Callapplicationoncreate calls the OnCreate () method of the application application, stating that the OnCreate () method of application is called first, than the OnCreate () method of all activity.

The mstacksupervisor is a member variable of Activitymanagerservice, and the type is activitystacksupervisor.

/** Run all activitystacks through this */activitystacksupervisor mstacksupervisor;

As you can see from the annotations,Mstacksupervisor is an instance of the helper class that manages the activity stack. The attachapplicationlocked () method of Activitystacksupervisor calls the realstartactivitylocked () method, In the Realstartactivitylocked () method, the Schedulelaunchactivity () method is called:

Final Boolean realstartactivitylocked (Activityrecord R,        Processrecord app, Boolean Andresume, Boolean checkconfig)        throws RemoteException {     //...      try {        //...        App.thread.scheduleLaunchActivity (New Intent (r.intent), R.apptoken,                System.identityhashcode (R), R.info,                New Configuration (mservice.mconfiguration),                R.compat, r.icicle, results, newintents,!andresume,                Mservice.isnexttransitionforward (), Profilefile, PROFILEFD,                profileautostop);         //...     } catch (RemoteException e) {        //...    }    //...        return true;}

App.thread is also a proxy object for the Applicationthread object in Activitymanagerservice, and eventually calls the Schedulelaunchactivity method of Applicationthread.

We use tokens to identify this activity without have to send the//activity itself back to the activity manager. (matters more with IPC) @Overridepublic final void schedulelaunchactivity (Intent Intent, ibinder token, int ident,    Act Ivityinfo info, configuration curconfig, configuration overrideconfig,    compatibilityinfo compatinfo, String Referrer, Ivoiceinteractor voiceinteractor,    int procstate, Bundle state, Persistablebundle PersistentState,    List<resultinfo> Pendingresults, List<referrerintent> pendingnewintents,    boolean notResumed, Boolean isforward, Profilerinfo profilerinfo) {        updateprocessstate (procstate, false);        Activityclientrecord r = new Activityclientrecord ();        ... SendMessage (h.launch_activity, R);}

The same bindapplication () method, which ends with sending a message to the Activitythread message queue, completes the actual launch_activity operation at Activitythread.

public void Handlemessage (Message msg) {    if (debug_messages) slog.v (TAG, ">>> handling:" + codetostring (msg . what));    Switch (msg.what) {case        launch_activity: {            trace.tracebegin (Trace.trace_tag_activity_manager, " Activitystart ");            Final Activityclientrecord r = (activityclientrecord) msg.obj;            R.packageinfo = Getpackageinfonocheck (                r.activityinfo.applicationinfo, r.compatinfo);            Handlelaunchactivity (R, NULL);            Trace.traceend (Trace.trace_tag_activity_manager);            } break;    ......}

Handlelaunchactivity () is used to initiate activity. The specific start-up process is not detailed here, which focuses on the thread communication mechanism of applicationthread and activitythread.

2.2 Main thread Message processing

In the "Android thread management-thread communication" in the general thread of the handler, MessageQueue, message and looper of the relationship between the four, then the activitythread of the thread communication is different? The difference is mainly shown as two points: 1) looper initialization mode, 2) handler generation.

First, Activitythread Looper.preparemainlooper () initializes the Looper, in order to visually compare the differences between activitythread and normal thread initialization looper, put together two initialization methods:

/** Initialize The current thread as a looper. * This gives you a chance to create handlers so reference * This looper, before actually starting the loop.      Be sure to call * {@link #loop ()} After calling this method, and end it by calling * {@link #quit ()}.    */public static void prepare () {prepare (true); } private static void Prepare (Boolean quitallowed) {if (sthreadlocal.get () = null) {throw new Runt        Imeexception ("Only one Looper could be created per thread");    } sthreadlocal.set (New Looper (quitallowed)); }/** * Initialize the current thread as a looper, marking it as an * application ' s main looper. The main looper for your application * are created by the Android environment, so we should never need * to call T  His function yourself.        See also: {@link #prepare ()} */public static void Preparemainlooper () {prepare (false); Synchronized (looper.class) {iF (smainlooper! = null) {throw new IllegalStateException ("The main Looper has already been prepared.");        } Smainlooper = Mylooper (); }    }
    • The prepare () method of the normal thread is true for the default quitallowed parameter, which means that exit is allowed, Activitythread calls the prepare () method in the Preparemainlooper () method, and the argument is false, Indicates that the main thread is not allowed to exit.
    • The normal thread only calls the prepare () method, activitythread the local thread <ThreadLocal> by the Mylooper () method after the prepare () method is called The reference to the Looper object is given to Smainlooper. Mylooper () is actually a call to Sthreadlocal's get () method implementation.
/**     * Return The Looper object associated with the current thread.  Returns     * NULL if the calling thread is not associated with a Looper.     *    /public static Looper Mylooper () {        return sthreadlocal.get ();    }
    • The reason to pass Smainlooper to the Looper object of Activitythread is to open the Looper object of the main thread to other threads through the Getmainlooper () method.
/** Returns The application ' s main Looper, which lives in the main thread of the application.     *    /public static Looper Getmainlooper () {        synchronized (looper.class) {            return smainlooper;        }    }

Second, the handler generation of activitythread and normal threads is not the same. The normal line generates into a looper bound handler, activitythread through Smainthreadhandler to the return value of GetHandler (), and GetHandler () method returns an H object that inherits handler.

Private class H extends Handler {    ...} Final h MH = new H (); final Handler gethandler () {    return MH;}

The real implementation of the message mechanism "pass" the letter is actually the Looper loop () method, the loop () method core implementation is as follows:

/** * Run The message queue in this thread.     Be sure to call * {@link #quit ()} to end of the loop.        */public static void loop () {final Looper me = Mylooper (); if (me = = null) {throw new RuntimeException ("No Looper;        Looper.prepare () wasn ' t called on this thread. ");        Final MessageQueue queue = Me.mqueue; Make sure the identity of the the the the The local process,//and keep track of what the identity toke        n actually is.        Binder.clearcallingidentity ();        Final Long ident = Binder.clearcallingidentity (); for (;;) {Message msg = Queue.next ();//might block if (msg = = NULL) {//No Message Indicat                ES the message queue is quitting.            Return }//This must is in a local variable, in case a UI event sets the logger Printer logging = Me.mlogg            ing if (logging! = null) {LOGGING.PRINTLN (">>>>> dispatching to "+ Msg.target +" "+ Msg.callback +": "+ msg.what);            } msg.target.dispatchMessage (msg); if (logging! = null) {logging.println ("<<<<< finished to" + Msg.target + "" + Msg.callbac            k);             }//Make sure that during the course of dispatching the//identity of the thread wasn ' t corrupted.            Final Long newident = Binder.clearcallingidentity (); if (ident! = newident) {LOG.WTF (TAG, "Thread identity changed from 0x" + Long.tohex                        String (ident) + "to 0x" + long.tohexstring (newident) + "when dispatching to"            + Msg.target.getClass (). GetName () + "" + Msg.callback + "what=" + msg.what);        } msg.recycle (); }    }

The approximate process is as follows:

    • First obtains the Looper object through above Mylooper () method, takes out Looper holds the MessageQueue;
    • The message is then removed from the MessageQueue, if the message is NULL, indicating that the thread is exiting;
    • Message is not empty, the message is distributed by the target handler that invokes the message, and the specific distribution and processing process can refer to "Android Thread management-thread communication";
    • After the message is processed, the recycle () method is called to recycle.

Android thread Management (ii)--activitythread

Related Article

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.