Android VirtualDisplay解析

一.概述

???????我們知道催首,Android設(shè)備都有錄屏功能,其實(shí)主要是通過(guò)VirtualDisplay來(lái)實(shí)現(xiàn)的洒疚,VirtualDisplay對(duì)應(yīng)虛擬Display鸠姨,主要用來(lái)進(jìn)行屏幕錄制等相關(guān)功能;
???????在DMS的registerDefaultDisplayAdapters()內(nèi)部,除了創(chuàng)建LocalDisplayAdapter抓韩,還創(chuàng)建了VirtualDisplayAdapter纠永,可以參考文章Android Display管理服務(wù)DMS,接下來(lái)一起看一下VirtualDisplayAdapter類(lèi)實(shí)現(xiàn):

二.VirtualDisplayAdapter

public VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
            Context context, Handler handler, Listener listener) {
    this(syncRoot, context, handler, listener,
                (String name, boolean secure) -> SurfaceControl.createDisplay(name, secure));
}

@VisibleForTesting
VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,Context context, Handler handler, Listener listener,
            SurfaceControlDisplayFactory surfaceControlDisplayFactory) {
    super(syncRoot, context, handler, listener, TAG);
    mHandler = handler;
    mSurfaceControlDisplayFactory = surfaceControlDisplayFactory;
}

???????在構(gòu)造方法內(nèi)部會(huì)通過(guò)SurfaceControl的createDisplay()獲取的對(duì)象賦值給mSurfaceControlDisplayFactory變量谒拴,后續(xù)在創(chuàng)建VirtualDisplayDevice時(shí)需要尝江;

三.VirtualDisplayDevice

???????通過(guò)VirtualDisplayAdapter內(nèi)部的createVirtualDisplayLocked()來(lái)創(chuàng)建VirtualDisplayDevice;

public DisplayDevice createVirtualDisplayLocked(IVirtualDisplayCallback callback,
            IMediaProjection projection, int ownerUid, String ownerPackageName, String name,
            int width, int height, int densityDpi, Surface surface, int flags, String uniqueId) {
    boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0;
    IBinder appToken = callback.asBinder();
    IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure);
    final String baseUniqueId =
                UNIQUE_ID_PREFIX + ownerPackageName + "," + ownerUid + "," + name + ",";
    final int uniqueIndex = getNextUniqueIndex(baseUniqueId);
    if (uniqueId == null) {
        uniqueId = baseUniqueId + uniqueIndex;
    } else {
        uniqueId = UNIQUE_ID_PREFIX + ownerPackageName + ":" + uniqueId;
    }
    VirtualDisplayDevice device = new VirtualDisplayDevice(displayToken, appToken,
                ownerUid, ownerPackageName, name, width, height, densityDpi, surface, flags,
                new Callback(callback, mHandler), uniqueId, uniqueIndex);

    mVirtualDisplayDevices.put(appToken, device);
    try {
        if (projection != null) {
            projection.registerCallback(new MediaProjectionCallback(appToken));
        }
        appToken.linkToDeath(device, 0);
    }
    return device;
}

???????1.通過(guò)mSurfaceControlDisplayFactory的createDisplay()來(lái)獲取對(duì)應(yīng)的displayToken英上,由于是虛擬設(shè)備炭序,跟BUILT_IN設(shè)備獲取方式是不同的;
???????2.VirtualDisplay的mUniqueId格式為:virtual:com.hly.test,1000(ownerUid),-display(name),0苍日;
???????3.將創(chuàng)建的VirtualDisplayDevice加入mVirtualDisplayDevices進(jìn)行管理惭聂;
???????4.projection.registerCallback()執(zhí)行錄屏相關(guān)注冊(cè);

四.VirtualDisplay創(chuàng)建

???????當(dāng)要執(zhí)行屏幕錄制前相恃,會(huì)先通過(guò)MediaProjection執(zhí)行createVirtualDisplay()來(lái)創(chuàng)建VirtualDisplay彼妻;

1.createVirtualDisplay()

