Window-创建到显示过程

Post on Feb 05, 2023 by Wei Lin

概述

Activity创建过程

Window的创建与Activity是强相关的,首先看一下Activity创建过程中需要执行哪些函数,再通过这些函数看一下与Window创建的关系。


(1) APP端

Activity.startActivity(1 args)
Activity.startActivity(2 args)
Activity.startActivityForResult(2 args)
Activity.startActivityForResult(3 args)
Instrumentation.execStartActivity()


(2) system_server端

ATMS.startActivity()
ATMS.startActivityAsUser()
ActivityStarter.setxxx()
ActivityStarter.execute()
ActivityStarter.executeRequest()
ActivityStarter.startActivityUnchecked()
ActivityStarter.startActivityInner()
RootWindowContainer.resumeFocusedStacksTopActivities()
ActivityStack.resumeTopActivityUncheckedLocked()
ActivityStack.resumeTopActivityInnerLocked()
ActivityTaskSupervisor.startSpecificActivity()  //这里可能启动进程
ActivityTaskSupervisor.realStartActivityLocked()
ClientLifecycleManager.scheduleTransaction()
// APP端
ClientTransaction.schedule()
ApplicationThread.scheduleTransaction()
ClientTransactionHandler.scheduleTransaction()
TransactionExecutor.execute()

之后走Activity的生命周期流程。


(3) onCreate生命周期

TransactionExecutor.executeCallbacks() ->
LaunchActivityItem.execute() ->
ActivityThread.handleLaunchActivity() ->
ActivityThread.performLaunchActivity() ->
Instrumentation.callActivityOnCreate() ->
Activity.performCreate() ->
MainActivity.onCreate() ->
Activity.onCreate()

接下来执行onStart()和onResume()生命周期
TransactionExecutor.execute() ->
TransactionExecutor.executeLifecycleState()


(4) onStart生命周期

TransactionExecutor.cycleToPath() ->
TransactionExecutor.performLifecycleSequence() ->
ActivityThread.handleStartActivity() ->
Activity.performStart() ->
Instrumentation.callActivityOnStart() ->
MainActivity.onStart() ->
Activity.onStart()


(5) onResume生命周期

ResumeActivityItem.execute() ->
ActivityThread.handleResumeActivity() ->
ActivityThread.performResumeActivity() ->
Activity.performResume() ->
Instrumentation.callActivityOnResume() ->
MainActivity.onResume() ->
Activity.onResume()

接下来看一下与Window创建相关的流程。

Window的创建->显示过程

在Android中,Window的创建到显示过程涉及到多个组件的协同工作,主要包括Activity、WindowManagerService和SurfaceFlinger等。


以下是Window从创建到显示的基本过程:

序号 过程 详情
1 Activity的启动 当开发者调用startActivity()方法启动一个Activity时,系统会根据指定的Activity类名找到对应的Activity,并进行实例化和启动
2 ActivityThread创建 每个应用程序运行在一个独立的线程中,称为主线程或UI线程。当Activity启动时,系统会在主线程中创建一个ActivityThread对象,该对象负责管理该应用程序的主消息循环
3 创建Window 在ActivityThread中,系统会通过调用Activity的attach()方法来创建Window对象。Window是一个抽象的窗口类,用于表示Activity的窗口
4 创建WindowManager 每个应用程序都有一个WindowManager对象,它是WindowManagerService的客户端,用于管理应用程序的窗口
5 向WindowManager注册Window Activity的Window创建后,系统会将其注册到WindowManager中,即通过调用WindowManager的addView()方法将Window添加到WindowManagerService中
6 创建Surface Surface是SurfaceFlinger系统服务的一部分,用于管理屏幕上的图形显示。当Window添加到WindowManagerService后,系统会为该Window创建一个Surface,用于显示该Window中的视图内容
7 绘制视图 Activity的布局和视图会通过调用View的onDraw()方法进行绘制,最终将绘制的内容渲染到对应的Surface上
8 显示到屏幕 SurfaceFlinger会将所有应用程序的Surface上的图形合成为一个整体,并显示到屏幕上
9 用户交互 此时,Activity已经显示在屏幕上,用户可以与界面进行交互,响应用户的触摸事件和其他操作

Window创建过程

Base on: Android 13

AT.handleLaunchActivity()

​ 这一步是在执行Activity的onCreate()生命周期过程中执行的,流程见”Activity创建过程”。在handleLaunchActivity()中主要做了以下工作:

  • WindowManagerGlobal.initialize()作创建Window的初始准备,主要拿到WMS的引用;
  • 调用了performLaunchActivity(),来真正完成Activity的创建以及Window的创建。
