android開機動畫啟動流程


  開機動畫是在SurfaceFlinger實例通過調用startBootAnim()啟動的,BootAnim是如何啟動和結束的,總體框架圖如下:

 技術分享

 

1.init.rc

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

  init進程會根據init.rc配置啟動surfaceflinger進程,surfaceflinger進程啟動了,跟着就會跑進程的main()函數。

 

2.frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp

int main(int argc, char** argv) {
....

    // instantiate surfaceflinger
    sp<SurfaceFlinger> flinger = new SurfaceFlinger();//創建surfaceflinger服務實例

....
    flinger->init();

    // publish surface flinger
    sp<IServiceManager> sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);//注冊到service manager里

    // run in this thread
    flinger->run();//運行

    return 0;
}

  首先new一個SurfaceFlinger實例,然后init,然后run

 

3.frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

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

 .....
    // start boot animation
    startBootAnim();//開始播放動畫
}

  初始化graphics之后,就調用startBootAnim()播放開機動畫。

void SurfaceFlinger::startBootAnim() {
    // start boot animation
    mBootFinished = false;
    property_set("service.bootanim.exit", "0");//這個會有bootanimation進程周期檢測,=1退出動畫
    property_set("ctl.start", "bootanim");//通過ctl.start命令啟動bootanim
}

  把service.bootanim.exit屬性設為0,這個屬性bootanimation進程里會周期檢查,=1時就退出動畫,這里=0表示要播放動畫。

后面通過ctl.start的命令啟動bootanim進程,動畫就開始播放了。

 

4.frameworks/base/cmds/bootanimation/bootanimation_main.cpp

int main(int argc, char** argv)
{
        sp<ProcessState> proc(ProcessState::self());
        ProcessState::self()->startThreadPool();

        // create the boot animation object
        sp<BootAnimation> boot = new BootAnimation();//創建BootAnimation實例

        IPCThreadState::self()->joinThreadPool();//binder線程池,與surfaceflinger通信用的。
    }
    return 0;
}

  new一個BootAnimation實例,然后建個binder線程池,因為BootAnimation在顯示動畫時要與SurfaceFlinger服務進程通信,所以要啟個binder線程池。

 

5.frameworks/base/cmds/bootanimation/BootAnimation.cpp

BootAnimation::BootAnimation() : Thread(false)
{
    mSession = new SurfaceComposerClient();//創建一個對象
}

  創建實例時,構造函數就會被調用,new一個SurfaceComposerClient實例,他是用來與surfaceflinger通信的

 
         
復制代碼
void BootAnimation::onFirstRef() {
    status_t err = mSession->linkToComposerDeath(this);//注冊surfaceflinger死亡消息的通知書
    ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
    if (err == NO_ERROR) {
        run("BootAnimation", PRIORITY_DISPLAY);//開跑
    }
}
復制代碼

 

linkTocomposerDeath的作用是當surfaceflinger死掉是,BootAnimation就會得到通知。

 

如下,收到通知后就退出動畫了,因為surfaceflinger都掛掉了,播放不了了。

 

復制代碼
void BootAnimation::binderDied(const wp<IBinder>& who)
{
    // woah, surfaceflinger died!
    ALOGD("SurfaceFlinger died, exiting...");

    // calling requestExit() is not enough here because the Surface code
    // might be blocked on a condition variable that will never be updated.
    kill( getpid(), SIGKILL );//收到surfaceflinger死亡的消息,好吧自己也跟着去了。
    requestExit();
}
復制代碼

 

另一個函數run()在BootAnimation的父類Thead里,用來創建一個線程並跑起來。

 

父類

system/core/libutils/Threads.cpp

復制代碼
status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
    ...
    
    if (mCanCallJava) {
        res = createThreadEtc(_threadLoop,//創建線程
                this, name, priority, stack, &mThread);
    } else {
        res = androidCreateRawThreadEtc(_threadLoop,
                this, name, priority, stack, &mThread);
    }
    ....
}
復制代碼

 