public VirtualDisplay createVirtualDisplay(@NonNull String name,int width, int height, int dpi, int flags, @Nullable Surface surface,@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
     DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
     return dm.createVirtualDisplay(this, name, width, height, dpi, surface, flags, callback,handler, null /* uniqueId */);
}

???????需要傳入VirtualDisplay的name、width豆茫、height侨歉、Surface等,Surface用來(lái)獲取或顯示屏幕數(shù)據(jù)揩魂,最后會(huì)調(diào)用到DisplayMangerGlobal內(nèi)部的createVirtualDisplay()方法:

2.createVirtualDisplay()

public VirtualDisplay createVirtualDisplay(Context context, MediaProjection projection,
            String name, int width, int height, int densityDpi, Surface surface, int flags,
            VirtualDisplay.Callback callback, Handler handler, String uniqueId) {
    ..........................
    VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, handler);
    IMediaProjection projectionToken = projection != null ? projection.getProjection() : null;
    int displayId;
    try {
        displayId = mDm.createVirtualDisplay(callbackWrapper, projectionToken,
                    context.getPackageName(), name, width, height, densityDpi, surface, flags,
                    uniqueId);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
    Display display = getRealDisplay(displayId);
    ...............................
    return new VirtualDisplay(this, display, callbackWrapper, surface);
}

???????接下來(lái)會(huì)調(diào)用執(zhí)行到DMS的createVirtualDisplay()來(lái)先創(chuàng)建VirtualDisplayDevice和LogicalDisplay幽邓,根據(jù)LogicalDisplay的displayId創(chuàng)建Display,然后將Display作為參數(shù)創(chuàng)建VirtualDisplay返回火脉;

3.總結(jié)

???????用一張流程圖總結(jié)一下創(chuàng)建流程:


image.png

五.鏡像實(shí)現(xiàn)

???????在錄屏?xí)r牵舵,其實(shí)就是一個(gè)鏡像,VirtualDisplayDevice是沒(méi)有內(nèi)容顯示的倦挂,所以需要將其鏡像到要錄制屏對(duì)應(yīng)的DisplayDevice就可以了畸颅,具體實(shí)現(xiàn)邏輯是在DMS的configureDisplayInTransactionLocked()方法,那該方法是什么時(shí)候會(huì)觸發(fā)調(diào)用呢方援?
???????根據(jù)前面的分析没炒,在創(chuàng)建VirtualDisplay時(shí),會(huì)執(zhí)行到handleDisplayDeviceAddedLocked()犯戏,一起看一下該方法:

1.handleDisplayDeviceAddedLocked()

private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
    DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
    .....................
    mDisplayDevices.add(device);
    LogicalDisplay display = addLogicalDisplayLocked(device);
    Runnable work = updateDisplayStateLocked(device);
    if(work != null) {
        work.run();
    }
    scheduleTraversalLocked(false);
}

???????在該方法內(nèi)部會(huì)創(chuàng)建VirtualDisplayDevice對(duì)應(yīng)的LogicalDisplay送火,繼而分配displayId及l(fā)ayerStack,那創(chuàng)建完后是如何跟目標(biāo)屏建立對(duì)應(yīng)關(guān)系的呢先匪?關(guān)鍵點(diǎn)就在scheduleTraversalLocked(false)种吸,一起看一下:

2.scheduleTraversalLocked()

private void scheduleTraversalLocked(boolean inTraversal) {
    if (!mPendingTraversal && mWindowManagerInternal != null) {
        mPendingTraversal = true;
        if (!inTraversal) {
            mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
        }
    }
}

case MSG_REQUEST_TRAVERSAL:
     mWindowManagerInternal.requestTraversalFromDisplayManager();
     break;

private final class LocalService extends WindowManagerInternal {
    @Override
     public void requestTraversalFromDisplayManager() {
        requestTraversal();
     }
}

void requestTraversal() {
    synchronized (mWindowMap) {
        mWindowPlacerLocked.requestTraversal();
    }
}

