android Activity中ViewRootImpl何时被创建?

/ android / 没有评论 / 740浏览

用到的代码文件

frameworks/base/core/java/:
android/app/ActivityThread.java
android/view/WindowManagerImpl.java
android/view/WindowManagerGlobal.java
android/view/ViewRootImpl.java
android/app/Activity.java
com/android/internal/policy/PhoneWindow.java
android/util/LayoutDirection.java

代码执行流程图

activity ViewRootImpl 查看原图

代码分析

下面的代码基于aosp (api:27 branch: android-7.1.2_r28)。

这篇文章主要记录ViewRootImpl何时被创建。
首先进入ActivityThread.java类的handleResumeActivity()方法。

final void handleResumeActivity(IBinder token,
        boolean clearHide, boolean isForward, boolean reallyResume, 
        int seq, String reason) {
    log("method handleResumeActivity()");
    /*
    token: android.os.BinderProxy@3537eb1
    clearHide: false
    isForward: true
    reallyResume: true
    seq: 0
    reason: LAUNCH_ACTIVITY
    */
    log("token: "+token);
    log("clearHide: "+clearHide);
    log("isForward: "+isForward);
    log("reallyResume: "+reallyResume);
    log("seq: "+seq);
    log("reason: "+reason);
    ActivityClientRecord r = mActivities.get(token);
    if (!checkAndUpdateLifecycleSeq(seq, r, "resumeActivity")) {
        return;
    }

    // If we are getting ready to gc after going to the
    // background, well we are back active so skip it.
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;

    /*
      * 这个方法里面主要是执行activity的onResume()方法和
      * 设置当前activity各状态对应的布尔值
      */
    // TODO Push resumeArgs into the activity for consideration
    r = performResumeActivity(token, clearHide, reason);

    if (r != null) {
        final Activity a = r.activity;
        /*
        Resume ActivityRecord{d9e1d58 
        token=android.os.BinderProxy@3537eb1
        {org.tuzhao.test/org.tuzhao.test.main.TestNormalActivity}}
        started activity: false, hideForNow: false, 
        finished: false
        */
        if (localLOGV) Slog.v(
            TAG, "Resume " + r + " started activity: " +
            a.mStartedActivity + ", hideForNow: " 
            + r.hideForNow + ", finished: " + a.mFinished);

        final int forwardBit = isForward ?
            WindowManager.LayoutParams
              .SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
        //forwardBit: 256
        log("forwardBit: "+forwardBit);

        // If the window hasn't yet been added to the window
        // manager,and this guy didn't finish itself or start
        // another activity,then go ahead and add the window.
        boolean willBeVisible = !a.mStartedActivity;
        //willBeVisible: true
        log("willBeVisible: "+willBeVisible);
        if (!willBeVisible) {
            try {
                willBeVisible = ActivityManagerNative
                        .getDefault().willActivityBeVisible(
                        a.getActivityToken());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        if (r.window == null && !a.mFinished && willBeVisible) {
            /*
             * 这里获取的PhoneWindow对象是在Activity的
             * attach()方法中创建的
             */
            r.window = r.activity.getWindow();
            //r.window: com.android.internal.policy
            //    .PhoneWindow@7073f70
            log("r.window: " + r.window);
            /*
             * 这里的DecorView是在PhoneWindow类中
             * 的installDecor()方法中创建
             */
            View decor = r.window.getDecorView();
            decor.setVisibility(View.INVISIBLE);
            /*
             * 这里的wm就是WindowManagerImpl对象。
             * 当前Activity中保存的WindowManager也是
             * 在Activity的attach()方法中创建
             */
            ViewManager wm = a.getWindowManager();
            WindowManager.LayoutParams l = 
                    r.window.getAttributes();
            a.mDecor = decor;
            l.type = WindowManager.LayoutParams
                        .TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            //r.mPreserveWindow: false
            log("r.mPreserveWindow: "+r.mPreserveWindow);
            if (r.mPreserveWindow) {// -> false
                a.mWindowAdded = true;
                r.mPreserveWindow = false;
                // Normally the ViewRoot sets up callbacks
                //  with the Activity
                // in addView->ViewRootImpl#setView. If we
                // are instead reusing the decor view we have
                // to notify the view root that the
                // callbacks may have changed.
                ViewRootImpl impl = decor.getViewRootImpl();
                if (impl != null) {
                    impl.notifyChildRebuilt();
                }
            }
            // get in
            if (a.mVisibleFromClient && !a.mWindowAdded) {
                //wm: android.view.WindowManagerImpl
                log("wm: "+wm.getClass().getName());
                a.mWindowAdded = true;
                /*
                 * 先进入这里
                 */
                wm.addView(decor, l);
            }

        // If the window has already been added, but during resume
        // we started another activity, then don't yet make the
        // window visible.
        } else if (!willBeVisible) {// false
            if (localLOGV) Slog.v(
                TAG, "Launch " + r + " mStartedActivity set");
            r.hideForNow = true;
        }

        // Get rid of anything left hanging around.
        cleanUpPendingRemoveWindows(r, false /* force */);

        // The window is now visible if it has been added, we
        // are not simply finishing, and we are not starting
        // another activity.
        /* get in */
        if (!r.activity.mFinished && willBeVisible
                && r.activity.mDecor != null && !r.hideForNow) {
            // r.newConfig: null
            log("r.newConfig: "+r.newConfig);
            if (r.newConfig != null) {// false
                performConfigurationChangedForActivity(r, 
                    r.newConfig, REPORT_TO_ACTIVITY);
                if (DEBUG_CONFIGURATION) Slog.v(TAG, 
                        "Resuming activity "+ r.activityInfo.name 
                        + " with newConfig " 
                        + r.activity.mCurrentConfig);
                r.newConfig = null;
            }
            /*
            Resuming ActivityRecord{d9e1d58 
            token=android.os.BinderProxy@3537eb1
            {org.tuzhao.test/org.tuzhao.test.main.TestNormalActivity}} 
            with isForward=true
            */
            if (localLOGV) Slog.v(TAG, "Resuming " + r 
                    + " with isForward="
                    + isForward);
            WindowManager.LayoutParams l = r.window.getAttributes();
            if ((l.softInputMode
                    & WindowManager.LayoutParams
                        .SOFT_INPUT_IS_FORWARD_NAVIGATION)
                    != forwardBit) {// false
                l.softInputMode = (l.softInputMode
                        &(~WindowManager.LayoutParams
                            .SOFT_INPUT_IS_FORWARD_NAVIGATION))
                        | forwardBit;
                log("r.activity.mVisibleFromClient: "
                        + r.activity.mVisibleFromClient);
                if (r.activity.mVisibleFromClient) {
                    ViewManager wm = a.getWindowManager();
                    View decor = r.window.getDecorView();
                    wm.updateViewLayout(decor, l);
                }
            }
            r.activity.mVisibleFromServer = true;
            mNumVisibleActivities++;
            log("mNumVisibleActivities: "
                    + mNumVisibleActivities);
            if (r.activity.mVisibleFromClient) {
                log("activity make visible");
                r.activity.makeVisible();
            }
        }

        //r.onlyLocalRequest: false
        log("r.onlyLocalRequest: "+r.onlyLocalRequest);
        if (!r.onlyLocalRequest) {// get in
            r.nextIdle = mNewActivities;
            mNewActivities = r;
            /*
            Scheduling idle handler for ActivityRecord
            {d9e1d58 token=android.os.BinderProxy@3537eb1
            {org.tuzhao.test/org.tuzhao.test
                .main.TestNormalActivity}}
            */
            if (localLOGV) Slog.v(
                TAG, "Scheduling idle handler for " + r);
            Looper.myQueue().addIdleHandler(new Idler());
        }
        r.onlyLocalRequest = false;

        //reallyResume: true
        log("reallyResume: "+reallyResume);
        // Tell the activity manager we have resumed.
        if (reallyResume) {
            try {
                ActivityManagerNative.getDefault()
                        .activityResumed(token);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }

    } else {
        // If an exception was thrown when trying to 
        // resume, then just end this activity.
        try {
            ActivityManagerNative.getDefault()
                .finishActivity(token, Activity.RESULT_CANCELED,
                 null,Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}

接下来进入WindowManagerImpl类的addView()方法中。

@Override
public void addView(@NonNull View view, 
    @NonNull ViewGroup.LayoutParams params) {
    log("method addView()");
    /*params: WM.LayoutParams{(0,0)(fillxfill) sim=#100 
    ty=1 fl=#80810100 pfl=0x20000 wanim=0x103046a 
    needsMenuKey=2}
    */
    log("params: "+params);
    //为当前的params设置token,如果没有设置的话。
    applyDefaultToken(params);
    /*
     同一个应用不同的Activity使用的mGlobal对象是同一个;
     同一个应用不同的Activity使用的当前WindowManagerImpl对
     象不一样;
     */
    mGlobal.addView(view, params, mContext.getDisplay(), 
            mParentWindow);
}

接下来进入WindowManagerGlobal类的addView()方法中。

public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
    log("method addView() start");
    
    ......(省略判断代码)
    
    //在Acitvity的attach()方法中创建的PhoneWindow对象
    //parentWindow: com.android.internal.policy.PhoneWindow@7073f70
    log("parentWindow: "+parentWindow);
    final WindowManager.LayoutParams wparams = 
            (WindowManager.LayoutParams) params;
    if (parentWindow != null) {
        parentWindow.adjustLayoutParamsForSubWindow(wparams);
    } else {
        // If there's no parent, then hardware acceleration
        // for this view is set from the application's
        // hardware acceleration setting.
        final Context context = view.getContext();
        if (context != null
                && (context.getApplicationInfo().flags
                        & ApplicationInfo
                        .FLAG_HARDWARE_ACCELERATED) != 0) {
            log("|= FLAG_HARDWARE_ACCELERATED");
            wparams.flags |= WindowManager.LayoutParams
                    .FLAG_HARDWARE_ACCELERATED;
        }
    }

    ViewRootImpl root;
    View panelParentView = null;

    synchronized (mLock) {
        //mSystemPropertyUpdater: android.view
        //    .WindowManagerGlobal$2@f0391a2
        log("mSystemPropertyUpdater: "+mSystemPropertyUpdater);
        // Start watching for system property changes.
        if (mSystemPropertyUpdater == null) {// false
          ......
        }

        int index = findViewLocked(view, false);
        //index: -1
        log("index: "+index);
        if (index >= 0) {// false
          ......
        }

        ......
        
        /*
         * 这里是核心,当前Activity的ViewRootImpl就是这个时候创建的。
         */
        root = new ViewRootImpl(view.getContext(), display);
        //DecorView设置params
        view.setLayoutParams(wparams);
        //mViews, mRoots,mParams均为ArrayList
        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);
    }

    //最后做这件事是因为它触发了消息开始做事
    // do this last because it fires off messages to
    // start doing things
    try {
        root.setView(view, wparams, panelParentView);
    } catch (RuntimeException e) {
        // BadTokenException or InvalidDisplayException, clean up.
        synchronized (mLock) {
            final int index = findViewLocked(view, false);
            if (index >= 0) {
                removeViewLocked(index, true);
            }
        }
        throw e;
    }
    log("method addView() end");
}

接下来进入ViewRootImpl类的setView()方法中。

/**
 * We have one child
 */
public void setView(View view, WindowManager.LayoutParams attrs,
    View panelParentView) {
    log("method setView()");
    synchronized (this) {
        //mView: null
        log("mView: "+mView);
        if (mView == null) {
            mView = view;

            mAttachInfo.mDisplayState = mDisplay.getState();
            mDisplayManager.registerDisplayListener(
                    mDisplayListener, mHandler);

            mViewLayoutDirectionInitial = mView
                    .getRawLayoutDirection();
            mFallbackEventHandler.setView(view);
            mWindowAttributes.copyFrom(attrs);
            
            /*
            mViewLayoutDirectionInitial: 2
            返回的布局值都定义在LayoutDirection.java中。
            2->此视图的水平布局方向是从其父项继承的。
            */
            log("mViewLayoutDirectionInitial: "
                + mViewLayoutDirectionInitial);
            //mWindowAttributes.packageName: org.tuzhao.test
            log("mWindowAttributes.packageName: "
                + mWindowAttributes.packageName);
            //mBasePackageName: org.tuzhao.test
            log("mBasePackageName: "+mBasePackageName);
            if (mWindowAttributes.packageName == null) {
                mWindowAttributes.packageName = mBasePackageName;
            }
            attrs = mWindowAttributes;
            
            //这个方法就是设置log输出的TAG
            //mTag: ViewRootImpl[TestNormalActivity]
            setTag();

            ......
            
            // Keep track of the actual window flags supplied
            // by the client.
            mClientWindowLayoutFlags = attrs.flags;

            setAccessibilityFocus(null, null);

            if (view instanceof RootViewSurfaceTaker) {
                mSurfaceHolderCallback =
                        ((RootViewSurfaceTaker)view)
                        .willYouTakeTheSurface();
                //mSurfaceHolderCallback: null
                log("mSurfaceHolderCallback: "+mSurfaceHolderCallback);
                if (mSurfaceHolderCallback != null) {
                    mSurfaceHolder = new TakenSurfaceHolder();
                    mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
                }
            }

            //计算在指定的Z值下所需绘制的表面插图。
            // Compute surface insets required to draw at
            // specified Z value.
            // TODO: Use real shadow insets for a constant max Z.
            if (!attrs.hasManualSurfaceInsets) {// true
                log("setSurfaceInsets");
                attrs.setSurfaceInsets(view, 
                  false /*manual*/, true /*preservePrevious*/);
            }

            CompatibilityInfo compatibilityInfo =
                    mDisplay.getDisplayAdjustments()
                    .getCompatibilityInfo();
            mTranslator = compatibilityInfo.getTranslator();
            //compatibilityInfo: {560dpi always-compat}
            log("compatibilityInfo: "+compatibilityInfo);
            //mTranslator: null
            log("mTranslator: "+mTranslator);
            //mSurfaceHolder: null
            log("mSurfaceHolder: "+mSurfaceHolder);
            // If the application owns the surface, 
            // don't enable hardware acceleration
            if (mSurfaceHolder == null) {
                enableHardwareAcceleration(attrs);
            }

            boolean restore = false;
            if (mTranslator != null) {//false
                mSurface.setCompatibilityTranslator(mTranslator);
                restore = true;
                attrs.backup();
                mTranslator.translateWindowLayout(attrs);
            }
            /*
            WindowLayout in setView:WM.LayoutParams{(0,0)
            (fillxfill) sim=#100 
            ty=1 fl=#81810100 pfl=0x20000 wanim=0x103046a
            needsMenuKey=2}
            */
            if (DEBUG_LAYOUT) Log.d(mTag, 
                    "WindowLayout in setView:" + attrs);
            // false
            if (!compatibilityInfo.supportsScreen()) {
                log("not support screen");
                attrs.privateFlags |=WindowManager.LayoutParams
                        .PRIVATE_FLAG_COMPATIBLE_WINDOW;
                mLastInCompatMode = true;
            }

            mSoftInputMode = attrs.softInputMode;
            mWindowAttributesChanged = true;
            mWindowAttributesChangesFlag = WindowManager
                    .LayoutParams.EVERYTHING_CHANGED;
            mAttachInfo.mRootView = view;
            mAttachInfo.mScalingRequired = mTranslator != null;
            mAttachInfo.mApplicationScale =
                    mTranslator == null 
                    ? 1.0f 
                    : mTranslator.applicationScale;
            //panelParentView: null
            log("panelParentView: "+panelParentView);
            if (panelParentView != null) {
                mAttachInfo.mPanelParentWindowToken
                        = panelParentView
                            .getApplicationWindowToken();
            }
            mAdded = true;
            int res; /* = WindowManagerImpl.ADD_OKAY; */
            
            /*
             * requestLayout()这个方法会发送消息执行整个
             * 界面的measure,layout,draw!
             */
            // Schedule the first layout -before- adding
            // to the window manager, to make sure we do
            // the relayout before receiving
            // any other events from the system.
            requestLayout();
            if ((mWindowAttributes.inputFeatures
                    & WindowManager.LayoutParams
                    .INPUT_FEATURE_NO_INPUT_CHANNEL)
                     == 0) {//true
                log("create new input channel");
                mInputChannel = new InputChannel();
            }
            mForceDecorViewVisibility = (mWindowAttributes
                    .privateFlags
                    & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY)
                    != 0;
            try {
                mOrigWindowType = mWindowAttributes.type;
                mAttachInfo.mRecomputeGlobalAttributes = true;
                collectViewAttributes();
                //mWindowSession: android.view
                //    .IWindowSession$Stub$Proxy
                log("mWindowSession: "
                    + mWindowSession.getClass().getName());
                /*
                 * 这里与WMS进行通信(WindowManagerService)
                 */
                res = mWindowSession.addToDisplay(mWindow,
                        mSeq, mWindowAttributes,
                        getHostVisibility(), 
                        mDisplay.getDisplayId(),
                        mAttachInfo.mContentInsets, 
                        mAttachInfo.mStableInsets,
                        mAttachInfo.mOutsets, mInputChannel);
            } catch (RemoteException e) {
                mAdded = false;
                mView = null;
                mAttachInfo.mRootView = null;
                mInputChannel = null;
                mFallbackEventHandler.setView(null);
                unscheduleTraversals();
                setAccessibilityFocus(null, null);
                throw new RuntimeException(
                        "Adding window failed", e);
            } finally {
                //restore: false
                log("restore: "+restore);
                if (restore) {
                    attrs.restore();
                }
            }
            //res: 3
            log("res: "+res);
            //mTranslator: null
            log("mTranslator: "+mTranslator);
            if (mTranslator != null) {
                mTranslator
                    .translateRectInScreenToAppWindow(
                    mAttachInfo.mContentInsets);
            }
            mPendingOverscanInsets.set(0, 0, 0, 0);
            mPendingContentInsets.set(mAttachInfo.mContentInsets);
            mPendingStableInsets.set(mAttachInfo.mStableInsets);
            mPendingVisibleInsets.set(0, 0, 0, 0);
            mAttachInfo.mAlwaysConsumeNavBar =
                    (res 
                    & WindowManagerGlobal
                    .ADD_FLAG_ALWAYS_CONSUME_NAV_BAR) != 0;
            mPendingAlwaysConsumeNavBar = mAttachInfo
                    .mAlwaysConsumeNavBar;
            //Added window android.view.ViewRootImpl$W@40a52e9
            if (DEBUG_LAYOUT) Log.v(mTag, "Added window " 
                + mWindow);
            // false
            if (res < WindowManagerGlobal.ADD_OKAY) {
              ......
            }

            if (view instanceof RootViewSurfaceTaker) {
                mInputQueueCallback =
                    ((RootViewSurfaceTaker)view)
                        .willYouTakeTheInputQueue();
                //mInputQueueCallback: null
                log("mInputQueueCallback: "
                    + mInputQueueCallback);
            }
            if (mInputChannel != null) {//true
                if (mInputQueueCallback != null) {//false
                    mInputQueue = new InputQueue();
                    mInputQueueCallback
                      .onInputQueueCreated(mInputQueue);
                }
                mInputEventReceiver = 
                    new WindowInputEventReceiver(
                        mInputChannel,
                        Looper.myLooper());
            }

            view.assignParent(this);
            mAddedTouchMode = (res & WindowManagerGlobal
                .ADD_FLAG_IN_TOUCH_MODE) != 0;
            mAppVisible = (res & WindowManagerGlobal
                .ADD_FLAG_APP_VISIBLE) != 0;
            //mAddedTouchMode: true
            log("mAddedTouchMode: "+mAddedTouchMode);
            //mAppVisible: true
            log("mAppVisible: "+mAppVisible);
            //false
            if (mAccessibilityManager.isEnabled()) {
                log("mAccessibilityManager isEnabled");
                mAccessibilityInteractionConnectionManager
                    .ensureConnection();
            }
            //true
            if (view.getImportantForAccessibility() == 
                View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
                log("IMPORTANT_FOR_ACCESSIBILITY_AUTO");
                view.setImportantForAccessibility(
                    View.IMPORTANT_FOR_ACCESSIBILITY_YES);
            }

            // Set up the input pipeline.
            CharSequence counterSuffix = attrs.getTitle();
            //counterSuffix: org.tuzhao.test/
            //  org.tuzhao.test.main.TestNormalActivity
            log("counterSuffix: "+counterSuffix);
            mSyntheticInputStage = new SyntheticInputStage();
            InputStage viewPostImeStage = 
                new ViewPostImeInputStage(mSyntheticInputStage);
            InputStage nativePostImeStage = 
                new NativePostImeInputStage(viewPostImeStage,
                    "aq:native-post-ime:" + counterSuffix);
            InputStage earlyPostImeStage = 
                new EarlyPostImeInputStage(nativePostImeStage);
            InputStage imeStage = new ImeInputStage(
                earlyPostImeStage,"aq:ime:" + counterSuffix);
            InputStage viewPreImeStage = 
                new ViewPreImeInputStage(imeStage);
            InputStage nativePreImeStage = 
                new NativePreImeInputStage(viewPreImeStage,
                    "aq:native-pre-ime:" + counterSuffix);

            mFirstInputStage = nativePreImeStage;
            mFirstPostImeInputStage = earlyPostImeStage;
            mPendingInputEventQueueLengthCounterName = 
                "aq:pending:" + counterSuffix;
        }
    }
}