android12 WindowManagerService窗口的添加过程

窗口的添加是一个从应用进程到系统服务进程(SystemServer)的跨进程通信(IPC)过程。核心逻辑在 WindowManagerService (WMS) 的 addWindow 方法中。

整体流程大致如下:

  • 应用进程侧WindowManagerImpl.addView() -> WindowManagerGlobal.addView() -> 创建 ViewRootImpl -> ViewRootImpl.setView()
  • 跨进程通信ViewRootImpl 通过 Session.addToDisplayAsUser() 发起 IPC 调用。
  • 系统服务侧 (WMS)WindowManagerService.addWindow() 进行权限验证、创建 WindowState 等核心工作。

应用进程:从 addViewViewRootImpl

  1. WindowManagerImpl.addView() :应用调用 WindowManageraddView,实际由 WindowManagerImpl 实现,它直接转发给单例 WindowManagerGlobal
less 复制代码
//frameworks/base/core/java/android/view/WindowManagerImpl.java
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyTokens(params);
    //mGlobal = WindowManagerGlobal
    mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
            mContext.getUserId());
}
  1. WindowManagerGlobal.addView() :核心工作在此:

    • 为每个窗口创建一个 ViewRootImpl 对象。
    • ViewLayoutParams 等信息存储。
    • 调用 root.setView(view, wparams, panelParentView) 将视图和参数关联。
scss 复制代码
//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;
        }
    }
}
  1. ViewRootImpl 初始化 :构造时会通过 WindowManagerGlobal.getWindowSession() 获取与 WMS 通信的 IWindowSession 对象(Binder 代理),同时创建一个 W 对象(IWindow.Stub 实现)供 WMS 反向回调。
java 复制代码
//ViewRootImpl 初始化
//frameworks/base/core/java/android/view/ViewRootImpl.java
public ViewRootImpl(Context context, Display display) {
          this(context, display, WindowManagerGlobal.getWindowSession(),
                  false /* useSfChoreographer */);
}

//获取与 WMS 通信的IWindowSession
//frameworks/base/core/java/android/view/WindowManagerGlobal.java
public static IWindowSession getWindowSession() {
          synchronized (WindowManagerGlobal.class) {
              if (sWindowSession == null) {
                  try {
                      
                      IWindowManager windowManager = getWindowManagerService();
                      //创建Session对象
                      sWindowSession = windowManager.openSession(
                              new IWindowSessionCallback.Stub() {
                                  @Override
                                  public void onAnimatorScaleChanged(float scale) {
                                      ValueAnimator.setDurationScale(scale);
                                  }
                              });
                  } catch (RemoteException e) {
                      throw e.rethrowFromSystemServer();
                  }
              }
              return sWindowSession;
          }
  }
  1. ViewRootImpl.setView() :进行布局请求和绘制调度,并调用 mWindowSession.addToDisplayAsUser() 发起跨进程请求
scss 复制代码
//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);
                 ...
           
              }
         }
}

跨进程通信:Session 的中介作用

Session 是每个应用进程在 WMS 端的"代理人"。ViewRootImpl 调用的 mWindowSession.addToDisplayAsUser() 是一个 AIDL 接口方法,调用后请求会进入 system_server 进程,由 Session 对象接收并转交给 WMS 的 addWindow 方法。

arduino 复制代码
//frameworks/base/services/core/java/com/android/server/wm/Session.java
public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
        int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
        InputChannel outInputChannel, InsetsState outInsetsState,
        InsetsSourceControl[] outActiveControls) {
        //mService = WindowManagerService
    return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
            requestedVisibility, outInputChannel, outInsetsState, outActiveControls);
}

WMS 系统服务:addWindow 的核心处理

WindowManagerService.addWindow() 中,系统会进行以下关键步骤:

  • 权限与参数检查:验证调用者权限及窗口参数有效性。
  • 创建 WindowState :这是 WMS 管理窗口的核心数据对象,记录窗口所有属性。
  • 处理 WindowToken :根据窗口类型,查找或创建对应的 WindowToken 作为容器。
  • 注册窗口 :将新创建的 WindowState 存入全局映射表 mWindowMap 等数据结构中。
  • 分配 Z-Order:触发窗口层级重新排序,确定新窗口在 Z 轴上的位置。
  • 返回结果 :将结果(如 ADD_OKAY)返回给应用进程。
