再上一篇文章中,介绍了Surface的创建的流程,我们说到在App层生成的Surface实质上即一个BBQSurface,它继承自Surface,Surfaced的继承比较隐晦,它实际上是继承自ANativeWindow的。
frameworks/native/include/gui/Surface.h
class Surface
: public ANativeObjectBase<ANativeWindow, Surface, RefBase>
{
frameworks/native/libs/ui/include/ui/ANativeObjectBase.h
template <typename NATIVE_TYPE, typename TYPE, typename REF,
typename NATIVE_BASE = android_native_base_t>
class ANativeObjectBase : public NATIVE_TYPE, public REF
这里是通过模板的方式,间接继承自NATIVE_TYPE,此处是ANativeWindow,因此明确了Surface继承自ANativeWindow的关系。
因为ANativeWindow在绘制的过程中是比较重要的一个类,因此这里专门写一篇文章来介绍一下。
1 定义
1.1 定义
我们来看一下ANativeWindow的定义:
frameworks/native/libs/nativewindow/include/system/window.h
frameworks/native/libs/nativewindow/include/vndk/window.h
frameworks/native/libs/nativewindow/include/apex/window.h
frameworks/native/libs/nativewindow/include/android/native_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));
}
...
}
它也定义了一些成员函数, 比如下面的:
int (*query)(const struct ANativeWindow* window,
int what, int* value);
int (*perform)(struct ANativeWindow* window,
int operation, ... );
int (*dequeueBuffer)(struct ANativeWindow* window,
struct ANativeWindowBuffer** buffer, int* fenceFd);
int (*queueBuffer)(struct ANativeWindow* window,
struct ANativeWindowBuffer* buffer, int fenceFd);
这些header文件里还定义了一系列的全局函数:
int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);
int ANativeWindow_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd);
int ANativeWindow_queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd);
这些函数的定义分散在上述个header文件,但是实现是在一个cpp文件中
frameworks/native/libs/nativewindow/ANativeWindow.cpp
int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer,
ARect* inOutDirtyBounds) {
return window->perform(window, NATIVE_WINDOW_LOCK, outBuffer, inOutDirtyBounds);
}
int32_t ANativeWindow_unlockAndPost(ANativeWindow* window) {
return window->perform(window, NATIVE_WINDOW_UNLOCK_AND_POST);
}
int ANativeWindow_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd) {
return window->dequeueBuffer(window, buffer, fenceFd);
}
int ANativeWindow_queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) {
return window->queueBuffer(window, buffer, fenceFd);
}
...
所以这些全局方法都转发到了window上去执行的,window类型是ANativeWindow的指针,而实际上就一个Surface.
java层的Surface 可以与ANativeWindow相互转换
1.2 Surface转换成ANativeWindow
frameworks/base/native/android/native_window_jni.cpp
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface) {
sp<ANativeWindow> win = android_view_Surface_getNativeWindow(env, surface);
if (win != NULL) {
ANativeWindow_acquire(win.get());
}
return win.get();
}
frameworks/base/core/jni/android_view_Surface.cpp
sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) {
return android_view_Surface_getSurface(env, surfaceObj);
}
sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) {
sp<Surface> sur;
jobject lock = env->GetObjectField(surfaceObj,
gSurfaceClassInfo.mLock);
if (env->MonitorEnter(lock) == JNI_OK) {
sur = reinterpret_cast<Surface *>(
env->GetLongField(surfaceObj, gSurfaceClassInfo.mNativeObject));
env->MonitorExit(lock);
}
env->DeleteLocalRef(lock);
return sur;
}
它是直接读取Surface对象的mNativeObject字段,这个是一个指向JNI层的的Surface的指针。然后直接转换成ANativeWindow。
1.3 ANativeWindow转Java层的Surface对象
jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) {
if (window == NULL) {
return NULL;
}
sp<Surface> surface = static_cast<Surface*>(window);
return android_view_Surface_createFromSurface(env, surface);
}
jobject android_view_Surface_createFromSurface(JNIEnv* env, const sp<Surface>& surface) {
jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
gSurfaceClassInfo.ctor, (jlong)surface.get());
if (surfaceObj == NULL) {
if (env->ExceptionCheck()) {
ALOGE("Could not create instance of Surface from IGraphicBufferProducer.");
LOGE_EX(env);
env->ExceptionClear();
}
return NULL;
}
surface->incStrong(&sRefBaseOwner);
return surfaceObj;
}
直接以surface的指针为参数,反射构造方法构造一个java层的Surface对象。
2 Surface与ANativeWindow
如上所说,他们的直接关系是Surface继承自ANativeWindow。但是我们想知道是Surface扩展了什么
frameworks/native/libs/gui/Surface.cpp
Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp,
const sp<IBinder>& surfaceControlHandle)
: mGraphicBufferProducer(bufferProducer),
...
// Initialize the ANativeWindow function pointers.
ANativeWindow::setSwapInterval = hook_setSwapInterval;
ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
ANativeWindow::cancelBuffer = hook_cancelBuffer;
ANativeWindow::queueBuffer = hook_queueBuffer;
ANativeWindow::query = hook_query;
ANativeWindow::perform = hook_perform;
ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
ANativeWindow::cancelBuffer_DEPRECATED = hook_cancelBuffer_DEPRECATED;
ANativeWindow::lockBuffer_DEPRECATED = hook_lockBuffer_DEPRECATED;
ANativeWindow::queueBuffer_DEPRECATED = hook_queueBuffer_DEPRECATED;
...
}
我们看到构造方法里对ANativeWindow类的方法进行了hook,比如常见的 ANativeWindow::dequeueBuffer = hook_dequeueBuffer;,ANativeWindow::perform = hook_perform;,因此调用ANativeWindow的这些方法的时候,会去执行Surface中定义的hook_xxx方法。
我们这里来分析几个主要的方法
2.1 hook_dequeueBuffer
int Surface::hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd) {
Surface* c = getSelf(window);
{
std::shared_lock<std::shared_mutex> lock(c->mInterceptorMutex);
if (c->mDequeueInterceptor != nullptr) {
auto interceptor = c->mDequeueInterceptor;
auto data = c->mDequeueInterceptorData;
return interceptor(window, Surface::dequeueBufferInternal, data, buffer, fenceFd);
}
}
return c->dequeueBuffer(buffer, fenceFd);
}
frameworks/native/libs/ui/include/ui/ANativeObjectBase.h
static inline TYPE const* getSelf(NATIVE_TYPE const* self) {
return static_cast<TYPE const *>(self);
}
首先强制将window转换成Surface,因为这个window本身就是一个Surface,因此可以强转。然后经过一些拦截处理,如果没有被拦截的话才调用Surface->dequeueBuffer(buffer, fenceFd)。拦截者保存在suface上的mDequeueInterceptor字段。这个拦截者会在后面的文章里继续介绍。在调用拦截者的时候又传入了Surface::dequeueBufferInternal这个函数执行,因此执行完拦截后,可以调用这个函数来实现dequeueBuffer的目的
int Surface::dequeueBufferInternal(ANativeWindow* window, ANativeWindowBuffer** buffer,
int* fenceFd) {
Surface* c = getSelf(window);
return c->dequeueBuffer(buffer, fenceFd);
}
最后调用的还是suface的dequeueBuffer方法。
2.2 dequeueBuffer
dequeueBuffer是一个重要的方法,Surface是的角色是生产者,它持有一个IGraphicBufferProducer类型的producer,当需要生产新的内容的时候,需要调用dequeueBuffer获得一个可用的图形缓存GraphcBuffer用于绘制。传入的buffer指针将指向这个可用的GraphcBuffer。下面介绍一下这个方法。
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
...
IGraphicBufferProducer::DequeueBufferInput dqInput;
{
Mutex::Autolock lock(mMutex);
if (mReportRemovedBuffers) {
mRemovedBuffers.clear();
}
getDequeueBufferInputLocked(&dqInput);
/*注释1:
一般模式下,GraphicBuffer会受到Fence的保护,从而只能被串行访问.
mSharedBufferMode 下这个GraphicBuffer将会被Application和SurfaceFlingger同时访问,可能会导致画面撕裂。正常情况下不会开启这个模式
*/
if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot !=
BufferItem::INVALID_BUFFER_SLOT) {
sp<GraphicBuffer>& gbuf(mSlots[mSharedBufferSlot].buffer);
if (gbuf != nullptr) {
*buffer = gbuf.get();
*fenceFd = -1;
return OK;
}
}
} // Drop the lock so that we can still touch the Surface while blocking in IGBP::dequeueBuffer
int buf = -1;
sp<Fence> fence;
nsecs_t startTime = systemTime();
FrameEventHistoryDelta frameTimestamps;
/*注释2:
通过调用mGraphicBufferProducer的dequeueBuffer的方法获取一个graphicbuffer,将其索引index保存到buf指针,每个graphicbuffer都有对应的fence,它的fence保存到fence。
返回的result中会包含一些控制信息位。
*/
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, dqInput.width,
dqInput.height, dqInput.format,
dqInput.usage, &mBufferAge,
dqInput.getTimestamps ?
&frameTimestamps : nullptr);
mLastDequeueDuration = systemTime() - startTime;
/**
dequeue失败,直接返回
*/
if (result < 0) {
ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
"(%d, %d, %d, %#" PRIx64 ") failed: %d",
dqInput.width, dqInput.height, dqInput.format, dqInput.usage, result);
return result;
}
if (buf < 0 || buf >= NUM_BUFFER_SLOTS) {
ALOGE("dequeueBuffer: IGraphicBufferProducer returned invalid slot number %d", buf);
android_errorWriteLog(0x534e4554, "36991414"); // SafetyNet logging
return FAILED_TRANSACTION;
}
Mutex::Autolock lock(mMutex);
// Write this while holding the mutex
mLastDequeueStartTime = startTime;
/*
这个mSlots是Surface中定义的一个结构体BufferSlot数组,与BufferQueueCore中定义的BufferSlot不是一个概念,但是都有相同的长度64,二者
之间可以通过index来映射。如果第一次执行,此处取到的mSlots[buf].buffer应该是为空的。同时result中也包含有BUFFER_NEEDS_REALLOCATION位
*/
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
// this should never happen
ALOGE_IF(fence == nullptr, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
static FenceMonitor hwcReleaseThread("HWC release");
hwcReleaseThread.queueFence(fence);
}
if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
freeAllBuffers();
}
if (dqInput.getTimestamps) {
mFrameEventHistory->applyDelta(frameTimestamps);
}
/*
此处需要进一步调用 mGraphicBufferProducer->requestBuffer去获取buf索引中的GraphicBuffer,并保存到&gbuf,也即保存到了mSlot[buf].buffer.
*/
if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) {
if (mReportRemovedBuffers && (gbuf != nullptr)) {
mRemovedBuffers.push_back(gbuf);
}
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
if (result != NO_ERROR) {
ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
mGraphicBufferProducer->cancelBuffer(buf, fence);
return result;
}
}
if (fence->isValid()) {
/**
复制fenceFd给fenceFd,供调用方使用。
*/
*fenceFd = fence->dup();
if (*fenceFd == -1) {
ALOGE("dequeueBuffer: error duping fence: %d", errno);
// dup() should never fail; something is badly wrong. Soldier on
// and hope for the best; the worst that should happen is some
// visible corruption that lasts until the next frame.
}
} else {
*fenceFd = -1;
}
/**
buffer将指向一个graphicBuffer,供调用方使用。
*
*buffer = gbuf.get();
if (mSharedBufferMode && mAutoRefresh) {
mSharedBufferSlot = buf;
mSharedBufferHasBeenQueued = false;
} else if (mSharedBufferSlot == buf) {
mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
mSharedBufferHasBeenQueued = false;
}
mDequeuedSlots.insert(buf);
return OK;
}
上面的代码中加入了相关的注释。它主要是通过mGraphicBufferProducer->dequeueBuffer去获取到一个可用的GraphicBuffer索引buf,以及该GraphicBuffer绑定的fence,然后通过mGraphicBufferProducer->requestBuffer去获取buf索引处的GraphicBuffer,保存到Surface的mSlot对应索引位置,并保存到调用方指定的buffer位置。从而调用就可以通过buffer引用到这个GraphicBuffer,将绘制的内容写入其中。
2.3. queueBuffer
hook_queueBuffer就介绍了,和hook_dequeueBuffer的原理差不多,我们就直接介绍queueBuffer方法。当Surface中的绘制结束后,需要将GraphicBuffer还回来,并通知消费者有新的数据可以展示。
int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
...
int i = getSlotFromBufferLocked(buffer);
IGraphicBufferProducer::QueueBufferOutput output;
IGraphicBufferProducer::QueueBufferInput input;
getQueueBufferInputLocked(buffer, fenceFd, mTimestamp, &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;
}
它传入的参数buffer的类型是android_native_buffer_t* buffer, 它的定义在frameworks/native/libs/nativebase/include/nativebase/nativebase.h,是一个ANativeWindowBuffer,主要持有一个native_handle_t的属性handle用于保存文件句柄。
typedef struct native_handle
{
int version; /* sizeof(native_handle_t) */
int numFds; /* number of file-descriptors at &data[0] */
int numInts; /* number of ints at &data[numFds] */
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wzero-length-array"
#endif
int data[0]; /* numFds + numInts ints */
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} native_handle_t;
通过这个buffer参数, 调用getSlotFromBufferLocked获取这个buffer的在mSlots中的索引
int Surface::getSlotFromBufferLocked(
android_native_buffer_t* buffer) const {
if (buffer == nullptr) {
ALOGE("%s: input buffer is null!", __FUNCTION__);
return BAD_VALUE;
}
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
if (mSlots[i].buffer != nullptr &&
mSlots[i].buffer->handle == buffer->handle) {
return i;
}
}
ALOGE("%s: unknown buffer: %p", __FUNCTION__, buffer->handle);
return BAD_VALUE;
}
通过比较mSlots中的graphicbuffer的handle是否与传入的handle一致,匹配出索引位置i,然后后通过调用mGraphicBufferProducer->queueBuffer(i, input, &output);来实现的。
需要额外说明一点的是,mSlots是一个BufferSlot的数组,每个元素都是一个BufferSlot对象,每个BufferSlot持有的是一个GraphicBuffer对象,这里queueBuffer方法传入的是一个android_native_buffer_t*类型的参数,或者说是一个ANativeWindowBuffer。他们二者之间是什么关系呢?答案是GraphicBuffer继承自ANativeWindowBuffer。
最后,通过mQueueBufferCondition通知等待的线程
void Surface::onBufferQueuedLocked(int slot, sp<Fence> fence,
const IGraphicBufferProducer::QueueBufferOutput& output) {
mDequeuedSlots.erase(slot);
...
mQueueBufferCondition.broadcast();
...
}
3. 总结
本文介绍了一个非常重要的类ANativeWindow,它是Surface类的父类,虽然在C层,很多场景都是使用的ANativeWindow,但实质上是一个Surface对象,对ANativeWindow的调用最后都会进入到Surface定义的方法。 接着分析了Surface作为生产者的两个重要方法,dequeueBuffer和queueBuffer,它们最后都进入到GraphicBufferProducer对应的方法。Surface还有很多其他的方法,这里就不一一介绍了。