android12 ViewRootImpl分析

71 阅读23分钟

ViewRootImpl 是 Android 视图系统中一个极其核心的内部类,它不是一个普通的 View,而是连接窗口管理器(WindowManager)和 View 树的“枢纽” 。你可以把它理解为一个窗口的“总管家”,负责驱动整个 View 树的测量、布局、绘制,以及接收和分发所有的输入事件

1. 入口与创建:从 WindowManager.addView 开始

每个需要显示在屏幕上的窗口(如 Activity、Dialog、Toast),最终都会通过 WindowManager.addView() 将 DecorView(视图树的根)添加到系统中。

  • WindowManagerGlobal 会为这个窗口创建一个 ViewRootImpl 实例。

  • 随后调用其 setView() 方法,这一步至关重要:

    • 保存 View 根:将传入的 DecorView 赋值给 ViewRootImpl 的 mView 成员变量,作为后续操作的对象。
    • 向系统添加窗口:通过 mWindowSession.addToDisplayAsUser() 向系统服务 WindowManagerService (WMS) 请求添加一个窗口。
    • 请求首次布局:调用requestLayout()请求首次布局。
    • 初始化输入通道:建立一个 InputChannel,为后续接收来自系统 InputFlinger(是 IMS 在 Native 层(C++)  的核心处理逻辑) 的输入事件做准备。
//frameworks/base/core/java/android/view/WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow, int userId) {
    ...
    final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
    if (parentWindow != null) {
        //当前窗口为子窗口,需要让父窗口对当前窗口布局参数进行一些修改
        parentWindow.adjustLayoutParamsForSubWindow(wparams);
    } 
    ...

    ViewRootImpl root;
    View panelParentView = null;
    synchronized (mLock) {
        ...
        //同一个view不允许添加两次
        int index = findViewLocked(view, false);
        if (index >= 0) {
           ...
        }
        ...
        //创建ViewRootImpl
        root = new ViewRootImpl(view.getContext(), display);
        view.setLayoutParams(wparams);
        //保存到全局变量中
        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);

        try {
            //将View设置给ViewRootImpl,将触发真正的窗口添加过程
            root.setView(view, wparams, panelParentView, userId);
        } catch (RuntimeException e) {
            // BadTokenException or InvalidDisplayException, clean up.
            if (index >= 0) {
                removeViewLocked(index, true);
            }
            throw e;
        }
    }
}


//frameworks/base/core/java/android/view/ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
              int userId) {
        synchronized (this) {
            if (mView == null) {
                mView = view;
                ...
                //注册监听,监听屏幕变化(如横竖屏、折叠屏状态)
                mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
                //保存视图布局方向
                mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
                //处理未捕获的按键事件
                mFallbackEventHandler.setView(view);
                 //复制 Window 属性
                 mWindowAttributes.copyFrom(attrs);
                  ...
   //强制设置`PRIVATE_FLAG_USE_BLAST`(BLAST是Android 10+引入的新Surface合成架构)
                 mWindowAttributes.privateFlags |=
                          WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST;
  
                 attrs = mWindowAttributes;
                 ...
                 if (view instanceof RootViewSurfaceTaker) {
                     //允许应用自己管理Surface,而不是由WindowManager绘制
                      ...
                 }
                 ...
                 if (mSurfaceHolder == null) {
                      //启用硬件加速
                      //只有非自绘Surface的窗口才会尝试开启硬件加速(GPU渲染)
                      enableHardwareAcceleration(attrs);
                      ...
                      
                 }
                 ...
                 //请求首次布局
                 requestLayout();
                  
               //创建InputChannel,用于接收输入事件(触摸/按键),此时还是空壳
                 InputChannel inputChannel = null;
                 if ((mWindowAttributes.inputFeatures
                          & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                      inputChannel = new InputChannel();
                  }
                  ...
  
                 try {
                      ...
                     // 通过 Binder请求WMS添加窗口,携带参数inputChannel
                     res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
                              getHostVisibility(), mDisplay.getDisplayId(), userId,
                              mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,
                              mTempControls);
                    ...
                      
                 } 
                 ...
                 //处理添加窗口返回结果
                 if (res < WindowManagerGlobal.ADD_OKAY) {
                  //表示添加失败,根据不同错误码抛出对应的运行时异常
                  //常见的失败原因:Activity已退出、Token无效、权限不足、窗口类型重复等
                 ...
                 //创建`WindowInputEventReceiver`,接收原始输入事件,
                 //启动应用内的分发流程
                  if (inputChannel != null) {
                      if (mInputQueueCallback != null) {
                          mInputQueue = new InputQueue();
                          mInputQueueCallback.onInputQueueCreated(mInputQueue);
                      }
                      mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
                              Looper.myLooper());
  
                      ...
                  }
                 //ViewRootImpl将作为view的Parent
                 view.assignParent(this);
                 ...
           
              }
         }
}

建立通道

  • WindowManagerService 创建 InputChannel
    当窗口添加或更新时(ViewRootImpl.setView()),WMS 会通过 InputManagerService 创建一个 InputChannel(这是一个用于进程间通信的 Socket/管道对)。其中一个通道(Server 端)留在 SystemServer 进程供 IMS 写入事件,另一个通道(Client 端)通过 Binder 返回给应用进程。

  • 应用端注册接收器
    ViewRootImpl 拿到 Client 端的 InputChannel 后,会创建 WindowInputEventReceiver(继承自 InputEventReceiver),并调用其构造函数。
    在父类 InputEventReceiver 的构造函数中,会调用 nativeInit -> 在 Native 层创建 NativeInputEventReceiver 对象 -> 最终调用的 InputChannel.setNativeInputChannel,将 Native 层的 InputChannel 指针保存到 Java 层的 mPtr 中。

  • Native 层开始监听
    绑定完成后,Native 层的 NativeInputEventReceiver 会通过 Looper(或 epoll)开始监听这个 InputChannel 的文件描述符(fd)。当 IMS 将触摸或按键事件写入该通道时,Native 层会立即收到回调,并触发 InputEventReceiver.dispatchInputEvent(),进而一步步走到 ViewRootImpl.deliverInputEvent()

//frameworks/base/services/java/com/android/server/wm/WindowState.java
//在IMS中创建InputChannel
void openInputChannel(InputChannel outInputChannel) {
    ...
    mInputChannel = mWmService.mInputManager.createInputChannel(name);
    mInputChannelToken = mInputChannel.getToken();
    mInputWindowHandle.setToken(mInputChannelToken);
    mWmService.mInputToWindowMap.put(mInputChannelToken, this);
    if (outInputChannel != null) {
        mInputChannel.copyTo(outInputChannel);
    } else {
        ...
    }
}


//frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public InputChannel createInputChannel(String name) {
    return nativeCreateInputChannel(mPtr, name);
}

//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jobject nativeCreateInputChannel(JNIEnv* env, jclass /* clazz */, jlong ptr,
                                        jstring nameObj) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
    ...
    base::Result<std::unique_ptr<InputChannel>> inputChannel = im->createInputChannel(env, name);
    ...
    return inputChannelObj;
}

//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
base::Result<std::unique_ptr<InputChannel>> NativeInputManager::createInputChannel(
        JNIEnv* /* env */, const std::string& name) {
    ATRACE_CALL();
    return mInputManager->getDispatcher()->createInputChannel(name);
}


//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
//创建一对 `InputChannel` ,一个传给客户端(通过 `outInputChannel`),
//一个保留在 WMS 中用于接收输入事件
Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {

    std::unique_ptr<InputChannel> serverChannel;
    std::unique_ptr<InputChannel> clientChannel;
    //创建 Socket 管道
    status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);

  
    { // acquire lock
        std::scoped_lock _l(mLock);
        const sp<IBinder>& token = serverChannel->getConnectionToken();
        int fd = serverChannel->getFd();
        //构建 Connection 对象
        sp<Connection> connection =
                new Connection(std::move(serverChannel), false /*monitor*/, mIdGenerator);

        if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) {
           
        }
        //缓存起来,使用 `emplace` 插入,避免重复键
        mConnectionsByToken.emplace(token, connection);

        std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
                                                            this, std::placeholders::_1, token);
        //注册 Looper 回调
        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);
    } // release lock

    // Wake the looper because some connections have changed.
    
    mLooper->wake();
    return clientChannel;
}


public void copyTo(InputChannel outParameter) {
    ...
    //将 Java 层的对象与 Native(C++)层的输入管道绑定起来。
    outParameter.setNativeInputChannel(nativeDup(mPtr));
}

2. 绘制流程的引擎:scheduleTraversals 与 VSync

绘制流程的启动,实际上是由 requestLayout() 或 invalidate() 等操作触发的,它们最终都会调用到 scheduleTraversals() 方法。scheduleTraversals() 的核心工作包括:

  1. 发送同步屏障:在 Handler 的消息队列中插入一个同步屏障,保证后续的绘制消息(异步消息)能被优先处理,提高 UI 响应速度。
  2. 注册 VSync 回调:向 Choreographer(编舞者)注册一个 CALLBACK_TRAVERSAL 类型的回调。Choreographer 负责接收系统的垂直同步(VSync)信号,并按照输入 > 动画 > 遍历(绘制) 的优先级顺序执行回调。
  3. 等待信号:当下一个 VSync 信号到来时,Choreographer 就会执行之前注册的 mTraversalRunnable,进而调用到 doTraversal(),最终触发整个绘制流程的核心方法 performTraversals()
//frameworks/base/core/java/android/view/ViewRootImpl.java
public void requestLayout() {
    if (!mHandlingLayoutInLayoutRequest) {
        ...
        scheduleTraversals();
    }
}