/**
 * Extended implementation of activity launch. Used when server requests a launch or relaunch.
 */
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, Intent customIntent) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;

    if (r.profilerInfo != null) {
        mProfiler.setProfiler(r.profilerInfo);
        mProfiler.startProfiling();
    }

    // Make sure we are running with the most recent config.
    mConfigurationController.handleConfigurationChanged(null, null);

    if (localLOGV) Slog.v(
        TAG, "Handling launch of " + r);

    // Initialize before creating the activity
    if (ThreadedRenderer.sRendererEnabled
            && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
        HardwareRenderer.preload();
    }
    WindowManagerGlobal.initialize();

    // Hint the GraphicsEnvironment that an activity is launching on the process.
    GraphicsEnvironment.hintActivityLaunch();

    final Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfigurationController.getConfiguration());
        reportSizeConfigurations(r);
        if (!r.activity.mFinished && pendingActions != null) {
            pendingActions.setOldState(r.state);
            pendingActions.setRestoreInstanceState(true);
            pendingActions.setCallOnPostCreate(true);
        }
    } else {
        // If there was an error, for any reason, tell the activity manager to stop us.
        ActivityClient.getInstance().finishActivity(r.token, Activity.RESULT_CANCELED,
                null /* resultData */, Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
    }

    return a;
}

AT.performLaunchActivity()

在该方法内首先获取Activity的一些组件信息,然后Instrumentation通过反射创建Activity,接着会创建Application、Context上下文对象等,之后会调用Activity的attach()来完成Window的创建等工作。

主要看一下Window相关的代码:

Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
    window = r.mPendingRemoveWindow;
    r.mPendingRemoveWindow = null;
    r.mPendingRemoveWindowManager = null;
}
activity.attach(appContext, this, getInstrumentation(), r.token,
        r.ident, app, r.intent, r.activityInfo, title, r.parent,
        r.embeddedID, r.lastNonConfigurationInstances, config,
        r.referrer, r.voiceInteractor, window, r.activityConfigCallback,
        r.assistToken, r.shareableActivityToken);

Activity.attach()

该方法中主要完成以下工作:

  • Window的创建,实际上创建的是PhoneWindow,然后给其设置各种回调,来建立起与Activity的关联;
  • 初始化Activity的相关参数;
  • 给PhoneWindow设置WindowManager,实际上设置的是WindowManagerImpl。


在这里看似Window已经创建完成,但实际上这个Window只是一个空架子,里面没有任何内容。在Activity的onCreate()方法内,会调用setContentView(),该方法会触发DecorView的创建,并将需要的视图添加到DecorView中,之后通过WindowManager将DecorView添加到Window中。

