窗口的添加是一个从应用进程到系统服务进程(SystemServer)的跨进程通信(IPC)过程。核心逻辑在 WindowManagerService (WMS) 的 addWindow 方法中。
整体流程大致如下:
- 应用进程侧 :
WindowManagerImpl.addView()->WindowManagerGlobal.addView()-> 创建ViewRootImpl->ViewRootImpl.setView()。 - 跨进程通信 :
ViewRootImpl通过Session.addToDisplayAsUser()发起 IPC 调用。 - 系统服务侧 (WMS) :
WindowManagerService.addWindow()进行权限验证、创建WindowState等核心工作。
应用进程:从 addView 到 ViewRootImpl
- WindowManagerImpl.addView() :应用调用
WindowManager的addView,实际由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());
}
-
WindowManagerGlobal.addView() :核心工作在此:
- 为每个窗口创建一个
ViewRootImpl对象。 - 将
View、LayoutParams等信息存储。 - 调用
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;
}
}
}
- 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;
}
}
- 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 阶段。ViewRootImpl 在 performTraversals() 中调用 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 分配,最终让窗口显示出来。