窗口的显示过程

本文基于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;
    }

猜你喜欢

转载自blog.csdn.net/xiaoyantan/article/details/127319943