1. 程式人生 > >Android6.0 開機動畫(二) AMS通知系統啟動&WMS通知SurfaceFlinger關閉開機動畫

Android6.0 開機動畫(二) AMS通知系統啟動&WMS通知SurfaceFlinger關閉開機動畫



http://blog.csdn.net/kc58236582/article/details/52794846部落格中我們已經講了開機動畫的大致流程,這裡我們就Launcher啟動後,Launcher的執行緒閒的時候在ActivityThread呼叫AMS的activityIdle方法。

在分析訊息機制 空閒訊息處理器中http://blog.csdn.net/kc58236582/article/details/52919904,我們知道在訊息執行緒空閒時會呼叫IdleHandler的queueIdle方法,這裡我們來看ActivityThread中的IdleHandler,是在ActivityThread的handleResumeActivity函式中有下面一段程式碼,呼叫了MessageQueue的addIdleHandler函式。

......
            if (!r.onlyLocalRequest) {
                r.nextIdle = mNewActivities;
                mNewActivities = r;
                if (localLOGV) Slog.v(
                    TAG, "Scheduling idle handler for " + r);
                Looper.myQueue().addIdleHandler(new Idler());
            }
......

在Idler的queueIdle函式中呼叫了AMS的activityIdle函式,我們來看下,獲取ActivityStack後呼叫了activityIdleInternalLocked函式。

    @Override
    public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
        final long origId = Binder.clearCallingIdentity();
        synchronized (this) {
            ActivityStack stack = ActivityRecord.getStackLocked(token);//得到ActivityStack
            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);
    }

看如下函式,我們先根據token來得到其ActivityRecord,然後將ActivityRecord的idle置為true。如果是isFrontStack呼叫checkFinishBootingLocked函式。

    final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
            Configuration config) {
        if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);

        ArrayList<ActivityRecord> stops = null;
        ArrayList<ActivityRecord> finishes = null;
        ArrayList<UserState> startingUsers = null;
        int NS = 0;
        int NF = 0;
        boolean booting = false;
        boolean activityRemoved = false;

        ActivityRecord r = ActivityRecord.forTokenLocked(token);
        if (r != null) {
            if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternalLocked: Callers="
                    + Debug.getCallers(4));
            mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
            r.finishLaunchTickingLocked();
            if (fromTimeout) {
                reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
            }

            // This is a hack to semi-deal with a race condition
            // in the client where it can be constructed with a
            // newer configuration from when we asked it to launch.
            // We'll update with whatever configuration it now says
            // it used to launch.
            if (config != null) {
                r.configuration = config;
            }

            // We are now idle.  If someone is waiting for a thumbnail from
            // us, we can now deliver.
            r.idle = true;//idle置為true

            //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
            if (isFrontStack(r.task.stack) || fromTimeout) {
                booting = checkFinishBootingLocked();
            }
        }
......

checkFinishBootingLocked函式,如果AMS正在啟動會呼叫其postFinishBooting函式

    private boolean checkFinishBootingLocked() {
        final boolean booting = mService.mBooting;
        boolean enableScreen = false;
        mService.mBooting = false;
        if (!mService.mBooted) {
            mService.mBooted = true;
            enableScreen = true;
        }
        if (booting || enableScreen) {
            mService.postFinishBooting(booting, enableScreen);
        }
        return booting;
    }

AMS的postFinishBooting函式傳送FINISH_BOOTING_MSG訊息

    void postFinishBooting(boolean finishBooting, boolean enableScreen) {
        mHandler.sendMessage(mHandler.obtainMessage(FINISH_BOOTING_MSG,
                finishBooting ? 1 : 0, enableScreen ? 1 : 0));
    }

我們再來看訊息處理,當finishBooting為true,就呼叫finishBooting函式,這個函式中會發送一些廣播,以及將SystemService啟動到PHASE_BOOT_COMPLETED階段。

            case FINISH_BOOTING_MSG: {
                if (msg.arg1 != 0) {
                    finishBooting();
                }
                if (msg.arg2 != 0) {
                    enableScreenAfterBoot();
                }
                break;
            }

當enableScreen為true會呼叫enableScreenAfterBoot函式,會在這個函式中呼叫WMS的enableScreenAfterBoot函式

    void enableScreenAfterBoot() {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
                SystemClock.uptimeMillis());
        mWindowManager.enableScreenAfterBoot();

        synchronized (this) {
            updateEventDispatchingLocked();
        }
    }

在WMS的enableScreenAfterBoot方法又會呼叫performEnableScreen方法,這個方法會呼叫SurfaceFlinger的Binder

    public void performEnableScreen() {
        synchronized(mWindowMap) {
            if (mDisplayEnabled) {
                return;
            }
            if (!mSystemBooted && !mShowingBootMessages) {
                return;
            }

            // Don't enable the screen until all existing windows have been drawn.
            if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) {
                return;
            }

            if (!mBootAnimationStopped) {
                // Do this one time.
                try {
                    IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
                    if (surfaceFlinger != null) {
                        //Slog.i(TAG, "******* 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();
                    }
                } catch (RemoteException ex) {
                    Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
                }
                mBootAnimationStopped = true;
            }
......
FIRST_CALL_TRANSACTION就是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,
我們再來看ISurfaceComposer.cpp對BOOT_FINISHED的處理,會呼叫bootFinished函式。
        case BOOT_FINISHED: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            bootFinished();
            return NO_ERROR;
        }
bootFinished會計算開機的時間,然後將service.bootanim.exit屬性設為1,這樣bootanim會結束,這樣開機動畫結束。
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.
    property_set("service.bootanim.exit", "1");
    char boot_exit_value[32];
    property_get("service.bootanim.exit", boot_exit_value, "0");
    ALOGD("The service.bootanim.exit property value is %d", atoi(boot_exit_value));
}