1. 程式人生 > >Android開機動畫流程

Android開機動畫流程

Android系統在啟動過程中,最多可以出現三個畫面。第一個開機畫面是在核心啟動的過程中出現,是一個靜態的畫面;第二個畫面是在init程序啟動的過程中出現的,也是一個靜態的畫面;第三個畫面是在系統服務啟動的過程中出現 ,是一個動態的畫面。這三個畫面都是在一個被稱為幀緩衝區(frame buffer,簡稱fb)的硬體裝置上進行渲染的。本文主要分析第三個啟動畫面的流程。
在Android層動畫的流程圖:

先由init啟動SurfaceFlinger程序,對圖形系統進行初始化,再由SurfaceFlinger程序啟動BootAnimation 程序顯示動畫。動畫由一個 while 迴圈播放,在播放迴圈裡呼叫 checkExit ()檢查一個系統標誌,判斷是否應該結束動畫。由此可見,動畫的顯示流程較為簡單,但動畫的結束流程相對複雜,其中經歷了Launcher、ActivityManagerService、SurfaceFlinger……等層層呼叫傳遞訊息,最終在SurfaceFlinger.bootFinished()設定動畫的結束標誌

。下面來具體分析整個從顯示到結束的流程。
首先從init程序開始,init程序是linux核心啟動後啟動的第一個程序,init 會解析init.rc 檔案,啟動其中宣告的服務。關於動畫部分,在init.rc檔案中有這樣的配置:

service surfaceflinger /system/bin/surfaceflinger
    class main
    user system
    group graphics drmrpc
    onrestart restart zygote

init程序會啟動surfaceflinger服務,入口原始檔為/frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp:

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <sys/resource.h> #include <cutils/sched_policy.h> #include <binder/IServiceManager.h> #include <binder/IPCThreadState.h> #include <binder/ProcessState.h> #include <binder/IServiceManager.h> #include "GpuService.h" #include "SurfaceFlinger.h" using namespace android; int main(int, char**) { signal(SIGPIPE, SIG_IGN); // When SF is launched in its own process, limit the number of // binder threads to 4. ProcessState::self()->setThreadPoolMaxThreadCount(4); // start the thread pool sp<ProcessState> ps(ProcessState::self()); ps->startThreadPool(); // instantiate surfaceflinger //建立了一個SurfaceFlinger物件flinger sp<SurfaceFlinger> flinger = new SurfaceFlinger(); setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY); set_sched_policy(0, SP_FOREGROUND); #ifdef ENABLE_CPUSETS // Put most SurfaceFlinger threads in the system-background cpuset // Keeps us from unnecessarily using big cores // Do this after the binder thread pool init set_cpuset_policy(0, SP_SYSTEM); #endif // initialize before clients can connect //初始化 flinger->init(); // publish surface flinger //加入ServiceManager中進行管理,最後啟動服務 sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false); // publish GpuService sp<GpuService> gpuservice = new GpuService(); sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false); // run surface flinger in this thread flinger->run(); return 0; }

在上面的原始檔中建立了一個SurfaceFlinger物件flinger,然後呼叫flinger->init()進行初始化,再將其加入ServiceManager中進行管理,最後啟動服務。
我們來看一下frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp中的init()初始化函式:

void SurfaceFlinger::init() {
    ALOGI(  "SurfaceFlinger's main thread ready to run. "
            "Initializing graphics H/W...");

    { // Autolock scope
        Mutex::Autolock _l(mStateLock);

        // initialize EGL for the default display
        mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        eglInitialize(mEGLDisplay, NULL, NULL);

        // start the EventThread
        sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                vsyncPhaseOffsetNs, true, "app");
        mEventThread = new EventThread(vsyncSrc, *this);
        sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                sfVsyncPhaseOffsetNs, true, "sf");
        mSFEventThread = new EventThread(sfVsyncSrc, *this);
        mEventQueue.setEventThread(mSFEventThread);

        // Get a RenderEngine for the given display / config (can't fail)
        mRenderEngine = RenderEngine::create(mEGLDisplay,
                HAL_PIXEL_FORMAT_RGBA_8888);
    }

    // Drop the state lock while we initialize the hardware composer. We drop
    // the lock because on creation, it will call back into SurfaceFlinger to
    // initialize the primary display.
    mHwc = new HWComposer(this);
    mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));

    Mutex::Autolock _l(mStateLock);

    // retrieve the EGL context that was selected/created
    mEGLContext = mRenderEngine->getEGLContext();

    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
            "couldn't create EGLContext");

    // make the GLContext current so that we can create textures when creating
    // Layers (which may happens before we render something)
    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);

    mEventControlThread = new EventControlThread(this);
    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);

    // initialize our drawing state
    mDrawingState = mCurrentState;

    // set initial conditions (e.g. unblank default device)
    initializeDisplays();

    // start boot animation
    //呼叫startBootAnim()開始動畫顯示
    startBootAnim();

    ALOGV("Done initializing");
}

