libsync
源代码位于:system/core/libsync。
主要提供sync_wait、sync_merge两个接口分别用来等待、合并fence。fence由文件描述符表示。
window.h
源代码位于:system/core/include/system/window.h。
定义了本地窗口缓存和本地窗口类,用于和EGL对接。
android_native_base_t,是本地对象的虚基类,但是使用C语言方式定义。
成员 | 类型 | 说明 |
magic | int | EGL本地类型的魔术数字 |
version | int | EGL本地类型的实际大小 |
incRef | void(*) | 增加引用计数,虚函数 |
dump | void(*) | 减少引用计数,虚函数 |
ANativeWindowBuffer(android_native_buffer_t)描述本地窗口缓存。
成员 | 类型 | 说明 |
common [继承] | android_native_base_t | 魔术数字:ANDROID_NATIVE_BUFFER_MAGIC |
incStrong | void(void const *) | 支持智能指针sp<T> |
decStrong | void(void const *) | 支持智能指针sp<T> |
width、height | int | 图像尺寸 |
stride | int | |
format | int | 图像格式 |
usage | int | |
handle | buffer_handle_t | 内存句柄,实际类型const native_handle_t* |
ANativeWindow(android_native_window_t)描述本地窗口。
成员 | 类型 | 说明 |
common [继承] | android_native_base_t | 魔术数字: ANDROID_NATIVE_WINDOW_MAGIC |
incStrong | void(void const *) | 支持智能指针sp<T> |
decStrong | void(void const *) | 支持智能指针sp<T> |
flags | const uint32_t | Surface或者渲染者属性 |
minSwapInterval | const int | 渲染者支持最小渲染周期 |
maxSwapInterval | const int | 渲染者支持最大渲染周期 |
xdpi、ydpi | const float | 每英寸点数(DPI) |
oem | intptr_t[4] | 厂商自定义数据 |
setSwapInterval | int(int) | 设置Surface交换周期 |
dequeueBuffer | int(ANativeWindowBuffer**) | 获取缓存用作渲染,废弃的 |
lockBuffer | int(ANativeWindowBuffer*) | 在修改缓存前调用,废弃的 |
queueBuffer | int(ANativeWindowBuffer*) | 修改完成后调用,废弃的 |
cancelBuffer | int(ANativeWindowBuffer*) | 丢弃获取的缓存,废弃的 |
query | int(int, int*) | 获取窗口指定的信息 |
perform | int(int, …) | 执行指定的操作 |
dequeueBuffer | int(ANativeWindowBuffer**, init*) | 获取缓存用作渲染,需要在修改缓存前等待Fence |
queueBuffer | int(ANativeWindowBuffer*,int) | 修改完成后调用 |
cancelBuffer | int(ANativeWindowBuffer*,int) | 丢弃获取的缓存,可能直接用之前拿到的Fence |
ANativeObjectBase用来帮助实现android_native_base_t的引用计数管理。后面的ANativeWindowBuffer、ANativeWindow的派生类都是通过ANativeObjectBase间接继承父类的。
实现ANativeWindowBuffer的类有NativeBuffer(FramebufferNativeWindow.cpp中),另一个是GraphicBuffer。
实现ANativeWindow的类有FramebufferNativeWindow,另一个是Surface。
opengl
源代码位于:frameworks/native/opengl/。
库 | 源代码子目录 | 说明 |
libEGL.so | libs/EGL | EGL库,OpenGL ES库的封装 |
libGLESv1_CM.so | libs/GLES_CM | OpenGL ES库的封装 |
libGLESv2.so | libs/GLES2 | OpenGL ES 2.0库的封装 |
egl/libGLES_android.so | libagl | 基于Android平台的软件实现方案 |
egl/libGLES_*.so | 硬件厂商实现 | 硬件实现,有这个,就不需要后面三个了 |
egl/libEGL_*.so | 硬件厂商实现 | 硬件实现 |
egl/libGLESv1_*_CM.so | 硬件厂商实现 | 硬件实现 |
egl/libGLESv2_*.so | 硬件厂商实现 | 硬件实现 |
libui
源代码位于:frameworks/native/libs/ui。
头文件位于:frameworks/native/include/ui。
Fence类封装了驱动fence描述符,通过继承Flattenable能够跨进程传递Fence对象。
GraphicBufferAllocator封装了alloc_device_t的缓存申请、释放功能。已经申请的缓存记录在数组sAllocList中。
GraphicBufferMapper封装了gralloc_module_t的缓存注册、注销、锁定、解锁功能。
GraphicBuffer继承实现了ANativeWindowBuffer,管理缓存的申请释放已经跨进程传递(使用util库的Flattenable管理进程传递)。GraphicBuffer对缓存的持有分为持有数据和持有句柄两种情形。自己申请的为持有数据,跨进程传递过来的为持有句柄。这两种情形下释放方式不同。
GraphicBuffer也可以持有外部的ANativeWindowBuffer,并使用引用计数管理。ANativeWindowBuffer使用android_native_base_t的引用管理机制,为此GraphicBuffer通过ANativeObjectBase将引用计数实现在RefBase上。
FramebufferNativeWindow类继承实现ANativeWindow。通过framebuffer HAL设备实现GL本地窗口。除了调用gralloc申请并管理缓存,调用framebuffer交换缓存,还处理了的fence的同步。
libgui
源代码位于:frameworks/native/libs/gui。
头文件位于:frameworks/native/include/gui。
libgui 包含图形GUI系统的基础组件:BufferQueue、Consumer、Surface;也包含SurfaceFlinger客户端的代理类Composer、SurfaceComposerClient、SurfaceControl、Surface。
BufferQueue继承BnGraphicBufferProducer、BnGraphicBufferConsumer,也就是实现了IGraphicBufferProducer、IGraphicBufferConsumer接口。他并不是生产者,消费者,而是为生产者、消费者提供访问BufferQueue的接口。
IGraphicBufferProducer的成员:
成员 | 类型 | 说明 |
requestBuffer | status_t (int, sp<GraphicBuffer>*) | 请求指定slot的缓存,获取实际句柄,与dequeue分两步做,减少传递句柄消耗 |
setBufferCount | status_t (int) | 设置可以slot数目,会清空所有缓存 |
dequeueBuffer | status_t (int*, sp<Fence>*, bool, uint32_t, uint32_t, int32_t,uint32_t) | 获取一个缓存slot,可能返回BUFFER_NEEDS_REALLOCATION,此时需要重新requestBuffer |
queueBuffer | status_t (int, const QueueBufferInput&, QueueBufferOutput*) | 返回缓存,缓存已经填充数据 |
cancelBuffer | void(int,const sp<Fence>&) | 返回缓存,缓存数据丢弃 |
query | int (int, int*) | 查询Surface信息 |
connect | status_t (const sp<IBinder>&, int, bool, QueueBufferOutput*) | 客户端连接,需要在其他接口前调用 |
disconnect | status_t(int) | 客户端端口连接 |
IGraphicBufferConsumer的成员:
成员 | 类型 | 说明 |
acquireBuffer | status_t(BufferItem*, nsecs_t) | 获取缓存 |
releaseBuffer | status_t( int, uint64_t, EGLDisplay, EGLSyncKHR, const sp<Fence>&) | 释放缓存 |
consumerConnect | status_t(const sp<IConsumerListener>&, bool) | 消费者连接 |
consumerDisconnect | status_t () | 消费者断开 |
getReleasedBuffers | status_t(uint32_t*) | 获取已经释放的缓存列表,在onBuffersReleased中调用 |
setDefaultBufferSize | status_t(uint32_t, uint32_t) | 设置deque返回的默认缓存尺寸 |
setDefaultMaxBufferCount | status_t(int) | 设置默认最大缓存个数,生产者可以setBufferCount覆盖 |
disableAsyncBuffer | status_t () | 同时设置了isControlledByApp的情况下,使用非阻塞模式 |
setMaxAcquiredBufferCount | status_t (int) | 设置消费者最大持有缓存数目 |
setConsumerName | void (const String8&) | 设置消费者名字,用于日志 |
setDefaultBufferFormat | status_t(uint32_t) | 设置deque返回的默认缓存图像格式 |
setConsumerUsageBits | status_t (uint32_t) | 设置deque额外的缓存使用标志 |
setTransformHint | status_t (uint32_t) | 设置缓存旋转角度 |
dump | void (String8&, const char*) |
ConsumerListener的成员:
成员 | 类型 | 说明 |
onFrameAvailable | void () | 从queueBuffer中调用,异步原来队列空,或者同步 |
onBuffersReleased | void () | 当消费者持有的缓存被释放了 |
在BufferQueue的内部,缓存存放在数组中,数组单元是BufferSlot。生产者将缓存排队之后,缓存存放在队列中,先入先出,队列单元为BufferItem。
BufferSlot的成员:
成员 | 类型 | 说明 |
mGraphicBuffer | sp<GraphicBuffer> | 缓存, |
mEglDisplay | EGLDisplay | 用于创建EGLSyncKHR对象 |
mBufferState | BufferState | 状态FREE、DEQUEUED、QUEUED 、ACQUIRED |
mRequestBufferCalled | bool | 校验生产者确实调用过requestBuffer |
mFrameNumber | uint64_t | 队列排队号,用于dequeue时LRU |
mEglFence | EGLSyncKHR | EGL 同步对象,dequeue时要等待 |
mFence | sp<Fence> | 等待缓存先前所有者完成工作的同步对象 |
mAcquireCalled | bool | 是否被消费者拿到过 |
mNeedsCleanupOnRelease | bool | 当缓存在ACQUIRED状态被释放时设置 |
BufferItem的成员:
成员 | 类型 | 说明 |
mGraphicBuffer | sp<GraphicBuffer> | 缓存, |
mFence | sp<Fence> | 访问Fence |
mCrop | Rect | 当前剪裁区域 |
mTransform | uint32_t | 当前slot转换Flags |
mScalingMode | uint32_t | 当前slot缩放模式 |
mTimestamp | int64_t | 当前slot时间戳,queueBuffer设置 |
mIsAutoTimestamp | bool | 时间戳是否是排队时自动设置 |
mFrameNumber | uint64_t | 当前slot已经排队过的帧数 |
mBuf | int | slot编号 |
mIsDroppable | bool | 是否可以丢弃,保证dequeue不阻塞 |
mAcquireCalled | bool | 是否被消费者拿到 |
mTransformToDisplayInverse | bool | 转换方向后是否再翻转 |
ConsumerBase是消费者的基类,也实现了ConsumerListener与BufferQueue连接。ConsumerBase还管理已经获取的缓存。
BufferItemConsumer继承ConsumerBase,允许调用者访问整个BufferItem。支持同时持有多个缓存,支持同步(等待)、异步模式。
CpuConsumer继承ConsumerBase,是一个软件消费者,用LockedBuffer表示锁定的缓存。其lockNextBuffer方法完成了acquireBuffer、等待Fence、映射内存(lock、lockYCbCr)。
GLConsumer继承ConsumerBase,处理到GL Texture的转换,支持GL渲染。
Surface类继承实现了ANativeWindow,同时作为BufferQueue的生产者。
ComposerService持有ISurfaceComposer的实现对象引用,ISurfaceComposer实际由SurfaceFlinger服务实现。ComposerService是一个单例。
Composer是ISurfaceComposer的代理类,主要任务是将Display、Surface状态改变封装为事务发送给SurfaceFlinger。Composer是一个单例。
SurfaceComposerClient是ISurfaceComposerClient的代理类,通过连接(createConnection)ISurfaceComposer获得一个ISurfaceComposerClient实现对象。SurfaceComposerClient也代理Composer的很多接口。SurfaceComposerClient通过createSurface创建的Surface由SurfaceControl管理。
ScreenshotClient封装抓取屏幕功能,使用了CpuConsumer。
SurfaceControl管理SurfaceFlinger创建的Surface句柄(IBinder),这个句柄与SurfaceComposerClient是相关的。
部分类的名称历史:
4.2 | 4.3 | 4.4 |
ISurfaceTexture | IGraphicBufferProducer | IGraphicBufferProducer |
IGraphicBufferConsumer | ||
SurfaceTexture | GLConsumer | GLConsumer |
SurfaceTextureClient | Surface | Surface |
应用程序创建Surface的过程:
BitTube通过UNIX域匿名(socketpair,SOCK_SEQPACKET)管道实现了一个简单的在进程间传递数据结构(二进制报文)的管道。
DisplayEventReceiver负责创建并代理与SurfaceFlinger之间的事件连接(接口为IDisplayEventConnection),提供方法帮助从连接的数据管道(使用BitTube机制)读取事件,包括vsync、显示设备插拔事件。
libhwui
源代码位于:frameworks/base/libs/hwui。
使用opengl渲染UI组件。
libsurfaceflinger
源代码位于:frameworks/native/services/surfaceflinger。
硬件(DisplayHardware)
其中的DisplayHardware子目录中提供对HAL层封装的代码,包括PowerHAL、HWComposer、FramebufferSurface、VirtualDisplaySurface。
PowerHAL。
HWComposer封装hwcomposer HAL。管理显示设备属性DisplayData,转发vsync回调。创建Display的工作图层列表hwc_display_contents_1_t。
HWComposer::HWCLayerVersion1继承HWComposer::HWCLayer,后者继承HWComposer::HWCLayerInterface。HWComposer::HWCLayerVersion1封装了C数据结构hwc_layer_1_t,代理其读写操作。
HWComposer::LayerListIterator是HWComposer::HWCLayer枚举器。
DisplaySurface是一个虚基类,定义了几个回调接口。下面的FramebufferSurface和VirtualDisplaySurface都继承实现了DisplaySurface。
成员 | 类型 | 说明 |
beginFrame | status_t() | 在帧配置前被调用,为HWC提供配置参考信息 |
prepareFrame | int(CompositionType) | 在帧配置完成后被调用 |
compositionComplete | status_t() | 帧合成输出后被调用,HWC1.0需要的 |
advanceFrame | status_t() | GLES合成完成后被调用 |
onFrameCommitted | void() | 帧提交到HWC后被调用 |
dump | void(String8&) |
FramebufferSurface作为BufferQueue的消费者,将收到的frame推送给硬件(HWC),HWC将其保存到framebufferTarget。
VirtualDisplaySurface实现一个虚拟屏幕,作为一个BufferQueue的消费者,同时代理另一个BufferQueue的生产者接口。VirtualDisplaySurface使用了HWC的虚拟屏幕支持。
软件(Display与Surface)
DisplayDevice封装了DisplaySurface(内部设备使用FramebufferSurface实现,消费缓存)。DisplayDevice包含一个BufferQueue,使用Surface包装后交给GLES渲染(合成图层),合成后交换缓存会通知到FramebufferSurface,将合成后图像交给HWC作为framebufferTarget。
SurfaceFlingerConsumer继承GLConsumer。
SurfaceTextureLayer继承BufferQueue。是对BufferQueue的简单包装,然后被Layer类使用。
Layer处理剪辑区域的计算,GLES的叠加,内部算法比较复杂。Layer在客户端用句柄IBinder代表,该句柄继承LayerCleaner,在释放时会通知SurfaceFlinger。Layer继承实现了ConsumerBase::FrameAvailableListener,内部持有SurfaceFlingerConsumer对象。在回调onFrameAvailable中调用SurfaceFlinger的signalLayerUpdate,后者向MessageQueue中插入INVALIDATE消息。Layer第一次被引用onFirstRef时创建SurfaceTextureLayer(BufferQueue)以及消费者SurfaceFlingerConsumer。
LayerDim继承Layer。
Client类实现ISurfaceComposerClient,内部保存Layer句柄到Layer的映射集。
软件(Sync与Thread)
DispSync通过统计算法与硬件vsync信号同步,消除vsync信号在软件层传递引起的随机偏移。DispSync通过内部线程(DispSyncThread)为每个侦听者分别增加一定的信号延迟。
DispSync内部保存最近32个硬件vsync采样时间点,用统计方法计算vsync的周期和相位偏移。同步后可以关闭硬件vsync,由DispSyncThread周期唤醒模拟vsync信号。当显示设备重新打开或者通过PresentFence计算的偏移方差超过一定值时,需要重新同步。
DispSyncSource定义在SurfaceFlinger.cpp中。DispSyncSource是对DispSync的包装,可以定义不同的周期偏移(PhaseOffset)。
EventThread实现vsync信号分派线程,EventThread侦听外部传入VSyncSource,在没有VSyncSource的时候会内部模拟一个60fps的vsync信号。EventThread也分派显示设备插拔事件。
外部可以与EventThread建立连接(IDisplayEventConnection,由内部类Connection实现),可以请求只接收一次vsync回调(requestNextVsync),也可以指定按某个频率接收vsync回调(setVsyncRate,参数count表示每count个vsync信号调用一次回调)。连接通过BitTube管道返回事件。
实际上,SurfaceFlinger创建了两个DispSyncSource,分别被上层应用(APP)和SurfaceFlinger内部使用。两个DispSyncSource使用不同的信号延迟,延迟时间由厂商在BoardConfig.mk中定义,没有定义的情况下,默认为0,这两个变量分别是:
- VSYNC_EVENT_PHASE_OFFSET_NS(APP)
- SF_VSYNC_EVENT_PHASE_OFFSET_NS(SurfaceFlinger)
对应两个DispSyncSource,SurfaceFlinger也创建了两个EventThread,并且向其中对应APP的那个发送设备插拔事件。
MessageQueue通过封装Looper实现了消息队列,同时与EventThread建立连接,并将vsync事件转换为消息插入到消息队列。
EventControlThread用来协助SurfaceFlinger,在独立线程控制硬件vsync开启关闭。
surfaceflinger
surfaceflinger进程,创建Binder线程池(4线程),创建SurfaceFlinger对象,调用其init方法,然后注册到ServiceManager中,最后调用SurfaceFlinger的run方法进入SurfaceFlinger的MessageQueue派发循环。
从4.0开始,surfaceflinger不在system_init中启动,而是有独立的进程。但是可以通过init.rc配置从system_init中启动。
surfaceflinger服务init.rc中的定义:
# Set this property so surfaceflinger is not started by system_init setprop system_init.startsurfaceflinger 0 |
service surfaceflinger /system/bin/surfaceflinger class main user system group graphics drmrpc onrestart restart zygote |
从4.4开始,只有进程启动方式了。
bootanimation
源代码位于:frameworks/base/cmds/bootanimation。
Bootanimation使用opengl在新建的SurfaceFlinger layer上作图。开机启动的动画。
Bootanimation由init进程响应属性设置ctl.start=bootanim启动。Bootanimation检查到系统属性service.bootanim.exit=1退出。
service bootanim /system/bin/bootanimation class main user graphics group graphics disabled oneshot |
screencap
源代码位于:frameworks/base/cmds/screencap。
通过ScreenshotClient或者直接从/dev/graphics/fb0抓取图像数据,保存到文件或者通过stdout输出。通过SkBitmap转换为PNG格式。
screenshot
源代码位于:frameworks/native/cmds/screenshot。
直接从/dev/graphics/fb0(字节流方式读取)抓取图像数据,通过libpng(external/libpng)转换为PNG格式,保存到文件。
screenrecord
源代码位于:frameworks/av/cmds/screenrecord。
通过建立虚拟屏幕持续抓取屏幕,并使用编码压缩保存到文件。容器格式:Mp4,编码格式:AVC。