对于wms来说,主要功能就是将View添加到窗口层级树中,并通过surface显示出来 主要有下面三个步骤 1:app(ViewRootImpl) -> setView;对应session中addToDisplayAsUser; 对应WMS中的addWindow
2:app(ViewRootImpl) -> relayoutWindow; 对应session中的relayout; 对应WMS中的relayoutWindow
3:app -> draw 绘制surface,传递到surfaceflinger 然后surfaceflinger通过vsync在某个时间节点传递到hwc
4:app:finishDraw() :绘制完成后,会通知到app端,修改mDrawState为has_drawn,将状态修改
过程1
上述4个过程,过程1的setView是在ViewRootImpl的setView中。对于这个过程,直接到wms的addwindow中主要作用:
- 创建windowtoken;
- 创建windowstate;
- 将windowstate放入map中,方便后续取用;
- 创建事件传递openInputChannel;
public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
int displayId, int requestUserId, InsetsVisibilities requestedVisibilities,
InputChannel outInputChannel, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls){
token = new WindowToken.Builder(this, binder, type)
.setDisplayContent(displayContent)
.setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
.setRoundedCornerOverlay(isRoundedCornerOverlay)
.setFromClientToken(true)
.setOptions(options)
.build();
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], attrs, viewVisibility, session.mUid, userId,
session.mCanAddInternalSystemWindow);
mWindowMap.put(client.asBinder(), win);
if (openInputChannels) {
win.openInputChannel(outInputChannel);
}
...
}
对于2,3,4这三个过程是在performTraversals中依次调用的;
//frameworks/base/core/java/android/view/ViewRootImpl.java
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
@UnsupportedAppUsage
void invalidate() {
mDirty.set(0, 0, mWidth, mHeight);
if (!mWillDrawSoon) {
scheduleTraversals();
}
}
上诉app开发应该都知道,在requestLayout和invalidate调用后,会通过编舞者Choreographer调用doTraversal,执行layout和draw流程;
接着看下doTraversal
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
performTraversals();
}
}
private void performTraversals() {
...
/跨进程获取布局大小,位置
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
// Ask host how big it wants to be;
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
performLayout(lp, mWidth, mHeight);
if (!cancelAndRedraw) {
createSyncIfNeeded();
}
performDraw();
...
}
过程2:看下relayoutWindow方法;
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
mRelayoutRequested = true;
float appScale = mAttachInfo.mApplicationScale;
int relayoutResult = 0;
WindowConfiguration winConfig = getConfiguration().windowConfiguration;
if (LOCAL_LAYOUT) {
mWindowSession.updateLayout(mWindow, params,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mTmpFrames,
requestedWidth, requestedHeight);
} else {
relayoutResult = mWindowSession.relayout(mWindow, params,
requestedWidth, requestedHeight, viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
mTempControls, mRelayoutBundle);
}
final int transformHint = SurfaceControl.rotationToBufferTransform(
(mDisplayInstallOrientation + mDisplay.getRotation()) % 4);
WindowLayout.computeSurfaceSize(mWindowAttributes, winConfig.getMaxBounds(), requestedWidth,
requestedHeight, mTmpFrames.frame, mPendingDragResizing, mSurfaceSize);
setFrame(mTmpFrames.frame);
return relayoutResult;
}
//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,
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls, Bundle outSyncIdBundle) {
//1.在wms中将布局大小计算完成
win.fillClientWindowFramesAndConfiguration(outFrames, mergedConfiguration,
false /* useLatestConfig */, shouldRelayout);
//这里aidl有个outSurfaceControl传递参数的out关键字,主要是服务端创建好该数据之后,传递给客户端
result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
}
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");
//2.构建出surfaceControl
surfaceController = winAnimator.createSurfaceLocked();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
if (surfaceController != null) {
surfaceController.getSurfaceControl(outSurfaceControl);
} else {
outSurfaceControl.release();
}
return result;
}
//frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java
WindowSurfaceController createSurfaceLocked() {
final WindowState w = mWin;
if (mSurfaceController != null) {
return mSurfaceController;
}
w.setHasSurface(false);
resetDrawState();
}
void resetDrawState() {
mDrawState = DRAW_PENDING;
...
}
mWindowSession.relayout通过跨进程到wms中,主要做了这些
- 在wms中将布局大小计算完成
- 将mSurfaceControl构建完成
- 将mDrawState设置为DRAW_PENDING
过程3:绘制
private boolean performDraw() {
boolean canUseAsync = draw(fullRedrawNeeded, usingAsyncReport && mSyncBuffer);
}
private boolean draw(boolean fullRedrawNeeded, boolean forceDraw) {
drawSoftware(surface, mAttachInfo, xOffset, yOffset,scalingRequired, dirty, surfaceInsets)
}
private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,boolean scalingRequired, Rect dirty, Rect surfaceInsets) {
// Draw with software renderer.
final Canvas canvas;
canvas = mSurface.lockCanvas(dirty);
//将绘制的结果显示在canvas上
mView.draw(canvas);
try {
// 提交绘制结果
surface.unlockCanvasAndPost(canvas);
} catch (IllegalArgumentException e) {
mLayoutRequested = true; // ask wm for a new surface next time.
return false;
}
}
因为Surface是java层,这里进入了native层
// android_view_Surface.cpp
static void Surface_unlockCanvasAndPost(JNIEnv* env, jobject clazz, jobject canvas) {
sp<Surface> surface = getSurface(env, clazz);
// 调用Surface的unlockAndPost方法
surface->unlockAndPost();
// ...
}
// Surface.cpp
status_t Surface::unlockAndPost()
{
if (mLockedBuffer == nullptr) {
ALOGE("Surface::unlockAndPost failed, no locked buffer");
return INVALID_OPERATION;
}
int fd = -1;
status_t err = mLockedBuffer->unlockAsync(&fd);
ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
//取出buffer
err = queueBuffer(mLockedBuffer.get(), fd);
ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
mLockedBuffer->handle, strerror(-err));
mPostedBuffer = mLockedBuffer;
mLockedBuffer = nullptr;
return err;
}
int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
ATRACE_CALL();
ALOGV("Surface::queueBuffer");
Mutex::Autolock lock(mMutex);
int i = getSlotFromBufferLocked(buffer);
if (i < 0) {
if (fenceFd >= 0) {
close(fenceFd);
}
return i;
}
if (mSharedBufferSlot == i && mSharedBufferHasBeenQueued) {
if (fenceFd >= 0) {
close(fenceFd);
}
return OK;
}
IGraphicBufferProducer::QueueBufferOutput output;
IGraphicBufferProducer::QueueBufferInput input;
getQueueBufferInputLocked(buffer, fenceFd, mTimestamp, &input);
applyGrallocMetadataLocked(buffer, input);
sp<Fence> fence = input.fence;
nsecs_t now = systemTime();
//从生产者中取出队列
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
mLastQueueDuration = systemTime() - now;
if (err != OK) {
ALOGE("queueBuffer: error queuing buffer, %d", err);
}
onBufferQueuedLocked(i, fence, output);
return err;
}
生产者是:frameworks/native/libs/gui/BufferQueueProducer.cpp
// BlastBufferQueue.cpp (AOSP 13)
status_t BlastBufferQueue::lock(...) {
// 向SurfaceFlinger申请空闲缓冲区
status_t err = mProducer->dequeueBuffer(&mCurrentBuf, &fence, ...);
// 将缓冲区包装为GraphicBuffer
mCurrentGraphicBuffer = mProducer->requestBuffer(mCurrentBuf, ...);
// 创建Canvas(关联该GraphicBuffer)
*canvas = new SkiaCanvas(mCurrentGraphicBuffer->getSkImageInfo());
return OK;
}
// BlastBufferQueue.cpp
status_t BlastBufferQueue::unlockAndPost() {
// 准备提交参数(如时间戳、区域)
QueueBufferInput input(mTimestamp, ...);
// 提交缓冲区到SurfaceFlinger
status_t err = mProducer->queueBuffer(mCurrentBuf, input, &output);
return err;
}
过程4
在createSyncIfNeeded();中执行了finishDrawing
//frameworks/base/core/java/android/view/ViewRootImpl.java
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 -> {
//这里是一个异步操作,所以会在performDraw后面执行
// Callback will be invoked on executor thread so post to main thread.
mHandler.postAtFrontOfQueue(() -> {
mSurfaceChangedTransaction.merge(transaction);
//绘制结束时调用
reportDrawFinished(seqId);
});
});
mSurfaceSyncer.addToSync(mSyncId, mSyncTarget);
notifySurfaceSyncStarted();
}
private void reportDrawFinished(int seqId) {
try {
mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction, seqId);
} catch (RemoteException e) {
mSurfaceChangedTransaction.apply();
} finally {
mSurfaceChangedTransaction.clear();
}
}
接着就进入wms中
//frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
void finishDrawingWindow(Session session, IWindow client,
@Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
WindowState win = windowForClientLocked(session, client, false);
//**** 先调用windowstate的finishDrawing方法
if (win != null && win.finishDrawing(postDrawTransaction, seqId)) {
if (win.hasWallpaper()) {
win.getDisplayContent().pendingLayoutChanges |=
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
}
win.setDisplayLayoutNeeded();
//再调用requestTraversal
mWindowPlacerLocked.requestTraversal();
}
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
先调用windowstate的finishDrawing方法
//frameworks/base/services/core/java/com/android/server/wm/WindowState.java
boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId) {
final boolean layoutNeeded =
mWinAnimator.finishDrawingLocked(postDrawTransaction, mClientWasDrawingForSync);
mClientWasDrawingForSync = false;
return !skipLayout && (hasSyncHandlers || layoutNeeded);
}
boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction,
boolean forceApplyNow) {
boolean layoutNeeded = false;
//这里将mDrawState设置为COMMIT_DRAW_PENDING
if (mDrawState == DRAW_PENDING) {
mDrawState = COMMIT_DRAW_PENDING;
layoutNeeded = true;
}
...
return layoutNeeded;
}
再调用requestTraversal
从WindowSurfacePlacer一路调到performSurfacePlacementLoop。在调用RootWindowContainer中的
//frameworks/base/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
void requestTraversal() {
mService.mAnimationHandler.post(mPerformSurfacePlacement);
}
private final Traverser mPerformSurfacePlacement = new Traverser();
private class Traverser implements Runnable {
@Override
public void run() {
synchronized (mService.mGlobalLock) {
performSurfacePlacement();
}
}
}
final void performSurfacePlacement() {
performSurfacePlacement(false /* force */);
}
final void performSurfacePlacement(boolean force) {
int loopCount = 6;
do {
mTraversalScheduled = false;
performSurfacePlacementLoop();
mService.mAnimationHandler.removeCallbacks(mPerformSurfacePlacement);
loopCount--;
} while (mTraversalScheduled && loopCount > 0);
}
private void performSurfacePlacementLoop() {
try {
mService.mRoot.performSurfacePlacement();
...
} catch (RuntimeException e) {
mInLayout = false;
Slog.wtf(TAG, "Unhandled exception while laying out windows", e);
}
}
进入到RootWindowContainer的performSurfacePlacement中执行
//frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
void performSurfacePlacement() {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performSurfacePlacement");
try {
performSurfacePlacementNoTrace();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
void performSurfacePlacementNoTrace() {
try {
applySurfaceChangesTransaction();
} catch (RuntimeException e) {
Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
}
......
}
private void applySurfaceChangesTransaction() {
final int count = mChildren.size();
for (int j = 0; j < count; ++j) {
final DisplayContent dc = mChildren.get(j);
dc.applySurfaceChangesTransaction();
}
}
//frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
void applySurfaceChangesTransaction() {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges");
try {
forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
// Moved from updateWindowsAndWallpaperLocked().
if (w.mHasSurface) {
//调用WindowAnimation的commitFinishDrawingLocked
final boolean committed = winAnimator.commitFinishDrawingLocked();
}
};
//frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java
boolean commitFinishDrawingLocked() {
//这里mDrawState==COMMIT_DRAW_PENDING;所以不从这里返回false
if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
return false;
}
mDrawState = READY_TO_SHOW;
boolean result = false;
final ActivityRecord activity = mWin.mActivityRecord;
if (activity == null || activity.canShowWindows()
|| mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
//****** 这里会执行窗口添加动画的逻辑
result = mWin.performShowLocked();
}
return result;
}
这里执行结束后,mDrawState会被赋值为READY_TO_SHOW;
boolean performShowLocked() {
在上面mDrawState已经被赋值为READY_TO_SHOW了
if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) {
return false;
}
//这里执行窗口进入动画
mWinAnimator.applyEnterAnimationLocked();
//这里重新被赋值为HAS_DRAWN;
mWinAnimator.mDrawState = HAS_DRAWN;
mWmService.scheduleAnimationLocked();
return true;
}
至此结束,mDrawState也被赋值为HAS_DRAWN
wms的动画
对于wms来说动画分成两种,一种是本地动画,只有systemserver端的; 另一种是远程动画,systemserver和远程进程systemUI和launcher进程
对于本地动画,主要由leash实现;而leash动画在哪执行呢;问题非常好,就在上面过程4的最后一步,在mDrawState被赋值为HAS_DRAWN的上一行代码中就是执行leash的窗口动画
mWinAnimator.applyEnterAnimationLocked();