WindowManagerService(WMS)窗口显示流程分析之创建Window

625 阅读13分钟

在android中,WMS 负责管理设备上所有的 Window ,所以应用想显示一个 Window 则要通过 WMS 来完成。 而 WMS 毕竟还是上层,窗口的内容要显示到屏幕上,还需要 SurfaceFlinger 来处理。
整个窗口的显示逻辑会涉及到三个模块:应用模块、WMS模块、SurfaceFlinger模块。 应用模块用来控制其内部的窗口的添加及 UI 绘制逻辑;WMS 模块作为系统窗口管理模块,处理应用模块的窗口显示逻辑;SurfaceFlinger 模块用于在屏幕上完成显示,WMS 只能控制上层的窗口逻辑,真正想要在屏幕上显示内容还需要 SurfaceFlinger 来完成。
整体而言,窗口显示分为如下三个流程。
(1) addWindow流程:WMS 是维护系统所有窗口的模块,所以应用必须先向 WMS 请求添加窗口,这一阶段 WMS 的处理为:为应用端创建对应的 WindowState 并挂载。
(2) relayoutWindow流程:addWindow 流程后执行后,屏幕上就有新的 WindowState 添加了,WMS 也需要对屏幕上所有的窗口执行一遍 layout 来确定各个窗口所在的位置。 而应用端想要绘制 UI 数据,则也需要知道自己的窗口大小,位置信息,并且还需要一个 Surface 来承载 UI 数据。所以这一阶段 WMS 的处理为:为窗口申请 Surface 并返回给应用端;计算返窗口的大小,位置信息并返回给应用端。
(3) finishDrawingWindow流程:执行完上一流程后,应用端就可以绘制 UI 了,绘制完成后需要将 UI 显示到屏幕上,这一步还是需要 WMS 来完成。即通知 SurfaceFlinger 进行显示这个 Surface。
本文以android 13代码为例进行源码分析。
创建窗口分析流程如下:

1,在frameworks/base/core/java/android/app/ActivityThread.java中

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { //第一个参数 ActivityClientRecord 是在ActivityThread.java中定义的内部类,即public static final class ActivityClientRecord {}
		ActivityInfo aInfo = r.activityInfo;
		ComponentName component = r.intent.getComponent();
		ContextImpl appContext = createBaseContextForActivity(r);
		Activity activity = null;
		java.lang.ClassLoader cl = appContext.getClassLoader();
		activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);//创建新的activity
		Window window = null; //定义window
		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.java中的attach方法,创建window
		if (r.isPersistable()) {
		    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
		} else {
		    mInstrumentation.callActivityOnCreate(activity, r.state); //会进一步调用到Activity.java中的performCreate函数
		}
		
		return activity;
	}

上面的函数调用Activity类的 attach 方法以及Instrumentation类的 callActivityOnCreate 方法。
下面先分析attach函数调用的路径。

2,在frameworks/base/core/java/android/app/Activity.java中

public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2,Window.Callback, KeyEvent.Callback,OnCreateContextMenuListener, 
			ComponentCallbacks2,Window.OnWindowDismissedCallback,ContentCaptureManager.ContentCaptureClient {
	private Window mWindow; //定义Window对象
	private WindowManager mWindowManager;
	View mDecor = null;

	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); // 将Activity的基础上下文(context)设置为传入的context。这是Activity上下文初始化的第一步
        mFragments.attachHost(null /*parent*/); // 将Activity作为宿主(host)与它的FragmentManager关联起来。这里传入的null表示没有父宿主,因为这是在创建顶层Activity时调用的。
        
	     // 创建一个PhoneWindow实例,并设置一系列的回调和参数,这些设置确保了Activity的窗口(UI)能够正确显示和处理用户交互
        mWindow = new PhoneWindow(this, window, activityConfigCallback); 
        mWindow.setWindowControllerCallback(mWindowControllerCallback);
        
		mWindow.setCallback(this); // 将 Activity 设置给了 Window,因为 Activity 也实现了 Window.Callback 接口,所以能传递 this ,这个接口主要是处理 Input 事件的。
        
		mToken = token; // 设置token为 ActivityRecord
		
		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(); // 设置当前线程为UI线程
        
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); // 将Activity的窗口与系统的窗口管理服务关联起来,包括设置硬件加速选项。

        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow()); // 如果这个Activity是作为另一个Activity的子Activity(如对话框Activity),则将其窗口的容器设置为父Activity的窗口。
        }
        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());
	}
}