init()函式主要是對螢幕顯示視窗進行初始化工作。在最後呼叫了startBootAnim(),我們來看一下SurfaceFlinger.cpp中的startBootAnim()函式:

void SurfaceFlinger::startBootAnim() {
    // start boot animation
    property_set("service.bootanim.exit", "0");
    property_set("ctl.start", "bootanim");
}

其中先將”service.bootanim.exit”標誌為 0,這個標誌用於在bootanim程序中檢測開機動畫是否結束,然後通過發”ctl.start”請求給init程序,啟動”bootanim”服務。
這裡需要注意的是,開機動畫程序在init.rc中註冊過了,但是在解析init.rc檔案時並沒有直接啟動,而是由SurfaceFlinger服務來啟動。這是因為init.rc 雖然註冊了bootanimation服務,但是被disabled了。所以在解析init.rc檔案時,bootanimation並沒有被直接啟動。

service bootanim /system/bin/bootanimation
    class main
    user root
    group graphics
    disabled
    oneshot

由SurfaceFlinger啟動的原因是開機動畫必須得有顯示視窗,而這個顯示視窗則是由SurfaceFlinger提供的,所以必須得在SurfaceFlinger初始化完成之後,才開始顯示開機動畫。
下面轉到bootanimation,入口檔案為 frameworks/base/cmds/bootanimation/bootanimation_main.cpp :

int main()
{
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);

    char value[PROPERTY_VALUE_MAX];
    property_get("debug.sf.nobootanimation", value, "0");
    int noBootAnimation = atoi(value);
    ALOGI_IF(noBootAnimation,  "boot animation disabled");
    if (!noBootAnimation) {

        sp<ProcessState> proc(ProcessState::self());
        ProcessState::self()->startThreadPool();

        // create the boot animation object
        sp<BootAnimation> boot = new BootAnimation();

        IPCThreadState::self()->joinThreadPool();

    }
    return 0;
}

啟動了一個執行緒池。BootAnimation物件在顯示第三個開機畫面的過程中,需要與SurfaceFlinger服務通訊,因此bootanimation就需要啟動一個Binder執行緒池。
這裡的BootAnimation類(frameworks\base\cmds\bootanimation\BootAnimation.cpp)間接地繼承了RefBase類,並且重寫了RefBase類的成員函式onFirstRef():

void BootAnimation::onFirstRef() {
    status_t err = mSession->linkToComposerDeath(this);
    ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
    if (err == NO_ERROR) {
        run("BootAnimation", PRIORITY_DISPLAY);
    }
}

因此,當一個BootAnimation物件boot第一次被智慧指標引用的時,物件的成員函式onFirstRef()會被呼叫。
此外BootAnimation類繼承了Thread類(\system\core\libutils\Threads.cpp):

BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true) {
    mSession = new SurfaceComposerClient();
}

Thread 類有個run() 函式,在run()函式中會呼叫_threadLoop()函式,而_threadLoop函式又呼叫了readyToRun和threadLoop兩個函式:

do {
        bool result;
        if (first) {
            first = false;
            self->mStatus = self->readyToRun();
            result = (self->mStatus == NO_ERROR);

            if (result && !self->exitPending()) {
                // Binder threads (and maybe others) rely on threadLoop
                // running at least once after a successful ::readyToRun()
                // (unless, of course, the thread has already been asked to exit
                // at that point).
                // This is because threads are essentially used like this:
                //   (new ThreadSubclass())->run();
                // The caller therefore does not retain a strong reference to
                // the thread and the thread would simply disappear after the
                // successful ::readyToRun() call instead of entering the
                // threadLoop at least once.
                result = self->threadLoop();
            }
        } else {
            result = self->threadLoop();
        }

BootAnimation類重寫了readyToRun和threadLoop這兩個函式:

status_t BootAnimation::readyToRun() {
    mAssets.addDefaultAssets();

    sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
            ISurfaceComposer::eDisplayIdMain));
    DisplayInfo dinfo;
    status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
    if (status)
        return -1;

    // create the native surface
    // 初始化opengl和繪圖表面surface
    sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);

    SurfaceComposerClient::openGlobalTransaction();
    control->setLayer(0x40000000);
    SurfaceComposerClient::closeGlobalTransaction();

    sp<Surface> s = control->getSurface();

    // initialize opengl and egl
    const EGLint attribs[] = {
            EGL_RED_SIZE,   8,
            EGL_GREEN_SIZE, 8,
            EGL_BLUE_SIZE,  8,
            EGL_DEPTH_SIZE, 0,
            EGL_NONE
    };
    EGLint w, h;
    EGLint numConfigs;
    EGLConfig config;
    EGLSurface surface;
    EGLContext context;

    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

    eglInitialize(display, 0, 0);
    eglChooseConfig(display, attribs, &config, 1, &numConfigs);
    surface = eglCreateWindowSurface(display, config, s.get(), NULL);
    context = eglCreateContext(display, config, NULL, NULL);
    eglQuerySurface(display, surface, EGL_WIDTH, &w);
    eglQuerySurface(display, surface, EGL_HEIGHT, &h);

    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
        return NO_INIT;

    mDisplay = display;
    mContext = context;
    mSurface = surface;
    mWidth = w;
    mHeight = h;
    mFlingerSurfaceControl = control;
    mFlingerSurface = s;

    // If the device has encryption turned on or is in process
    // of being encrypted we show the encrypted boot animation.
    char decrypt[PROPERTY_VALUE_MAX];
    property_get("vold.decrypt", decrypt, "");

    bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
    // 判斷是否有開機動畫檔案 bootanimation.zip 存在
    if (encryptedAnimation && (access(getAnimationFileName(IMG_ENC), R_OK) == 0)) {
        mZipFileName = getAnimationFileName(IMG_ENC);
    }
    else if (access(getAnimationFileName(IMG_OEM), R_OK) == 0) {
        mZipFileName = getAnimationFileName(IMG_OEM);
    }
    else if (access(getAnimationFileName(IMG_SYS), R_OK) == 0) {
        mZipFileName = getAnimationFileName(IMG_SYS);
    }
    return NO_ERROR;
}

bool BootAnimation::threadLoop()
{
    bool r;
    // We have no bootanimation file, so we use the stock android logo
    // animation.
    if (mZipFileName.isEmpty()) {
        r = android();
    } else {
        r = movie();
    }

    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglDestroyContext(mDisplay, mContext);
    eglDestroySurface(mDisplay, mSurface);
    mFlingerSurface.clear();
    mFlingerSurfaceControl.clear();
    eglTerminate(mDisplay);
    IPCThreadState::self()->stopProcess();
    return r;
}

readyToRun() 主要是對opengl工作環境進行初始化,判斷使用者自定義的開機動畫檔案是否存在,儲存結果到mZipFileName 成員變數中。threadLoop 就開始真正的播放動畫了,當mZipFileName是空時,則播放Android系統預設的開機動畫,否則播放使用者自定義的開機動畫 。自定義的開機動畫是由檔案USER_BOOTANIMATION_FILE或者檔案SYSTEM_BOOTANIMATION_FILE來描述的。只要其中的一個檔案存在,那麼開機畫面就會使用使用者自定義的開機動畫。
android() 播放的是系統原生動畫,“android”字樣加上不斷移動的光影效果。movie() 則是讀取bootanimation.zip 中的幀動畫,一張一張的輪播,形成動畫效果。下面來分析下這Android系統動畫函式android(),它還是存在於BootAnimation.cpp檔案中:

//播放系統原生動畫
bool BootAnimation::android()
{
    initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
    initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");

    // clear screen
    glShadeModel(GL_FLAT);
    glDisable(GL_DITHER);
    glDisable(GL_SCISSOR_TEST);
    glClearColor(0,0,0,1);
    glClear(GL_COLOR_BUFFER_BIT);
    eglSwapBuffers(mDisplay, mSurface);

    glEnable(GL_TEXTURE_2D);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    const GLint xc = (mWidth  - mAndroid[0].w) / 2;
    const GLint yc = (mHeight - mAndroid[0].h) / 2;
    const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);

    glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
            updateRect.height());

    // Blend state
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    const nsecs_t startTime = systemTime();
    do {
        nsecs_t now = systemTime();
        double time = now - startTime;
        float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w;
        GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w;
        GLint x = xc - offset;

        glDisable(GL_SCISSOR_TEST);
        glClear(GL_COLOR_BUFFER_BIT);

        glEnable(GL_SCISSOR_TEST);
        glDisable(GL_BLEND);
        glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
        glDrawTexiOES(x,                 yc, 0, mAndroid[1].w, mAndroid[1].h);
        glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h);

        glEnable(GL_BLEND);
        glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
        glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h);

        EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
        if (res == EGL_FALSE)
            break;

        // 12fps: don't animate too fast to preserve CPU
        const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now);
        if (sleepTime > 0)
            usleep(sleepTime);

        checkExit();
    } while (!exitPending());

    glDeleteTextures(1, &mAndroid[0].name);
    glDeleteTextures(1, &mAndroid[1].name);
    return false;
}

使用一個while迴圈去繪圖,並在迴圈中呼叫 checkExit()判斷是否應該結束動畫。
checkExit()也存在於BootAnimation.cpp檔案中:

void BootAnimation::checkExit() {
    // Allow surface flinger to gracefully request shutdown
    char value[PROPERTY_VALUE_MAX];
    property_get(EXIT_PROP_NAME, value, "0");
    int exitnow = atoi(value);
    if (exitnow) {
        requestExit();
        if (mAudioPlayer != NULL) {
            mAudioPlayer->requestExit();
        }
    }
}

檢測到 “service.bootanim.exit” 的值被修改成非 0 之後,就呼叫 requestExit() 結束動畫。
requestExit() 函式是父類 Thread 中定義的,在Threads.cpp檔案中:

void Thread::requestExit()
{
    Mutex::Autolock _l(mLock);
    mExitPending = true;
}
bool Thread::exitPending() const
{
    Mutex::Autolock _l(mLock);
    return mExitPending;
}

設定了一個標誌位 mExitPending = true,表明準備退出執行緒。while (!exitPending()) 迴圈條件就變為 false了,退出動畫執行緒。movie() 的流程也是類似。
下面我們來看看”service.bootanim.exit”。經過分析可知在\frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp檔案中將這個標誌設定為了 “1”:

void SurfaceFlinger::bootFinished()
{
    const nsecs_t now = systemTime();
    const nsecs_t duration = now - mBootTime;
    ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
    mBootFinished = true;

    // wait patiently for the window manager death
    const String16 name("window");
    sp<IBinder> window(defaultServiceManager()->getService(name));
    if (window != 0) {
        window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
    }

    // stop boot animation
    // formerly we would just kill the process, but we now ask it to exit so it
    // can choose where to stop the animation.
    //將service.bootanim.exit的值設定為1
    property_set("service.bootanim.exit", "1");

    const int LOGTAG_SF_STOP_BOOTANIM = 60110;
    LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
                   ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}

在frameworks\native\libs\gui\ISurfaceComposer.cpp中呼叫了bootFinished():

status_t BnSurfaceComposer::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
    ……
            case BOOT_FINISHED: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            bootFinished();
            return NO_ERROR;
        }
        ……
   }
}

現在來探究是誰傳送了BOOT_FINISHED 訊息給SurfaceFlinger 服務,檢視程式碼發現,在\frameworks\native\include\gui\ISurfaceComposer.h中有定義BOOT_FINISHED:

class BnSurfaceComposer: public BnInterface<ISurfaceComposer> {
……
public:
    enum {
        // Note: BOOT_FINISHED must remain this value, it is called from
        // Java by ActivityManagerService.
        BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
……
}
……
}

發現在\services\core\java\com\android\server\wm\WindowManagerService.java中有傳送 IBinder::FIRST_CALL_TRANSACTION 訊息,並註釋說是 BOOT_FINISHED :

public void performEnableScreen() {
……
try {
                    IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
                    if (surfaceFlinger != null) {
                        //Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
                        Parcel data = Parcel.obtain();
                        data.writeInterfaceToken("android.ui.ISurfaceComposer");
                        surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
                                data, null, 0);
                        data.recycle();
                    }
                    ……
}

