Android 支持多個屏幕,主屏(主顯的物理屏),虛擬屏(非物理屏),外部顯示屏(折疊屏),其中主屏和外部顯示屏是實實在在的硬件物理屏,這兩者在SurfaceFlinger側的顯示流程相差不大,而VirtualDisplay雖然也是走的SurfaceFlinger流程,但數據源的方式有較大的不同,本文就分析下VirtualDisplay的數據源。
對VirtualDisplay框架層的分析可以看下這篇文章:http://www.lxweimin.com/p/c4ea60bc73d2
這里主要探索一下VirtualDisplay的數據源。
CreateDisplay
首先框架層會通過DMS來創建虛擬屏,通過jni調到SurfaceCompoerClient:: createDisplay,再通過binder調到SurfaceFlinger,看下SurfaceFlinger側:
文件:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName, bool secure) {
class DisplayToken : public BBinder {
sp<SurfaceFlinger> flinger;
virtual ~DisplayToken() {
// no more references, this display must be terminated
Mutex::Autolock _l(flinger->mStateLock);
flinger->mCurrentState.displays.removeItem(this);
flinger->setTransactionFlags(eDisplayTransactionNeeded);
}
public:
explicit DisplayToken(const sp<SurfaceFlinger>& flinger)
: flinger(flinger) {
}
};
// new了一個token ,這個是可以跨進程傳遞的對象
sp<BBinder> token = new DisplayToken(this);
Mutex::Autolock _l(mStateLock);
// Display ID is assigned when virtual display is allocated by HWC.
DisplayDeviceState state;
state.isSecure = secure;
state.displayName = displayName;
// 把display的狀態存放在mCurrentState
mCurrentState.displays.add(token, state);
mInterceptor->saveDisplayCreation(state);
return token;
}
CreateDisplay 的作用是創建了一個token返回給框架層,框架層通過這個token就能識別到這個display,然后存放到mCurrentState.displays 里面。
setDisplaySurface
WMS會通過這個接口給SurfaceFlinger傳一個Surface,這個Surface是創建VirtualDisplay的進程用來顯示內容的。要注意這個Surface與SurfaceFlinger不在同一個進程。
文件:frameworks/native/libs/gui/SurfaceComposerClient.cpp
status_t SurfaceComposerClient::Transaction::setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer) {
...
DisplayState& s(getDisplayState(token));
// 設置DisplayState的surface
s.surface = bufferProducer;
s.what |= DisplayState::eSurfaceChanged;
return NO_ERROR;
}
這個接口的主要作用就是設置surface給SurfaceFlinger,這個surface是個BufferQufferProducer對象,由vds所在的進程創建而成。
processDisplayAdded
有display發生變化時,transactionFlags 就會被置上eDisplayTransactionNeeded 這個flag,有新增加的display時,就會走processDisplayAdded這個邏輯,這個函數承載著主要的邏輯。
文件:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
const DisplayDeviceState& state) {
...
// 物理屏的邏輯,虛擬屏不走
if (state.physical) {
const auto& activeConfig =
getCompositionEngine().getHwComposer().getActiveConfig(state.physical->id);
width = activeConfig->getWidth();
height = activeConfig->getHeight();
pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888);
} else if (state.surface != nullptr) {
// 虛擬屏邏輯走這里,查詢傳進來的Surface的寬,高,格式
int status = state.surface->query(NATIVE_WINDOW_WIDTH, &width);
ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status);
status = state.surface->query(NATIVE_WINDOW_HEIGHT, &height);
ALOGE_IF(status != NO_ERROR, "Unable to query height (%d)", status);
int intPixelFormat;
status = state.surface->query(NATIVE_WINDOW_FORMAT, &intPixelFormat);
ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status);
pixelFormat = static_cast<ui::PixelFormat>(intPixelFormat);
...
} else {
// Virtual displays without a surface are dormant:
// they have external state (layer stack, projection,
// etc.) but no internal state (i.e. a DisplayDevice).
return;
}
compositionengine::DisplayCreationArgsBuilder builder;
if (const auto& physical = state.physical) {
// 如果是主屏則設置display id
builder.setPhysical({physical->id, physical->type});
}
// 設置display的屬性參數
builder.setPixels(ui::Size(width, height));
builder.setPixelFormat(pixelFormat);
builder.setIsSecure(state.isSecure);
builder.setLayerStackId(state.layerStack);
builder.setPowerAdvisor(&mPowerAdvisor);
// 設置是否支持使用HWC合成 VDS
builder.setUseHwcVirtualDisplays((mUseHwcVirtualDisplays && canAllocateHwcForVDS) ||
getHwComposer().isUsingVrComposer());
builder.setName(state.displayName);
// 創建compositionDisplay,這個函數的作用是創建對應的Output和Display
const auto compositionDisplay = getCompositionEngine().createDisplay(builder.build());
sp<compositionengine::DisplaySurface> displaySurface;
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferProducer> bqProducer;
sp<IGraphicBufferConsumer> bqConsumer;
// 創建一個BufferQueue,拿到對應的BufferQueueProducer和BufferQueueConsumer
getFactory().createBufferQueue(&bqProducer, &bqConsumer, /*consumerIsSurfaceFlinger =*/false);
std::optional<DisplayId> displayId = compositionDisplay->getId();
if (state.isVirtual()) {
// 創建VirtualDisplaySurface
sp<VirtualDisplaySurface> vds =
new VirtualDisplaySurface(getHwComposer(), displayId, state.surface,
bqProducer, bqConsumer, state.displayName,
state.isSecure);
// 將vds設置給displaySurface 和 producer
displaySurface = vds;
producer = vds;
} else {
// 主屏會創建FrameBufferSurface
...
}
// 創建nativeWindowSurface和displaydevice
const auto display = setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
displaySurface, producer);
mDisplays.emplace(displayToken, display);
...
}
(1) getCompositionEngine().createDisplay(builder.build()) 會創建相應的Output和 Display對象,對應的類序圖如下:
(2)new VirtualDisplaySurface,創建VDS,將surface作為 mSource[SOURCE_SINK]
文件:frameworks/native/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc,
const std::optional<DisplayId>& displayId,
const sp<IGraphicBufferProducer>& sink,
const sp<IGraphicBufferProducer>& bqProducer,
const sp<IGraphicBufferConsumer>& bqConsumer,
const std::string& name, bool secure)
: ConsumerBase(bqConsumer),
... {
// 將surface作為mSource[SOURCE_SINK], BufferQueueProducer作為mSource[SOURCE_SCRATCH]
mSource[SOURCE_SINK] = sink;
mSource[SOURCE_SCRATCH] = bqProducer;
resetPerFrameState();
int sinkWidth, sinkHeight;
// 查詢surface的寬高
sink->query(NATIVE_WINDOW_WIDTH, &sinkWidth);
sink->query(NATIVE_WINDOW_HEIGHT, &sinkHeight);
mSinkBufferWidth = sinkWidth;
mSinkBufferHeight = sinkHeight;
// 查詢和設置usage,format
int sinkUsage;
sink->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &sinkUsage);
mSinkUsage |= (GRALLOC_USAGE_HW_COMPOSER | sinkUsage);
setOutputUsage(mSinkUsage);
if (sinkUsage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
int sinkFormat;
sink->query(NATIVE_WINDOW_FORMAT, &sinkFormat);
mDefaultOutputFormat = sinkFormat;
} else {
mDefaultOutputFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
}
mOutputFormat = mDefaultOutputFormat;
// 設置BufferQueueConsumer的name,usage,BufferSize
ConsumerBase::mName = String8::format("VDS: %s", mDisplayName.c_str());
mConsumer->setConsumerName(ConsumerBase::mName);
mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight);
sink->setAsyncMode(true);
IGraphicBufferProducer::QueueBufferOutput output;
mSource[SOURCE_SCRATCH]->connect(nullptr, NATIVE_WINDOW_API_EGL, false, &output);
}
這一步最重要的就是將surface設置成了mSource[SOURCE_SINK]。
(3) setupNewDisplayDeviceInternal 這個函數創建了nativeWindowSurface和displaydevice
文件:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
const wp<IBinder>& displayToken,
std::shared_ptr<compositionengine::Display> compositionDisplay,
const DisplayDeviceState& state,
const sp<compositionengine::DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer) {
...
// 將producer作為參數創建一個NativeWindowSurface,這個producer就是vds
auto nativeWindowSurface = getFactory().createNativeWindowSurface(producer);
auto nativeWindow = nativeWindowSurface->getNativeWindow();
creationArgs.nativeWindow = nativeWindow;
// Make sure that composition can never be stalled by a virtual display
// consumer that isn't processing buffers fast enough. We have to do this
// here, in case the display is composed entirely by HWC.
if (state.isVirtual()) {
nativeWindow->setSwapInterval(nativeWindow.get(), 0);
}
...
這里重要的是將vds作為producer創建了Surface
文件:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
const wp<IBinder>& displayToken,
std::shared_ptr<compositionengine::Display> compositionDisplay,
const DisplayDeviceState& state,
const sp<compositionengine::DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer) {
...
// 虛擬屏一直設為power on
creationArgs.initialPowerMode = state.isVirtual() ? hal::PowerMode::ON : hal::PowerMode::OFF;
// 創建DisplayDevice
sp<DisplayDevice> display = getFactory().createDisplayDevice(creationArgs);
...
// 設置vds displaydevice的參數
display->setLayerStack(state.layerStack);
display->setProjection(state.orientation, state.viewport, state.frame);
display->setDisplayName(state.displayName);
}
文件:frameworks/native/services/surfaceflinger/DisplayDevice.cpp
DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args)
: mFlinger(args.flinger),
mDisplayToken(args.displayToken),
mSequenceId(args.sequenceId),
mConnectionType(args.connectionType),
mCompositionDisplay{args.compositionDisplay},
mPhysicalOrientation(args.physicalOrientation),
mIsPrimary(args.isPrimary) {
mCompositionDisplay->editState().isSecure = args.isSecure;
// 創建RenderSurface,將vds 和 windowSurface 作為參數傳進來
mCompositionDisplay->createRenderSurface(
compositionengine::RenderSurfaceCreationArgs{ANativeWindow_getWidth(
args.nativeWindow.get()),
ANativeWindow_getHeight(
args.nativeWindow.get()),
args.nativeWindow, args.displaySurface});
...
}
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
RenderSurface::RenderSurface(const CompositionEngine& compositionEngine, Display& display,
const RenderSurfaceCreationArgs& args)
: mCompositionEngine(compositionEngine),
mDisplay(display),
// mNativeWindow 為 surface對象 mDisplaySurface 為vds對象
mNativeWindow(args.nativeWindow),
mDisplaySurface(args.displaySurface),
mSize(args.displayWidth, args.displayHeight) {
LOG_ALWAYS_FATAL_IF(!mNativeWindow);
}
這一步最重要的就是創建了nativeWindowSurface和displaydevice對象,到這里初始化的流程就走完了。
數據源
vds創建后,跟著SurfaceFlinger主線程進行刷新,SurfaceFlinger refresh的幾個接口在“顯示框架之SurfaceFlinger Refresh流程”里面有分析,這個流程對于VDS沒差,但有些函數調用有差別,來看下:
Refresh主要執行的幾個函數:
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::present(const compositionengine::CompositionRefreshArgs& refreshArgs) {
ATRACE_CALL();
ALOGV(__FUNCTION__);
updateColorProfile(refreshArgs);
updateAndWriteCompositionState(refreshArgs);
setColorTransform(refreshArgs);
beginFrame();
prepareFrame();
devOptRepaintFlash(refreshArgs);
finishFrame(refreshArgs);
postFramebuffer();
}
beginFrame
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::beginFrame() {
...
mRenderSurface->beginFrame(mustRecompose);
if (mustRecompose) {
outputState.lastCompositionHadVisibleLayers = !empty;
}
}
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
status_t RenderSurface::beginFrame(bool mustRecompose) {
return mDisplaySurface->beginFrame(mustRecompose);
}
文件:frameworks/native/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) {
// 因為hwc暫不支持vds功能,故這里displayid為null,直接return
if (!mDisplayId) {
return NO_ERROR;
}
mMustRecompose = mustRecompose;
//For WFD use cases we must always set the recompose flag in order
//to support pause/resume functionality
if (mOutputUsage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
mMustRecompose = true;
}
VDS_LOGW_IF(mDbgState != DBG_STATE_IDLE,
"Unexpected beginFrame() in %s state", dbgStateStr());
mDbgState = DBG_STATE_BEGUN;
return refreshOutputBuffer();
}
注意這里因為hwc不支持vds,故displayid 為null,直接return,沒做什么事情。
prepareFrame
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::prepareFrame() {
ATRACE_CALL();
ALOGV(__FUNCTION__);
const auto& outputState = getState();
if (!outputState.isEnabled) {
return;
}
// 沒有hwcid,故直接走GPU合成
chooseCompositionStrategy();
mRenderSurface->prepareFrame(outputState.usesClientComposition,
outputState.usesDeviceComposition);
}
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
void RenderSurface::prepareFrame(bool usesClientComposition, bool usesDeviceComposition) {
DisplaySurface::CompositionType compositionType;
...
} else if (usesClientComposition) {
// 這里直接走GPU合成
compositionType = DisplaySurface::COMPOSITION_GPU;
...
if (status_t result = mDisplaySurface->prepareFrame(compositionType); result != NO_ERROR) {
ALOGE("updateCompositionType failed for %s: %d (%s)", mDisplay.getName().c_str(), result,
strerror(-result));
}
}
文件:frameworks/native/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) {
// 沒有Displayid 直接return
if (!mDisplayId) {
return NO_ERROR;
}
...
}
這個函數的作用就是判斷了vds的合成類型,因為hwc不支持的原因,所以目前走GPU合成。
finishFrame
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
void Output::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) {
...
// dequeueBuffer
auto optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs);
if (!optReadyFence) {
return;
}
// swap buffers (presentation)
mRenderSurface->queueBuffer(std::move(*optReadyFence));
}
std::optional<base::unique_fd> Output::composeSurfaces(
const Region& debugRegion, const compositionengine::CompositionRefreshArgs& refreshArgs) {
...
base::unique_fd fd;
sp<GraphicBuffer> buf;
// If we aren't doing client composition on this output, but do have a
// flipClientTarget request for this frame on this output, we still need to
// dequeue a buffer.
if (hasClientComposition || outputState.flipClientTarget) {
buf = mRenderSurface->dequeueBuffer(&fd);
if (buf == nullptr) {
ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
"client composition for this frame",
mName.c_str());
return {};
}
}
// GPU合成的邏輯
...
}
文件:frameworks/native/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
sp<GraphicBuffer> RenderSurface::dequeueBuffer(base::unique_fd* bufferFence) {
ATRACE_CALL();
int fd = -1;
ANativeWindowBuffer* buffer = nullptr;
// 主要的區別在這里,mNativeWindow 為Surface對象,調到Surface.cpp里面的dequeueBuffer,然后再調到VirtualDisplay的deququBuffer
status_t result = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fd);
if (result != NO_ERROR) {
ALOGE("ANativeWindow::dequeueBuffer failed for display [%s] with error: %d",
mDisplay.getName().c_str(), result);
// Return fast here as we can't do much more - any rendering we do
// now will just be wrong.
return mGraphicBuffer;
}
ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].",
mGraphicBuffer->getNativeBuffer()->handle);
mGraphicBuffer = GraphicBuffer::from(buffer);
*bufferFence = base::unique_fd(fd);
return mGraphicBuffer;
}
文件:frameworks/native/libs/gui/Surface.cpp
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
...
// 這里mGraphicBufferProducer 對象為VirtualDisplaySurface
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, reqWidth, reqHeight,
reqFormat, reqUsage, &mBufferAge,
enableFrameTimestamps ? &frameTimestamps
: nullptr);
...
}
文件:frameworks/native/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, uint32_t w, uint32_t h,
PixelFormat format, uint64_t usage,
uint64_t* outBufferAge,
FrameEventHistoryDelta* outTimestamps) {
if (!mDisplayId) {
// 這里執行的是mSource[SOURCE_SINK] 的dequeueBuffer,mSource[SOURCE_SINK] 實質上就是應用傳進來的surface
return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, w, h, format, usage, outBufferAge,
outTimestamps);
}
這里最重要的就是理解dequeueBuffer的執行對象是誰,RenderSurface::dequeueBuffer -> NativeWindow:: dequeueBuffer -> Surface::dequeueBuffer ->VirtualDisplaySurface:: dequeueBuffer-> sf對端進程的Surface::dequeueBuffer
同理,queueBuffer的執行對象跟dequeueBuffer一樣,RenderSurface::queueBuffer -> NativeWindow:: queueBuffer -> Surface::queueBuffer ->VirtualDisplaySurface:: queueBuffer-> sf對端進程的Surface::queueBuffer
可以看出來dequeueBuffer和queueBuffer都是在sf對端進程實現,從systrace也可以看到,這里SurfaceFlinger作為Client端,media.codec為Server端。
在 ”顯示框架之SurfaceFlinger GPU合成 “ 分析到dequeueBuffer出來的Buffer作為輸出的Buffer,輸入為當前layer的Buffer,可以理解為GPU將輸入的n塊Buffer合成輸出到1塊Buffer,具體流程可以看“顯示框架之SurfaceFlinger GPU合成” 的分析,可以看到其實數據源就是GPU合成的這塊Buffer, 交給media.codec去消費,這塊Buffer的acquire進程也是media.codec。
之后Buffer就給到media去處理了
總結:對于VDS,SurfaceFlinger是作為Client端,GPU合成的結果是數據源,所以虛擬屏顯示的內容和主屏是一樣的。