ini 复制代码
//frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
        int displayId, int requestUserId, InsetsState requestedVisibility,
        InputChannel outInputChannel, InsetsState outInsetsState,
        InsetsSourceControl[] outActiveControls) {
    //清空输出参数:防止返回脏数据
    Arrays.fill(outActiveControls, null);
    int[] appOp = new int[1];
    final boolean isRoundedCornerOverlay = (attrs.privateFlags
            & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
    //检查调用者是否有权限添加指定类型的窗口。
    //不同类型的窗口需要不同权限,如 `TYPE_SYSTEM_ALERT`
    //需要 `SYSTEM_ALERT_WINDOW` 权限。
    int res = mPolicy.checkAddPermission(attrs.type, isRoundedCornerOverlay, attrs.packageName,
            appOp);
    //如果权限不足,直接返回错误码。
    if (res != ADD_OKAY) {
        return res;
    }

    WindowState parentWindow = null;
    //获取调用者的PID和UID
    final int callingUid = Binder.getCallingUid();
    final int callingPid = Binder.getCallingPid();
    //临时清除调用者的 Binder 身份,让后续操作以系统身份执行(用于权限绕过,
    //之后 `restoreCallingIdentity` 恢复)
    final long origId = Binder.clearCallingIdentity();
    final int type = attrs.type;

    synchronized (mGlobalLock) {
        if (!mDisplayReady) {
            throw new IllegalStateException("Display has not been initialialized");
        }
        //根据 `displayId` 获取对应的显示器内容对象。
        final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);
        //显示器不存在。
        if (displayContent == null) {
            return WindowManagerGlobal.ADD_INVALID_DISPLAY;
        }
        //应用无权访问
        if (!displayContent.hasAccess(session.mUid)) {
            return WindowManagerGlobal.ADD_INVALID_DISPLAY;
        }
        //`mWindowMap` 是 WMS 维护的 `IBinder -> WindowState` 映射表
        //检查窗口是否重复添加
        if (mWindowMap.containsKey(client.asBinder())) {
            return WindowManagerGlobal.ADD_DUPLICATE_ADD;
        }
        //如果是子窗口
        if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
            parentWindow = windowForClientLocked(null, attrs.token, false);
            //子窗口必须依附于一个父窗口,父窗口必须存在
            if (parentWindow == null) {
                return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
            }
            //父窗口不能是子窗口(不允许嵌套子窗口)
            if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW
                    && parentWindow.mAttrs.type <= LAST_SUB_WINDOW) {
                return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
            }
        }
        //私有演示窗口:只能在私有显示器上添加
        if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
           
            return WindowManagerGlobal.ADD_PERMISSION_DENIED;
        }
        //演示窗口:显示器必须支持公开演示
        if (type == TYPE_PRESENTATION && !displayContent.getDisplay().isPublicPresentation()) {
            
            return WindowManagerGlobal.ADD_INVALID_DISPLAY;
        }

        int userId = UserHandle.getUserId(session.mUid);
        //如果请求的用户 ID 与调用者不同,
        if (requestUserId != userId) {
            try {
                //校验调用者是否有权限切换到该用户。
                //多用户场景下,确保窗口添加到正确的用户空间
                mAmInternal.handleIncomingUser(callingPid, callingUid, requestUserId,
                        false /*allowAll*/, ALLOW_NON_FULL, null, null);
            } catch (Exception exp) {
                return WindowManagerGlobal.ADD_INVALID_USER;
            }
            
            userId = requestUserId;
        }

        ActivityRecord activity = null;
        final boolean hasParent = parentWindow != null;
        //获取WindowToken
        WindowToken token = displayContent.getWindowToken(
                hasParent ? parentWindow.mAttrs.token : attrs.token);
        //子窗口复用父窗口的 Token:保证同一窗口组的 Token 一致
        final int rootType = hasParent ? parentWindow.mAttrs.type : type;

        boolean addToastWindowRequiresToken = false;

        final IBinder windowContextToken = attrs.mWindowContextToken;
        //Token不存在
        if (token == null) {
            ...
            if (hasParent) {
                //子窗口复用父窗口的 Token
                token = parentWindow.mToken;
            } else if (mWindowContextListenerController.hasListener(windowContextToken)) {
                final IBinder binder = attrs.token != null ? attrs.token : windowContextToken;
                ...
                //创建WindowToken
                token = new WindowToken.Builder(this, binder, type)
                        .setDisplayContent(displayContent)
                        .setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
                        .setRoundedCornerOverlay(isRoundedCornerOverlay)
                        .setFromClientToken(true)
                        .setOptions(options)
                        .build();
            } else {
                final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
                //创建WindowToken
                token = new WindowToken.Builder(this, binder, type)
                        .setDisplayContent(displayContent)
                        .setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
                        .setRoundedCornerOverlay(isRoundedCornerOverlay)
                        .build();
            }
        } 
        //Token存在
        else if (rootType >= FIRST_APPLICATION_WINDOW
                && rootType <= LAST_APPLICATION_WINDOW) {
            //应用窗口,token是 `ActivityRecord`(即 Activity 的 Token)
            activity = token.asActivityRecord();
            //ActivityRecord不存在
            if (activity == null) {
                return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
            } else if (activity.getParent() == null) {
               ...
            }
            //输入法窗口,Token 类型必须匹配
        } else if (rootType == TYPE_INPUT_METHOD) {
            if (token.windowType != TYPE_INPUT_METHOD) {
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
             //语音交互窗口,Token 类型必须匹配
        } else if (rootType == TYPE_VOICE_INTERACTION) {
            if (token.windowType != TYPE_VOICE_INTERACTION) {
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
            //壁纸窗口,Token 类型必须匹配
        } else if (rootType == TYPE_WALLPAPER) {
            if (token.windowType != TYPE_WALLPAPER) {
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
        } else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
            if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
            //Toast 窗口,需要 Token
        } else if (type == TYPE_TOAST) {
            
            addToastWindowRequiresToken = doesAddToastWindowRequireToken(attrs.packageName,
                    callingUid, parentWindow);
            if (addToastWindowRequiresToken && token.windowType != TYPE_TOAST) {
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
            //快捷设置对话框,Token 类型必须匹配
        } else if (type == TYPE_QS_DIALOG) {
            if (token.windowType != TYPE_QS_DIALOG) {
                
                return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
            }
        } else if (token.asActivityRecord() != null) {
            
            attrs.token = null;
            //创建 WindowToken
            token = new WindowToken.Builder(this, client.asBinder(), type)
                    .setDisplayContent(displayContent)
                    .setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
                    .build();
        }

        
         //创建WindowState,这个对象维护了窗口的所有状态信息
        /WindowState构造函数:
        //计算窗口的主序 (`mBaseLayer`) 和子序 (`mSubLayer`) 的初始值
        final WindowState win = new WindowState(this, session, client, token, parentWindow,
                appOp[0], attrs, viewVisibility, session.mUid, userId,
                session.mCanAddInternalSystemWindow);
       // 客户端进程已死亡
       if (win.mDeathRecipient == null) {
            return WindowManagerGlobal.ADD_APP_EXITING;
        }

        if (win.getDisplayContent() == null) {
            return WindowManagerGlobal.ADD_INVALID_DISPLAY;
        }

        final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
        //根据显示器策略调整窗口参数(如系统栏可见性)。
        displayPolicy.adjustWindowParamsLw(win, win.mAttrs);
        win.updateRequestedVisibility(requestedVisibility);
         //做最后的策略校验(如是否允许在锁屏上添加窗口等)
        res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid);
        if (res != ADD_OKAY) {
            return res;
        }
        //创建一对 `InputChannel`(服务端和客户端),通过 SocketPair 建立连接。
        //服务端通道由 WMS 持有,用于向应用发送输入事件。
        //客户端通道通过 `outInputChannel` 返回给应用进程(`ViewRootImpl` 使用)
        final boolean openInputChannels = (outInputChannel != null
                && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
        if  (openInputChannels) {
            win.openInputChannel(outInputChannel);
        }

        if (type == TYPE_TOAST) {
            //每个 UID 同时只能显示一个 Toast
            if (!displayContent.canAddToastWindowForUid(callingUid)) {
                return WindowManagerGlobal.ADD_DUPLICATE_ADD;
            }
            
            if (addToastWindowRequiresToken
                    || (attrs.flags & FLAG_NOT_FOCUSABLE) == 0
                    || displayContent.mCurrentFocus == null
                    || displayContent.mCurrentFocus.mOwnerUid != callingUid) {
               //发送延迟消息,在 Toast 超时后自动隐藏窗口。
                mH.sendMessageDelayed(
                        mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win),
                        win.mAttrs.hideTimeoutMilliseconds);
            }
        }

        //WindowContext(Android 11+):允许在非 Activity 上下文中创建窗口
        if (!win.isChildWindow()
                && mWindowContextListenerController.hasListener(windowContextToken)) {
            // 校验窗口类型匹配
            final int windowContextType = mWindowContextListenerController
                    .getWindowType(windowContextToken);
            if (type != windowContextType) {
                return WindowManagerGlobal.ADD_INVALID_TYPE;
            }
            final Bundle options = mWindowContextListenerController
                    .getOptions(windowContextToken);
           // 注册监听器,使 WindowToken 能响应配置变化
            mWindowContextListenerController.registerWindowContainerListener(
                    windowContextToken, token, callingUid, type, options);
        }


        res = ADD_OKAY;
        //BLAST(Buffered Layer Stack):Android 12 引入的新渲染架构标志
        if (mUseBLAST) {
            res |= WindowManagerGlobal.ADD_FLAG_USE_BLAST;
        }
        //如果当前没有焦点窗口,记录此窗口
        if (displayContent.mCurrentFocus == null) {
            displayContent.mWinAddedSinceNullFocus.add(win);
        }
        //某些窗口类型(如系统窗口)不参与点击外部关闭 Task 的判断
        if (excludeWindowTypeFromTapOutTask(type)) {
            displayContent.mTapExcludedWindows.add(win);
        }
        //将窗口与 DisplayContent 关联,并设置 SurfaceControl
        win.attach();
        //将窗口注册到 WMS 的全局映射表中
        mWindowMap.put(client.asBinder(), win);
        ...

        final ActivityRecord tokenActivity = token.asActivityRecord();
        //设置 Starting Window
        if (type == TYPE_APPLICATION_STARTING && tokenActivity != null) {
            tokenActivity.mStartingWindow = win;
        }

        boolean imMayMove = true;
        /将窗口加入所属 `WindowToken` 的窗口列表
        //将窗口作为一个节点,添加到 `WindowContainer` 层级树中。
        //`WindowContainer` 树中的父子关系和兄弟顺序,
        //由之前计算的 `mBaseLayer` 和 `mSubLayer` 决定
        win.mToken.addWindow(win);
        //通知 `DisplayPolicy` 添加窗口(更新系统 UI 布局,如状态栏、导航栏)。
        displayPolicy.addWindowLw(win, attrs);
        
        //输入法窗口处理
        if (type == TYPE_INPUT_METHOD) {
            //设置当前输入法窗口
            displayContent.setInputMethodWindowLocked(win);
            imMayMove = false;
        } else if (type == TYPE_INPUT_METHOD_DIALOG) {
            //计算输入法目标
            displayContent.computeImeTarget(true /* updateImeTarget */);
            imMayMove = false;
        } else {
            //壁纸窗口处理
            if (type == TYPE_WALLPAPER) {
               //标记需要重新布局壁纸 displayContent.mWallpaperController.clearLastWallpaperTimeoutTime();
                displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
            } else if (win.hasWallpaper()) {
                ////标记需要重新布局壁纸 
                displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
            } else if (displayContent.mWallpaperController.isBelowWallpaperTarget(win)) {
                
                displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
            }
        }

        final WindowStateAnimator winAnimator = win.mWinAnimator;
        //标记需要执行入场动画
        winAnimator.mEnterAnimationPending = true;
        //标记窗口是否正在执行入场动画
        winAnimator.mEnteringAnimation = true;
        //检查当前 Activity 是否有"窗口替换"的需求(即 `mReplacingWindow` 不为空)
        //,如果有,则创建一个 `WindowTransition` 来驱动新旧窗口的过渡动画
        if (activity != null && activity.isVisible()
                && !prepareWindowReplacementTransition(activity)) {
            //它会检查 Activity 是否处于"正在重启"状态(`mRelaunching` 标志),
            //如果是,则确保一个  **"空过渡"(None Transition)**  被设置。这个"空过
            //渡"的目的是让 WMS 知道"这个 Activity 要重新绘制,需要等待它的窗口绘制
            //完成后再显示",防止出现白屏或闪屏。
            prepareNoneTransitionForRelaunching(activity);
        }
        
         ...
        //标记输入窗口需要更新
        //`InputMonitor` 是 WMS 中管理**输入系统状态**的核心类,
        //负责维护所有窗口的输入信息,并与系统的 `InputDispatcher`(输入分发器)通信
        displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();

        boolean focusChanged = false;
        if (win.canReceiveKeys()) {
            //更新焦点窗口
            //焦点变化会影响输入法显示、按键分发等
            focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                    false /*updateInputWindows*/);
            if (focusChanged) {
                imMayMove = false;
            }
        }

        if (imMayMove) {
            //计算输入法目标:如果没有焦点变化,仍可能需要重新计算输入法目标窗口
            displayContent.computeImeTarget(true /* updateImeTarget */);
        }

       //计算窗口的 Z-order 层级
        win.getParent().assignChildLayers();

        if (focusChanged) {
          //通知InputMonitor更新输入焦点 displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
                    false /*updateInputWindows*/);
        }
        
        //通知系统输入子系统(InputFlinger)更新窗口信息(用于触摸事件分发)
        displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
        //如果窗口可见且屏幕方向需要变化,发送配置变更通知
        if (win.isVisibleOrAdding() && displayContent.updateOrientation()) {
            displayContent.sendNewConfiguration();
        }

        // 新系统栏(状态栏、导航栏)的 Insets 信息
        displayContent.getInsetsStateController().updateAboveInsetsState(
                win, false /* notifyInsetsChanged */);
        //通过 `outActiveControls` 将控制信息返回给应用
        getInsetsSourceControls(win, outActiveControls);
    }
    //恢复调用者身份
    Binder.restoreCallingIdentity(origId);

    return res;
}

