BufferQueue
前面結合應用中WindowSurfaceWrapper的,講解了應用怎麼和SurfaceFlinger建立連接,進行交互的。
BufferQueue 類是 Android 中所有圖形處理操作的核心。它的作用很簡單:將生成圖形數據緩衝區的一方(生產方)連接到接受數據以進行顯示或進一步處理的一方(消耗方)。幾乎所有在系統中移動圖形數據緩衝區的內容都依賴於 BufferQueue。
現在,我們添加一個空的drawNativeWindow實現,先將我們的應用跑起來吧。
int drawNativeWindow(sp<WindowSurfaceWrapper> /* windowSurface */) {
return NO_ERROR;
}
int main(int argc, char *argv[]) {
unsigned samples = 0;
printf("usage: %s [samples]\n", argv[0]);
if (argc == 2) {
samples = atoi( argv[1] );
printf("Multisample enabled: GL_SAMPLES = %u\n", samples);
}
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
sp<WindowSurfaceWrapper> windowSurface(new WindowSurfaceWrapper(String8("NativeBinApp")));
drawNativeWindow(windowSurface);
IPCThreadState::self()->joinThreadPool();
return EXIT_SUCCESS;
}
Android.bp如下:
cc_binary {
name: "NativeApp",
srcs: [
"NativeApp.cpp",
"WindowSurfaceWrapper.cpp",
],
shared_libs: [
"liblog",
"libbinder",
"libui",
"libgui",
"libutils",
],
init_rc: ["NativeApp.rc"],
}
NativeApp.rc文件如下:
service NativeApp /system/bin/NativeApp
class core
oneshot
將應用push到系統的bin目錄下就可以運行了:
adb push out/target/product/generic/system/bin/NativeApp /vendor/bin/
運行應用:
adb shell NativeBin
很遺憾的是,我們在手機屏幕上是看不是任何東西的。Why?因爲沒有畫任何東西。但是,我們dump SurfaceFlinger的時候,還是能夠看到我們創建的應用窗口的,只是沒有內容,SurfaceFlinger不顯示,即使去顯示,也看不到。
adb shell dumpsys SurfaceFlinger
我們創建應用Layer時,名字爲“NativeBinApp”,下面就是我們dump出來的Layer的信息:
+ Layer 0x7b3ba66000 (NativeBinApp#0)
Region transparentRegion (this=0x7b3ba66380, count=1)
[ 0, 0, 0, 0]
Region visibleRegion (this=0x7b3ba66010, count=1)
[ 0, 0, 0, 0]
Region surfaceDamageRegion (this=0x7b3ba66088, count=1)
[ 0, 0, 0, 0]
layerStack= 0, z=2147483647, pos=(0,0), size=( 720,1280), crop=( 0, 0, -1, -1), finalCrop=( 0, 0, -1, -1), isOpaque=0, invalidate=0, dataspace=Default (0), pixelformat=Unknown/None alpha=1.000, flags=0x00000002, tr=[1.00, 0.00][0.00, 1.00]
client=0x7b4002d0c0
format= 2, activeBuffer=[ 0x 0: 0, 0], queued-frames=0, mRefreshPending=0
mTexName=7 mCurrentTexture=-1
mCurrentCrop=[0,0,0,0] mCurrentTransform=0
mAbandoned=0
- BufferQueue mMaxAcquiredBufferCount=1 mMaxDequeuedBufferCount=2
mDequeueBufferCannotBlock=0 mAsyncMode=0
default-size=[720x1280] default-format=2 transform-hint=00 frame-counter=0
FIFO(0):
Slots:
[00:0x0] state=FREE
[01:0x0] state=FREE
[02:0x0] state=FREE
我們已經創建了窗口,但是界面沒有內容顯示,我們先完善我們的應用,在窗口中顯示點內容吧~
Native應用繪製界面
下面是drawNativeWindow窗口的對應的代碼,關鍵的步驟的用序號標出來了~
int drawNativeWindow(sp<WindowSurfaceWrapper> windowSurface) {
status_t err = NO_ERROR;
ANativeWindowBuffer *aNativeBuffer = nullptr;
sp<SurfaceControl> surfaceControl = windowSurface->getSurfaceControl();
ANativeWindow* aNativeWindow = surfaceControl->getSurface().get();
// 1. We need to reconnect to the ANativeWindow as a CPU client to ensure that no frames
// get dropped by SurfaceFlinger assuming that these are other frames.
err = native_window_api_disconnect(aNativeWindow, NATIVE_WINDOW_API_CPU);
if (err != NO_ERROR) {
ALOGE("ERROR: unable to native_window_api_disconnect ignore...\n");
}
// 2. connect the ANativeWindow as a CPU client
err = native_window_api_connect(aNativeWindow, NATIVE_WINDOW_API_CPU);
if (err != NO_ERROR) {
ALOGE("ERROR: unable to native_window_api_connect\n");
return EXIT_FAILURE;
}
// 3. set the ANativeWindow dimensions
err = native_window_set_buffers_user_dimensions(aNativeWindow, windowSurface->width(), windowSurface->height());
if (err != NO_ERROR) {
ALOGE("ERROR: unable to native_window_set_buffers_user_dimensions\n");
return EXIT_FAILURE;
}
// 4. set the ANativeWindow format
int format = PIXEL_FORMAT_RGBX_8888;
err = native_window_set_buffers_format(aNativeWindow,format );
if (err != NO_ERROR) {
ALOGE("ERROR: unable to native_window_set_buffers_format\n");
return EXIT_FAILURE;
}
// 5. set the ANativeWindow transform
int rotation = 0;
int transform = 0;
if ((rotation % 90) == 0) {
switch ((rotation / 90) & 3) {
case 1: transform = HAL_TRANSFORM_ROT_90; break;
case 2: transform = HAL_TRANSFORM_ROT_180; break;
case 3: transform = HAL_TRANSFORM_ROT_270; break;
default: transform = 0; break;
}
}
err = native_window_set_buffers_transform(aNativeWindow, transform);
if (err != NO_ERROR) {
ALOGE("native_window_set_buffers_transform failed: %s (%d)", strerror(-err), -err);
return err;
}
// 6. handle the ANativeWindow usage
int consumerUsage = 0;
err = aNativeWindow->query(aNativeWindow, NATIVE_WINDOW_CONSUMER_USAGE_BITS, &consumerUsage);
if (err != NO_ERROR) {
ALOGE("failed to get consumer usage bits. ignoring");
err = NO_ERROR;
}
// Make sure to check whether either requested protected buffers.
int usage = GRALLOC_USAGE_SW_WRITE_OFTEN;
if (usage & GRALLOC_USAGE_PROTECTED) {
// Check if the ANativeWindow sends images directly to SurfaceFlinger.
int queuesToNativeWindow = 0;
err = aNativeWindow->query(
aNativeWindow, NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &queuesToNativeWindow);
if (err != NO_ERROR) {
ALOGE("error authenticating native window: %s (%d)", strerror(-err), -err);
return err;
}
// Check if the consumer end of the ANativeWindow can handle protected content.
int isConsumerProtected = 0;
err = aNativeWindow->query(
aNativeWindow, NATIVE_WINDOW_CONSUMER_IS_PROTECTED, &isConsumerProtected);
if (err != NO_ERROR) {
ALOGE("error query native window: %s (%d)", strerror(-err), -err);
return err;
}
// Deny queuing into native window if neither condition is satisfied.
if (queuesToNativeWindow != 1 && isConsumerProtected != 1) {
ALOGE("native window cannot handle protected buffers: the consumer should either be "
"a hardware composer or support hardware protection");
return PERMISSION_DENIED;
}
}
// 7. set the ANativeWindow usage
int finalUsage = usage | consumerUsage;
ALOGE("gralloc usage: %#x(producer) + %#x(consumer) = %#x", usage, consumerUsage, finalUsage);
err = native_window_set_usage(aNativeWindow, finalUsage);
if (err != NO_ERROR) {
ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
return err;
}
// 8. set the ANativeWindow scale mode
err = native_window_set_scaling_mode(
aNativeWindow, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
if (err != NO_ERROR) {
ALOGE("native_window_set_scaling_mode failed: %s (%d)", strerror(-err), -err);
return err;
}
ALOGE("set up nativeWindow %p for %dx%d, color %#x, rotation %d, usage %#x",
aNativeWindow, windowSurface->width(), windowSurface->height(), format, rotation, finalUsage);
// 9. set the ANativeWindow permission to allocte new buffer, default is true
static_cast<Surface*>(aNativeWindow)->getIGraphicBufferProducer()->allowAllocation(true);
// 10. set the ANativeWindow buffer count
int numBufs = 0;
int minUndequeuedBufs = 0;
err = aNativeWindow->query(aNativeWindow,
NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
"failed: %s (%d)", strerror(-err), -err);
goto handle_error;
}
numBufs = minUndequeuedBufs + 1;
err = native_window_set_buffer_count(aNativeWindow, numBufs);
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)", strerror(-err), -err);
goto handle_error;
}
// 11. draw the ANativeWindow
for (int i = 0; i < numBufs + 1; i++) {
// 12. dequeue a buffer
int hwcFD= -1;
err = aNativeWindow->dequeueBuffer(aNativeWindow, &aNativeBuffer, &hwcFD);
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
strerror(-err), -err);
break;
}
// 13. make sure really control the dequeued buffer
sp<Fence> hwcFence(new Fence(hwcFD));
int waitResult = hwcFence->waitForever("dequeueBuffer_EmptyNative");
if (waitResult != OK) {
ALOGE("dequeueBuffer_EmptyNative: Fence::wait returned an error: %d", waitResult);
break;
}
sp<GraphicBuffer> buf(GraphicBuffer::from(aNativeBuffer));
// 14. Fill the buffer with black
uint8_t *img = NULL;
err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: lock failed: %s (%d)", strerror(-err), -err);
break;
}
//15. Draw the window, here we fill the window with black.
*img = 0;
err = buf->unlock();
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: unlock failed: %s (%d)", strerror(-err), -err);
break;
}
// 16. queue the buffer to display
int gpuFD = -1;
err = aNativeWindow->queueBuffer(aNativeWindow, buf->getNativeBuffer(), gpuFD);
if (err != NO_ERROR) {
ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)", strerror(-err), -err);
break;
}
aNativeBuffer = NULL;
}
handle_error:
// 17. cancel buffer
if (aNativeBuffer != NULL) {
aNativeWindow->cancelBuffer(aNativeWindow, aNativeBuffer, -1);
aNativeBuffer = NULL;
}
// 18. Clean up after success or error.
status_t err2 = native_window_api_disconnect(aNativeWindow, NATIVE_WINDOW_API_CPU);
if (err2 != NO_ERROR) {
ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", strerror(-err2), -err2);
if (err == NO_ERROR) {
err = err2;
}
}
return err;
}
關鍵步驟如下:
0. 獲取我們已經創建的Layer的窗口ANativeWindow
- 斷掉之前的BufferQueue連接native_window_api_disconnect,這一步是可選的
- 連接Window到BufferQueue native_window_api_connect
- 設置Buffer的大小尺寸native_window_set_buffers_user_dimensions,可選
- 設置Buffer格式,可選,之前創建Layer的時候已經設置了。
- 設置Buffer的transform
- 處理Buffer的usage,主要的DRM內容的處理
- 設置Buffer的usage,usage由producer的usage和Consumer的usage組成
- 設置scale模式,如果上層給的數據,比如Video,超出Buffer的大小後,怎麼處理,是截取一部分還是,縮小。
- 設置permission,設置Buffer,默認true,可選。
- 設置Buffer數量,就是,BufferQueue中有多少個buffer可以用,可選
- 繪製窗口,窗口有一個buffer隊列,對每一個buffer都需要繪製。
- dequeueBuffer先拿到一塊可用的Buffer,也就是FREE的Buffer。
- Buffer雖然是Free的,但是在異步模式下,Buffer不可能還在使用中,需要等到Fence才能確保buffer沒有在被使用
- 往Free的Buffer裏面繪製東西,
- 我們這裏直接顯示全黑,*img = 0
- 將繪製好的Buffer,queue到Buffer隊列中,queueBuffer。
- 錯誤處理,取消掉Buffer,cancelBuffer
- 斷開BufferQueue和窗口的連接,native_window_api_disconnect
OK~再編譯執行一下,屏幕是不是黑了?
Dumps一下SurfaceFlinger,我們的應用窗口信息如下:
+ Layer 0x7b3ba61000 (NativeBinApp#0)
Region transparentRegion (this=0x7b3ba61380, count=1)
[ 0, 0, 0, 0]
Region visibleRegion (this=0x7b3ba61010, count=1)
[ 0, 0, 720, 1280]
Region surfaceDamageRegion (this=0x7b3ba61088, count=1)
[ 0, 0, -1, -1]
layerStack= 0, z=2147483647, pos=(0,0), size=( 720,1280), crop=( 0, 0, -1, -1), finalCrop=( 0, 0, -1, -1), isOpaque=1, invalidate=0, dataspace=Default (0), pixelformat=RGBx_8888 alpha=1.000, flags=0x00000002, tr=[1.00, 0.00][0.00, 1.00]
client=0x7b4002d6c0
format= 2, activeBuffer=[ 720x1280: 720, 2], queued-frames=0, mRefreshPending=0
mTexName=2 mCurrentTexture=1
mCurrentCrop=[0,0,0,0] mCurrentTransform=0
mAbandoned=0
- BufferQueue mMaxAcquiredBufferCount=1 mMaxDequeuedBufferCount=1
mDequeueBufferCannotBlock=0 mAsyncMode=0
default-size=[720x1280] default-format=2 transform-hint=00 frame-counter=3
FIFO(0):
Slots:
[01:0x0] state=FREE
[02:0x0] state=FREE
對比看一下,和前面的dump信息有什麼不一樣?
另外,如果我們將原來的*img = 0替換掉,可以繪製其他一些東西。fillWithCheckerboard可以將屏幕填充爲小方塊。
fillWithCheckerboard(img, windowSurface->width(), windowSurface->height(), buf->getStride());
void fillWithCheckerboard(uint8_t* img, int width, int height, int stride) {
bool change = false;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
uint8_t* pixel = img + (4 * (y*stride + x));
if ( x % 10 == 0) {
change = !change;
}
if(change) {
pixel[0] = 255;
pixel[1] = 255;
pixel[2] = 255;
} else {
pixel[0] = 0;
pixel[1] = 0;
pixel[2] = 0;
}
pixel[3] = 0;
}
if ( y % 10 == 0) {
change = !change;
}
}
}
繪製應用,我們這裏直接用的API,這些API是怎麼工作的,數據怎麼送給顯示的?接下里,我們將具體分析。
SurfaceFlinger創建Layer
上一章講到,應用創建Layer時,流程只跟到SurfaceFlinger,SurfaceFlinger是怎麼窗口Layer的,和 Layer和BufferQueue又是怎麼關聯的,我們接着就來看看。
Layer分兩種類型:
- bNormal Layer,普通Layer,由createBufferLayer創建,由BufferLayer類描述。
- Coler Layer,由createColorLayer創建,由ColorLayer類描述。
Layer相關類的關係如下:
- BufferLayer和ColorLayer繼承Layer類
- Layer類,有LayerBE的一個實例
- BufferLayer實現ContentsChangedListener和FrameAvailableListener兩個接口類,主要是監聽顯示內容的改變。
ColorLayer比較 簡單,我們先來看BufferLayer。reateBufferLayer實現如下:
status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
{
... ...
sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags);
status_t err = layer->setBuffers(w, h, format, flags);
if (err == NO_ERROR) {
*handle = layer->getHandle();
*gbp = layer->getProducer();
*outLayer = layer;
}
ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err));
return err;
}
createBufferLayer時,創建一個BufferLayer。
BufferLayer的構造函數如下:
BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
uint32_t w, uint32_t h, uint32_t flags)
: Layer(flinger, client, name, w, h, flags),
mConsumer(nullptr),
mTextureName(UINT32_MAX),
mFormat(PIXEL_FORMAT_NONE),
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mBufferLatched(false),
mPreviousFrameNumber(0),
mUpdateTexImageFailed(false),
mRefreshPending(false) {
ALOGV("Creating Layer %s", name.string());
mFlinger->getRenderEngine().genTextures(1, &mTextureName);
mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);
if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false;
mCurrentState.requested = mCurrentState.active;
// drawing state & current state are identical
mDrawingState = mCurrentState;
}
在LayerBuffer的構造函數中,主要是初始化了一個mTextureName,已經一些狀態的初始化;以及調用Layer的構造函數。
Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
uint32_t h, uint32_t flags)
: contentDirty(false),
sequence(uint32_t(android_atomic_inc(&sSequence))),
mFlinger(flinger),
mPremultipliedAlpha(true),
mName(name),
mTransactionFlags(0),
mPendingStateMutex(),
mPendingStates(),
mQueuedFrames(0),
mSidebandStreamChanged(false),
mActiveBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
mCurrentTransform(0),
mOverrideScalingMode(-1),
mCurrentOpacity(true),
mCurrentFrameNumber(0),
mFrameLatencyNeeded(false),
mFiltering(false),
mNeedsFiltering(false),
mProtectedByApp(false),
mClientRef(client),
mPotentialCursor(false),
mQueueItemLock(),
mQueueItemCondition(),
mQueueItems(),
mLastFrameNumberReceived(0),
mAutoRefresh(false),
mFreezeGeometryUpdates(false) {
mCurrentCrop.makeInvalid();
uint32_t layerFlags = 0;
if (flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden;
if (flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque;
if (flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure;
mName = name;
mTransactionName = String8("TX - ") + mName;
mCurrentState.active.w = w;
... ... init mCurrentState
mCurrentState.type = 0;
// drawing state & current state are identical
mDrawingState = mCurrentState;
const auto& hwc = flinger->getHwComposer();
const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY);
nsecs_t displayPeriod = activeConfig->getVsyncPeriod();
mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
CompositorTiming compositorTiming;
flinger->getCompositorTiming(&compositorTiming);
mFrameEventHistory.initializeCompositorTiming(compositorTiming);
}
Layerd的構造函數中,主要做一些變量的初始化,以及mCurrentState的初始化。
BufferLayer和Layer都是繼承RefBase的,還要一個地方做初始化,那就是onFirstRef。
Layer的onFirstRef是空的:
void Layer::onFirstRef() {}
BufferLayer的onFirstRef則做了很多操作。在這裏我們就看到Producer和Consumer出場了。
void BufferLayer::onFirstRef() {
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer, true);
mProducer = new MonitoredProducer(producer, mFlinger, this);
mConsumer = new BufferLayerConsumer(consumer,
mFlinger->getRenderEngine(), mTextureName, this);
mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
mConsumer->setContentsChangedListener(this);
mConsumer->setName(mName);
if (mFlinger->isLayerTripleBufferingDisabled()) {
mProducer->setMaxDequeuedBufferCount(2);
}
const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
updateTransformHint(hw);
}
BufferLayer,通過BufferQueue的createBufferQueue,創建了一個buffer隊列,一個buffer隊列,有一個生產者producer,和一個消費者consumer。
createBufferQueue實現如下:
void BufferQueue::createBufferQueue(sp* outProducer,
sp* outConsumer,
bool consumerIsSurfaceFlinger) {
… …
sp<BufferQueueCore> core(new BufferQueueCore());
LOG_ALWAYS_FATAL_IF(core == NULL,
"BufferQueue: failed to create BufferQueueCore");
sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
LOG_ALWAYS_FATAL_IF(producer == NULL,
"BufferQueue: failed to create BufferQueueProducer");
sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
LOG_ALWAYS_FATAL_IF(consumer == NULL,
"BufferQueue: failed to create BufferQueueConsumer");
*outProducer = producer;
*outConsumer = consumer;
}
- 首先創建了一個BufferQueueCore,這個是BufferQueue的核心。
- 然後創建了一個BufferQueueProducer和一個BufferQueueConsumer,注意Producer和Consumer都持有BufferQueueCore的引用。
BufferQueue創建完後,BufferLayer,又對BufferQueueCore中的Producer和Consume進行封裝。分別創建了MonitoredProducer和BufferLayerConsumer。
最後,再對創建的mConsumer和mProducer進行初始化。
mConsumer這邊主要有:
- setConsumerUsageBits,設置Consumer的usage
- setContentsChangedListener,這種內容改變的監聽,注意這裏傳的是this指針,因爲BufferLayer實現了兩個接口,還記得不?
- setName,設置Consumer 名
mProducer這邊主要有
- setMaxDequeuedBufferCount
根據系統的屬性,設置Producer最多可以申請多少個Buffer,默認是3個;如果配置了屬性ro.sf.disable_triple_buffer
爲true,那就只能用2個。
這個是在SurfaceFlinger初始化時,在SurfaceFlinger的構造函數中決定的。
property_get("ro.sf.disable_triple_buffer", value, "1");
mLayerTripleBufferingDisabled = atoi(value);
ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering");
我們來看看Layer和BufferQueue之間的關係~
解釋一下:
- 一個Layer對應一個BufferQueue,一個BufferQueue中有多個Buffer,一般是2個或者3個。
- 一個Layer有一個Producer,一個Consumer
- 結合前面的分析,一個Surface和一個Layer也是一一對應的,和窗口也是一一對應的。
可見,BufferQueue就是兩個連接紐帶,連接着Producer和Consumer。接下來,我們就來分別看一下Producer和Consumer。
MonitoredProducer是對BufferQueueProducer的封裝,其目的,就是Producer銷燬時,能通知SurfaceFlinger。這就是取名Monitored的願意。餘下的,MonitoredProducer的很多接口都是直接調,對應的BufferQueueProducer的實現。
銷燬監聽,就是在MonitoredProducer析構函數中,post一個消息到SurfaceFlinger的主線程中。通知SurFaceFlinger Producer已經銷燬,SurfaceFlinger 會將銷燬的Producer從mGraphicBufferProducerList中刪掉。代碼如下:
MonitoredProducer::~MonitoredProducer() {
// Remove ourselves from SurfaceFlinger's list. We do this asynchronously
// because we don't know where this destructor is called from. It could be
// called with the mStateLock held, leading to a dead-lock (it actually
// happens).
class MessageCleanUpList : public MessageBase {
public:
MessageCleanUpList(const sp<SurfaceFlinger>& flinger,
const wp<IBinder>& producer)
: mFlinger(flinger), mProducer(producer) {}
virtual ~MessageCleanUpList() {}
virtual bool handler() {
Mutex::Autolock _l(mFlinger->mStateLock);
mFlinger->mGraphicBufferProducerList.remove(mProducer);
return true;
}
private:
sp<SurfaceFlinger> mFlinger;
wp<IBinder> mProducer;
};
mFlinger->postMessageAsync(new MessageCleanUpList(mFlinger, asBinder(mProducer)));
}
BufferQueueProducer就是Producer真是實現的地方了。前面我們的應用代碼中,要繪製一個窗口,有很多個步驟,而每一步的實現,基本都在BufferQueueProducer中。
BufferQueueProducer的類圖如下:
其中,dequeueBuffer和queueBuffer是兩個非常重要的函數。我們的應用中,是不是通過ANativeWindow的dequeueBuffer函數,獲取到一個Buffer,再通過ANativeWindow的queueBuffer,送到顯示這邊的。具體過程我們稍後我講解。
再來看Consumer,BufferLayerConsumer繼承ConsumerBase。BufferLayerConsumer的構造函數中,主要是一些變量的初始化,主要是ConsumerBase的構造函數:
* frameworks/native/libs/gui/ConsumerBase.cpp
ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
mAbandoned(false),
mConsumer(bufferQueue),
mPrevFinalReleaseFence(Fence::NO_FENCE) {
// Choose a name using the PID and a process-unique ID.
mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
// Note that we can't create an sp<...>(this) in a ctor that will not keep a
// reference once the ctor ends, as that would cause the refcount of 'this'
// dropping to 0 at the end of the ctor. Since all we need is a wp<...>
// that's what we create.
wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
if (err != NO_ERROR) {
CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
strerror(-err), err);
} else {
mConsumer->setConsumerName(mName);
}
}
在ConsumerBase的構造函數中,給BufferQueue設置了監聽,這樣Consumer和BufferQueue,就算是連上了。
注意這裏的Listener。BufferLayer是實現了BufferLayerConsumer的ContentsChangedListener,在BufferLayer的onFirstRef中,這個Listener被設置給了BufferLayerConsumer。
mConsumer->setContentsChangedListener(this);
BufferLayerConsumer的setContentsChangedListener函數如下:
void BufferLayerConsumer::setContentsChangedListener(const wp<ContentsChangedListener>& listener) {
setFrameAvailableListener(listener);
Mutex::Autolock lock(mMutex);
mContentsChangedListener = listener;
}
可見,在setFrameAvailableListener函數中,BufferLayer的Listener實現被賦值給了mFrameAvailableListener。同時調用setFrameAvailableListener
setFrameAvailableListener的實現在父類ConsumerBase中。
void ConsumerBase::setFrameAvailableListener(
const wp<FrameAvailableListener>& listener) {
CB_LOGV("setFrameAvailableListener");
Mutex::Autolock lock(mFrameAvailableMutex);
mFrameAvailableListener = listener;
}
此時,又被賦值給了mFrameAvailableListener,注意,這裏的mFrameAvailableListener是BufferLayer中實現的Listener。
ConsumerBase自身實現ConsumerListener,中構造的Listener,通過代理ProxyConsumerListener,在connect時傳給了BufferQueueConsumer。
* frameworks/native/libs/gui/BufferQueueConsumer.cpp
status_t BufferQueueConsumer::connect(
const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
ATRACE_CALL();
if (consumerListener == NULL) {
BQ_LOGE("connect: consumerListener may not be NULL");
return BAD_VALUE;
}
BQ_LOGV("connect: controlledByApp=%s",
controlledByApp ? "true" : "false");
Mutex::Autolock lock(mCore->mMutex);
if (mCore->mIsAbandoned) {
BQ_LOGE("connect: BufferQueue has been abandoned");
return NO_INIT;
}
mCore->mConsumerListener = consumerListener;
mCore->mConsumerControlledByApp = controlledByApp;
return NO_ERROR;
}
看明白了吧?BufferLayer實現的ContentsChangedListener被保存在ConsumerBase中mFrameAvailableListener。而ConsumerBase實現的ConsumerListener,被傳到BufferQueueConsumer,保存在BufferQueueCore的mConsumerListener中。
所以,Listener的通知路線應該是這樣的~
- Producer生產完後,會通過BufferQueueCore中的mConsumerListener通知ConsumerBase
- ConsumerBase,接受到BufferQueueConsumer的通知,再通過BufferLayer傳下來的信使mFrameAvailableListener,通知BufferLayer。
- BufferLayer接受到通知後,就可以去消費生產完的Buffer了。
到此,Consumer這邊準備就緒了,就等着Producer去生產了。注意一點,在分析應用創建Layer時,會得到一個IGraphicBufferProducer,這個就是對應BufferLayer
sp<SurfaceControl> SurfaceComposerClient::createSurface(
... ...
sp<IGraphicBufferProducer> gbp;
if (parent != nullptr) {
parentHandle = parent->getHandle();
}
status_t err = mClient->createSurface(name, w, h, format, flags, parentHandle,
windowType, ownerUid, &handle, &gbp);
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
sur = new SurfaceControl(this, handle, gbp);
}
}
return sur;
}
讓我們回到我們的應用代碼~
Native窗口
在應用代碼中,我們已經用到幾個關鍵的類,Surface和SurfaceControl,ANativeWindow和ANativeWindowBuffer;他們又是什麼的關係呢,怎麼和BufferQueue產生聯繫的呢?
ANativeWindow
ANativeWindow是Native對一個窗口的描述,和Surface是對等的,Why?可以通過接口ANativeWindow_fromSurface()將Surface轉換爲ANativeWindow。而事實也ANativeWindow是對BufferQueue的Producer端進行一個封裝。
ANativeWindow的定義如下,英文的註釋很詳細
* frameworks/native/libs/nativewindow/include/system/window.h
struct ANativeWindow
{
#ifdef __cplusplus
ANativeWindow()
: flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
{
common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
common.version = sizeof(ANativeWindow);
memset(common.reserved, 0, sizeof(common.reserved));
}
/* Implement the methods that sp<ANativeWindow> expects so that it
can be used to automatically refcount ANativeWindow's. */
void incStrong(const void* /*id*/) const {
common.incRef(const_cast<android_native_base_t*>(&common));
}
void decStrong(const void* /*id*/) const {
common.decRef(const_cast<android_native_base_t*>(&common));
}
#endif
// 相當於從android_native_base_t繼承
struct android_native_base_t common;
/* flags describing some attributes of this surface or its updater */
const uint32_t flags;
/* min swap interval supported by this updated */
const int minSwapInterval;
/* max swap interval supported by this updated */
const int maxSwapInterval;
/* horizontal and vertical resolution in DPI */
const float xdpi;
const float ydpi;
/* Some storage reserved for the OEM's driver. */
intptr_t oem[4];
// 設置swap的間隔,也就是設置Producer是同步還是異步
int (*setSwapInterval)(struct ANativeWindow* window,
int interval);
// dequeue一塊buffer,執行後,buffer就不是locked狀態,內容不能修改
// 這裏會造成block,引起ANR等如果沒有空閒Buffer
// 這個方法現象不建議使用,現在直接使用下面的dequeueBuffer方法
int (*dequeueBuffer_DEPRECATED)(struct ANativeWindow* window,
struct ANativeWindowBuffer** buffer);
// 在修改Buffer的內容前,先鎖住這個Buffer
int (*lockBuffer_DEPRECATED)(struct ANativeWindow* window,
struct ANativeWindowBuffer* buffer);
// 修改完後,通過此方法將buffer送輸出,這個Buffer也沒有在用了。
int (*queueBuffer_DEPRECATED)(struct ANativeWindow* window,
struct ANativeWindowBuffer* buffer);
// 獲取我們需要的值
int (*query)(const struct ANativeWindow* window,
int what, int* value);
// 執行對應的操縱
int (*perform)(struct ANativeWindow* window,
int operation, ... );
// 取消掉一個已經被deueue出來的值
int (*cancelBuffer_DEPRECATED)(struct ANativeWindow* window,
struct ANativeWindowBuffer* buffer);
// dequeueBuffer_DEPRECATED的新版本,使用者自己處理Fence
int (*dequeueBuffer)(struct ANativeWindow* window,
struct ANativeWindowBuffer** buffer, int* fenceFd);
// queueBuffer_DEPRECATED的新版本
int (*queueBuffer)(struct ANativeWindow* window,
struct ANativeWindowBuffer* buffer, int fenceFd);
// cancelBuffer_DEPRECATED的新版本,必須要和dequeue在同一個線程中
int (*cancelBuffer)(struct ANativeWindow* window,
struct ANativeWindowBuffer* buffer, int fenceFd);
};
此外,window.h頭文件中還提供了很多類型native_window_**的API,這些API就是通過ANativeWindow的perform函數調下去的。API很多,這裏就不一一介紹了,前面我們的應用代碼中已經使用了不少。
爲什麼說ANativeWindow和Surface是對等的?我們來看看Surface
Surface
Surface也是BufferQueue在Producer端的封裝,每個窗口都有且只有一個自己的Surface(同一時刻)。爲什麼說ANativeWindow和Surface是對等的,實際上Surface繼承ANativeWindow。
* frameworks/native/libs/gui/include/gui/Surface.h
class Surface
: public ANativeObjectBase<ANativeWindow, Surface, RefBase>
ANativeWindow是一個模板類,主要是將類似ANativeWindow這樣的類型,轉換爲引用計數控制的類型,實現對象的自動釋放。
template <typename NATIVE_TYPE, typename TYPE, typename REF,
typename NATIVE_BASE = android_native_base_t>
class ANativeObjectBase : public NATIVE_TYPE, public REF
{
Surface的代碼比較多,這裏就不貼代碼了。但是整體而言,主要如下:
- ANativeWindow的hooks函數,命名爲hook_***,總共10個hook函數,如hook_perform,hook_dequeueBuffer等
- window.h頭文件中定義的API的分發,命名爲dispatch***,總共29個,如dispatchConnect,dispatchSetCrop等
- Surface對hook函數和dispatch函數的具體實現,這些給函數就和BufferQueue交互。
- 窗口,Buffer的很多描述的屬性定義在Surface中。
Surface的實現在:
* frameworks/native/libs/gui/Surface.cpp
在構造函數中,主要是變量的初始化,和ANativeWindow的函數的初始化,將hook函數直接賦值給ANativeWindow對應的函數。
根據我們應用的代碼,我們來看看具有代表行的一兩個流程,就看native_window_set_buffers_format。
* frameworks/native/libs/nativewindow/include/system/window.h
static inline int native_window_set_buffers_format(
struct ANativeWindow* window,
int format)
{
return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_FORMAT, format);
}
native_window_api_connect 調的是 ANativeWindow 的 perform 函數,而perform的類型爲 NATIVE_WINDOW_SET_BUFFERS_FORMAT。
perform函數是Surface中實現的:
* frameworks/native/libs/gui/Surface.cpp
int Surface::perform(int operation, va_list args)
{
int res = NO_ERROR;
switch (operation) {
... ...
case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
res = dispatchSetBuffersFormat(args);
break;
... ...
}
dispatch函數爲dispatchSetBuffersFormat
int Surface::dispatchSetBuffersFormat(va_list args) {
PixelFormat format = va_arg(args, PixelFormat);
return setBuffersFormat(format);
}
Surface的實現爲:
int Surface::setBuffersFormat(PixelFormat format)
{
ALOGV("Surface::setBuffersFormat");
Mutex::Autolock lock(mMutex);
if (format != mReqFormat) {
mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
}
mReqFormat = format;
return NO_ERROR;
}
設置的Buffer格式被賦值給了mReqFormat。
以此類推,window.h 頭文件中的API,都會設置一個類型,然後通過perform函數,調到Surface中的具體實現。
hook的函數也是類似的,我們以ANativeWindow的dequeueBuffer爲例,ANativeWindow的dequeueBuffer函數,直接被賦值爲Surface的dequeueBuffer。
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
... ...
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, reqWidth, reqHeight,
reqFormat, reqUsage, &mBufferAge,
enableFrameTimestamps ? &frameTimestamps
: nullptr);
... ...
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
... ...
*buffer = gbuf.get();
... ...
return OK;
}
dequeueBuffer的時候,通過mGraphicBufferProducer的dequeueBuffer,去找到可用Buffer的id,然後根據id去隊列裏面取Buffer。
這下明白,爲什麼說 ANativeWindow和Surface是對等的了吧。但是… …
但是,對不對等,取決於是否真是的用到Surface。比如,我不想用 Surface的這個流程,我自己寫一個MySurface,繼承與ANativeWindow,然後我用自己的MySurface。此時,元芳,你怎麼看?
那麼ANativeWindow和Surface怎麼對等的呢?我們且來看SurfaceControl。
SurfaceControl
SurfaceControl,簡單理解就是控制Surface的。怎麼控制?我們先來看,什麼時候創建的SurfaceControl。
創建Layer的時候,通過createSurface創建了Layer,
sp<SurfaceControl> SurfaceComposerClient::createSurface(
... ...
sp<IGraphicBufferProducer> gbp;
if (parent != nullptr) {
parentHandle = parent->getHandle();
}
status_t err = mClient->createSurface(name, w, h, format, flags, parentHandle,
windowType, ownerUid, &handle, &gbp);
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
sur = new SurfaceControl(this, handle, gbp);
}
}
return sur;
}
創建了Layer後,獲取到Layer的handle和BufferQueue的Producer,SurfaceControl中就有了Layer的handle和Producer了。
SurfaceControl的類圖:
構造函數如下:
* frameworks/native/libs/gui/SurfaceControl.cpp
SurfaceControl::SurfaceControl(
const sp<SurfaceComposerClient>& client,
const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbp)
: mClient(client), mHandle(handle), mGraphicBufferProducer(gbp)
{
}
這裏SurfaceControl就和Layer,BufferQueue建立聯繫了。
再回到我們的代碼:
ANativeWindow* aNativeWindow = surfaceControl->getSurface().get();
這裏SurfaceControl的getSurface是一個sp,這裏是多態的用法,這就是爲什麼說ANativeWindow和Surface對等了。
getSurface函數如下:
sp<Surface> SurfaceControl::getSurface() const
{
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0) {
return generateSurfaceLocked();
}
return mSurfaceData;
}
generateSurfaceLocked函數中,創建一個Surface
sp<Surface> SurfaceControl::generateSurfaceLocked() const
{
// This surface is always consumed by SurfaceFlinger, so the
// producerControlledByApp value doesn't matter; using false.
mSurfaceData = new Surface(mGraphicBufferProducer, false);
return mSurfaceData;
}
看到了吧,Surface中的mGraphicBufferProducer是從哪兒來的了吧。在Layer端爲MonitoredProducer,Surface這邊是Binder的Bp端。
我們先來看Surface相關類的關係吧
看了Surface相關的關係類圖,再和SurfaceFlinger,Layer相關的關係類似結合,應用和SurfaceFlinger服務的關係是不是就很清楚了。
到此,應用該做的準備工作都準備完了,應用端主要通過IGraphicBufferProducer和ISurfaceComposerClient兩個接口SurfaceFlinger進行交互。
在開始下面的知識之前,我們先來看看這個LayerCleaner
窗口銷燬的善後處理
應用被銷燬後,Client端就被清理了,SurfaceControl,SurfaceComposerClient,被銷燬。但是服務端,SurfaceFlinger是另外一個進程,爲應用進程申請的相關資源什麼很好釋放呢?
關鍵還是看上面類圖中的Handler。我們就來看一下流程:
SurfaceControl::~SurfaceControl()
{
destroy();
}
在destroy函數中,銷燬應用進程中的資源:
void SurfaceControl::destroy()
{
if (isValid()) {
mClient->destroySurface(mHandle);
}
// clear all references and trigger an IPC now, to make sure things
// happen without delay, since these resources are quite heavy.
mClient.clear();
mHandle.clear();
mGraphicBufferProducer.clear();
IPCThreadState::self()->flushCommands();
}
而服務端的,有兩種方式:
- 直接通過 Client destroySurface:
* frameworks/native/services/surfaceflinger/Client.cpp
status_t Client::destroySurface(const sp<IBinder>& handle) {
return mFlinger->onLayerRemoved(this, handle);
}
status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
{
// called by a client when it wants to remove a Layer
status_t err = NO_ERROR;
sp<Layer> l(client->getLayerUser(handle));
if (l != NULL) {
mInterceptor.saveSurfaceDeletion(l);
err = removeLayer(l);
ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
"error removing layer=%p (%s)", l.get(), strerror(-err));
}
return err;
}
但是,注意這裏的isValid()
如果isValid無效呢?
這個時候,我們就要通過mClient和mHandle。這個時候是引用計數控制的自動釋放。
- 引用計數控制自動釋放
mClient.clear();
mHandle.clear();
clear函數會是否對象的應用,最終調用析構函數:
Client::~Client()
{
const size_t count = mLayers.size();
for (size_t i=0 ; i<count ; i++) {
sp<Layer> l = mLayers.valueAt(i).promote();
if (l != nullptr) {
mFlinger->removeLayer(l);
}
}
}
這裏是不是和destroySurface函數是異曲同工之處。
再來看Handle:
* frameworks/native/services/surfaceflinger/Layer.h
class Handle : public BBinder, public LayerCleaner {
public:
Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
: LayerCleaner(flinger, layer), owner(layer) {}
wp<Layer> owner;
};
Handle析構時,會調父類的析構:
protected:
~LayerCleaner() {
// destroy client resources
mFlinger->onLayerDestroyed(mLayer);
}
};
LayerCleaner的析構中同樣調的SurfaceFlinger的onLayerRemoved函數。再調的removeLayer
status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer, bool topLevelOnly) {
... ...
const auto& p = layer->getParent();
ssize_t index;
if (p != nullptr) {
... ...
index = p->removeChild(layer);
} else {
index = mCurrentState.layersSortedByZ.remove(layer);
}
... ...
layer->onRemovedFromCurrentState();
mLayersPendingRemoval.add(layer);
mLayersRemoved = true;
mNumLayers -= 1 + layer->getChildrenCount();
setTransactionFlags(eTransactionNeeded);
return NO_ERROR;
}
刪除Layer時,主要做了以下幾件事:
- 將Layer從父Layer中刪掉,或者從mCurrentState中刪掉,放到待刪除Layer列表中
- onRemovedFromCurrentState,清理Layer,如果是父Layer,子Layer也刪掉
- setTransactionFlags,通知SurfaceFlinger更新,更新後,我們刪掉的Layer就沒有了,屏幕就不顯示了。
最後銷燬Layer
* frameworks/native/services/surfaceflinger/Layer.cpp
Layer::~Layer() {
sp<Client> c(mClientRef.promote());
if (c != 0) {
c->detachLayer(this);
}
for (auto& point : mRemoteSyncPoints) {
point->setTransactionApplied();
}
for (auto& point : mLocalSyncPoints) {
point->setFrameAvailable();
}
mFrameTracker.logAndResetStats(mName);
}
善終… …