本文基于android 13.0
// 跟踪单个窗口的的动画和surface操作
frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java
// 根据frames放置surface
frameworks/base/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
// surface的控制器
frameworks/base/services/core/java/com/android/server/wm/WindowSurfaceController.java
// WMS service
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
添加窗口-NO_SURFACE
窗口对应surface的默认绘制状态为NO_SURFACE
app进程
app进程执行完当前Activity的onResume方法后,会通过ViewRootImpl去告诉system server进程添加当前activity的窗口。
@Override
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
boolean isForward, String reason) {
......
// 执行Activity的onResume等相关操作
if (!performResumeActivity(r, finalStateRequest, reason)) {
return;
}
......
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
......
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
// WindowManagerImpl的addView添加当前的decor
wm.addView(decor, l);
} else {
a.onWindowAttributesChanged(l);
}
}
} else if (!willBeVisible) {
r.hideForNow = true;
}
// 等待主线程idle执行Idler的queueIdle方法告知system server当前处于idle状态
Looper.myQueue().addIdleHandler(new Idler());
}
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow, int userId) {
......
IWindowSession windowlessSession = null;
.....
if (windowlessSession == null) {
// 创建当前Activity对应的ViewRootImpl实例
root = new ViewRootImpl(view.getContext(), display);
} else {
root = new ViewRootImpl(view.getContext(), display,
windowlessSession);
}
view.setLayoutParams(wparams);
// 添加Decor、ViewRootImpl、布局参数等到对应列表
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// do this last because it fires off messages to start doing things
try {
// 调用ViewRootImpl的setView方法并随后将当前window添加到display中
root.setView(view, wparams, panelParentView, userId);
} catch (RuntimeException e) {
.....
}
}
}
system server进程
在WindowState的构造方法中创建该窗口对应的windowStateAnimator
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState parentWindow, int appOp, WindowManager.LayoutParams a, int viewVisibility,
int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow,
PowerManagerWrapper powerManagerWrapper) {
super(service);
......
mWinAnimator = new WindowStateAnimator(this);
.......
}
创建surface-DRAW_PENDING
app进程调用system server端relayoutWindow,开始创建surface;suface创建完成后等待绘制。
app进程
上次的Vsync信号来临主线程执行doFrame操作,并通过系列回调执行下一次的sheduleVsync。
scheduleTraversals中主要两个操作:
- post同步屏障到消息队列中,阻塞同步消息的执行。
- post mTraversalRunnable到Choreographer的mCallbackQueues对应的链表中,等待下次Vsync信号来临执行对应的回调。
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
// post 同步屏障到消息队列中,阻塞后续同步消息的执行,避免界面刷新时出现问题
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// post CALLBACK_TRAVERSAL类型的callback,mTraversalRunnable类型的runnable到Choreographer的mCallbackQueues对应的链表中
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
mFirstFrame = false;
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
// 移除消息队列中的同步障碍
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
// 执行相关的遍历
performTraversals();
}
}
@Override
public void onVsync(long timestampNanos, long physicalDisplayId, int frame,
VsyncEventData vsyncEventData) {
try {
......
// 发送当前runnable的异步消息到消息队列中
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
@Override
public void run() {
// 异步消息执行
mHavePendingVsync = false;
// 执行doFrame操作
doFrame(mTimestampNanos, mFrame, mLastVsyncEventData);
}
}
system server进程
public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility, int flags,
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls, Bundle outSyncIdBundle) {
.......
synchronized (mGlobalLock) {
final WindowState win = windowForClientLocked(session, client, false);
......
// We should only relayout if the view is visible, it is a starting window, or the
// associated appToken is not hidden.
final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
(win.mActivityRecord == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
|| win.mActivityRecord.isClientVisible());
.......
// Create surfaceControl before surface placement otherwise layout will be skipped
// (because WS.isGoneForLayout() is true when there is no surface.
if (shouldRelayout) {
try {
// 创建surfacecontroller并copy到outSurfaceControl
result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
} catch (Exception e) {
displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
ProtoLog.w(WM_ERROR,
"Exception thrown when creating surface for client %s (%s). %s",
client, win.mAttrs.getTitle(), e);
Binder.restoreCallingIdentity(origId);
return 0;
}
}
.......
}
}
private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,
WindowState win, WindowStateAnimator winAnimator) {
if (!win.mHasSurface) {
result |= RELAYOUT_RES_SURFACE_CHANGED;
}
WindowSurfaceController surfaceController;
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
// 调用windowState对应的WindowStateAnimator去创建surface
surfaceController = winAnimator.createSurfaceLocked();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
// 将创建的surface copy到outSurfaceControl中,将在此surface上绘制
if (surfaceController != null) {
surfaceController.getSurfaceControl(outSurfaceControl);
ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl);
} else {
// For some reason there isn't a surface. Clear the
// caller's object so they see the same state.
ProtoLog.w(WM_ERROR, "Failed to create surface control for %s", win);
outSurfaceControl.release();
}
return result;
}
给窗口创建一个空白的surface,但是还没有开始绘制,所以surface是隐藏的
WindowSurfaceController createSurfaceLocked() {
final WindowState w = mWin;
if (mSurfaceController != null) {
return mSurfaceController;
}
// 创建surface前将WindowState的mHasSurface设置为false
w.setHasSurface(false);
// 设置当前的mDrawState状态为DRAW_PENDING,代表以创建surface,等待绘制
resetDrawState();
mService.makeWindowFreezingScreenIfNeededLocked(w);
// 默认隐藏
int flags = SurfaceControl.HIDDEN;
final WindowManager.LayoutParams attrs = w.mAttrs;
......
// Set up surface control with initial size.
try {
// This can be removed once we move all Buffer Layers to use BLAST.
final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
// 创建WindowSurfaceController对象,内部创建surfacecontroller对象,跟surfaceflinger通信
mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), format,
flags, this, attrs.type);
mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
// 将WindowState的mHasSurface设置为false
w.setHasSurface(true);
// The surface instance is changed. Make sure the input info can be applied to the
// new surface, e.g. relaunch activity.
w.mInputWindowHandle.forceChange();
} catch (OutOfResourcesException e) {
Slog.w(TAG, "OutOfResourcesException creating surface");
mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true);
mDrawState = NO_SURFACE;
return null;
} catch (Exception e) {
Slog.e(TAG, "Exception creating surface (parent dead?)", e);
mDrawState = NO_SURFACE;
return null;
}
mLastHidden = true;
return mSurfaceController;
}
绘制完成-COMMIT_DRAW_PENDING
窗口surface已经绘制完成,正在等待布局系统进行提交;具体的布局相关流程将在anim线程中去执行(当前是在binder线程)。
app进程
private void createSyncIfNeeded() {
// Started a sync already or there's nothing needing to sync
if (isInLocalSync() || !mReportNextDraw) {
return;
}
final int seqId = mSyncSeqId;
mSyncId = mSurfaceSyncer.setupSync(transaction -> {
// Callback will be invoked on executor thread so post to main thread.
mHandler.postAtFrontOfQueue(() -> {
mSurfaceChangedTransaction.merge(transaction);
reportDrawFinished(seqId);
});
});
if (DEBUG_BLAST) {
Log.d(mTag, "Setup new sync id=" + mSyncId);
}
mSurfaceSyncer.addToSync(mSyncId, mSyncTarget);
notifySurfaceSyncStarted();
}
private void reportDrawFinished(int seqId) {
try {
// 回调到system server
mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction, seqId);
} catch (RemoteException e) {
Log.e(mTag, "Unable to report draw finished", e);
mSurfaceChangedTransaction.apply();
} finally {
mSurfaceChangedTransaction.clear();
}
}
system server进程
void finishDrawingWindow(Session session, IWindow client,
@Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
if (postDrawTransaction != null) {
postDrawTransaction.sanitize();
}
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
WindowState win = windowForClientLocked(session, client, false);
// 调用WindowState的finishDrawing并判断是否需要layout
if (win != null && win.finishDrawing(postDrawTransaction, seqId)) {
if (win.hasWallpaper()) {
win.getDisplayContent().pendingLayoutChanges |=
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
}
win.setDisplayLayoutNeeded();
//需要layout,请求刷新窗口
mWindowPlacerLocked.requestTraversal();
}
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
判断当前窗口是否需要布局
boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId) {
......
final boolean hasSyncHandlers = executeDrawHandlers(postDrawTransaction, syncSeqId);
boolean skipLayout = false;
......
// 调用WindowStateAnimator的finishDrawingLocked判断是否需要layout
final boolean layoutNeeded =
mWinAnimator.finishDrawingLocked(postDrawTransaction, mClientWasDrawingForSync);
mClientWasDrawingForSync = false;
// We always want to force a traversal after a finish draw for blast sync.
return !skipLayout && (hasSyncHandlers || layoutNeeded);
}
将窗口绘制状态转为COMMIT_DRAW_PENDING
boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction,
boolean forceApplyNow) {
final boolean startingWindow =
mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
boolean layoutNeeded = false;
// 设置当前的mDrawState为COMMIT_DRAW_PENDING
if (mDrawState == DRAW_PENDING) {
mDrawState = COMMIT_DRAW_PENDING;
// 绘制完成,等待布局
layoutNeeded = true;
}
if (postDrawTransaction != null) {
// If there is no surface, the last draw was for the previous surface. We don't want to
// wait until the new surface is shown and instead just apply the transaction right
// away.
if (mLastHidden && mDrawState != NO_SURFACE && !forceApplyNow) {
//
mPostDrawTransaction.merge(postDrawTransaction);
} else {
mWin.getSyncTransaction().merge(postDrawTransaction);
}
layoutNeeded = true;
}
return layoutNeeded;
}
提交窗口布局-READY_TO_SHOW
READY_TO_SHOW表示窗口已经绘制完成并已完成提交;等待同一WindowToken绘制完成后,一起执行show操作。
// This must be called while inside a transaction.
boolean commitFinishDrawingLocked() {
if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
return false;
}
// 赋值mDrawState状态为READY_TO_SHOW
mDrawState = READY_TO_SHOW;
boolean result = false;
final ActivityRecord activity = mWin.mActivityRecord;
// 所有窗口已经绘制完成,或者当前是starting 窗口,则执行windowState的performShowLocked
if (activity == null || activity.canShowWindows()
|| mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
result = mWin.performShowLocked();
}
return result;
}
窗口在屏幕上显示-HAS_DRAWN
窗口正在屏幕上显示
// This must be called while inside a transaction.
boolean performShowLocked() {
......
final int drawState = mWinAnimator.mDrawState;
if ((drawState == HAS_DRAWN || drawState == READY_TO_SHOW) && mActivityRecord != null) {
// 非启动窗口,回调ActivityRecord的onFirstWindowDrawn移除starting window
if (mAttrs.type != TYPE_APPLICATION_STARTING) {
mActivityRecord.onFirstWindowDrawn(this);
} else {
// 否则回调ActivityRecord的onStartingWindowDrawn
mActivityRecord.onStartingWindowDrawn();
}
}
if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) {
return false;
}
logPerformShow("Showing ");
mWmService.enableScreenIfNeededLocked();
// 加载窗口动画
mWinAnimator.applyEnterAnimationLocked();
// Force the show in the next prepareSurfaceLocked() call.
mWinAnimator.mLastAlpha = -1;
ProtoLog.v(WM_DEBUG_ANIM, "performShowLocked: mDrawState=HAS_DRAWN in %s", this);
// 赋值当前mDrawState的状态为HAS_DRAWN
mWinAnimator.mDrawState = HAS_DRAWN;
// 执行窗口动画
mWmService.scheduleAnimationLocked();
if (mHidden) {
mHidden = false;
final DisplayContent displayContent = getDisplayContent();
// 执行子窗口的performShowLocked
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowState c = mChildren.get(i);
if (c.mWinAnimator.mSurfaceController != null) {
c.performShowLocked();
// It hadn't been shown, which means layout not performed on it, so now we
// want to make sure to do a layout. If called from within the transaction
// loop, this will cause it to restart with a new layout.
if (displayContent != null) {
displayContent.setLayoutNeeded();
}
}
}
}
return true;
}