上面用于在Activity被创建时,将其与Android系统的其他组件进行关联和初始化,attach 方法是 Activity 生命周期中的一个重要环节,它确保了Activity能够正确地与Android系统框架的其他部分集成,并准备好接收和处理用户输入及显示UI。
在上面的代码中,mWindow.setCallback(this);将 Activity 设置给了 Window,因为 Activity 也实现了 Window.Callback 接口,所以能传递 this ,这个接口主要是处理 Input 事件的。 Input 事件的传递流程都是先走到 Window,因为在 WMS 模块没有 Activity 的概念,只有 Window ,那么最后是怎么走到 Activity 呢?就是这里设置的 setCallback 。
同样在 Activity 类中,

public Window getWindow() { //getWindow 方法返回的其实是 PhoneWindow ,这是因为 Window 是个抽象类,而 PhoneWindow 是 Window 的唯一子类
    return mWindow;
}

在上面的 attach 函数中,通过 mWindow.setWindowManager 将Activity的窗口与系统的窗口管理服务关联起来。

3,在frameworks/base/core/java/android/view/Window.java中

public abstract class Window {
	private WindowManager mWindowManager;
	
	public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
        mAppToken = appToken; // appToken 这个就是AMS中与当前Activity对应的ActivityRecord
        mAppName = appName; //Activity全类名
        mHardwareAccelerated = hardwareAccelerated;
		//在SystemServer.java中,有wm的添加服务
		//wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);// WindowManagerService.main是WindowManagerService的启动入口。它创建并初始化WindowManagerService的实例
		//ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO); // 将WindowManagerService的实例注册到ServiceManager中
        if (wm == null) {
            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        }
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this); //调用createLocalWindowManager函数
    }
	
	public WindowManager getWindowManager() {
	    return mWindowManager;
	}
	
}

上面的代码调用WindowManagerImpl类的 createLocalWindowManager 函数。

4, 在frameworks/base/core/java/android/view/WindowManagerImpl.java中

public final class WindowManagerImpl implements WindowManager {
	private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
	private final Window mParentWindow;
	
	public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
	    return new WindowManagerImpl(mContext, parentWindow, mWindowContextToken); //重新创建返回了一个 WindowManagerImpl 对象
	}
	
	private WindowManagerImpl(Context context, Window parentWindow,
	        @Nullable IBinder windowContextToken) {
	    mContext = context;
	    mParentWindow = parentWindow; // 将 Window 设置给了 mParentWindow,相当于通过新创建的PhonWindow创建了一个 WindowManagerImpl ,作为其mWindowManager的对象
	    mWindowContextToken = windowContextToken;
	}

}

在 attach 函数中,通过 new PhoneWindow 创建一个PhoneWindow实例。

5, 在frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java中

public class PhoneWindow extends Window implements MenuBuilder.Callback {
	// This is the top-level view of the window, containing the window decor.
    private DecorView mDecor;

	public PhoneWindow(@UiContext Context context, Window preservedWindow,
            ActivityConfigCallback activityConfigCallback) {
        this(context);
        // Only main activity windows use decor context, all the other windows depend on whatever
        // context that was given to them.
        mUseDecorContext = true; // 设置了一个标志,表明这个PhoneWindow将使用装饰上下文(DecorContext)。装饰上下文通常用于主活动窗口,以确保窗口内的视图能够正确地继承和应用的主题属性。
        if (preservedWindow != null) {
            mDecor = (DecorView) preservedWindow.getDecorView(); // 复用之前窗口的装饰视图(DecorView)。
            mElevation = preservedWindow.getElevation();
            mLoadElevation = false;
            mForceDecorInstall = true; // 设置标志,表明强制安装装饰视图
            // If we're preserving window, carry over the app token from the preserved
            // window, as we'll be skipping the addView in handleResumeActivity(), and
            // the token will not be updated as for a new window.
            getAttributes().token = preservedWindow.getAttributes().token;
            mProxyOnBackInvokedDispatcher.setActualDispatcher(
                    preservedWindow.getOnBackInvokedDispatcher());
        }
        // Even though the device doesn't support picture-in-picture mode,
        // an user can force using it through developer options.
        boolean forceResizable = Settings.Global.getInt(context.getContentResolver(),
                DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
        mSupportsPictureInPicture = forceResizable || context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_PICTURE_IN_PICTURE);
        mActivityConfigCallback = activityConfigCallback;
    }

上面的代码调用 getDecorView 函数。