final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor,
        Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
        IBinder shareableActivityToken) {
    attachBaseContext(context);

    mFragments.attachHost(null /*parent*/);

    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    mWindow.setWindowControllerCallback(mWindowControllerCallback);
    mWindow.setCallback(this);  //设置窗口回调接口
    mWindow.setOnWindowDismissedCallback(this);
    mWindow.getLayoutInflater().setPrivateFactory(this);
    if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
        mWindow.setSoftInputMode(info.softInputMode);  // 设置软键盘输入区域显示模式
    }
    if (info.uiOptions != 0) {
        mWindow.setUiOptions(info.uiOptions);
    }
    mUiThread = Thread.currentThread();

    mMainThread = aThread;
    mInstrumentation = instr;
    mToken = token;
    mAssistToken = assistToken;
    mShareableActivityToken = shareableActivityToken;
    mIdent = ident;
    mApplication = application;
    mIntent = intent;
    mReferrer = referrer;
    mComponent = intent.getComponent();
    mActivityInfo = info;
    mTitle = title;
    mParent = parent;
    mEmbeddedID = id;
    mLastNonConfigurationInstances = lastNonConfigurationInstances;
    if (voiceInteractor != null) {
        if (lastNonConfigurationInstances != null) {
            mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
        } else {
            mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                    Looper.myLooper());
        }
    }

    mWindow.setWindowManager(
            (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
            mToken, mComponent.flattenToString(),
            (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    if (mParent != null) {
        mWindow.setContainer(mParent.getWindow());
    }
    mWindowManager = mWindow.getWindowManager();
    mCurrentConfig = config;

    mWindow.setColorMode(info.colorMode);
    mWindow.setPreferMinimalPostProcessing(
            (info.flags & ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING) != 0);

    getAutofillClientController().onActivityAttached(application);
    setContentCaptureOptions(application.getContentCaptureOptions());
}

……

中间过程略,最终会调用到onCreate()方法中,并在onCreate()中调用setContentView()。调用过程如下:

ActivityThread$H.handleMessage() ->
TransactionExecutor.execute() ->
TransactionExecutor.executeCallbacks() ->
LaunchActivityItem.execute() ->
ActivityThread.handleLaunchActivity() ->
ActivityThread.performLaunchActivity() ->
Instrumentation.callActivityOnCreate() ->
Activity.performCreate() ->
Activity.performCreate() ->
MainActivity.onCreate()

Activity.setContentView()

getWindow()实际上返回的是PhoneWindow。

public void setContentView(@LayoutRes int layoutResID) {
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}

public void setContentView(View view) {
    getWindow().setContentView(view);
    initWindowDecorActionBar();
}

public void setContentView(View view, ViewGroup.LayoutParams params) {
    getWindow().setContentView(view, params);
    initWindowDecorActionBar();
}

PhoneWindow.setContentView()

​ PhoneWindow同样也对应着3个setContentView()方法,这里主要看一下常用的传入的layoutResID的方法。

主要完成以下工作:

  • 如果DecorView不存在则创建installDecor(),如果存在则移除mContentParent中所有的View;
  • 通过inflate()将View填充到mContentParent中;
  • 回调Activity来通知改变,调用onContentChanged()。
@Override
public void setContentView(int layoutResID) {
    // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
    // decor, when theme attributes and the like are crystalized. Do not check the feature
    // before this happens.
    if (mContentParent == null) {
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }

    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                getContext());
        transitionTo(newScene);
    } else {
        mLayoutInflater.inflate(layoutResID, mContentParent);
    }
    mContentParent.requestApplyInsets();
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        cb.onContentChanged();
    }
    mContentParentExplicitlySet = true;
}

Window的绘制过程

Base on: Android 13

Branch: android-13.0.0_r30

AT.handleResumeActivity()

​ 本方法是在Activity的Resume生命周期中调用(在onResume()前)的,在这里会调用performResumeActivity()执行到onResume()。

在if (r.window == null && !a.mFinished && willBeVisible)中进行的工作如下:

  • 获取WindowManager,即getWindowManager(),实际上是一个WindowManagerImpl;
  • 设置Window相关参数WindowManager.LayoutParams;
  • 通过decor和参数添加View,wm.addView(decor, l)。
if (!performResumeActivity(r, finalStateRequest, reason)) {
    return;
}
//...
if (r.window == null && !a.mFinished && willBeVisible) {
    r.window = r.activity.getWindow();
    View decor = r.window.getDecorView();
    decor.setVisibility(View.INVISIBLE);
    ViewManager wm = a.getWindowManager();
    WindowManager.LayoutParams l = r.window.getAttributes();
    a.mDecor = decor;
    l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
    l.softInputMode |= forwardBit;
    if (r.mPreserveWindow) {
        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();
        }
    }
    if (a.mVisibleFromClient) {
        if (!a.mWindowAdded) {
            a.mWindowAdded = true;
            wm.addView(decor, l);
        } else {
            // The activity will get a callback for this {@link LayoutParams} change
            // earlier. However, at that time the decor will not be set (this is set
            // in this method), so no action will be taken. This call ensures the
            // callback occurs with the decor set.
            a.onWindowAttributesChanged(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) {
    if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
    r.hideForNow = true;
}

不论是 Activity、Dialog、PopupWindow还是其他浮动窗口,屏幕上可以看到的一切窗口最终都是通过调用 WindowManager.addView(View view, ViewGroup.LayoutParams params) 方法添加的。我们在调查一个窗口的显示的时候只要找到调用WindowManager.addView()的位置就可以。


void addView(View view, ViewGroup.LayoutParams params)方法里有两个参数:

  • View view:View 树的根 View,也就是需要在窗口上显示的内容
  • ViewGroup.LayoutParams params:窗口相关的参数,实际为 WindowManager.LayoutParams,包括显示的位置、大小、层级、焦点处理标记等

WindowManagerImpl.addView()

通过桥接模式实际调用WindowManagerGlobal.addView()

public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyTokens(params);
    mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
            mContext.getUserId());
}

WindowManagerGlobal.addView()

​ WindowManagerGlobal.addView()进入View的创建过程,通过一系列调用,measure、layout、draw等过程最终将视图文件绘制到页面上。

addView方法大概做了如下几件事:

  • 检查参数是否合法,并判断当前添加的是否为子Window(parentWindow是否为空),若为子Window则为其做相关调整,否则为其开启硬件加速
  • 监视系统属性的变化
  • 通过findViewLocked获取mViews中view的索引,看添加的view是否在mViews的集合里,如果获取的index>=0,此view存在,接着判断要删除的集合是否包含此view,若包含则直接执行doDie()删除当前view,若不包含则会抛出异常(此view正在被删除,还没有完成)
  • 判断添加的是否为panel window,若是则找出以备后查
  • 将Window的一系列参数添加到集合中,几种集合如下:

​ mViews:存储了所有Window所对应的View

​ mRoots:存储了所有Window所对应的ViewRootImpl

​ mParams:存储了所有Window所对应的布局参数

​ mDyingViews:存储的是即将被删除的View对象或正在被删除的View对象

  • 通过ViewRootImpl的setView方法来完成界面的更新,并完成Window的添加。
/**
 * 这里的几个参数:
 * View view, view 树
 * ViewGroup.LayoutParams params,窗口参数
 * Display display, 确定这个窗口需要显示到哪个屏幕,默认为主屏幕
 * Window parentWindow,父窗口
 *        Dialog、PopupWindow 等浮动窗口的父窗口为弹出它的Activity窗口,
 *        从后台 Service 启动的窗口可以没有父窗口
 */
public void addView(View view, ViewGroup.LayoutParams params,
                    Display display, Window parentWindow) {
    // wparams 会给窗口再附加一些属性
    final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
    ViewRootImpl root;//注意WindowManagerImpl和ViewRoot在同一进程中
    // 如果将要添加的是子窗口,panelParentView 为父窗口的 View 树,用来参考设置该子窗口的显示
    View panelParentView = null;

    synchronized (mLock) {。。。//锁保护
        // Start watching for system property changes.
        if (mSystemPropertyUpdater == null) {
            mSystemPropertyUpdater = new Runnable() {
                @Override public void run() {
                    synchronized (mLock) {
                        for (int i = mRoots.size() - 1; i >= 0; --i) {
                            mRoots.get(i).loadSystemProperties();
                        }
                    }
                }
            };
            SystemProperties.addChangeCallback(mSystemPropertyUpdater);
        }

        int index = findViewLocked(view, false);//以前是否已经添加过这个view对象
        if (index >= 0) {//已经添加过,禁止重复操作
            if (mDyingViews.contains(view)) {
                // Don't wait for MSG_DIE to make it's way through root's queue.
                mRoots.get(index).doDie();
            } else {
                throw new IllegalStateException("View " + view
                        + " has already been added to the window manager.");
            }
            // The previous removeView() had not completed executing. Now it has.
        }


        // 创建 ViewRootImpl
        root = new ViewRootImpl(view.getContext(), display);
        // 给 View 树关联窗口属性
        view.setLayoutParams(wparams);

        // 将 View 树、ViewRootImpl、以及窗口参数添加到各个列表里
        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);

        // 将 View 树关联到 ViewRootImpl
        root.setView(view, wparams, panelParentView);
    }
}

ViewRootImpl.setView()

经过一系列的处理之后最终会调用 mWindowSession.addToDisplay()请求 WindowManagerService 添加一个窗口。

这里传入的参数中最重要的几个是:

  • mWindow 应用端窗口代理
  • mWindowAttributes 窗口属性
  • 屏幕ID
  • 最后返回的 res 如果为 WindowManagerGlobal.ADD_OKAY 表示添加窗口成功,其他值为添加失败以及对应错误码。
try {
    mOrigWindowType = mWindowAttributes.type;
    mAttachInfo.mRecomputeGlobalAttributes = true;
    collectViewAttributes();
    adjustLayoutParamsForCompatibility(mWindowAttributes);
    controlInsetsForCompatibility(mWindowAttributes);
    res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
            getHostVisibility(), mDisplay.getDisplayId(), userId,
            mInsetsController.getRequestedVisibilities(), inputChannel, mTempInsets,
            mTempControls);

    if (mTranslator != null) {
        mTranslator.translateInsetsStateInScreenToAppWindow(mTempInsets);
        mTranslator.translateSourceControlsInScreenToAppWindow(mTempControls);
    }
} catch (RemoteException e) {
    mAdded = false;
    mView = null;
    mAttachInfo.mRootView = null;
    mFallbackEventHandler.setView(null);
    unscheduleTraversals();
    setAccessibilityFocus(null, null);
    throw new RuntimeException("Adding window failed", e);
} finally {
    if (restore) {
        attrs.restore();
    }
}

