在Android中,BufferQueue是Surface實現本地窗口的關鍵,駐留在SurfaceFlinger進程中進行服務,下面從BufferQueue的結構開始分析,
class BufferQueue : public BnGraphicBufferProducer,
public BnGraphicBufferConsumer,
private IBinder::DeathRecipient {
可見BufferQueue擁有producer和consumer兩端。再看看createBufferQueue的實現,這裏創建了一個BufferQueueCore,然後以這個爲參數依次創建了BufferQueueProducer和BufferQueueConsumer。
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
const sp<IGraphicBufferAlloc>& allocator) {
sp<BufferQueueCore> core(new BufferQueueCore(allocator));
sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));
sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
*outProducer = producer;
*outConsumer = consumer;
}
這裏的producer和consumer是要設置的,而allocator是從外面傳進來的,如果傳NULL,則在BufferQueueCore中會初始化,如下:
BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) {
if (allocator == NULL) {
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
mAllocator = composer->createGraphicBufferAlloc();
}
}
這裏的ISurfaceComposer實現在SurfaceFlinger中,再看createGraphicBufferAlloc的實現:
sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc() {
sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
return gba;
}
這個GraphicBufferAlloc構造函數是個空殼,看看createGraphicBuffer的實現,
sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width,
uint32_t height, PixelFormat format, uint32_t usage, status_t* error) {
sp<GraphicBuffer> graphicBuffer(
new GraphicBuffer(width, height, format, usage));
status_t err = graphicBuffer->initCheck();
return graphicBuffer;
}
GraphicBuffer繼承自ANativeWindowBuffer,這個定義在window.h中,值得注意的是裏面有個buffer_handle_t句柄,用於共享內存映射的文件句柄就保存在裏面了。GraphicBuffer實現了Flattenable接口從而可以跨進程傳輸。GraphicBuffer構造函數中調用initSize開闢內存,
status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight,
PixelFormat inFormat, uint32_t inUsage) {
GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
status_t err = allocator.alloc(inWidth, inHeight, inFormat, inUsage,
&handle, &outStride);
......
return err;
}
這裏又冒出來一個GraphicBufferAllocator類,注意和之前的GraphicBufferAlloc是兩回事,這裏是真正創建內存了。這個allocator是個單例,構造函數中加載Gralloc模塊。具體的alloc應該會跟平臺相關了。
GraphicBufferAllocator::GraphicBufferAllocator() : mAllocDev(0) {
hw_module_t const* module;
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
if (err == 0) {
gralloc_open(module, &mAllocDev);
}
}
status_t GraphicBufferAllocator::alloc(uint32_t width, uint32_t height,
PixelFormat format, uint32_t usage, buffer_handle_t* handle,
uint32_t* stride) {
err = mAllocDev->alloc(mAllocDev, static_cast<int>(width),
static_cast<int>(height), format, static_cast<int>(usage), handle,
&outStride);
......
return err;
}
到這裏整個BufferQueue的創建就大致清楚了,其核心是GraphicBuffer的Allocator,最終是調用的Gralloc模塊來開闢GraphicBuffer。
搜索一下BufferQueue在哪些地方被創建的,有以下幾處,
- SurfaceTexture初始化時
- SurfaceFlinger初始化時,爲每個顯示器創建一個BufferQueue
- Layer創建時的onFirstRef中
我們重點關注Surface,這是應用端和SurfaceFlinger交互的關鍵了,SurfaceTexture和Layer都和Surface有千絲萬縷的聯繫。
接下來分析BufferQueueProducer,下面是dequeueBuffer函數,首先找空閒的slot,如果buffer需要重新分配則創建GraphicBuffer設置到mSlots中。
status_t BufferQueueProducer::dequeueBuffer(int *outSlot, ...) {
int found = BufferItem::INVALID_BUFFER_SLOT;
while (found == BufferItem::INVALID_BUFFER_SLOT) {
status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, &found);
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
}
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
*outSlot = found;
......
if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(...);
......
mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
}
return returnFlags;
}
我們再來看Surface中的dequeueBuffer,Surface作爲BufferQueue的client端,其mGraphicBufferProducer必定是IGraphicBufferProducer的Bp端,對應的Bn端在BufferQueue中。這裏通過dequeueBuffer後,先判斷Buffer是否在BufferQueue端重新分配過了,如果是則需要調用requestBuffer刷新本地的GraphicBuffer。
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
reqWidth, reqHeight, reqFormat, reqUsage,
enableFrameTimestamps ? &frameTimestamps : nullptr);
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) {
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
}
*buffer = gbuf.get();
return OK;
}
這裏的問題是Surface和BufferQueue運行於不同的進程,其GraphicBuffer是否指向同一塊物理內存。我們分析requestBuffer函數,我們首先看BpGraphicBufferProducer的transact,這裏首先IPC調用REQUEST_BUFFER,獲取到reply,然後本地先創建一個GraphicBuffer空殼,再從reply中將真正的數據讀進來。
// IGraphicBufferProducer.cpp
virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
data.writeInt32(bufferIdx);
status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
bool nonNull = reply.readInt32();
if (nonNull) {
*buf = new GraphicBuffer();
result = reply.read(**buf);
}
result = reply.readInt32();
return result;
}
再來看BnGraphicBufferProducer的onTransact,
case REQUEST_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
int bufferIdx = data.readInt32();
sp<GraphicBuffer> buffer;
int result = requestBuffer(bufferIdx, &buffer);
reply->writeInt32(buffer != 0);
if (buffer != 0) {
reply->write(*buffer);
}
reply->writeInt32(result);
return NO_ERROR;
}
這裏會調用GraphicBufferProducer中的requestBuffer,然後將buffer寫入reply中。可見GraphicBuffer可以通過Binder傳遞,
class GraphicBuffer
: public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>,
public Flattenable<GraphicBuffer>
原來這裏實現了Flattenable,實現這個接口的對象可以序列化到buffer中,包括其中的文件描述符。我們看其unflatten實現,這裏的fds很可能已經變了,這裏關鍵是registerBuffer,很可能是要開始映射內存了。這個mBufferMapper是GraphicBufferMapper,
status_t GraphicBuffer::unflatten(
void const*& buffer, size_t& size, int const*& fds, size_t& count) {
......
if (handle != 0) {
status_t err = mBufferMapper.registerBuffer(handle);
......
}
......
return NO_ERROR;
}
再來看GraphicBufferMapper的實現,在構造函數中加載了Gralloc模塊,看來是平臺相關的。到這裏有點眼熟,之前提到的GraphicBufferAllocator初始化時也會加載Gralloc模塊,那是在SurfaceFlinger中真正創建GraphicBuffer用的,而這裏應用端只需將句柄映射到自己的內存空間即可,所以有了這個GraphicBufferMapper。
GraphicBufferMapper::GraphicBufferMapper() : mAllocMod(0) {
hw_module_t const* module;
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
if (err == 0) {
mAllocMod = (gralloc_module_t const *) module;
}
}
status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle) {
status_t err;
err = mAllocMod->registerBuffer(mAllocMod, handle);
return err;
}
這裏的registerBuffer是和平臺相關的,我們看msm8960平臺的實現:
gralloc_register_buffer(gralloc_module_t const* module,
buffer_handle_t handle) {
private_handle_t* hnd = (private_handle_t*)handle;
hnd->base = 0;
hnd->base_metadata = 0;
int err = gralloc_map(module, handle);
return 0;
}
這裏調用了gralloc_map將handle句柄映射到自己的進程空間,而這塊區域與BufferQueue中指向的物理空間是一致的,從而實現了兩者跨進程緩衝區共享。
到這裏我們大致明白了本地Surface和對端BufferQueue之間的dequeueBuffer時的過程,接下來我們瞭解一下Surface是怎麼和BufferQueue建立聯繫的。
我們在本文開頭提到,在Layer創建時的onFirstRef中會createBufferQueue,而Layer的創建在SurfaceFlinger中的createLayer函數,而這個函數被Client的createSurface調用,這個Client是BnSurfaceComposerClient的子類,因此其中包含createSurface的實現,我們注意到裏面會將所有Bp端發起的createSurface請求串行化後再丟給SurfaceFlinger。
再看BpSurfaceComposerClient中的createSurface是被誰調到的,我們發現SurfaceControl中的nativeCreate時會調到,這是SurfaceControl的構造函數中調到的。
// android_view_SurfaceControl.cpp
static jint nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
jstring nameStr, jint w, jint h, jint format, jint flags) {
sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
sp<SurfaceControl> surface = client->createSurface(
String8(name.c_str()), w, h, format, flags);
surface->incStrong((void *)nativeCreate);
return int(surface.get());
}
這裏createSurface返回的是SurfaceControl,這個其實是SurfaceComposerClient封裝了一層,將遠端返回的Binder句柄和GraphicBufferProducer都封裝起來了,所以通過SurfaceControl可以和SurfaceFlinger通信。再看nativeCreate中通過android_view_SurfaceSession_getClient獲取SurfaceComposerClient,看看SurfaceSession是什麼,這個是連接到SurfaceFlinger的,Java類中保存了一個long型的mNativeClient,這在Native層對應着SurfaceComposerClient。
public final class SurfaceSession {
// Note: This field is accessed by native code.
private long mNativeClient; // SurfaceComposerClient*
private static native long nativeCreate();
private static native long nativeCreateScoped(long surfacePtr);
private static native void nativeDestroy(long ptr);
private static native void nativeKill(long ptr);
/** Create a new connection with the surface flinger. */
public SurfaceSession() {
mNativeClient = nativeCreate();
}
......
}
再看Native層實現:
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
SurfaceComposerClient* client = new SurfaceComposerClient();
client->incStrong((void*)nativeCreate);
return reinterpret_cast<jlong>(client);
}
這裏創建了一個SurfaceComposerClient,並沒有看到連到SurfaceFlinger端,看其構造函數也沒有,我們想到onFirstRef,
void SurfaceComposerClient::onFirstRef() {
sp<ISurfaceComposer> sm(ComposerService::getComposerService());
if (sm != 0) {
auto rootProducer = mParent.promote();
sp<ISurfaceComposerClient> conn;
conn = sm->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
}
}
到這裏就清楚了,ISurfaceComposer是個與SurfaceFlinger通信的Binder句柄,通過該句柄的createConnection可以獲取ISurfaceComposerClient,而SurfaceComposerClient是在其基礎上包裝了一層而已。
所以本地應用需要通過SurfaceSession建立和SurfaceFlinger連接,獲取SurfaceComposerClient,然後再通過這個句柄調用createSurface,返回GraphicBufferProducer,封裝到SurfaceControl中,有了這個GraphicBufferProducer接下來就好辦了。