后续流程:布局与绘制 (relayoutWindow)

addWindow 只是"登记",窗口真正获得尺寸和绘图表面(Surface)在后续的 relayoutWindow 阶段。ViewRootImplperformTraversals() 中调用 Session.relayout(),WMS 进而:

  • 计算窗口尺寸。
  • 通过 SurfaceFlinger 为窗口分配 Surface
  • Surface 传回应用进程供其绘制 UI。
WindowManagerService 复制代码
//frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
 public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
              int requestedWidth, int requestedHeight, int viewVisibility, int flags,
              long frameNumber, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
              SurfaceControl outSurfaceControl, InsetsState outInsetsState,
              InsetsSourceControl[] outActiveControls, Point outSurfaceSize) {
          ...
          synchronized (mGlobalLock) {
          //根据 `client` 查找对应的 `WindowState`,若找不到则直接返回
              final WindowState win = windowForClientLocked(session, client, false);
              if (win == null) {
                  return 0;
              }
              ...
  
              WindowStateAnimator winAnimator = win.mWinAnimator;
              if (viewVisibility != View.GONE) {
              //设置窗口大小为客户端需要的大小
                  win.setRequestedSize(requestedWidth, requestedHeight);
              }
              //`frameNumber` 用于同步帧的序列号(与 BLAST 同步机制相关)
              win.setFrameNumber(frameNumber);
  
              int attrChanges = 0;
              int flagChanges = 0;
              int privateFlagChanges = 0;
              if (attrs != null) {
                  //根据系统状态(如是否锁屏、是否在沉浸模式)调整窗口参数
                  displayPolicy.adjustWindowParamsLw(win, attrs);
                  win.mToken.adjustWindowParams(win, attrs);
                  int disableFlags =
                          (attrs.systemUiVisibility | attrs.subtreeSystemUiVisibility) & DISABLE_MASK;
                  if (disableFlags != 0 && !hasStatusBarPermission(pid, uid)) {
                      disableFlags = 0;
                  }
                  win.mDisableFlags = disableFlags;
                  
               ...
 
              //记录可见性变化,用于后续判断是否需要移动IME或壁纸
              final int oldVisibility = win.mViewVisibility;
  
             
              final boolean becameVisible =
                      (oldVisibility == View.INVISIBLE || oldVisibility == View.GONE)
                              && viewVisibility == View.VISIBLE;
              boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0
                      || becameVisible;
              boolean focusMayChange = win.mViewVisibility != viewVisibility
                      || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
                      || (!win.mRelayoutCalled);
  
              boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
                      && win.hasWallpaper();
              wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
              if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) {
                  winAnimator.mSurfaceController.setSecure(win.isSecureLocked());
              }
  
              win.mRelayoutCalled = true;
              win.mInRelayout = true;
  
              win.setViewVisibility(viewVisibility);
           
  
  
              win.setDisplayLayoutNeeded();
              win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
  
              
      
     //只有当窗口可见且关联的 Activity 可见时,才真正执行relayout(创建/更新 Surface)
              final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
                      (win.mActivityRecord == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
                              || win.mActivityRecord.isClientVisible());
  
              
              if (!shouldRelayout && winAnimator.hasSurface() && !win.mAnimatingExit) {
                  
                  }
                  result |= RELAYOUT_RES_SURFACE_CHANGED;
                  if (!win.mWillReplaceWindow) {
                     
                      if (wallpaperMayMove) {
                          displayContent.mWallpaperController.adjustWallpaperWindows();
                      }

         //如果窗口不可见但已有 Surface,且没有正在播放退出动画,则尝试启动退出动画
         //启动退出动画后,Surface 会在动画结束后被释放
                      focusMayChange = tryStartExitingAnimation(win, winAnimator, focusMayChange);
                  }
              }
  
     
              if (shouldRelayout) {
                  try {
                  //创建 Surface
                      result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
                  } catch (Exception e) {
                     ...
                      return 0;
                  }
              }
  
              
               //####重点
              //遍历整个窗口树,进行最终的层级计算、位置确定和 Surface 显示
              mWindowPlacerLocked.performSurfacePlacement(true /* force */);
  
              if (shouldRelayout) {
                  
   //标记 `mHasSurface = true`
   //如果窗口之前是隐藏的,设置 `mFirstTimeVisible = true`
   //更新窗口的显示状态
   //如果是输入法窗口且尚未注册,立即注册
                  result = win.relayoutVisibleWindow(result);
  
                  if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
                      focusMayChange = true;
                  }
                  if (win.mAttrs.type == TYPE_INPUT_METHOD
                          && displayContent.mInputMethodWindow == null) {
                      displayContent.setInputMethodWindowLocked(win);
                      imMayMove = true;
                  }
                  win.adjustStartingWindowFlags();
                  Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
              } else {
                 ...
  
                  if (viewVisibility == View.VISIBLE && winAnimator.hasSurface()) {
                  //可见但没有执行 relayout(如 Activity 不可见),返回现有 Surface
                      winAnimator.mSurfaceController.getSurfaceControl(outSurfaceControl);
                    
                  } else {
                     
                        ...
                      try {
                         
                        // 窗口不可见,释放 Surface
                          outSurfaceControl.release();
                      } finally {
                          ...
                      }
                  }
  
                 
              }
  
              if (focusMayChange) {
                  //更新焦点窗口
                  if (updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/)) {
                      imMayMove = false;
                  }
              }
  
      
              boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
              //更新输入法窗口
              if (imMayMove) {
                  displayContent.computeImeTarget(true /* updateImeTarget */);
                  if (toBeDisplayed) {
                      //IME 目标窗口可能因可见性或焦点变化而改变
                      displayContent.assignWindowLayers(false /* setLayoutNeeded */);
                  }
              }
  
              if (wallpaperMayMove) {
              //壁纸可能需要因窗口显示/隐藏而重新调整层级
                  displayContent.pendingLayoutChanges |=
                          WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
              }
  
              if (win.mActivityRecord != null) {
                  displayContent.mUnknownAppVisibilityController.notifyRelayouted(win.mActivityRecord);
              }
  
              
              configChanged = displayContent.updateOrientation();
  
              final DisplayInfo rotatedDisplayInfo =
                      win.mToken.getFixedRotationTransformDisplayInfo();
                      
               //处理屏幕旋转
              if (rotatedDisplayInfo != null) {
               //告诉 SurfaceFlinger 该窗口的 Buffer 应该如何旋转 outSurfaceControl.setTransformHint(rotatedDisplayInfo.rotation);
              } else {
                       outSurfaceControl.setTransformHint(displayContent.getDisplayInfo().rotation);
              }
  
          
             ...
          }
  
          Binder.restoreCallingIdentity(origId);
          return result;
  }
   
  
 //创建SurfaceControl
 private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,
              WindowState win, WindowStateAnimator winAnimator) {
          if (!win.mHasSurface) {
              result |= RELAYOUT_RES_SURFACE_CHANGED;
          }
  
          WindowSurfaceController surfaceController;
          try {
             // 创建WindowSurfaceController
              surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type);
          } finally {
              
          }
          if (surfaceController != null) {
          //创建成功,将其复制到客户端的 SurfaceControl 对象
              surfaceController.getSurfaceControl(outSurfaceControl);
  
          } else {
            //创建失败则释放
              outSurfaceControl.release();
          }
  
          return result;
      }



//frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java
 WindowSurfaceController createSurfaceLocked(int windowType) {
          final WindowState w = mWin;
  
          if (mSurfaceController != null) {
              return mSurfaceController;
          }
  
          w.setHasSurface(false);
  
          ...
          try {
  
              ...
              //创建WindowSurfaceController
              mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), width,
                      height, format, flags, this, windowType);
              mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags
                      & WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
  
              ...
          } 
          ...
         
          return mSurfaceController;
      }
      
  
//frameworks/base/services/core/java/com/android/server/wm/WindowSurfaceController.java
WindowSurfaceController(String name, int w, int h, int format,
              int flags, WindowStateAnimator animator, int windowType) {

          final SurfaceControl.Builder b = win.makeSurface()
                  .setParent(win.getSurfaceControl())
                  ...
          //调用 build创建SurfaceControl
          mSurfaceControl = b.build();
  
     
  }

//frameworks/base/core/java/android/view/SurfaceControl.java
public SurfaceControl build() {
              ...
              return new SurfaceControl(
                      mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata,
                      mLocalOwnerView, mCallsite);
 }
 
 
private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
              SurfaceControl parent, SparseIntArray metadata, WeakReference<View> localOwnerView,
              String callsite)
                      throws OutOfResourcesException, IllegalArgumentException {
          if (name == null) {
              throw new IllegalArgumentException("name must not be null");
          }
  
          mName = name;
          mWidth = w;
          mHeight = h;
          mLocalOwnerView = localOwnerView;
          Parcel metaParcel = Parcel.obtain();
          try {
              ...
              mNativeObject = nativeCreate(session, name, w, h, format, flags,
                      parent != null ? parent.mNativeObject : 0, metaParcel);
          } finally {
              metaParcel.recycle();
          }
          if (mNativeObject == 0) {
              throw new OutOfResourcesException(
                      "Couldn't allocate SurfaceControl native object");
          }
          mNativeHandle = nativeGetHandle(mNativeObject);
          mCloseGuard.openWithCallSite("release", callsite);
  }