Session.addToDisplay()

ViewRoot起到一中介作用,通过IWindowSession构建起与WMS的桥梁,mWindowSession.addToDisplay()最终调用是IWindowSession的服务实现端Session的addToDisplay()。

@Override
public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs,
        int viewVisibility, int displayId, InsetsVisibilities requestedVisibilities,
        InputChannel outInputChannel, InsetsState outInsetsState,
        InsetsSourceControl[] outActiveControls) {
    return mService.addWindow(this, window, attrs, viewVisibility, displayId,
            UserHandle.getUserId(mUid), requestedVisibilities, outInputChannel, outInsetsState,
            outActiveControls);
}

WMS.addWindow()

关键过程如下:

  • 创建一个 WindowState 对象,表示一个窗口;
  • WindowState attach到Window
  • 将WindowState添加到mWindowMap
final WindowState win = new WindowState(this, session, client, token, parentWindow,
        appOp[0], attrs, viewVisibility, session.mUid, userId,
        session.mCanAddInternalSystemWindow);
if (win.mDeathRecipient == null) {
    // Client has apparently died, so there is no reason to
    // continue.
    ProtoLog.w(WM_ERROR, "Adding window client %s"
            + " that is dead, aborting.", client.asBinder());
    return WindowManagerGlobal.ADD_APP_EXITING;
}

//...
win.attach();
mWindowMap.put(client.asBinder(), win);

在 WindowManagerService 每添加一个窗口都会创建一个 WindowState 实例,并保存到窗口列表管理表 mWindowMap 里。 WindowState 里保存着关于这个窗口的大小、位置等信息。

每个 WindowState 都会创建一个 WindowStateAnimator 的实例,用来进行 Surface 相关的操作。

WindowState.attach()

void attach() {
    if (DEBUG) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
    mSession.windowAddedLocked();
}

Session.windowAddedLocked()

会到 Session 里创建一个 SurfaceSession。SurfaceSession是Window与SurfaceFlinger通信的媒介,每个应用进程创建一个。

void windowAddedLocked() {
    if (mPackageName == null) {
        final WindowProcessController wpc = mService.mAtmService.mProcessMap.getProcess(mPid);
        if (wpc != null) {
            mPackageName = wpc.mInfo.packageName;
            mRelayoutTag = "relayoutWindow: " + mPackageName;
            mUpdateViewVisibilityTag = "updateVisibility: " + mPackageName;
            mUpdateWindowLayoutTag = "updateLayout: " + mPackageName;
        } else {
            Slog.e(TAG_WM, "Unknown process pid=" + mPid);
        }
    }
    if (mSurfaceSession == null) {
        if (DEBUG) {
            Slog.v(TAG_WM, "First window added to " + this + ", creating SurfaceSession");
        }
        mSurfaceSession = new SurfaceSession();
        ProtoLog.i(WM_SHOW_TRANSACTIONS, "  NEW SURFACE SESSION %s", mSurfaceSession);
        mService.mSessions.add(this);
        if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
            mService.dispatchNewAnimatorScaleLocked(this);
        }
    }
    mNumWindow++;
}

Window的显示过程

Base on: Android 13

Branch: android-13.0.0_r30

AT.handleResumeActivity()

开始进行Activity的Resume流程,并伴随着Window的显示。

// The window is now visible if it has been added, we are not
// simply finishing, and we are not starting another activity.
if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
    if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" + isForward);
    ViewRootImpl impl = r.window.getDecorView().getViewRootImpl();
    WindowManager.LayoutParams l = impl != null
            ? impl.mWindowAttributes : r.window.getAttributes();
    if ((l.softInputMode
            & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
            != forwardBit) {
        l.softInputMode = (l.softInputMode
                & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
                | forwardBit;
        if (r.activity.mVisibleFromClient) {
            ViewManager wm = a.getWindowManager();
            View decor = r.window.getDecorView();
            wm.updateViewLayout(decor, l);
        }
    }

    r.activity.mVisibleFromServer = true;
    mNumVisibleActivities++;
    if (r.activity.mVisibleFromClient) {
        r.activity.makeVisible();
    }
}

Activity.makeVisible()

void makeVisible() {
    if (!mWindowAdded) {
        ViewManager wm = getWindowManager();
        wm.addView(mDecor, getWindow().getAttributes());
        mWindowAdded = true;
    }
    mDecor.setVisibility(View.VISIBLE);
}

待补充