???????在scheduleTraversalLocked()內(nèi)部發(fā)送 MSG_REQUEST_TRAVERSAL消息,執(zhí)行該消息的時(shí)候就是調(diào)用WMS的LocalService執(zhí)行 requestTraversal()方法呀非,具體執(zhí)行過(guò)程簡(jiǎn)單羅列一下:

WindowSurfacePlacer -> requestTraversal()
 WindowSurfacePlacer -> performSurfacePlacement()
  WindowSurfacePlacer -> performSurfacePlacementLoop()
   RootWindowContainer -> performSurfacePlacement()
    void performSurfacePlacement(boolean recoveringMemory) {
       ...................
       mService.openSurfaceTransaction();
        try {
            applySurfaceChangesTransaction(recoveringMemory, defaultDw, defaultDh);
        } catch (RuntimeException e) {
            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
        } finally {
            mService.closeSurfaceTransaction();
        }
      ......
    }

???????可以看到坚俗,在RootWindowContainer內(nèi)部的performSurfacePlacement()會(huì)順序執(zhí)行以下方法:
???????1.mService.openSurfaceTransaction(),通過(guò)SurfaceControl來(lái)通知native開(kāi)始一個(gè)Transaction;
???????2.applySurfaceChangesTransaction(recoveringMemory, defaultDw, defaultDh)來(lái)處理Transaction猖败;
???????3.mService.closeSurfaceTransaction()形耗,通過(guò)SurfaceControl來(lái)通知native(SurfaceFlinger)關(guān)閉一個(gè)Transaction最終來(lái)執(zhí)行合成顯示等工作;

3.applySurfaceChangesTransaction()

private void applySurfaceChangesTransaction(boolean recoveringMemory, int defaultDw,
            int defaultDh) {
    ......................................
    // Give the display manager a chance to adjust properties like display rotation if it needs
    // to.
    mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
}

???????刷新后經(jīng)過(guò)一番調(diào)用辙浑,最終回到DisplayManagerService的performTraversalInTransactionFromWindowManager()方法激涤,該方法會(huì)調(diào)用到performTraversalInTransactionLocked()方法:

4.performTraversalInTransactionLocked()

private void performTraversalInTransactionLocked() {
    .....................
    // Configure each display device.
    final int count = mDisplayDevices.size();
    for (int i = 0; i < count; i++) {
        DisplayDevice device = mDisplayDevices.get(i);
        configureDisplayInTransactionLocked(device);
        device.performTraversalInTransactionLocked();
    }
    ......................
}

???????可以看到,在該方法內(nèi)會(huì)遍歷所有的DisplayDevice來(lái)主要干了兩件事:
???????1.執(zhí)行configureDisplayInTransactionLocked()進(jìn)行配置DisplayDevice要顯示的layerStack判呕;
???????2.執(zhí)行performTraversalInTransactionLocked()來(lái)關(guān)聯(lián)Surface倦踢,即數(shù)據(jù)顯示源;
???????先看configureDisplayInTransactionLocked():

5.configureDisplayInTransactionLocked()

private void configureDisplayInTransactionLocked(DisplayDevice device) {
    final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
    final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
    LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);

    if (!ownContent) {
        if (display != null && !display.hasContentLocked()) {
            // If the display does not have any content of its own, then
            // automatically mirror the default logical display contents.
            display = null;
        }
        if (display == null) {
            display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
        }
    }

    display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);
    ....................
}

???????當(dāng)DisplayDevice對(duì)應(yīng)VirtualDisplayDevice時(shí)侠草,返回的ownContent為false辱挥,即沒(méi)有自己內(nèi)容顯示的,進(jìn)入判斷边涕,通過(guò)display.hasContentLocked()返回false晤碘,所以得到的display為null,接下來(lái)如果display為null功蜓,會(huì)從mLogicalDisplays中取出DEFAULT_DISPLAY賦值給display园爷,那有什么用呢?
???????關(guān)鍵邏輯在display.configureDisplayInTransactionLocked():

6.configureDisplayInTransactionLocked()

public void configureDisplayInTransactionLocked(DisplayDevice device, boolean isBlanked) {
    // Set the layer stack.
    device.setLayerStackInTransactionLocked(isBlanked ? BLANK_LAYER_STACK : mLayerStack);
    .....................
    .....................
}

public final void setLayerStackInTransactionLocked(int layerStack) {
    if (mCurrentLayerStack != layerStack) {
        mCurrentLayerStack = layerStack;
        SurfaceControl.setDisplayLayerStack(mDisplayToken, layerStack);
    }
}

???????在該方法內(nèi)部執(zhí)行device.setLayerStackInTransactionLocked()式撼,即將VirtualDisplayDevice的layerStack設(shè)置為DEFAULT_DISPLAY對(duì)應(yīng)的layerStack童社,繼而調(diào)用SurfaceControl內(nèi)部的setDisplayLayerStack()方法,mDisplayToken用于唯一標(biāo)識(shí)SurfaceFliger創(chuàng)建的VirtualDisplay著隆,跟隨調(diào)用關(guān)系扰楼,再一起看一下:

public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
    nativeSetDisplayLayerStack(displayToken, layerStack);
}

static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz,jobject tokenObj, jint layerStack) {
    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    SurfaceComposerClient::setDisplayLayerStack(token, layerStack);
}

void SurfaceComposerClient::setDisplayLayerStack(const sp<IBinder>& token,uint32_t layerStack) {
    Composer::getInstance().setDisplayLayerStack(token, layerStack);
}

void Composer::setDisplayLayerStack(const sp<IBinder>& token,uint32_t layerStack) {
    Mutex::Autolock _l(mLock);
    DisplayState& s(getDisplayStateLocked(token));
    s.layerStack = layerStack;
    s.what |= DisplayState::eLayerStackChanged;
}

???????跟隨調(diào)用關(guān)系,主要有以下幾個(gè)要點(diǎn):
???????getDisplayStateLocked():如果不存在該token對(duì)應(yīng)的 DisplayState就會(huì)為該token創(chuàng)建一個(gè)DisplayState美浦,并保存在mDisplayStates中進(jìn)行管理弦赖;
???????接下來(lái)將layerStack賦值給DisplayyState的layerStack變量,此時(shí)layerStack配置完成浦辨;
???????前面講到蹬竖,在創(chuàng)建VirtualDisplay時(shí)會(huì)傳入Surface,那該Surface是如何與VirtualDisplay進(jìn)行關(guān)聯(lián)的呢荤牍?關(guān)鍵在performTraversalInTransactionLocked()方法:

7.performTraversalInTransactionLocked()

@Override
public void performTraversalInTransactionLocked() {
    if ((mPendingChanges & PENDING_RESIZE) != 0) {
         SurfaceControl.setDisplaySize(getDisplayTokenLocked(), mWidth, mHeight);
    }
    if ((mPendingChanges & PENDING_SURFACE_CHANGE) != 0) {
        setSurfaceInTransactionLocked(mSurface);
    }
    mPendingChanges = 0;
}

public final void setSurfaceInTransactionLocked(Surface surface) {
    if (mCurrentSurface != surface) {
        mCurrentSurface = surface;
        SurfaceControl.setDisplaySurface(mDisplayToken, surface);
    }
}

???????mSurface是在創(chuàng)建VirtualDisplay時(shí)傳入的案腺,可以是通過(guò)SurfaceView的getSurface()獲取的Surface庆冕,用來(lái)直接顯示康吵;也可以是通過(guò)MediaCodec獲取的Surface,用來(lái)實(shí)現(xiàn)遠(yuǎn)端視頻流傳輸访递;

public static void setDisplaySurface(IBinder displayToken, Surface surface) {
    ..........
    if (surface != null) {
        synchronized (surface.mLock) {
            nativeSetDisplaySurface(displayToken, surface.mNativeObject);
        }
    } else {
        nativeSetDisplaySurface(displayToken, 0);
    }
}

static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz,jobject tokenObj, jlong nativeSurfaceObject) {
    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    sp<IGraphicBufferProducer> bufferProducer;
    sp<Surface> sur(reinterpret_cast<Surface *>(nativeSurfaceObject));
    if (sur != NULL) {
        bufferProducer = sur->getIGraphicBufferProducer();
    }
    status_t err = SurfaceComposerClient::setDisplaySurface(token,
        bufferProducer);
    }
}

???????bufferProducer主要用于申請(qǐng) Buffer晦嵌,申請(qǐng)Buffer是寫(xiě)入圖形數(shù)據(jù);consumer主要用于消費(fèi)Buffer,消費(fèi)Buffer就是把應(yīng)用寫(xiě)入數(shù)據(jù)準(zhǔn)備好的Buffer取出來(lái)處理惭载;

status_t SurfaceComposerClient::setDisplaySurface(const sp<IBinder>& token,sp<IGraphicBufferProducer> bufferProducer) {
    return Composer::getInstance().setDisplaySurface(token, bufferProducer);
}

status_t Composer::setDisplaySurface(const sp<IBinder>& token,sp<IGraphicBufferProducer> bufferProducer) {
    DisplayState& s(getDisplayStateLocked(token));
    s.surface = bufferProducer;
    s.what |= DisplayState::eSurfaceChanged;
    return NO_ERROR;
}

???????把 bufferProducer 保存到 DisplayState 的 surface中旱函;
???????經(jīng)過(guò)上面的處理后,為VirtualDisplay配置好了 layerStack (鏡像屏)和bufferProducer描滔,那么接下來(lái)是如何進(jìn)行后續(xù)顯示處理的呢棒妨?
???????前面講到,在RootWindowContainer內(nèi)部的performSurfacePlacement()在執(zhí)行applySurfaceChangesTransaction()完后會(huì)執(zhí)行mService.closeSurfaceTransaction()含长,一起看一下該方法:

8.closeSurfaceTransaction()

void closeSurfaceTransaction() {
    try {
        synchronized (mWindowMap) {
            if (mRoot.mSurfaceTraceEnabled) {
                mRoot.mRemoteEventTrace.closeSurfaceTransaction();
            }
            SurfaceControl.closeTransaction();
        }
    } finally {
    }
}

public static void closeTransaction() {
    nativeCloseTransaction(false);
}

static void nativeCloseTransaction(JNIEnv* env, jclass clazz, jboolean sync) {
    SurfaceComposerClient::closeGlobalTransaction(sync);
}

void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) {
    Composer::closeGlobalTransaction(synchronous);
}

void Composer::closeGlobalTransactionImpl(bool synchronous) {
    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
    Vector<ComposerState> transaction;
    Vector<DisplayState> displayTransaction;
    ......
    {
        displayTransaction = mDisplayStates;
    }
     ......
   sm->setTransactionState(transaction, displayTransaction, flags); //sm  SurfaceFlinger
}

???????sm:指向SurfaceFlinger 代理對(duì)象券腔;mDisplayStates:里面保存了之前創(chuàng)建的VirtualDisplay對(duì)應(yīng)的DisplayState,在DisplayState中保存了layerStack(鏡像屏)和 bufferProducer(寫(xiě)入屏幕數(shù)據(jù))拘泞;

9.setTransactionState()

void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state,const Vector<DisplayState>& displays,uint32_t flags){
    .....
    size_t count = displays.size();
    for (size_t i=0 ; i<count ; i++) {
        const DisplayState& s(displays[i]);
        transactionFlags |= setDisplayStateLocked(s);
    }
    ......
    setTransactionFlags(transactionFlags);
    ......
}

???????1.遍歷mDisplayStates執(zhí)行setDisplayStateLocked()更新 mCurrentState.displays 中的數(shù)據(jù)纷纫,通過(guò)token取出 VirtualDisplay然后更新surface和layerStack;

uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s){
     ssize_t dpyIdx = mCurrentState.displays.indexOfKey(s.token);
     ......
     DisplayDeviceState& disp(mCurrentState.displays.editValueAt(dpyIdx));
     if (disp.isValid()) {
         const uint32_t what = s.what;
         if (what & DisplayState::eSurfaceChanged) {
            if (IInterface::asBinder(disp.surface) != IInterface::asBinder(s.surface)) {
                disp.surface = s.surface;
                flags |= eDisplayTransactionNeeded;
            }
         }
         if (what & DisplayState::eLayerStackChanged) {
             if (disp.layerStack != s.layerStack) {
                 disp.layerStack = s.layerStack;
                 flags |= eDisplayTransactionNeeded;
             }
         }
         ......
     }
     return flags;
}

???????2.通過(guò)setTransactionFlags()發(fā)起一次刷新陪腌;

uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) {
    signalTransaction();
}

void SurfaceFlinger::signalTransaction() {
    mEventQueue.invalidate();
}

void MessageQueue::invalidate() {
    mEvents->requestNextVsync();
}

???????SurfaceFlinger 請(qǐng)求下一個(gè)同步幀辱魁,執(zhí)行一次刷新,最終調(diào)用如下: SurfaceFlinger::handleTransaction()-->SurfaceFlinger::handleTransactionLocked()诗鸭;

10.handleTransactionLocked()

void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags){
    .......................
    .......................
    const KeyedVector<  wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays);
    const KeyedVector<  wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
    const size_t cc = curr.size();
    size_t dc = draw.size();
    for (size_t i=0 ; i<cc ; i++) {
       if (draw.indexOfKey(curr.keyAt(i)) < 0) {
           ..................
           if (state.isVirtualDisplay()) {
               ......
               if (state.surface != NULL) {
                  if (mUseHwcVirtualDisplays || mHwc->isUsingVrComposer()) {
                      .....
                      displayUtils->initVDSInstance(*mHwc, hwcId, state.surface,dispSurface, producer, bqProducer, bqConsumer,state.displayName, state.isSecure);
                  }
               }
          }
          ......
          if (dispSurface != NULL && producer != NULL) {
              sp<DisplayDevice> hw =new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
                                                  dispSurface, producer,mRenderEngine->getEGLConfig(),
                                                  hasWideColorDisplay);
              hw->setLayerStack(state.layerStack);
              hw->setProjection(state.orientation,state.viewport, state.frame);
              hw->setDisplayName(state.displayName);
              .......
              mDisplays.add(display, hw);
              if (!state.isVirtualDisplay()) {
                  mEventThread->onHotplugReceived(state.type, true);
              }
         }
     }
}

???????先看一下兩個(gè)變量含義:
???????mCurrentState:SurfaceFlinger中最新的狀態(tài)染簇,包括所有的display和所有要繪制的Layer;
???????mDrawingState:SurfaceFlinger中當(dāng)前顯示的狀態(tài)强岸,包括所有的display和所有要繪制的Layer剖笙;
???????通過(guò) mCurrentState 和 mDrawingState 比較是否有增加的display,如果有增加的dislay并且是 VirtualDisplay请唱,首先會(huì)通過(guò) initVDSInstance 函數(shù)創(chuàng)建一個(gè) VirtualDisplaySurface封裝了producer弥咪、consumer以及surface,然后創(chuàng)建一個(gè) DisplayDevice并設(shè)置其 layerStack十绑,最后保存到 mDisplays 中進(jìn)行管理聚至,此時(shí)虛擬屏幕的 DisplayDevice創(chuàng)建好了。
???????在SurfaceFliner刷新所有的Layer到屏幕上顯示之前本橙,需要確定那些Layer應(yīng)該顯示到哪個(gè)屏幕上扳躬,以上邏輯是通過(guò)rebuildLayerStacks()來(lái)進(jìn)行實(shí)現(xiàn)的:

11.rebuildLayerStacks()

void SurfaceFlinger::rebuildLayerStacks() {
     ......
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
          Region opaqueRegion;
          Region dirtyRegion;
          Vector<sp<Layer>> layersSortedByZ;
          Vector<sp<Layer>> layersNeedingFences;
          const sp<DisplayDevice>& displayDevice(mDisplays[dpy]);
          const Transform& tr(displayDevice->getTransform());
          const Rect bounds(displayDevice->getBounds());
          if (displayDevice->isDisplayOn()) {
              computeVisibleRegions(displayDevice, dirtyRegion, opaqueRegion);
              mDrawingState.traverseInZOrder([&](Layer* layer) {
                 if (layer->belongsToDisplay(displayDevice->getLayerStack(),displayDevice->isPrimary())) {
                      ......................
                      layersSortedByZ.add(layer);
                      ...........
                    });
                }
                displayDevice->setVisibleLayersSortedByZ(layersSortedByZ);
                ......
        }
    }
}

bool belongsToDisplay(uint32_t layerStack, bool isPrimaryDisplay) const {
     return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay);
}

???????在該方法內(nèi)部會(huì)遍歷mDisplays來(lái)將要顯示的layer分配到對(duì)應(yīng)的displayDevice上,主要有以下幾個(gè)變量:
???????Layer:對(duì)應(yīng)WMS中的WindowState甚亭;
???????layersSortedByZ:保存Layer的Vector贷币;
???????displayDevice->getLayerStack():創(chuàng)建VirtualDisplayDevice時(shí)為VirtualDisplay分配的LayerStack;
???????belongsToDisplay():判斷Layer的layerStack是否和 displayDevice的LayerStack一致亏狰,如果一致是就把該Layer加入到layersSortedByZ中保存役纹;
???????最后把所有要顯示到該display上的Layer (layersSortedByZ) 保存到 displayDevice 中;
???????總結(jié)一下:前面創(chuàng)建的VirtualDisplay的layerStack 對(duì)應(yīng)就是主屏的layerStack暇唾,也就是說(shuō)促脉,此方法會(huì)把所有要顯示到主屏的layer全部都保存到VirtualDisplay 中辰斋,這樣VirtualDisplay就拿到了所有要顯示到主屏的內(nèi)容。
???????關(guān)于錄屏實(shí)現(xiàn)瘸味,可以參考文章Android 屏幕直播分享之MediaProjection和MediaCodec分析宫仗;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市旁仿,隨后出現(xiàn)的幾起案子藕夫,更是在濱河造成了極大的恐慌,老刑警劉巖枯冈,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件汁胆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡霜幼,警方通過(guò)查閱死者的電腦和手機(jī)嫩码,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)罪既,“玉大人铸题,你說(shuō)我怎么就攤上這事∽粮校” “怎么了丢间?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)驹针。 經(jīng)常有香客問(wèn)我烘挫,道長(zhǎng),這世上最難降的妖魔是什么柬甥? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任饮六,我火速辦了婚禮,結(jié)果婚禮上苛蒲,老公的妹妹穿的比我還像新娘卤橄。我一直安慰自己,他們只是感情好臂外,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布窟扑。 她就那樣靜靜地躺著,像睡著了一般漏健。 火紅的嫁衣襯著肌膚如雪嚎货。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天蔫浆,我揣著相機(jī)與錄音殖属,去河邊找鬼。 笑死克懊,一個(gè)胖子當(dāng)著我的面吹牛忱辅,可吹牛的內(nèi)容都是我干的七蜘。 我是一名探鬼主播谭溉,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼墙懂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了扮念?” 一聲冷哼從身側(cè)響起损搬,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎柜与,沒(méi)想到半個(gè)月后巧勤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡弄匕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年颅悉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迁匠。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡剩瓶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出城丧,到底是詐尸還是另有隱情延曙,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布亡哄,位于F島的核電站枝缔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蚊惯。R本人自食惡果不足惜愿卸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望截型。 院中可真熱鬧擦酌,春花似錦、人聲如沸菠劝。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)赶诊。三九已至笼平,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間舔痪,已是汗流浹背寓调。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锄码,地道東北人夺英。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓晌涕,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親痛悯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子余黎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容