	@Override
    public final @NonNull View getDecorView() {
        if (mDecor == null || mForceDecorInstall) {
            installDecor(); //调用 installDecor 函数
        }
        return mDecor;
    }
	
	private void installDecor() {
        mForceDecorInstall = false;
        if (mDecor == null) {
            mDecor = generateDecor(-1); //调用 generateDecor 函数
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        } else {
            mDecor.setWindow(this);
        }
		if (mContentParent == null) {
			mContentParent = generateLayout(mDecor); // 调用generateLayout方法创建ViewGroup(Layout)
		}

	}
}

上面 mDecor 是 DecorView 本质上也是一个 View ,在 PhoneWindow::generateDecor 方法赋值,这个方法有多处会执行,最常见的就是我们在 Activity::onCreate 里执行 setContentView 的时候。 也就是说 Window 通过 mDecor 的变量持有一个 View。

protected DecorView generateDecor(int featureId) {
	    // System process doesn't have application context and in that case we need to directly use
	    // the context we have. Otherwise we want the application context, so we don't cling to the
	    // activity.
	    Context context;
	    if (mUseDecorContext) {
	        Context applicationContext = getContext().getApplicationContext();
	        if (applicationContext == null) {
	            context = getContext();
	        } else {
	            context = new DecorContext(applicationContext, this);
	            if (mTheme != -1) {
	                context.setTheme(mTheme);
	            }
	        }
	    } else {
	        context = getContext();
	    }
	    return new DecorView(context, featureId, this, getAttributes());
	}

上面的代码返回 new DecorView 对象。

6, 在frameworks/base/core/java/com/android/internal/policy/DecorView.java中

public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
	private PhoneWindow mWindow;
	
	DecorView(Context context, int featureId, PhoneWindow window,
	        WindowManager.LayoutParams params) {
	    super(context);
	    mFeatureId = featureId;
	
		 // 动画插值器:mShowInterpolator和mHideInterpolator分别被设置为显示和隐藏动画的插值器。这些插值器决定了动画的速度曲线,linear_out_slow_in和fast_out_linear_in是Android提供的预定义插值器资源。
	    mShowInterpolator = AnimationUtils.loadInterpolator(context,
	            android.R.interpolator.linear_out_slow_in);
	    mHideInterpolator = AnimationUtils.loadInterpolator(context,
	            android.R.interpolator.fast_out_linear_in);
	
		 // 从资源文件中加载了一些配置值,这些值通常定义在应用的资源文件中
	    mBarEnterExitDuration = context.getResources().getInteger(
	            R.integer.dock_enter_exit_duration);
	    mForceWindowDrawsBarBackgrounds = context.getResources().getBoolean(
	            R.bool.config_forceWindowDrawsStatusBarBackground)
	            && context.getApplicationInfo().targetSdkVersion >= N;
	    mSemiTransparentBarColor = context.getResources().getColor(
	            R.color.system_bar_background_semi_transparent, null /* theme */);
	
	    setWindow(window); // 将传入的PhoneWindow对象设置为DecorView的窗口。这是建立DecorView与PhoneWindow之间联系的关键步骤。
	
	    updateLogTag(params);
	
	    mResizeShadowSize = context.getResources().getDimensionPixelSize(
	            R.dimen.resize_shadow_size); // 从资源文件中加载调整大小的阴影大小。
	    initResizingPaints(); // 初始化用于绘制调整大小阴影的画笔。
	
	    mLegacyNavigationBarBackgroundPaint.setColor(Color.BLACK);
	}

上面的代码调用 setWindow 函数。

	void setWindow(PhoneWindow phoneWindow) {
	    mWindow = phoneWindow;
	    Context context = getContext();
	    if (context instanceof DecorContext) {
	        DecorContext decorContext = (DecorContext) context;
	        decorContext.setPhoneWindow(mWindow);
	    }
	    if (mPendingWindowBackground != null) {
	        Drawable background = mPendingWindowBackground;
	        mPendingWindowBackground = null;
	        setWindowBackground(background);
	    }
	}
}

在 new DecorView 之后,调用了 generateLayout 方法创建ViewGroup(Layout)。

7,在frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java中

protected ViewGroup generateLayout(DecorView decor) {
		
		int layoutResource;
		
		mDecor.startChanging(); // mDecor要改变的标记位
		mDecor.onResourcesLoaded(mLayoutInflater, layoutResource); // 将layoutResource布局文件解析成 View 添加到了 DecorView 之中
		// contentParent是用来添加Activity中布局的父布局(FrameLayout),并带有相关主题样式,就是上面提到的id为content的FrameLayout,返回后会赋值给PhoneWindow中的mContentParent
		ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
		
		return contentParent;
}

上面的 ID_ANDROID_CONTENT 是定义在 Window.java 中的静态常量。

/**
	 * The ID that the main layout in the XML layout file should have.
	 */
	public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;

到这里创建Window相关的就分析完了,创建的这个Window其实是 PhoneWindow。
在Android系统中,Window、PhoneWindow、WindowManagerImpl、WindowManager这几个类扮演着重要的角色,它们之间既存在区别又相互联系。 Window:是一个抽象类,表示一个窗口的概念。它负责窗口的创建、显示、隐藏以及用户界面的交互等操作。在Android开发中,不会直接实例化Window类,而是通过其子类PhoneWindow来实现具体的窗口功能。
PhoneWindow:是Window的一个具体实现类,专门为手机(或平板)设备设计。它负责Activity中的窗口管理,包括窗口的创建、销毁以及窗口内视图的布局等。PhoneWindow通过DecorView(一个特殊的ViewGroup)来承载应用的视图(View)。
WindowManager:是一个接口类,继承自ViewManager,用于对Window进行管理。它提供了添加View、更新View和删除View三个主要功能,这些功能定义在ViewManager接口中。WindowManager是外界访问Window的入口,对Window的访问必须通过WindowManager。
WindowManagerImpl:是WindowManager的实现类。它并没有直接实现Window的三大操作(添加、更新、删除),而是将这些操作委托给了WindowManagerGlobal来处理。
WindowManagerGlobal:是一个全局单例类,负责管理所有的Window和View。它提供了添加、更新和删除Window的方法,并维护了所有Window和View的列表。 在Android应用中,Activity通过PhoneWindow(Window的实现)来管理窗口和视图(View)。View树则通过ViewRootImpl与系统的窗口服务进行交互,完成视图的绘制和事件处理。WindowManager作为外界访问Window的入口,通过WindowManagerImpl和WindowManagerGlobal来实现对Window的具体操作。

以上分析了 attach 函数,下面接着分析与activity create 相关的代码。
在第一步代码中 performLaunchActivity 函数在调用了 Activity 的 attach 函数后,就会接着调用 callActivityOnCreate 函数。

8,在frameworks/base/core/java/android/app/Instrumentation.java中

public void callActivityOnCreate(Activity activity, Bundle icicle,
        PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState); // 调用performCreate函数
        postPerformCreate(activity);
}

上面的代码调用了Activity类的 performCreate 方法。在Activity.java中

9, 在frameworks/base/core/java/android/app/Activity.java中

public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2,Window.Callback, KeyEvent.Callback,OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback,ContentCaptureManager.ContentCaptureClient {
        ......
}

上面是Activity类的声明与继承。下面看Activity类中相关的函数。

final void performCreate(Bundle icicle, PersistableBundle persistentState) {
		if (persistentState != null) {
	        onCreate(icicle, persistentState); // 调用onCreate函数,在onCreate函数中执行setContentView函数
        } else {
            onCreate(icicle);
        }
	}

上面的代码调用 onCreate 函数。

@MainThread
	@CallSuper
	protected void onCreate(@Nullable Bundle savedInstanceState) {
	    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
	
	    if (mLastNonConfigurationInstances != null) { // 如果mLastNonConfigurationInstances不为空(这通常发生在配置改变如屏幕旋转时,系统尝试保留一些非配置改变的数据),则恢复加载器(Loaders)的状态。
	        mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);
	    }
	    if (mActivityInfo.parentActivityName != null) { // 如果Activity的父Activity名称不为空(意味着这个Activity可以向上导航),则根据是否已有ActionBar来设置默认的向上导航按钮。
	        if (mActionBar == null) { // 如果没有ActionBar,则标记为启用默认的向上导航
	            mEnableDefaultActionBarUp = true; 
	        } else { // 如果有ActionBar,则直接设置ActionBar的向上导航按钮为启用状态
	            mActionBar.setDefaultDisplayHomeAsUpEnabled(true);
	        }
	    }
	
	    if (savedInstanceState != null) { // 如果savedInstanceState不为空(意味着Activity之前的状态被保存了)
	        getAutofillClientController().onActivityCreated(savedInstanceState); // 调用getAutofillClientController().onActivityCreated(savedInstanceState)来处理自动填充客户端的创建
	
	        Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
	        mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
	                ? mLastNonConfigurationInstances.fragments : null); // 恢复Fragment的状态。
	    }
	    mFragments.dispatchCreate(); // 调用mFragments.dispatchCreate()来分发创建事件给所有的Fragment
		// 调用dispatchActivityCreated(savedInstanceState)来通知Activity已经创建完成,这允许子类在Activity创建完成后执行一些操作。
	    dispatchActivityCreated(savedInstanceState);
	    if (mVoiceInteractor != null) { // 如果mVoiceInteractor不为空(语音交互器),则将其附加到当前Activity上。
	        mVoiceInteractor.attachActivity(this);
	    }
	    mRestoredFromBundle = savedInstanceState != null; // 标记Activity是否是从一个保存的InstanceState中恢复的。
	    mCalled = true; // 标记onCreate方法已经被调用。
	
		  // 检查是否启用了提前的返回(Back)行为回调。如果启用了,则注册一个默认的返回行为回调,该回调会调用navigateBack方法。这是为了提供一种机制,允许系统或应用在某些情况下提前处理返回按钮的点击事件
	    boolean aheadOfTimeBack = WindowOnBackInvokedDispatcher
	            .isOnBackInvokedCallbackEnabled(this);
	    if (aheadOfTimeBack) {
	        // Add onBackPressed as default back behavior.
	        mDefaultBackCallback = this::navigateBack;
	        getOnBackInvokedDispatcher().registerSystemOnBackInvokedCallback(mDefaultBackCallback);
	    }
	}

上面的函数调用 dispatchActivityCreated 函数。

private void dispatchActivityCreated(@Nullable Bundle savedInstanceState) {
		  // getApplication()方法返回当前Activity所属的Application实例,然后调用Application实例的dispatchActivityCreated方法。
	    getApplication().dispatchActivityCreated(this, savedInstanceState); // 这个调用是为了通知Application类,有一个Activity已经完成了创建过程,并且可能带有一些保存的InstanceState。
		  // 收集所有注册的ActivityLifecycleCallbacks。这些回调允许应用程序或框架在Activity生命周期的关键点插入自定义的行为。
	    Object[] callbacks = collectActivityLifecycleCallbacks(); // collectActivityLifecycleCallbacks方法返回一个包含所有已注册回调的数组。
	    if (callbacks != null) {
	        for (int i = 0; i < callbacks.length; i++) { // 遍历这个数组,并对每个回调调用onActivityCreated方法。
	            ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityCreated(this,
	                    savedInstanceState);
	        }
	    }
	}

上面的函数调用 onActivityCreated 函数。

10,在frameworks/base/core/java/android/app/Application.java中

public class Application extends ContextWrapper implements ComponentCallbacks2 {
	
	public interface ActivityLifecycleCallbacks {
		/**
	     * Called when the Activity calls {@link Activity#onCreate super.onCreate()}.
	     */
	    void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState);
	}
}

定义一个Activity,在Activity中调用函数 setContentView 设置布局。

11,在frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java中

@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(); // 调用installDecor方法将Decor视图(即包含标题栏和状态栏的顶级视图)添加到Activity中
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }
    
        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene); // 调用transitionTo方法,利用内容转换特性将当前场景过渡到新创建的场景
        } else {
    		// 调用mLayoutInflater(LayoutInflater)的inflate方法,将XML布局文件解析成Viwe实例
            mLayoutInflater.inflate(layoutResID, mContentParent); // 使用mLayoutInflater(布局填充器)将指定的布局资源ID加载到mContentParent中。
        }
    	// 调用mContentParent的requestApplyInsets方法,用于请求应用窗口插入的方法,这个方法会触发ViewRootImpl的requestLayout方法,从而重新计算视图的布局
        mContentParent.requestApplyInsets(); // 调用mContentParent.requestApplyInsets()方法,这通常用于确保内容视图能够正确地考虑窗口的内边距(如状态栏和导航栏)
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }

mLayoutInflater.inflate 是 Android 中使用LayoutInflater类实例化布局的常见方式之一,针对实例化布局的要求,Android提供了 LayoutInflater 类。 LayoutInflater 是Android中一个用于加载布局的文件的类,主要负责将XML布局文件转换为对应的View对象。LayoutInflater类中有一个inflate()方法,可以将XML布局文件解析成Viwe实例。
至此执行到setContentView,其进一步的流程后续分析。