//frameworks/base/core/jni/android_view_SurfaceControl.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
          jstring nameStr, jint w, jint h, jint format, jint flags, jlong parentObject,
          jobject metadataParcel) {
      ScopedUtfChars name(env, nameStr);
      //`SurfaceComposerClient` 是应用进程与 SurfaceFlinger 通信的客户端代理
      sp<SurfaceComposerClient> client;
      //sessionOb就是`SurfaceSession`
      if (sessionObj != NULL) {
      //从SurfaceSession取出SurfaceComposerClient
          client = android_view_SurfaceSession_getClient(env, sessionObj);
      } else {
      //否则使用默认的全局 Client
          client = SurfaceComposerClient::getDefault();
      }
    //`parentObject` 是从 Java 层传入的 `SurfaceControl` 对象指针
    //每个 `SurfaceControl` 在 Native 层对应一个 `IBinder` 句柄,SurfaceFlinger 用它来识别父图层
    //父 Surface 用于构建 Z-Order 层级关系
      SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject);
      sp<SurfaceControl> surface;
      //`LayerMetadata` 是 Android 12+ 引入的,用于传递 BLAST 相关的额外参数
      LayerMetadata metadata;
      Parcel* parcel = parcelForJavaObject(env, metadataParcel);
      if (parcel && !parcel->objectsCount()) {
      //通过 `Parcel` 从 Java 层传递到 Native 层
          status_t err = metadata.readFromParcel(parcel);
          if (err != NO_ERROR) {
            jniThrowException(env, "java/lang/IllegalArgumentException",
                              "Metadata parcel has wrong format");
          }
      }
  
      sp<IBinder> parentHandle;
      if (parent != nullptr) {
          parentHandle = parent->getHandle();
      }
    
     //BpSurfaceComposerClient调用createSurfaceChecked,
     //通过 Binder 驱动发起远程调用
     //remote()->transact(CREATE_SURFACE, data, &reply);
     //服务端响应:`BnSurfaceComposerClient::onTransact`
     //class Client : public BnSurfaceComposerClient
      status_t err = client->createSurfaceChecked(String8(name.c_str()), w, h, format, &surface,
                                                  flags, parentHandle, 
      ...
      //增加强引用计数,防止被释放
      surface->incStrong((void *)nativeCreate);
      return reinterpret_cast<jlong>(surface.get());
  }