void scheduleTraversals() {
    if (!mTraversalScheduled) {
        mTraversalScheduled = true;
        //MessageQueue 中插入一个同步屏障 。这个屏障的作用是:
        //所有同步消息都不会被执行,只有异步消息可以绕过屏障继续执行
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
        //注册一个执行 View 的测量、布局、绘制的CallBack
        mChoreographer.postCallback(
                Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
    //通知 `ThreadedRenderer`(硬件加速渲染器)即将有新的帧需要渲染。
    //`ThreadedRenderer` 是 Android 硬件加速的核心组件,负责将绘制指令转换为 GPU 命令
        notifyRendererOfFramePending();
       //Android 系统有一个"Draw Lock"机制,用于防止设备在应用正在
       //绘制关键帧时进入休眠
        pokeDrawLockIfNeeded();
    }
}

//VSYNC信号请求:Choreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL)
//具体调用看我的文章 # android 12 中的VSYNC请求
private void scheduleVsyncLocked() {
     ...
     //mDisplayEventReceiver = FrameDisplayEventReceiver
     //它通过 JNI 向系统的 `SurfaceFlinger` 注册 VSync 监听。
     mDisplayEventReceiver.scheduleVsync();
     ...
}

//VSync 信号到达 → `onVsync()` → `doFrame()` →  `doCallbacks()`
//具体调用看我的文章 # android 12 中的VSYNC请求
final class TraversalRunnable implements Runnable {
    @Override
    public void run() {
        doTraversal();
    }
}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();

void doTraversal() {
    if (mTraversalScheduled) {
        mTraversalScheduled = false;
        //移除同步屏障
        mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
        ...
        //核心绘制流程
        performTraversals();
        ...
       
    }
}


3. 三大流程:performTraversals 详解

performTraversals() 是 ViewRootImpl 最核心的方法,它会按顺序执行一次完整的 View 树刷新:

测量 (Measure)performMeasure() , 从根 DecorView 开始,自上而下地递归调用每个子 View 的 measure() 方法,以确定每个 View 应该占据的宽度和高度。
布局 (Layout)performLayout() ,在上一步确定好尺寸后,自顶向下地递归调用每个 View 的 layout() 方法,确定每个 View 在父容器中的具体位置。
绘制 (Draw)performDraw() ,将 View 树的内容绘制到屏幕上。在硬件加速开启的情况下(Android 默认开启),它会通过 ThreadedRenderer 将绘制指令交给 GPU 处理,否则会通过 CPU 进行软件绘制。

窗口布局 (relayoutWindow)relayoutWindow() 通过Binder调用WMS(WindowManagerService),请求更新窗口尺寸、Surface等。

private void performTraversals() {
    final View host = mView;
    //如果根视图不存在,或者该ViewRootImpl还没有被添加到WindowManager
    if (host == null || !mAdded) {
        return;
    }

  //BLAST (BufferQueue Layer Architecture Sync):这是Android图形系统的一个同步机制
    if (mWaitForBlastSyncComplete) {
        //如果`mWaitForBlastSyncComplete`为`true`,意味着ViewRootImpl正在
        //等待上一帧的BufferQueue事务被SurfaceFlinger处理完成。为了防止在等待期间
        //再次请求绘制导致状态混乱,此方法会直接返回,并设置
        //`mRequestedTraverseWhilePaused`为`true`,
        //以便在同步完成后立即重新触发一次遍历
        mRequestedTraverseWhilePaused = true;
        return;
    }
    //标记当前正处于遍历过程中,防止重入
    mIsInTraversal = true;
    //表示即将进行绘制
    mWillDrawSoon = true;
    //用于后续判断窗口大小是否可能改变
    boolean windowSizeMayChange = false;
    WindowManager.LayoutParams lp = mWindowAttributes;
    //期望的窗口宽高
    int desiredWindowWidth;
    int desiredWindowHeight;
    //获取根视图当前的可见性状态。
    final int viewVisibility = getHostVisibility();
    //视图可见性是否发生了变化
    final boolean viewVisibilityChanged = !mFirst
            && (mViewVisibility != viewVisibility || mNewSurfaceNeeded
            || mAppVisibilityChanged);
    mAppVisibilityChanged = false;
    //视图是否在"可见"和"不可见"之间发生了切换
    final boolean viewUserVisibilityChanged = !mFirst &&
            ((mViewVisibility == View.VISIBLE) != (viewVisibility == View.VISIBLE));

    WindowManager.LayoutParams params = null;
    ...

    Rect frame = mWinFrame;
    //第一次遍历
    if (mFirst) {
        //强制要求完整重绘
        mFullRedrawNeeded = true;
        //强制要求重新布局
        mLayoutRequested = true;

        final Configuration config = getConfiguration();
        //如果窗口应该使用Display的真实尺寸(系统窗口)
        if (shouldUseDisplaySize(lp)) {
            //期望的窗口尺寸=屏幕真实大小
            Point size = new Point();
            mDisplay.getRealSize(size);
            desiredWindowWidth = size.x;
            desiredWindowHeight = size.y;
                  //如果布局参数是`WRAP_CONTENT`
        } else if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
                || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
            //期望的窗口尺寸使用屏幕的DP尺寸(转换为像素)
            desiredWindowWidth = dipToPx(config.screenWidthDp);
            desiredWindowHeight = dipToPx(config.screenHeightDp);
        } else {
            //直接使用`mWinFrame`(来自WindowManager的窗口尺寸)的尺寸
            desiredWindowWidth = frame.width();
            desiredWindowHeight = frame.height();
        }

        //设置`AttachInfo`的初始状态
        mAttachInfo.mUse32BitDrawingCache = true;
        mAttachInfo.mWindowVisibility = viewVisibility;
        mAttachInfo.mRecomputeGlobalAttributes = false;
        mLastConfigurationFromResources.setTo(config);
        mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
        //如果布局方向未设置,则从配置中获取并设置
        if (mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
            host.setLayoutDirection(config.getLayoutDirection());
        }
        //通知根视图它已经被附加到窗口。这是View生命周期的关键一步。
        host.dispatchAttachedToWindow(mAttachInfo, 0);
        mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(true);
        //分发窗口Insets(如状态栏、导航栏区域)
        dispatchApplyInsets(host);
    } else {
        //非首次遍历,期望的窗口尺寸直接使用当前的`mWinFrame`尺寸
        desiredWindowWidth = frame.width();
        desiredWindowHeight = frame.height();
        //当前窗口帧的尺寸与上次记录的尺寸(`mWidth`, `mHeight`)不同,
        if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) {
            //设置重绘、布局标志,并标记`windowSizeMayChange = true`。
            mFullRedrawNeeded = true;
            mLayoutRequested = true;
            windowSizeMayChange = true;
        }
    }
    //如果视图可见性发生了变化
    if (viewVisibilityChanged) {
        //更新`AttachInfo`中的可见性
        mAttachInfo.mWindowVisibility = viewVisibility;
        //分发窗口可见性变化事件给根视图,最终会传递到各个子View。
        host.dispatchWindowVisibilityChanged(viewVisibility);
        //如果用户可见性发生变化,分发聚合可见性变化
        if (viewUserVisibilityChanged) {
            host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
        }
        //如果变为不可见,或者需要新Surface,
        if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
            //则结束拖拽调整大小状态
            endDragResizing();
            //并销毁硬件渲染资源 
            destroyHardwareResources();
        }
    }

    //如果窗口不可见
    if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
        //清除其可能持有的无障碍焦点
        host.clearAccessibilityFocus();
    }

    //执行在运行队列(`RunQueue`)中排队的动作。这些动作通常是由已分离的View
    //在`Handler`上延迟执行的。
    getRunQueue().executeActions(mAttachInfo.mHandler);
    //确定是否需要布局
    boolean layoutRequested = mLayoutRequested && (!mStopped || mReportNextDraw);
    if (layoutRequested) {

        final Resources res = mView.getContext().getResources();
        //首次遍历
        if (mFirst) {
            //设置触摸模式
            mAttachInfo.mInTouchMode = !mAddedTouchMode;
            ensureTouchModeLocally(mAddedTouchMode);
        } else {
            //不是首次遍历,
            //并且布局参数是`WRAP_CONTENT`
            if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
                    || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
                //那么窗口大小可能改变 
                windowSizeMayChange = true;
                //并重新计算期望的窗口尺寸(基于Display大小或屏幕DP)
                if (shouldUseDisplaySize(lp)) {
                    // NOTE -- system code, won't try to do compat mode.
                    Point size = new Point();
                    mDisplay.getRealSize(size);
                    desiredWindowWidth = size.x;
                    desiredWindowHeight = size.y;
                } else {
                    Configuration config = res.getConfiguration();
                    desiredWindowWidth = dipToPx(config.screenWidthDp);
                    desiredWindowHeight = dipToPx(config.screenHeightDp);
                }
            }
        }

        //measureHierarchy这个方法会考虑窗口的`LayoutParams`(如`WRAP_CONTENT`、
        //`MATCH_PARENT`或固定尺寸)以及`desiredWindowWidth/Height`,最终调用
        //`performMeasure()`来执行实际的测量操作。
        //`measureHierarchy()`的返回值会与`windowSizeMayChange`进行或运算,
        //表示测量过程可能导致窗口尺寸发生变化。
        windowSizeMayChange |= measureHierarchy(host, lp, res,
                desiredWindowWidth, desiredWindowHeight);
    }
    //检查视图树中是否有View请求了特定的窗口属性
    if (collectViewAttributes()) {
        params = lp;
    }
    if (mAttachInfo.mForceReportNewAttributes) {
        mAttachInfo.mForceReportNewAttributes = false;
        params = lp;
    }

    if (mFirst || mAttachInfo.mViewVisibilityChanged) {
        mAttachInfo.mViewVisibilityChanged = false;
        //处理软键盘输入模式
        int resizeMode = mSoftInputMode & SOFT_INPUT_MASK_ADJUST;
        
        if (resizeMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
            final int N = mAttachInfo.mScrollContainers.size();
            for (int i=0; i<N; i++) {
                if (mAttachInfo.mScrollContainers.get(i).isShown()) {
                    resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
                }
            }
            if (resizeMode == 0) {
                resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
            }
            if ((lp.softInputMode & SOFT_INPUT_MASK_ADJUST) != resizeMode) {
                lp.softInputMode = (lp.softInputMode & ~SOFT_INPUT_MASK_ADJUST) | resizeMode;
                params = lp;
            }
        }
    }
    
    //如果有待处理的Insets应用请求 (`mApplyInsetsRequested`),
    //并且窗口没有在移动或调整大小
    if (mApplyInsetsRequested && !(mWillMove || mWillResize)) {
        //立即分发Insets (`dispatchApplyInsets`)。
        dispatchApplyInsets(host);
        if (mLayoutRequested) {
           //如果分发Insets后触发了新的布局请求,则再次执行`measureHierarchy()`
           //,因为Insets的变化可能会影响View的测量尺寸
            windowSizeMayChange |= measureHierarchy(host, lp,
                    mView.getContext().getResources(),
                    desiredWindowWidth, desiredWindowHeight);
        }
    }

    //清除布局请求标志。注意,后续代码如果再次设置此标志,会导致额外的布局操作
    if (layoutRequested) {
        mLayoutRequested = false;
    }
    
    //判断是否需要向WindowManager请求调整窗口大小
    //有布局请求 (`layoutRequested`) 且窗口大小可能变化(`windowSizeMayChange`)
    //并且 (View的测量尺寸与当前窗口尺寸不匹配,或者对于`WRAP_CONTENT`的宽/高,当前的窗口帧小于期望的尺寸且不等于当前记录的尺寸)
    //如果正处于自由形式的拖拽调整大小状态 (`mDragResizing && 
    //RESIZE_MODE_FREEFORM`),也认为需要调整。
    boolean windowShouldResize = layoutRequested && windowSizeMayChange
        && ((mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight())
            || (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT &&
                    frame.width() < desiredWindowWidth && frame.width() != mWidth)
            || (lp.height == ViewGroup.LayoutParams.WRAP_CONTENT &&
                    frame.height() < desiredWindowHeight && frame.height() != mHeight));
    windowShouldResize |= mDragResizing && mResizeMode == RESIZE_MODE_FREEFORM;

    //如果Activity被重新启动 (`mActivityRelaunched`),也需要调整。
    windowShouldResize |= mActivityRelaunched;

    //计算`computesInternalInsets`:是否有监听器需要计算内部Insets,
    //或者上一次计算的Insets非空
    final boolean computesInternalInsets =
            mAttachInfo.mTreeObserver.hasComputeInternalInsetsListeners()
            || mAttachInfo.mHasNonEmptyGivenInternalInsets;
    //初始化一系列用于记录`relayoutWindow`结果的标志
    boolean insetsPending = false;
    int relayoutResult = 0;
    boolean updatedConfiguration = false;
    //获取当前Surface的generation ID,用于后续判断Surface是否被替换
    final int surfaceGenerationId = mSurface.getGenerationId();
    //记录视图是否可见
    final boolean isViewVisible = viewVisibility == View.VISIBLE;
    final boolean windowRelayoutWasForced = mForceNextWindowRelayout;
    boolean surfaceSizeChanged = false;
    boolean surfaceCreated = false;
    boolean surfaceDestroyed = false;
    
    boolean surfaceReplaced = false;
   //检查窗口属性是否发生变化,如果变化,则设置`params`以便在下一次`relayoutWindow`
   //中更新
    final boolean windowAttributesChanged = mWindowAttributesChanged;
    if (windowAttributesChanged) {
        mWindowAttributesChanged = false;
        params = lp;
    }
    //如果`params`需要更新
    if (params != null) {
        //如果View请求透明区域但窗口格式不支持Alpha通道,则强制改为半透明格式
        if ((host.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0
                && !PixelFormat.formatHasAlpha(params.format)) {
            params.format = PixelFormat.TRANSLUCENT;
        }
        //对`LayoutParams`进行兼容性调整
        adjustLayoutParamsForCompatibility(params);
        controlInsetsForCompatibility(params);
        //如果系统栏外观发生变化,通知View
        if (mDispatchedSystemBarAppearance != params.insetsFlags.appearance) {
            mDispatchedSystemBarAppearance = params.insetsFlags.appearance;
            mView.onSystemBarAppearanceChanged(mDispatchedSystemBarAppearance);
        }
    }
    final boolean wasReportNextDraw = mReportNextDraw;
     //### 执行窗口重布局 (relayoutWindow)
     //首次遍历、窗口需要调整大小、可见性变化、参数变化或强制重布局
    if (mFirst || windowShouldResize || viewVisibilityChanged || params != null
        || mForceNextWindowRelayout) {
        mForceNextWindowRelayout = false;
        //设置`insetsPending`,告知WindowManager我们稍后会提供内部Insets
        insetsPending = computesInternalInsets;
        //如果持有`SurfaceHolder`(例如SurfaceView)
        if (mSurfaceHolder != null) {
            //则加锁并允许绘制
            mSurfaceHolder.mSurfaceLock.lock();
            mDrawingAllowed = true;
        }

        boolean hwInitialized = false;
        boolean dispatchApplyInsets = false;
        //记录是否之前有有效的Surface (`hadSurface`)
        boolean hadSurface = mSurface.isValid();

        try {
            
            //如果硬件渲染器存在,
            if (mAttachInfo.mThreadedRenderer != null) {
                //暂停渲染
                if (mAttachInfo.mThreadedRenderer.pause()) {
                    //`pause()`返回`true`,说明有动画正在运行,
                    //需要推出一帧来恢复它们,因此将脏区域设置为整个窗口
                    mDirty.set(0, 0, mWidth, mHeight);
                }
            }
            //如果是首次遍历或可见性发生变化
            if (mFirst || viewVisibilityChanged) {
                mViewFrameInfo.flags |= FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED;
            }
             
            //这是一个IPC调用(通过`IWindowSession`),它会与WindowManagerService 
            //(WMS) 通信,请求重新布局窗口
            //`relayoutWindow`:更新窗口帧 (`mWinFrame`)、
            //更新Surface尺寸、创建或销毁Surface、应用窗口动画、返回合并后的配置 
            //(`mPendingMergedConfiguration`) 等。其返回值 `relayoutResult`
            //包含了各种状态标志。
            relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
            //判断窗口是否处于拖拽调整大小模式
            //自由窗口模式(如桌面模式下的窗口)
            final boolean freeformResizing = (relayoutResult
                    & WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM) != 0;       
            //分屏模式
            final boolean dockedResizing = (relayoutResult
                    & WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED) != 0;
            //任意一种拖拽调整大小模式
            final boolean dragResizing = freeformResizing || dockedResizing;
            //如果`relayoutResult`包含`RELAYOUT_RES_BLAST_SYNC`标志,
            //说明这次重布局需要与BLAST同步。
            if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_BLAST_SYNC) != 0) {
                //标记下一次绘制
                reportNextDraw();
                //如果硬件渲染开启
                if (isHardwareEnabled()) {
                    //表示下一次绘制使用BLAST同步机制
                    mNextDrawUseBlastSync = true;
                }
            }
            //检查SurfaceControl是否发生了变化。
            final boolean surfaceControlChanged =
                    (relayoutResult & RELAYOUT_RES_SURFACE_CHANGED)
                            == RELAYOUT_RES_SURFACE_CHANGED;

            //如果SurfaceControl有效
            if (mSurfaceControl.isValid()) {
                //会根据窗口属性、是否拖拽调整大小、Surface是否变化来更新透明度
                updateOpacity(mWindowAttributes, dragResizing,
                        surfaceControlChanged /*forceUpdate */);
            }

          
            ...

            surfaceSizeChanged = false;
            //检查Surface尺寸是否发生了变化
            if (!mLastSurfaceSize.equals(mSurfaceSize)) {
                surfaceSizeChanged = true;
                mLastSurfaceSize.set(mSurfaceSize.x, mSurfaceSize.y);
            }
            //检查"总是消费系统栏"的配置是否发生了变化。这个标志影响系统栏事件的分发方式
            final boolean alwaysConsumeSystemBarsChanged =
                    mPendingAlwaysConsumeSystemBars != mAttachInfo.mAlwaysConsumeSystemBars;
           //如果窗口的颜色模式(如广色域、HDR等)发生变化,更新渲染器的颜色模式设置
            updateColorModeIfNeeded(lp.getColorMode());
            //`surfaceCreated`:之前没有Surface,现在有了有效的Surface
            //`surfaceDestroyed`:之前有Surface,现在无效了
            surfaceCreated = !hadSurface && mSurface.isValid();
            surfaceDestroyed = hadSurface && !mSurface.isValid();

            //如果Surface的generation ID变化了,或者SurfaceControl发生了变化,
            //并且当前Surface有效,则认为Surface被替换了。
            surfaceReplaced = (surfaceGenerationId != mSurface.getGenerationId()
                    || surfaceControlChanged) && mSurface.isValid();
            if (surfaceReplaced) {
                //增加序列号,用于追踪Surface的变化
                mSurfaceSequenceId++;
            }
            //如果"总是消费系统栏"配置变化,
            if (alwaysConsumeSystemBarsChanged) {
                //更新`AttachInfo`并标记需要分发Insets
                mAttachInfo.mAlwaysConsumeSystemBars = mPendingAlwaysConsumeSystemBars;
                dispatchApplyInsets = true;
            }
            //如果标题栏Insets发生变化(例如窗口标题栏的位置变化),
            if (updateCaptionInsets()) {
               //标记需要分发Insets
                dispatchApplyInsets = true;
            }
            //如果需要分发Insets(配置变化、系统UI可见性变化、或有待处理的Insets请求),
            if (dispatchApplyInsets || mLastSystemUiVisibility !=
                    mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested) {
                mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
                dispatchApplyInsets(host);
                dispatchApplyInsets = true;
            }
            //**Surface创建**
            if (surfaceCreated) {
               //标记需要完全重绘,清空之前记录的透明区域。
                mFullRedrawNeeded = true;
                mPreviousTransparentRegion.setEmpty();
                 //如果硬件渲染器存在
                if (mAttachInfo.mThreadedRenderer != null) {
                    try {
                       //初始化
                        hwInitialized = mAttachInfo.mThreadedRenderer.initialize(mSurface);
                        //如果初始化成功,并且视图没有请求透明区域
                        if (hwInitialized && (host.mPrivateFlags
                                        & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
                            //预分配渲染缓冲区
                            mAttachInfo.mThreadedRenderer.allocateBuffers();
                        }
                    } catch (OutOfResourcesException e) {
                        handleOutOfResourcesException(e);
                        return;
                    }
                }    //**Surface销毁**
            } else if (surfaceDestroyed) {
                //清除滚动焦点
                if (mLastScrolledFocus != null) {
                    mLastScrolledFocus.clear();
                }
                //重置滚动位置
                mScrollY = mCurScrollY = 0;
                //如果根视图实现了`RootViewSurfaceTaker`
                if (mView instanceof RootViewSurfaceTaker) {
                    //通知滚动位置变化
                    ((RootViewSurfaceTaker) 
                    mView).onRootViewScrollYChanged(mCurScrollY);
                }
                
                if (mScroller != null) {
                   //终止滚动动画
                    mScroller.abortAnimation();
                }
                //如果硬件渲染开启,
                if (isHardwareEnabled()) {
                    //销毁渲染器
                    mAttachInfo.mThreadedRenderer.destroy();
                }
                
                 //如果Surface被替换、尺寸变化、或强制重布局,并且没有
                 //`SurfaceHolder`,硬件渲染器存在,Surface有效
            } else if ((surfaceReplaced
                    || surfaceSizeChanged || windowRelayoutWasForced)
                    && mSurfaceHolder == null
                    && mAttachInfo.mThreadedRenderer != null
                    && mSurface.isValid()) {
                //标记需要完全重绘
                mFullRedrawNeeded = true;
                try {
                    //更新Surface
                    mAttachInfo.mThreadedRenderer.updateSurface(mSurface);
                } catch (OutOfResourcesException e) {
                    handleOutOfResourcesException(e);
                    return;
                }
            }

            //拖拽调整大小状态处理
            if (mDragResizing != dragResizing) {
                //如果是拖拽调整大小模式
                if (dragResizing) {
                    //设置`mResizeMode`为自由窗口模式或分屏模式
                    mResizeMode = freeformResizing
                            ? RESIZE_MODE_FREEFORM
                            : RESIZE_MODE_DOCKED_DIVIDER;
                    //检查背景框尺寸是否与窗口帧匹配
                    final boolean backdropSizeMatchesFrame =
                            mWinFrame.width() == mPendingBackDropFrame.width()
                                    && mWinFrame.height() == mPendingBackDropFrame.height();
                    // 开始拖拽调整大小,传入背景框、是否匹配、内容Insets、
                    //稳定Insets和调整模式
                    startDragResizing(mPendingBackDropFrame, !backdropSizeMatchesFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mResizeMode);
                } else {
                    //如果退出拖拽调整大小模式
                    endDragResizing();
                }
            }
            //如果使用的是非移动端渲染器
            if (!mUseMTRenderer) {
                if (dragResizing) {
                    //设置Canvas偏移量为窗口左上角坐标,确保绘制内容正确偏移
                    mCanvasOffsetX = mWinFrame.left;
                    mCanvasOffsetY = mWinFrame.top;
                } else {
                    //重置偏移量为0
                    mCanvasOffsetX = mCanvasOffsetY = 0;
                }
            }
        } catch (RemoteException e) {
        }

      
        //更新`AttachInfo`中的窗口位置
        mAttachInfo.mWindowLeft = frame.left;
        mAttachInfo.mWindowTop = frame.top;
      
        //如果与之前不同则更新 ,更新记录的窗口尺寸`mWidth`和`mHeight`
        if (mWidth != frame.width() || mHeight != frame.height()) {
            mWidth = frame.width();
            mHeight = frame.height();
        }

        if (mSurfaceHolder != null) {
            //如果Surface有效,将Surface赋值给`SurfaceHolder`
            if (mSurface.isValid()) {
                mSurfaceHolder.mSurface = mSurface;
            }
            //设置Surface的尺寸为窗口尺寸
            mSurfaceHolder.setSurfaceFrameSize(mWidth, mHeight);
            mSurfaceHolder.mSurfaceLock.unlock();
            //如果Surface刚刚创建
            if (surfaceCreated) {
               //确保回调不会被重复调用
                mSurfaceHolder.ungetCallbacks();

                mIsCreating = true;
                SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks();
                if (callbacks != null) {
                    for (SurfaceHolder.Callback c : callbacks) {
                //遍历并调用每个回调的`surfaceCreated()`方法,通知应用Surface已创建
                        c.surfaceCreated(mSurfaceHolder);
                    }
                }
            }

            //如果Surface创建、替换、尺寸变化或窗口属性变化,并且Surface有效
            if ((surfaceCreated || surfaceReplaced || surfaceSizeChanged
                    || windowAttributesChanged) && mSurface.isValid()) {
                SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks();
                if (callbacks != null) {
                    for (SurfaceHolder.Callback c : callbacks) {
                        //遍历所有回调,调用`surfaceChanged()`方法,
                        //通知应用Surface发生了变化(格式、宽高)
                        c.surfaceChanged(mSurfaceHolder, lp.format,
                                mWidth, mHeight);
                    }
                }
                mIsCreating = false;
            }
            //如果Surface被销毁
            if (surfaceDestroyed) {
                //通知持有者Surface被销毁
                notifyHolderSurfaceDestroyed();
                mSurfaceHolder.mSurfaceLock.lock();
                try { 
                    //加锁并创建一个新的空的Surface对象替换原来的
                    mSurfaceHolder.mSurface = new Surface();
                } finally {
                    mSurfaceHolder.mSurfaceLock.unlock();
                }
            }
        }

        final ThreadedRenderer threadedRenderer = mAttachInfo.mThreadedRenderer;
        //检查是否需要设置/重新设置渲染器:硬件初始化、尺寸变化、或需要设置
        if (threadedRenderer != null && threadedRenderer.isEnabled()) {
            if (hwInitialized
                    || mWidth != threadedRenderer.getWidth()
                    || mHeight != threadedRenderer.getHeight()
                    || mNeedsRendererSetup) {
                 //配置渲染器,传入窗口尺寸、AttachInfo和Surface Insets
                threadedRenderer.setup(mWidth, mHeight, mAttachInfo,
                        mWindowAttributes.surfaceInsets);
                mNeedsRendererSetup = false;
            }
        }

       
        if (!mStopped || wasReportNextDraw) {
            //表示触摸模式变化是否导致了焦点变化
            boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
                    (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
            //触摸模式导致焦点变化、窗口尺寸与测量尺寸不匹配、应用了Insets、或配置更新
            if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
                    || mHeight != host.getMeasuredHeight() || dispatchApplyInsets ||
                    updatedConfiguration) {
                int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
                int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);

                //重新测量,会触发整个视图树的`onMeasure()`方法
                performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);

                //获取测量后的宽高,并初始化`measureAgain`
                int width = host.getMeasuredWidth();
                int height = host.getMeasuredHeight();
                boolean measureAgain = false;
                
                //如果`LayoutParams`中设置了水平或垂直权重
                if (lp.horizontalWeight > 0.0f) {
                   //根据剩余空间和权重比例计算额外的尺寸
                    width += (int) ((mWidth - width) * lp.horizontalWeight);
                    //创建精确模式的MeasureSpec
                    childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width,
                            MeasureSpec.EXACTLY);
                    //-   标记需要再次测量
                    measureAgain = true;
                }
                if (lp.verticalWeight > 0.0f) {
                    height += (int) ((mHeight - height) * lp.verticalWeight);
                    childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
                            MeasureSpec.EXACTLY);
                    measureAgain = true;
                }

                //如果需要再次测量(因为有权重)
                if (measureAgain) {
                    //执行第二次测量。
                    performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
                }

                layoutRequested = true;
            }
        }
    } else {
        //如果不满足任何重布局条件(没有首次、不需要调整大小、可见性没变、参数没变、
        //没有强制重布局)
        //检查窗口是否移动了位置,如果移动了则更新AttachInfo中的窗口位置。
        maybeHandleWindowMove(frame);
    }

    //如果Surface尺寸变化、替换、创建或窗口属性变化,
    if (surfaceSizeChanged || surfaceReplaced || surfaceCreated || windowAttributesChanged) {
        //会遍历窗口中的所有SurfaceView等子视图,更新它们的Surface相关状态
        prepareSurfaces();
    }

    
    //是否需要执行布局。条件是有布局请求,并且应用未停止或需要报告下一次绘制。
    final boolean didLayout = layoutRequested && (!mStopped || wasReportNextDraw);
    //是否需要触发全局布局监听器。布局执行了,或者需要重新计算全局属性。
    boolean triggerGlobalLayoutListener = didLayout
            || mAttachInfo.mRecomputeGlobalAttributes;
    //如果需要布局
    if (didLayout) {
      //执行布局
      //此方法会调用根视图的`layout()`方法,从而触发整个视图树的布局过程(`onLayout`)
        performLayout(lp, mWidth, mHeight);
        //如果视图请求透明区域(`PFLAG_REQUEST_TRANSPARENT_REGIONS`)
        if ((host.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
            //获取视图在窗口中的位置(
            host.getLocationInWindow(mTmpLocation);
            mTransparentRegion.set(mTmpLocation[0], mTmpLocation[1],
                    mTmpLocation[0] + host.mRight - host.mLeft,
                    mTmpLocation[1] + host.mBottom - host.mTop);

            //遍历视图树,收集所有子视图的透明区域。这个过程会从`mTransparentRegion`中
            //减去不透明子视图的区域,最终得到真正透明的区域。
            host.gatherTransparentRegion(mTransparentRegion);
            if (mTranslator != null) {
               //如果有坐标转换器(例如在兼容模式下),将透明区域从窗口坐标转换为屏幕坐标
               mTranslator.translateRegionInWindowToScreen(mTransparentRegion);
            }
            //如果透明区域发生了变化
            if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {
                //更新`mPreviousTransparentRegion`
                mPreviousTransparentRegion.set(mTransparentRegion);
                //标记需要完全重绘
                mFullRedrawNeeded = true;
                //-   获取SurfaceControl,通过SurfaceTransaction设置透明区域提示
                //给SurfaceFlinger,帮助优化合成性能
                SurfaceControl sc = getSurfaceControl();
                if (sc.isValid()) {
                    mTransaction.setTransparentRegionHint(sc, mTransparentRegion).apply();
                }
            }
        }

      
    }

    //**通知Surface生命周期事件**
    if (surfaceCreated) {
        notifySurfaceCreated();
    } else if (surfaceReplaced) {
        notifySurfaceReplaced();
    } else if (surfaceDestroyed)  {
        notifySurfaceDestroyed();
    }

    //触发全局布局监听器
    if (triggerGlobalLayoutListener) {
        mAttachInfo.mRecomputeGlobalAttributes = false;
        mAttachInfo.mTreeObserver.dispatchOnGlobalLayout();
    }
    //计算并报告内部Insets
    if (computesInternalInsets) {
        final ViewTreeObserver.InternalInsetsInfo insets = mAttachInfo.mGivenInternalInsets;
        insets.reset();

        mAttachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets);
        mAttachInfo.mHasNonEmptyGivenInternalInsets = !insets.isEmpty();

        // Tell the window manager.
        if (insetsPending || !mLastGivenInsets.equals(insets)) {
            mLastGivenInsets.set(insets);

            final Rect contentInsets;
            final Rect visibleInsets;
            final Region touchableRegion;
            if (mTranslator != null) {
                contentInsets = mTranslator.getTranslatedContentInsets(insets.contentInsets);
                visibleInsets = mTranslator.getTranslatedVisibleInsets(insets.visibleInsets);
                touchableRegion = mTranslator.getTranslatedTouchableArea(insets.touchableRegion);
            } else {
                contentInsets = insets.contentInsets;
                visibleInsets = insets.visibleInsets;
                touchableRegion = insets.touchableRegion;
            }

            try {
                //通过`mWindowSession.setInsets()`将计算出的内部Insets
                //报告给WindowManagerService。
                mWindowSession.setInsets(mWindow, insets.mTouchableInsets,
                        contentInsets, visibleInsets, touchableRegion);
            } catch (RemoteException e) {
            }
        }
    }
    //在首次遍历时处理焦点分配
    if (mFirst) {
        //如果`AlwaysAssignFocus`为true或者不在触摸模式
        if (sAlwaysAssignFocus || !isInTouchMode()) {
            
            if (mView != null) {
                //如果根视图没有焦点
                if (!mView.hasFocus()) {
                   //尝试恢复默认焦点
                    mView.restoreDefaultFocus();
                    
                    }
                } else {
                    
                }
            }
        } else {
            //(在触摸模式下)
            //查找当前焦点的View
            View focused = mView.findFocus();
            //如果焦点View是一个ViewGroup,并且其焦点策略是
            //`FOCUS_AFTER_DESCENDANTS`(先给子View
            if (focused instanceof ViewGroup
                    && ((ViewGroup) focused).getDescendantFocusability()
                            == ViewGroup.FOCUS_AFTER_DESCENDANTS) {
                //则尝试恢复默认焦点这是为了处理ScrollView等在布局完成后
                //才可能让子View获得焦点的情况
                focused.restoreDefaultFocus();
            }
        }
    }
    
    //可见性发生了变化(首次遍历或可见性变化)并且当前可见
    final boolean changedVisibility = (viewVisibilityChanged || mFirst) && isViewVisible;
    //窗口是否有焦点并且视图可见
    final boolean hasWindowFocus = mAttachInfo.mHasWindowFocus && isViewVisible;
    final boolean regainedFocus = hasWindowFocus && mLostWindowFocus;
    //重新获得焦点(有窗口焦点并且之前失去焦点)
    if (regainedFocus) {
        mLostWindowFocus = false;
    } else if (!hasWindowFocus && mHadWindowFocus) {
        mLostWindowFocus = true;
    }

    if (changedVisibility || regainedFocus) {
        //如果可见性变化或重新获得焦点,并且不是Toast窗口,
        boolean isToast = mWindowAttributes.type == TYPE_TOAST;
        if (!isToast) {
        //发送无障碍事件`TYPE_WINDOW_STATE_CHANGED`。
            host.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
        }
    }

    mFirst = false;
    mWillDrawSoon = false;
    mNewSurfaceNeeded = false;
    mActivityRelaunched = false;
    mViewVisibility = viewVisibility;
    mHadWindowFocus = hasWindowFocus;

    mImeFocusController.onTraversal(hasWindowFocus, mWindowAttributes);

    //如果`relayoutWindow()`返回`RELAYOUT_RES_FIRST_TIME`(表示这是第一次布局)
    if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
        reportNextDraw();
    }

    //### 执行绘制
    boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
    //如果不取消绘制
    if (!cancelDraw) {
        //如果有待处理的View属性动画过渡(`ViewPropertyAnimator`)
        if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
            for (int i = 0; i < mPendingTransitions.size(); ++i) {
                //启动过渡动画
                mPendingTransitions.get(i).startChangingAnimations();
            }
            //清空待处理过渡列表
            mPendingTransitions.clear();
        }
        performDraw();
    } else {
        //如果取消绘制
        //如果视图仍然可见
        if (isViewVisible) {
            //安排下一次遍历
            scheduleTraversals();
        } else {
        //如果视图不可见
            if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
                for (int i = 0; i < mPendingTransitions.size(); ++i) {
                    //结束所有待处理的过渡动画
                    mPendingTransitions.get(i).endChangingAnimations();
                }
                mPendingTransitions.clear();
            }

            //如果需要报告下一次绘制(`mReportNextDraw`为true)
            if (!wasReportNextDraw && mReportNextDraw) {
                mReportNextDraw = false;
                //完成绘制
                pendingDrawFinished();
            }
        }
    }
    ...
    mIsInTraversal = false;
}




private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
     ...
     mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
     ...
}


private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,
        int desiredWindowHeight) {
    //标记滚动可能发生变化
    mScrollMayChange = true;
    //表示当前正处于布局过程中
    mInLayout = true;
    final View host = mView;
    if (host == null) {
        return;
    }
    
    try {
        //调用根视图的`layout()`方法。
        //-   这里传入`(0, 0, measuredWidth, measuredHeight)`,
        //表示根视图从窗口的`(0,0)`位置开始,尺寸为测量阶段确定的尺寸。
        //这会触发整个视图树的递归布局过程,每个View的`onLayout()`方法会被调用,
        //以确定所有子View的位置。
        host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
        //立即将`mInLayout`设为`false`。这看起来有些反直觉,
        //但目的是为了检测在`layout()`执行完毕后,是否有View在`onLayout()`
        //或`onLayout()`之后的代码中调用了`requestLayout()`
        //如果在`layout()`执行过程中有View调用了`requestLayout()`,
        //它们会被添加到`mLayoutRequesters`列表中(在`requestLayout()`中通过
        //`ViewRootImpl`的`requestLayoutDuringLayout()`方法添加)。
        mInLayout = false;
        //检查在布局过程中是否有View请求了重新布局(调用了`requestLayout()`)
       //`mLayoutRequesters`是一个`ArrayList<View>`,存储了在布局过程中请求
       //重新布局的View。
        int numViewsRequestingLayout = mLayoutRequesters.size();
        if (numViewsRequestingLayout > 0) {
           ///遍历`mLayoutRequesters`列表,检查每个View的`mPrivateFlags`
           //中是否设置了`PFLAG_FORCE_LAYOUT`标志。返回仍然有效的请求者列表
           //(即`PFLAG_FORCE_LAYOUT`仍为`true`的View),同时会清除
           //这些View的`PFLAG_FORCE_LAYOUT`标志(因为`false`参数表示需要清除)
            ArrayList<View> validLayoutRequesters = getValidLayoutRequesters(mLayoutRequesters,
                    false);
            if (validLayoutRequesters != null) {
                //如果存在有效的布局请求者
                mHandlingLayoutInLayoutRequest = true;

                
                int numValidRequests = validLayoutRequesters.size();
                for (int i = 0; i < numValidRequests; ++i) {
                    //遍历所有有效的布局请求者
                    final View view = validLayoutRequesters.get(i);
                    //再次调用`view.requestLayout()`。这会重新设置
                    //`PFLAG_FORCE_LAYOUT`标志,并重新将View添加到
                    //`mLayoutRequesters`列表中,为第二次布局做准备。
                    view.requestLayout();
                }
                //执行第二次测量:由于某些View在布局过程中请求了重新布局
                //,需要重新执行测量阶段。
                //调用`measureHierarchy()`,传入窗口参数、资源和期望的宽高。
                //这会导致整个视图树重新测量,以确保尺寸正确。
                measureHierarchy(host, lp, mView.getContext().getResources(),
                        desiredWindowWidth, desiredWindowHeight);
                //表示进入第二次布局过程。
                mInLayout = true;
                //执行第二次布局。这次会使用重新测量后的尺寸
                host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
                //表示第二次布局过程结束
                mHandlingLayoutInLayoutRequest = false;

                //检查第二次布局过程中是否有新的请求
                //参数`true`表示**只检查但不清除**`PFLAG_FORCE_LAYOUT`标志。
                //如果第二次布局过程中又有View调用了`requestLayout()`,
                //它们会再次出现在`mLayoutRequesters`中。
                validLayoutRequesters = getValidLayoutRequesters(mLayoutRequesters, true);
                // 如果在第二次布局过程中仍有View调用了`requestLayout()`,
                if (validLayoutRequesters != null) {
                    final ArrayList<View> finalRequesters = validLayoutRequesters;
             //不立即处理(避免无限循环),而是通过`RunQueue`将请求延迟到下一帧执行
             //`RunQueue`是ViewRootImpl内部的机制,用于在Handler上延迟执行操作。
                    getRunQueue().post(new Runnable() {
                        @Override
                        public void run() {
                            int numValidRequests = finalRequesters.size();
                            for (int i = 0; i < numValidRequests; ++i) {
                                final View view = finalRequesters.get(i);
                                
                                view.requestLayout();
                            }
                        }
                    });
                }
            }

        }
    } finally {
        
    }
    //表示布局过程彻底结束。
    mInLayout = false;
}


4. 输入事件的中枢:InputStage 责任链

所有触摸、按键事件由系统 InputFlinger 分发给应用进程,ViewRootImpl 是应用内接收事件的入口。它内部设计了一套名为 InputStage 的责任链来处理事件。

  • 当 ViewRootImpl 的 InputChannel 收到原始事件后,会被封装成 QueuedInputEvent 放入队列。
  • 随后,doProcessInputEvents() 方法会从队列中取出事件,并通过 deliverInputEvent() 方法将其交给责任链的第一个节点(mFirstInputStage)处理。
  • InputStage 链上的每个节点(如 ViewPreImeInputStageViewPostImeInputStage)各司其职,依次处理事件的不同阶段。如果某个 Stage 消费了事件,链条就会终止;否则,事件会继续传递给下一个 Stage。最终,事件会被分发给具体的目标 View。

输入事件怎么分发的具体看我的文章# android12 InputManagerService分析之输入事件分发