創建_threadLoop線程
復制代碼
int Thread::_threadLoop(void* user)
{
....
    do {
        bool result;
        if (first) {
            first = false;
            self->mStatus = self->readyToRun();//這個函數被bootanimation重寫了
            result = (self->mStatus == NO_ERROR);

            if (result && !self->exitPending()) {
                ...
                result = self->threadLoop();//這個函數被bootanimation重寫了
            }
        } else {
            result = self->threadLoop();
        }

        ...
    
    return 0;
}
復制代碼

 

 readyToRun函數實現

復制代碼
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;
    char value[PROPERTY_VALUE_MAX];
    property_get("persist.panel.orientation", value, "0");
    int orient = atoi(value) / 90;

    if(orient == eOrientation90 || orient == eOrientation270) {
        int temp = dinfo.h;
        dinfo.h = dinfo.w;
        dinfo.w = temp;
    }

    Rect destRect(dinfo.w, dinfo.h);
    mSession->setDisplayProjection(dtoken, orient, destRect, destRect);

    // create the native 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, dummy;
    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;

    mAndroidAnimation = true;

    // 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);

    if ((encryptedAnimation &&
            (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) &&
            (mZip.open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE) == NO_ERROR)) ||

            ((access(USER_BOOTANIMATION_FILE, R_OK) == 0) &&
            (mZip.open(USER_BOOTANIMATION_FILE) == NO_ERROR)) ||

            ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&
            (mZip.open(SYSTEM_BOOTANIMATION_FILE) == NO_ERROR))) {
        mAndroidAnimation = false;
    }

    return NO_ERROR;
}
復制代碼

 

threadloop實現
復制代碼
bool BootAnimation::threadLoop()
{
    bool r;
    if (mAndroidAnimation) {
        r = android();//顯示android默認動畫
    } else {
        r = movie();//顯示自定義的動畫
    }

    // No need to force exit anymore
    property_set(EXIT_PROP_NAME, "0");

    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;
}
復制代碼

 

movie()的實現
復制代碼
bool BootAnimation::movie()
{
    //讀取bootanimation.zip文件並解釋

      // clear screen
   //下面是循環顯示 
       for (int i=0 ; i<pcount ; i++) {
        const Animation::Part& part(animation.parts[i]);
        const size_t fcount = part.frames.size();
        glBindTexture(GL_TEXTURE_2D, 0);

        for (int r=0 ; !part.count || r<part.count ; r++) {
            // Exit any non playuntil complete parts immediately
            if(exitPending() && !part.playUntilComplete)
                break;

            for (int j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) {
                const Animation::Frame& frame(part.frames[j]);
                nsecs_t lastFrame = systemTime();

                if (r > 0) {
                    glBindTexture(GL_TEXTURE_2D, frame.tid);
                } else {
                    if (part.count != 1) {
                        glGenTextures(1, &frame.tid);
                        glBindTexture(GL_TEXTURE_2D, frame.tid);
                        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                    }
                    initTexture(
                            frame.map->getDataPtr(),
                            frame.map->getDataLength());
                }

                if (!clearReg.isEmpty()) {
                    Region::const_iterator head(clearReg.begin());
                    Region::const_iterator tail(clearReg.end());
                    glEnable(GL_SCISSOR_TEST);
                    while (head != tail) {
                        const Rect& r(*head++);
                        glScissor(r.left, mHeight - r.bottom,
                                r.width(), r.height());
                        glClear(GL_COLOR_BUFFER_BIT);
                    }
                    glDisable(GL_SCISSOR_TEST);
                }
                glDrawTexiOES(xc, yc, 0, animation.width, animation.height);
                eglSwapBuffers(mDisplay, mSurface);

                nsecs_t now = systemTime();
                nsecs_t delay = frameDuration - (now - lastFrame);
                //ALOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay));
                lastFrame = now;

                if (delay > 0) {
                    struct timespec spec;
                    spec.tv_sec  = (now + delay) / 1000000000;
                    spec.tv_nsec = (now + delay) % 1000000000;
                    int err;
                    do {
                        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
                    } while (err<0 && errno == EINTR);
                }

                checkExit();//檢測是否退出動畫
            }

            usleep(part.pause * ns2us(frameDuration));

            // For infinite parts, we've now played them at least once, so perhaps exit
            if(exitPending() && !part.count)
                break;
        }

        // free the textures for this part
        if (part.count != 1) {
            for (int j=0 ; j<fcount ; j++) {
                const Animation::Frame& frame(part.frames[j]);
                glDeleteTextures(1, &frame.tid);
            }
        }
    }

    return false;
}
復制代碼

 

那么到movie為止,動畫是在播放了,而且還在循環檢測是否退出,即checkExit()

checkExit()的實現

復制代碼
void BootAnimation::checkExit() {
    // Allow surface flinger to gracefully request shutdown
    char value[PROPERTY_VALUE_MAX];
    property_get(EXIT_PROP_NAME, value, "0");//屬性為1,說明要退出了
    int exitnow = atoi(value);
    if (exitnow) {
        requestExit();
    }
}
復制代碼

 

property_get(EXIT_PROP_NAME, value, "0");檢測這個屬性,=1就退出動畫
#define EXIT_PROP_NAME "service.bootanim.exit"
這個屬性就是上面講到的,等到launcher跑起來后就會置1