//class Client : public BnSurfaceComposerClient
//frameworks/native/services/surfaceflinger/Client.cpp
status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
                                 uint32_t flags, const sp<IBinder>& parentHandle,
                                 LayerMetadata metadata, sp<IBinder>* handle,
                                 sp<IGraphicBufferProducer>* gbp, int32_t* outLayerId,
                                 uint32_t* outTransformHint) {
      
     //调用SurfaceFinger创建Layer
      return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
                                   parentHandle, outLayerId, nullptr, outTransformHint);
  }



//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,
                                       uint32_t h, PixelFormat format, uint32_t flags,
                                       LayerMetadata metadata, sp<IBinder>* handle,
                                       sp<IGraphicBufferProducer>* gbp,
                                       const sp<IBinder>& parentHandle, int32_t* outLayerId,
                                       const sp<Layer>& parentLayer, uint32_t* outTransformHint) {
      ...
  
      status_t result = NO_ERROR;
  
      sp<Layer> layer;
  
      std::string uniqueName = getUniqueLayerName(name.string());
  
      switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
          case ISurfaceComposerClient::eFXSurfaceBufferQueue:
          case ISurfaceComposerClient::eFXSurfaceBufferState: {
              //创建BufferStateLayer
              result = createBufferStateLayer(client, std::move(uniqueName), w, h, flags,
       break;
          case ISurfaceComposerClient::eFXSurfaceEffect:
             //创建EffectLayer
              result = createEffectLayer(client, std::move(uniqueName), w, h, flags,
                                         std::move(metadata), handle, &layer);
              break;
          case ISurfaceComposerClient::eFXSurfaceContainer:
              //创建ContainerLayer
              result = createContainerLayer(client, std::move(uniqueName), w, h, flags,
                                            std::move(metadata), handle, &layer);
              break;
          default:
              result = BAD_VALUE;
              break;
      }
  
      if (result != NO_ERROR) {
          return result;
      }
  
      bool addToRoot = callingThreadHasUnscopedSurfaceFlingerAccess();
      //创建 LayerHandle (Binder 句柄)                              
      //创建 BufferQueue (IGraphicBufferProducer)                   
      //插入层级树 (parent 或 root)  
      result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer, addToRoot,
                              outTransformHint);
      if (result != NO_ERROR) {
          return result;
      }
      //mInterceptor用于调试/监控(如 Systrace 跟踪 Layer 创建事件)
      mInterceptor->saveSurfaceCreation(layer);
     //**标记需要应用事务**,触发 SurfaceFlinger 在下一次合成时重新计算图层属性
      setTransactionFlags(eTransactionNeeded);
       //分配 Layer ID
      *outLayerId = layer->sequence;
      return result;
  }
  

四种图层:
**ContainerLayer是容器,用于组织和管理其他图层;BufferStateLayer是具体的绘图表面,承载应用内容;EffectLayer则用于实现各种视觉特效**,
**`BufferQueueLayer` 是基于 BufferQueue 机制的传统图层类型,在 Android 12 之前是应用窗口的默认实现,12以后已被BufferStateLayer替代。**

 sp<ContainerLayer> DefaultFactory::createContainerLayer(const LayerCreationArgs& args) {
      return new ContainerLayer(args);
  }
  

  sp<BufferQueueLayer> DefaultFactory::createBufferQueueLayer(const LayerCreationArgs& args) {
      return new BufferQueueLayer(args);
  }
  
  sp<BufferStateLayer> DefaultFactory::createBufferStateLayer(const LayerCreationArgs& args) {
      return new BufferStateLayer(args);
  }
  
  sp<EffectLayer> DefaultFactory::createEffectLayer(const LayerCreationArgs& args) {
      return new EffectLayer(args);
}

总而言之,Android 窗口添加是一个多阶段协同过程:应用进程通过 ViewRootImpl 发起请求,经由 Session 跨进程传递给 WMS;WMS 完成 WindowState 创建和窗口注册 等核心管理工作后,再通过后续的 relayout 流程完成尺寸计算Surface 分配,最终让窗口显示出来。

相关推荐
小小测试开发16 分钟前
RAG评测指标实战:忠实度、上下文精确率/召回率从原理到CI落地
android·人工智能·spring boot·ci/cd
Dovis(誓平步青云)2 小时前
同一条路线在手机和平板上怎样换一种排版
android·开发语言·数据库·智能手机·音视频
firstacui2 小时前
Mysql调优
android·mysql·adb
程序员-Benothing2 小时前
什么是 MySQL 的主从同步机制?它是如何实现的?
android·数据库·mysql
Android打工人2 小时前
c++ 、java 融为一体2,c++ 实例化Android虚拟机直接运行java,c,java 一个进程号
android·java·c++
IT毕设实战小研2 小时前
基于安卓的考研资讯系统设计与实现
android·大数据·vue.js·爬虫·python·考研·课程设计
Mr数据杨10 小时前
【Codex】用学生入学评估模块建立新生能力画像
android·java·javascript·django·codex·项目开发
●VON11 小时前
谁小时候不想要一个游戏修改器?我把电脑 Skill 做成了 Android 小助手
android·游戏·电脑
刃神太酷啦11 小时前
Linux 系统 MySQL 完整安装配置教程:从卸载 MariaDB 到优化 my.cnf----《Hello MySQL!》(1)
android·linux·c语言·c++·mysql·leetcode·mariadb