獲取 SurfaceFlinger 服務,傳送了 IBinder.FIRST_CALL_TRANSACTION 訊息。
在WindowManagerService.java中的enableScreenAfterBoot()是開機流程中的服務:

    public void enableScreenAfterBoot() {
        synchronized(mWindowMap) {
            if (DEBUG_BOOT) {
                RuntimeException here = new RuntimeException("here");
                here.fillInStackTrace();
                Slog.i(TAG_WM, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
                        + " mShowingBootMessages=" + mShowingBootMessages
                        + " mSystemBooted=" + mSystemBooted, here);
            }
            if (mSystemBooted) {
                return;
            }
            mSystemBooted = true;
            hideBootMessagesLocked();
            // If the screen still doesn't come up after 30 seconds, give
            // up and turn it on.
            mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
        }

        mPolicy.systemBooted();

        performEnableScreen();
    }

在frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java又呼叫了 ActivityManagerService.enableScreenAfterBoot() :

final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
        Configuration config) {
    ...
    if (enableScreen) {
        mService.enableScreenAfterBoot();
    }   
    ...
}

在WindowManagerService.java中呼叫了ActivityStackSupervisor.activityIdleInternalLocked():

@Override
public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
    final long origId = Binder.clearCallingIdentity();
    synchronized (this) {
        ActivityStack stack = ActivityRecord.getStackLocked(token);
        if (stack != null) {
            ActivityRecord r = 
                mStackSupervisor.activityIdleInternalLocked(token, false, config);
            if (stopProfiling) {
                if ((mProfileProc == r.app) && (mProfileFd != null)) {
                    try {
                        mProfileFd.close();
                    } catch (IOException e) {
                    }   
                    clearProfilerLocked();
                }   
            }   
        }   
    }   
    Binder.restoreCallingIdentity(origId);
}

而在ActivityThread 中又呼叫了ActivityManagerService.activityIdle():

private class Idler implements MessageQueue.IdleHandler {
    @Override
        public final boolean queueIdle() {
            ...
                    if (a.activity != null && !a.activity.mFinished) {
                        try {
                            am.activityIdle(a.token, a.createdConfig, stopProfiling);
                            a.createdConfig = null;
                        } catch (RemoteException ex) {
                            // Ignore
                        }
                    }
           ...
}

ActivityThread 類就是android應用程式的主執行緒。這個 Idler 類是在 handleResumeActivity 被註冊到主執行緒 ActivityThread 中的:

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
        boolean reallyResume) {
...
        if (!r.onlyLocalRequest) {
            r.nextIdle = mNewActivities;
            mNewActivities = r;
            if (localLOGV) Slog.v(
                    TAG, "Scheduling idle handler for " + r); 
            Looper.myQueue().addIdleHandler(new Idler());
        }   
        r.onlyLocalRequest = false;

        // Tell the activity manager we have resumed.
        if (reallyResume) {
            try {
                ActivityManagerNative.getDefault().activityResumed(token);
            } catch (RemoteException ex) {
            }   
        }   
...
}

也就是說一個Activity 在Resume的時候會註冊一個空閒處理函式到主執行緒,主執行緒空閒的時候就會呼叫這個函式。
那麼開機動畫結束和Activity的啟動有什麼關係呢?我們可以理解為Android系統啟動完成後,就會啟動Launcher中的主Activity,一旦Launcher的Activity啟動完成之後,如果沒有使用者操作,就會進入空閒狀態,ActivityThread就會呼叫註冊的IdleHandler。然後層層轉發呼叫,最終呼叫SurfaceFlinger去終止開機動畫。
上面的分析是從下往上分析的,下面再從頂向下理一遍:

  1. Launcher啟動,註冊一個Idler空閒處理器到ActivityThread中;
  2. Launcher主執行緒空閒的時候就會呼叫Idler。queueIdle()方法;
  3. Idler.queueIdle() 通過Binder通訊呼叫了ActivityManagerService.activityIdle()方法
  4. 呼叫ActivityStackSupervisor.activityIdleInternalLocked()方法;
  5. 呼叫ActivityManagerService.enableScreenAfterBoot()方法;
  6. 呼叫WindowManagerService.enableScreenAfterBoot()方法;
  7. 呼叫WindowManagerService.performEnableScreen()方法;
  8. performEnableScreen 通過Binder通訊傳送 BOOT_FINISHED 訊息給 ISurfaceComposer
  9. 呼叫ISurfaceComposer 收到 BOOT_FINISHED 訊息後呼叫SurfaceFlinger::bootFinished 函式設定動畫結束標誌。

我們可以在各個方法呼叫點加Log來進行除錯。