當launcher應用程序主線程跑起來后,如果主線程處於空閑,就會向ActivityManagerService發送一個activityIdle的消息。

應用程序主線程是ActivityThread.java來描述的,activityIdle是這個類來實現的

復制代碼
private class Idler implements MessageQueue.IdleHandler {
...
                IActivityManager am = ActivityManagerNative.getDefault();
    ...
                        try {
                            am.activityIdle(a.token, a.createdConfig, stopProfiling);
                            a.createdConfig = null;
                        } catch (RemoteException ex) {
                            // Ignore
                        }
                    ....
    }
復制代碼

 

上面的ActivityManagerNavtive.getDefault()得到am

來到frameworks/base/core/java/android/app/ActivityManagerNative.java

復制代碼
static public IActivityManager getDefault() {
        return gDefault.get();//getDefault的實現
    }

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };
復制代碼

  gDefault實際上是IActivityManager,往下看

class ActivityManagerProxy implements IActivityManager
{

 ActivityManagerProxy實現了IActivityManager

那么am.activityIdle()就是ActivityManagerProxy里的函數,如下

public void activityIdle(IBinder token, Configuration config, boolean stopProfiling)
            throws RemoteException
    {
        ...
        mRemote.transact(ACTIVITY_IDLE_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);//發送ACTIVITY_IDLE_TRANSACTION

  ....
    }

 

發送了ACTIVITY_IDLE_TRANSACTION的進程間通信,這個消息被ActivityManagerNative接收處理了。
復制代碼
case ACTIVITY_IDLE_TRANSACTION: {//收到消息
            data.enforceInterface(IActivityManager.descriptor);
            IBinder token = data.readStrongBinder();
            Configuration config = null;
            if (data.readInt() != 0) {
                config = Configuration.CREATOR.createFromParcel(data);
            }
            boolean stopProfiling = data.readInt() != 0;
            if (token != null) {
                activityIdle(token, config, stopProfiling);//這個函數在ActivityManagerService被重寫
            }
            reply.writeNoException();
            return true;
        }
復制代碼

 

收到消息后就調用了activityIdle函數,這個函數被ActivityManagerService重寫了,如下

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

復制代碼
@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);
    }
復制代碼
 
調用activityIdleInternalLocked函數,在下面實現

frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java

復制代碼
 

    final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
            Configuration config) {
        ....        

        if (enableScreen) {
            mService.enableScreenAfterBoot();//調ActivityManagerService類的enableScreenAfterBoot()函數
         }
....
        if (activityRemoved) {
            resumeTopActivitiesLocked();
        }

        return r;
    }
復制代碼

來到frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

復制代碼
void enableScreenAfterBoot() {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
                SystemClock.uptimeMillis());
        mWindowManager.enableScreenAfterBoot();//調WindowManagerService類里的enableScreenAfterBoot()函數

        synchronized (this) {
            updateEventDispatchingLocked();
        }
    }
復制代碼

 

來到frameworks/base/services/java/com/android/server/wm/WindowManagerService.java

   public void enableScreenAfterBoot() {
     ....

        performEnableScreen();
    }

performEnableScreen()實現

 public void performEnableScreen() {
        

.....
                    surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
                                            data, null, 0);
   ....
    }

發送了FIRST_CALL_TRANSACTION的請求

 

因為從下面知道FIRST_CALL_TRANSACTION = BOOT_FINISHED

所以BnSurfaceComposer收到消息

frameworks/native/include/gui/ISurfaceComposer.h

 

復制代碼
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,
        ...
    };

    virtual status_t onTransact(uint32_t code, const Parcel& data,
            Parcel* reply, uint32_t flags = 0);
};



 

</pre></p><p><span style="color:#333333;">frameworks/native/libs/gui/ISurfaceComposer.cpp</span></p><p><span style="color:#333333;"></span><pre name="code" class="cpp">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();//調用 bootFinished()
            return NO_ERROR;
        }
        
        ....
    }
    // should be unreachable
    return NO_ERROR;
}
復制代碼

 

bootFinished()函數BpSurfaceComposer里實現,但發現沒有,他又發了一個BOOT_FINISHED,死循環了,其實沒有。bootFinished()被SurfaceFlinger類重寫了

 

 

復制代碼
class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
{

    virtual void bootFinished()
    {
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
        remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
    }
復制代碼

 重寫

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::bootFinished()
{
...
    property_set("service.bootanim.exit", "1");
}

把service.bootanim.exit寫成1,然后bootanimation進程的checkExit()檢測到就退出進程,停止播放。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM