基于Android P源码分析,深入理解Android GUI的框架。
前言 Android图像系统框架比较复杂,涉及WindowManager、SurfaceFlinger、ActivityManager、InputManager等模块。因为笔者此前从事过底层显示驱动相关工作,期望通过梳理Android显示系统的框架构建完整的知识体系。
它们之间的关系如下:
图形框架
参考 https://source.android.com/devices/graphics
Android框架提供各种 2D 和 3D 图形渲染的 API,应用开发者可以通过 Canvas、OpenGL ES 和 Vulkan 三种方式将图像绘制到屏幕上。但无论开发者使用什么渲染 API,最终都会渲染到 Surface。Surface 表示缓冲队列中的生产者,每个 Window 都对应者一个或多个 Surface,而缓冲队列的消费者通常是 SurfaceFlinger,用以合成到显示部分,比如自身屏幕或者扩展屏幕。
IMAGE STREAM PRODUCERS: 可以生成图形缓冲区以供消耗的任何内容,比如OpenGL ES、Canvas 2D 和 mediaserver 视频解码器。
IMAGE STREAM CONSUMERS: 最常见的消费者就是 SurfaceFlinger,它是可以修改所显示部分内容的唯一服务,使用 OpenGL 和 Hardware Composer 来合成一组 Surface. 还有其他应用也可以作为消费者,比如相机应用和 ImageReader.
Hardware Composer: 作为显示子系统的硬件抽象层,完成SurfaceFlinger 合成显示的部分任务,以分担 OpenGL 和 GPU 的消耗。同时需要支持 Vsync Event 和 HDMI 的热插拔。
Gralloc HAL: 用来分配图像生产者所请求的内存。
数据处理
左侧黄色部分为图像缓冲区的生产者,比如状态栏、菜单栏和主界面等。SurfaceFlinger 完成 Surface 的合成,Hardware Composer 操作硬件控制器显示。
BufferQueue BufferQueue 是 Android 图像系统的重要组成部分,是缓冲区和队列结合的数据结构,通过Binder IPC在进程间传递。
上图描述了图像生产者和消费者的操作流程:
生产者请求队列中空闲的缓冲区:dequeueBuffer()
生产者填充缓冲区并添加到队列:queueBuffer()
消费者从队列中获取缓冲区:acquireBuffer()
消费者使用完毕返回给队列:releaseBuffer()
对应类图的关系如下:
SurfaceFlinger SurfaceFlinger 是一个本地系统服务,用来合成应用绘制的 Surface,借助 Hardware Composer 显示到屏幕上。
[surfaceflinger.rc]
1 2 3 4 5 6 7 8 service surfaceflinger /system/bin/surfaceflinger class core animation user system group graphics drmrpc readproc onrestart restart zygote writepid /dev/stune/foreground/tasks socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0 socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0 socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s
[main_surfaceflinger.cpp]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 int main(int, char**) { signal(SIGPIPE, SIG_IGN); hardware::configureRpcThreadpool(1 /* maxThreads */, false /* callerWillJoin */); startGraphicsAllocatorService(); // When SF is launched in its own process, limit the number of // binder threads to 4. ProcessState::self()->setThreadPoolMaxThreadCount(4); // start the thread pool sp<ProcessState> ps(ProcessState::self()); ps->startThreadPool(); // instantiate surfaceflinger sp<SurfaceFlinger> flinger = new SurfaceFlinger(); setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY); set_sched_policy(0, SP_FOREGROUND); // Put most SurfaceFlinger threads in the system-background cpuset // Keeps us from unnecessarily using big cores // Do this after the binder thread pool init if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM); // initialize before clients can connect flinger->init(); // publish surface flinger sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false, IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL); // publish GpuService sp<GpuService> gpuservice = new GpuService(); sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false); startDisplayService(); // dependency on SF getting registered above struct sched_param param = {0}; param.sched_priority = 2; if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) { ALOGE("Couldn't set SCHED_FIFO"); } // run surface flinger in this thread flinger->run(); return 0; }
SurfaceFlinger 类继承于 BnSurfaceComposer,实现 ISurfaceComposer 本地接口。Android P 版本从 SurfaceFlinger 类中拆分出 SurfaceFlingerBE,实现前后端分离,前端和上层进行交互,后端 SurfaceFlingerBE 和底层硬件合成进行交互。
1 2 3 4 class SurfaceFlinger : public BnSurfaceComposer, public PriorityDumper, private IBinder::DeathRecipient, private HWC2::ComposerCallback
具体的类图关系如下图:
后面我们将以 SurfaceFlinger 为主线,结合源代码进行情景分析,梳理整个图像系统。
WindowManager : 首先需要知道 Surface 是由谁创建的?是如何绘制和更新的,窗口的动画切换是怎样做的?窗口的显示和隐藏是如何控制的?
SurfaceFlinger : Surface 使用的图像缓冲区是什么时候创建、管理和销毁的?多个 Surface 是如何合成的?如何实现多屏显示的?
Activity : Activity 的生命周期是怎样的?
InputManager : 底层按键事件是如何上报到Android系统的,又是如何到具体的窗口进行处理的?