天天看點

Android系統的開機畫面顯示過程分析(12)

       接下來,我們再繼續分析第三個開機畫面是如何停止顯示的。

        一個Activity元件在啟動起來之後,就會被記錄起來,等到它所運作在的主線程空閑的時候,這個主線程就會向ActivityManagerService發送一個Activity元件空閑的通知。由于應用程式Launcher是系統中第一個被啟動的應用程式,即它的根Activity元件是系統中第一個被啟動的Activity元件,是以,當ActivityManagerService接收到它的空閑通知的時候,就可以知道系統是剛剛啟動起來的。在這種情況下,ActivityManagerService就會停止顯示開機動畫,以便可以在螢幕中顯示應用程式Lancher的界面。

       應用程式的主線程是通過ActivityThread類來描述的,它實作在檔案frameworks/base/core/java/android/app/ActivityThread.java中。每當有一個新的Activity元件啟動起來的時候,ActivityThread類都會向它所描述的應用程式主線程的消息隊列注冊一個類型為Idler的空閑消息處理器。這樣一個應用程式的主線程就可以在空閑的時候,向ActivityManagerService發送一個Activity元件空閑通知,相當于是通知ActivityManagerService,一個新的Activity元件已經準備就緒了。

Idler類定義在frameworks/base/core/java/android/app/ActivityThread.java中, 它的成員函數queueIdle的實作如下所示: 

public final class ActivityThread {   

    ......   

    private final class Idler implements MessageQueue.IdleHandler {   

        public final boolean queueIdle() {   

            ActivityClientRecord a = mNewActivities;   

            if (a != null) {   

                mNewActivities = null;   

                IActivityManager am = ActivityManagerNative.getDefault();   

                ActivityClientRecord prev;   

                do {   

                    ......   

                    if (a.activity != null && !a.activity.mFinished) {   

                        try {   

                            am.activityIdle(a.token, a.createdConfig);   

                            a.createdConfig = null;   

                        } catch (RemoteException ex) {   

                        }   

                    }   

                    prev = a;   

                    a = a.nextIdle;   

                    prev.nextIdle = null;   

                } while (a != null);   

            }   

            ensureJitEnabled();   

            return false;   

        }   

    }   

}   

       ActivityThread類有一個類型為ActivityClientRecord的成員變量mNewActivities,用來描述所有在目前應用程式主線程中新啟動起來的Activity元件。這些新啟動起來的Activity元件通過ActivityClientRecord類的成員變量nextIdle連接配接在一起。一旦目前應用程式主線程向ActivityManagerService發送了這些新啟動的Activity元件的空閑通知之後,這些新啟動起來的Activity元件就不會再被儲存在ActivityThread類的成員變量mNewActivities中了,即每一個新啟動的Activity元件隻有一次機會向ActivityManagerService發送一個空閑通知。

       向ActivityManagerService發送一個Activity元件空閑通知是通過調用ActivityManagerService代理對象的成員函數activityIdle來實作的,而ActivityManagerService代理對象可以通過調用ActivityManagerNative類的靜态成員函數getDefault來獲得。

       ActivityManagerService代理對象的類型為ActivityManagerProxy,它的成員函數activityIdle實作在檔案frameworks/base/core/java/android/app/ActivityManagerNative.java中,如下所示:

class ActivityManagerProxy implements IActivityManager   

{   

    public void activityIdle(IBinder token, Configuration config) throws RemoteException   

