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中

   @Override
    public 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

    @Override
    void 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方法

   @Override
    void 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过程的方法调用图
在这里插入图片描述

  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值