android wms主要流程

45 阅读6分钟

对于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中主要作用:

  1. 创建windowtoken;
  2. 创建windowstate;
  3. 将windowstate放入map中,方便后续取用;
  4. 创建事件传递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中,主要做了这些

  1. 在wms中将布局大小计算完成
  2. 将mSurfaceControl构建完成
  3. 将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();