    {   

        Parcel data = Parcel.obtain();   

        Parcel reply = Parcel.obtain();   

        data.writeInterfaceToken(IActivityManager.descriptor);   

        data.writeStrongBinder(token);   

        if (config != null) {   

            data.writeInt(1);   

            config.writeToParcel(data, 0);   

        } else {   

            data.writeInt(0);   

        mRemote.transact(ACTIVITY_IDLE_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);   

        reply.readException();   

        data.recycle();   

        reply.recycle();   

      ActivityManagerProxy類的成員函數activityIdle實際上是向ActivityManagerService發送一個類型為ACTIVITY_IDLE_TRANSACTION的Binder程序間通信請求,其中,參數token用來描述與這個程序間通信請求所關聯的一個Activity元件,在我們這個場景中,這個Activity元件即為應用程式Launcher的根Activity元件Launcher。

        類型為ACTIVITY_IDLE_TRANSACTION的Binder程序間通信請求是由ActivityManagerService類的成員函數activityIdle來處理的,如下所示:

public final class ActivityManagerService extends ActivityManagerNative   

        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   

    public final void activityIdle(IBinder token, Configuration config) {   

        final long origId = Binder.clearCallingIdentity();   

        mMainStack.activityIdleInternal(token, false, config);   

        Binder.restoreCallingIdentity(origId);   

    ActivityManagerService類有一個類型為ActivityStack的成員變量mMainStack,它用來描述系統的Activity元件堆棧,它的成員函數activityIdleInternal的實作如下所示:

public class ActivityStack {   

    final void activityIdleInternal(IBinder token, boolean fromTimeout,   

            Configuration config) {   

        ......   

        boolean enableScreen = false;   

        synchronized (mService) {   

            ......   

            // Get the activity record.   

            int index = indexOfTokenLocked(token);   

            if (index >= 0) {   

                ActivityRecord r = (ActivityRecord)mHistory.get(index);                   

                ......   

                if (mMainStack) {   

                    if (!mService.mBooted && !fromTimeout) {   

                        mService.mBooted = true;   

                        enableScreen = true;   

                }   

        if (enableScreen) {   

            mService.enableScreenAfterBoot();   

}           

        參數token用來描述剛剛啟動起來的Launcher元件,通過它來調用函數indexOfTokenLocked就可以得到Launcher元件在系統Activity元件堆棧中的位置index。得到了Launcher元件在系統Activity元件堆棧中的位置index之後,就可以在ActivityStack類的成員變量mHistory中得到一個ActivityRecord對象r。這個ActivityRecord對象r同樣是用來描述Launcher元件的。

        ActivityStack類的成員變量mMainStack是一個布爾變量,當它的值等于true的時候,就說明目前正在處理的ActivityStack對象是用來描述系統的Activity元件堆棧的。 ActivityStack類的另外一個成員變量mService指向了系統中的ActivityManagerService服務。ActivityManagerService服務有一個類型為布爾值的成員變量mBooted,它的初始值為false,表示系統尚未啟動完成。

        從前面的調用過程可以知道,參數fromTimeout的值等于false。在這種情況下,如果ActivityManagerService服務的成員變量mBooted也等于false,那麼就說明應用程式已經啟動起來了,即說明系統已經啟動完成了。這時候ActivityManagerService服務的成員變量mBooted以及變量enableScreen的值就會被設定為true。

        當變量enableScreen的值等于true的時候,ActivityStack類就會調用ActivityManagerService服務的成員函數enableScreenAfterBoot停止顯示開機動畫,以便可以将螢幕讓出來顯示應用程式Launcher的界面。

        ActivityManagerService類的成員函數enableScreenAfterBoot的實作如下所示:

    void enableScreenAfterBoot() {   

        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,   

                SystemClock.uptimeMillis());   

        mWindowManager.enableScreenAfterBoot();   

        ActivityManagerService類的成員變量mWindowManager指向了系統中的Window管理服務WindowManagerService,ActivityManagerService服務通過調用它的成員函數enableScreenAfterBoot來停止顯示開機動畫。

       WindowManagerService類的成員函數enableScreenAfterBoot的實作如下所示:

public class WindowManagerService extends IWindowManager.Stub   

        implements Watchdog.Monitor {   

    public void enableScreenAfterBoot() {   

        synchronized(mWindowMap) {   

            if (mSystemBooted) {   

                return;   

            mSystemBooted = true;   

        performEnableScreen();   

       WindowManagerService類的成員變量mSystemBooted用來記錄系統是否已經啟動完成的。如果已經啟動完成的話,那麼這個成員變量的值就會等于true,這時候WindowManagerService類的成員函數enableScreenAfterBoot什麼也不做就傳回了,否則的話,WindowManagerService類的成員函數enableScreenAfterBoot首先将這個成員變量的值設定為true,接着再調用另外一個成員函數performEnableScreen來執行停止顯示開機動畫的操作。

本文轉自 Luoshengyang 51CTO部落格,原文連結:http://blog.51cto.com/shyluo/967048,如需轉載請自行聯系原作者

繼續閱讀