欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > Android之WMS篇(五)窗口绘制的过程

Android之WMS篇(五)窗口绘制的过程

2025/4/23 15:01:08 来源:https://blog.csdn.net/Gary1_Liu/article/details/140507468  浏览:    关键词:Android之WMS篇(五)窗口绘制的过程

在上篇博客中提到WMS的addWindow方法中将Window对应的WindowToken和WindowState挂载到窗口层级树上,它们只是内存中的对象并没有做窗口绘制的动作。这篇博客将讲述Window添加到窗口层级树后,窗口绘制的过程。

1.窗口relayout的过程
在屏幕刷新的时候Choreographer会执行mTraversalRunnable

    void scheduleTraversals() {if (!mTraversalScheduled) {mTraversalScheduled = true;mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);notifyRendererOfFramePending();pokeDrawLockIfNeeded();}}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
  void doTraversal() {if (mTraversalScheduled) {mTraversalScheduled = false;//省略代码performTraversals();//省略代码}}

最后会在performTraversals方法中执行relayoutWindow方法

 private void performTraversals() {//省略代码   if (mFirst || windowShouldResize || viewVisibilityChanged || params != null|| mForceNextWindowRelayout) {//省略代码 		relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);//省略代码 		} catch (RemoteException e) {} finally {//省略代码 		}//省略代码 		}//省略代码 		}

relayoutWindow方法又会调用到Session.中

 private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,boolean insetsPending) throws RemoteException {//省略代码if (LOCAL_LAYOUT) {//省略代码} else {//省略代码relayoutResult = mWindowSession.relayout(mWindow, params,requestedWidth, requestedHeight, viewVisibility,insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, //省略代码 }//省略代码}

Session是跨进调用,Session又会调用到WMS中

   @Overridepublic int relayout(IWindow window, WindowManager.LayoutParams attrs,int requestedWidth, int requestedHeight, int viewFlags, int flags,ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,SurfaceControl outSurfaceControl, InsetsState outInsetsState,InsetsSourceControl[] outActiveControls, Bundle outSyncSeqIdBundle) {//省略代码int res = mService.relayoutWindow(this, window, attrs,requestedWidth, requestedHeight, viewFlags, flags,outFrames, mergedConfiguration, outSurfaceControl, outInsetsState,outActiveControls, outSyncSeqIdBundle);//省略代码return res;}

到了WMS中这里主要做了两件事情:

1.1.创建绘制使用的WindowSurfaceController

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) {       //省略代码if (!shouldRelayout && winAnimator.hasSurface() && !win.mAnimatingExit) {//省略代码if (shouldRelayout) {try {result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);} catch (Exception e) {//省略代码}}//省略代码}//省略代码}

createSurfaceControl方法会调用调用到WindowStateAnimator方法中的createSurfaceLocked

   private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,WindowState win, WindowStateAnimator winAnimator) {//省略代码WindowSurfaceController surfaceController;try {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");surfaceController = winAnimator.createSurfaceLocked();} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}//省略代码}

createSurfaceControl方法会调用调用到

   WindowSurfaceController createSurfaceLocked() {final WindowState w = mWin;//省略代码w.setHasSurface(false);//省略代码resetDrawState();//省略代码try {//省略代码mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), format,flags, this, attrs.type);//省略代码w.setHasSurface(true);//省略代码} catch (OutOfResourcesException e) {//省略代码} catch (Exception e) {//省略代码}//省略代码mLastHidden = true;if (DEBUG) Slog.v(TAG, "Created surface " + this);return mSurfaceController;}

1.1.1.设置了mDrawState = DRAW_PENDING

   void resetDrawState() {mDrawState = DRAW_PENDING;if (mWin.mActivityRecord == null) {return;}if (!mWin.mActivityRecord.isAnimating(TRANSITION)) {mWin.mActivityRecord.clearAllDrawn();}}

1.1.2.创建了WindowSurfaceController

 WindowSurfaceController(String name, int format, int flags, WindowStateAnimator animator,int windowType) {mAnimator = animator;title = name;mService = animator.mService;final WindowState win = animator.mWin;mWindowType = windowType;mWindowSession = win.mSession;Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");final SurfaceControl.Builder b = win.makeSurface().setParent(win.getSurfaceControl()).setName(name).setFormat(format).setFlags(flags).setMetadata(METADATA_WINDOW_TYPE, windowType).setMetadata(METADATA_OWNER_UID, mWindowSession.mUid).setMetadata(METADATA_OWNER_PID, mWindowSession.mPid).setCallsite("WindowSurfaceController");final boolean useBLAST = mService.mUseBLAST && ((win.getAttrs().privateFlags& WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0);if (useBLAST) {b.setBLASTLayer();}mSurfaceControl = b.build();Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}

WindowSurfaceController才是用来绘制的的SurfaceControl.前边的博客中讲过在addChild的过程中Window会创建对应的SurfaceControll这些SurfaceControl都是CONTAINER类型,只有这里的WindowSurfaceController它是BLAST用于绘制的

1.2.计算出Window的摆放位置
performSurfacePlacement方法计算Window的摆放位置

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) {//省略代码// We may be deferring layout passes at the moment, but since the client is interested// in the new out values right now we need to force a layout.mWindowPlacerLocked.performSurfacePlacement(true /* force */);//省略代码}//省略代码}

这里方法调用的层级比较多省去中间调用的部分,最后会直接调用到DisplayContent类中的
applySurfaceChangesTransaction方法,执行performLayout,计算出Window的摆放位置

 // TODO: Super unexpected long method that should be broken down...void applySurfaceChangesTransaction() {final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;   //省略代码// Perform a layout, if needed.performLayout(true /* initial */, false /* updateInputWindows */);//省略代码}

performLayout方法最后执行到performLayoutNoTrace方法

 private void performLayoutNoTrace(boolean initial, boolean updateInputWindows) {//省略代码// First perform layout of any root windows (not attached to another window).forAllWindows(mPerformLayout, true /* traverseTopToBottom */);// Now perform layout of attached windows, which usually depend on the position of the// window they are attached to. XXX does not deal with windows that are attached to windows// that are themselves attached.forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */);//省略代码}

这里通过forAllWindows遍历所有的Window

 private final Consumer<WindowState> mPerformLayout = w -> {//省略代码if (!gone || !w.mHaveFrame || w.mLayoutNeeded) {//省略代码getDisplayPolicy().layoutWindowLw(w, null, mDisplayFrames);//省略代码}//省略代码};

forAllWindows遍历所有的Window,mPerformLayout 它是一个WindowState类型的回调函数,在遍历所有Window的时候遇到WindowState时就会执行这个方法。主要会执行DisplayPolicy类的layoutWindowLw方法

 public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) {//省略代码mWindowLayout.computeFrames(attrs, win.getInsetsState(), displayFrames.mDisplayCutoutSafe,win.getBounds(), win.getWindowingMode(), requestedWidth, requestedHeight,win.getRequestedVisibilities(), attachedWindowFrame, win.mGlobalScale,sTmpClientFrames);//省略代码}

layoutWindowLw中就会执行computeFrames方法计算中Window的摆放位置。

跨进程调用图
在这里插入图片描述

2.finishDrawing的过程
2.1.App进程的入口方法还是performTraversals

     boolean cancelAndRedraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw();if (!cancelAndRedraw) {createSyncIfNeeded();}

createSyncIfNeeded方法中会调用到reportDrawFinished方法

private void createSyncIfNeeded() {//省略代码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);});});//省略代码}

reportDrawFinished方法中通过Session又跨进程调用finishDrawing

 private void reportDrawFinished(int seqId) {if (DEBUG_BLAST) {Log.d(mTag, "reportDrawFinished " + Debug.getCallers(5));}try {mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction, seqId);} catch (RemoteException e) {Log.e(mTag, "Unable to report draw finished", e);mSurfaceChangedTransaction.apply();} finally {mSurfaceChangedTransaction.clear();}}

2.2.SystemServer进程逻辑

  public void finishDrawing(IWindow window,@Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {if (DEBUG) Slog.v(TAG_WM, "IWindow finishDrawing called for " + window);mService.finishDrawingWindow(this, window, postDrawTransaction, seqId);}

Session中调用WMS的finishDrawingWindow

    void finishDrawingWindow(Session session, IWindow client,@Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {//省略代码try {synchronized (mGlobalLock) {WindowState win = windowForClientLocked(session, client, false);ProtoLog.d(WM_DEBUG_ADD_REMOVE, "finishDrawingWindow: %s mDrawState=%s",win, (win != null ? win.mWinAnimator.drawStateToString() : "null"));if (win != null && win.finishDrawing(postDrawTransaction, seqId)) {if (win.hasWallpaper()) {win.getDisplayContent().pendingLayoutChanges |=WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;}win.setDisplayLayoutNeeded();mWindowPlacerLocked.requestTraversal();}}} finally {//省略代码}}

2.2.1.执行WindowState的finishDrawing方法

    boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId) {//省略代码final boolean layoutNeeded =mWinAnimator.finishDrawingLocked(postDrawTransaction, mClientWasDrawingForSync);//省略代码}

调用WindowStateAnimator的finishDrawingLocked

 boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction,boolean forceApplyNow) {//省略代码boolean layoutNeeded = false;if (mDrawState == DRAW_PENDING) {ProtoLog.v(WM_DEBUG_DRAW,"finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s", mWin,mSurfaceController);if (startingWindow) {ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Draw state now committed in %s", mWin);}mDrawState = COMMIT_DRAW_PENDING;layoutNeeded = true;}//省略代码return layoutNeeded;}

这里最主要的时将mDrawState 的状态由DRAW_PENDING改变为COMMIT_DRAW_PENDING,并返回为true

2.2.2.执行mWindowPlacerLocked.requestTraversal(),这方方法经过多层调用又会执行到DisplayContent.java中的applySurfaceChangesTransaction方法

 // TODO: Super unexpected long method that should be broken down...void applySurfaceChangesTransaction() {//省略代码// Perform a layout, if needed.performLayout(true /* initial */, false /* updateInputWindows */);//省略代码Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges");try {forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}prepareSurfaces();//省略代码   }

2.2.2.1.前边讲过performLayout会计算出Window的摆放位置
2.2.2.2.在relayoutWindow的时候执行applySurfaceChangesTransaction方法时由于mDrawState = DRAW_PENDING导致forAllWindows执行mApplySurfaceChangesTransaction回调时退出,这次执行到这里时mDrawState = COMMIT_DRAW_PENDING就会往下执行

    private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;//省略代码// Moved from updateWindowsAndWallpaperLocked().if (w.mHasSurface) {// Take care of the window being ready to display.final boolean committed = winAnimator.commitFinishDrawingLocked();//省略代码}}//省略代码};

WindowState还是执行到了WindowStateAnimator的commitFinishDrawingLocked

    // This must be called while inside a transaction.boolean commitFinishDrawingLocked() {if (DEBUG_STARTING_WINDOW_VERBOSE &&mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState="+ drawStateToString());}if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {return false;}ProtoLog.i(WM_DEBUG_ANIM, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW %s",mSurfaceController);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 != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW的时候就退出了,这次mDrawState == COMMIT_DRAW_PENDING就不会退出了,会继续往下执行,mDrawState 改编为 READY_TO_SHOW;

由于我们添加的是一个System Window不是Activity所这里会执行mWin.performShowLocked()

    boolean performShowLocked() {//省略代码if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) {return false;}//省略代码mWinAnimator.mDrawState = HAS_DRAWN;//省略代码}return true;}

至此整个Window的mDrawState 已经走到了HAS_DRAWN状态,完成了Window的finishDrawing操作
Window的finishDrawing方法调用逻辑图在这里插入图片描述3.prepareSurfaces过程
prepareSurfaces是在完成finishDrawing后mDrawState = HAS_DRAWN时在DisplayContent.java的applySurfaceChangesTransaction方法中执行的

void applySurfaceChangesTransaction() {//省略代码prepareSurfaces();//省略代码}

DisplayContent.java的prepareSurfaces看似什么都没做,其实它调用了super的prepareSurfaces

    @Overridevoid prepareSurfaces() {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "prepareSurfaces");try {final Transaction transaction = getPendingTransaction();super.prepareSurfaces();// TODO: Once we totally eliminate global transaction we will pass transaction in here//       rather than merging to global.SurfaceControl.mergeToGlobalTransaction(transaction);} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}}

DisplayContent–>DispalyArea.Dimmable–>WindowContainer的prepareSurfaces

 void prepareSurfaces() {// If a leash has been set when the transaction was committed, then the leash reparent has// been committed.mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();for (int i = 0; i < mChildren.size(); i++) {mChildren.get(i).prepareSurfaces();}}

其实是调用到WindowState的prepareSurfaces方法

   @Overridevoid prepareSurfaces() {mIsDimming = false;applyDims();updateSurfacePositionNonOrganized();// Send information to SurfaceFlinger about the priority of the current window.updateFrameRateSelectionPriorityIfNeeded();updateScaleIfNeeded();mWinAnimator.prepareSurfaceLocked(getSyncTransaction());super.prepareSurfaces();}

最后是调用到WindowStateAnimator的prepareSurfaceLocked

  void prepareSurfaceLocked(SurfaceControl.Transaction t) {final WindowState w = mWin;//省略代码if (w.isParentWindowHidden() || !w.isOnScreen()) {//省略代码} else if (mLastAlpha != mShownAlpha|| mLastHidden) {//省略代码boolean prepared =mSurfaceController.prepareToShowInTransaction(t, mShownAlpha);if (prepared && mDrawState == HAS_DRAWN) {if (mLastHidden) {if (showSurfaceRobustlyLocked(t)) {//省略代码}}} //省略代码}

最重要的是调用showSurfaceRobustlyLocked方法

   */private boolean showSurfaceRobustlyLocked(SurfaceControl.Transaction t) {boolean shown = mSurfaceController.showRobustly(t);if (!shown)return false;t.merge(mPostDrawTransaction);return true;}
boolean showRobustly(SurfaceControl.Transaction t) {ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title);if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this+ " during relayout");if (mSurfaceShown) {return true;}setShown(true);t.show(mSurfaceControl);if (mAnimator.mIsWallpaper) {EventLog.writeEvent(EventLogTags.WM_WALLPAPER_SURFACE,mAnimator.mWin.getDisplayId(), 1 /* request shown */);}return true;}

这里最终调用t.show(mSurfaceControl)方法交给了SurfaceFlinger来绘制

prepareSurfaces过程的方法调用图
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词