Android graphics
1. Graphics框图
下图从binary level总结了Graphic相关的代码,不注重细节,主要目的是展示Android实现的思路和大框架,角度有区别于Android官网的文档,算是一个补充。
图中绿色的线主要展示渲染相关的流程;紫色的线主要展示合成和显示的流程;红色的线展示了BLASTBufferQueue分配内存的流程。

2. Frameworks
framework.jar和services.jar都安装在system/framework/ 目录。
2.1 Window
2.1.1 WindowContainer
DisplayContent是一个WindowContainer,管理一个屏幕上的所有窗口容器,其内有一个mTokenMap 用于存放WindowToken
WindowToken也是WindowContainer
Task 继承自TaskFragment, 也是WindowContainer
ActivityRecord继承了WindowToken, 本身就是一个WindowContainer,和RootWindowContainer的关系?
下面Window hierarchy的层级, DisplayContent继承自RootDisplayArea, 且是RootWindowContainer的成员。
DisplayContent对象的数量取决于display的数量。
RootWindowContainer
├── DisplayContent(继承自RootDisplayArea)
│ ├── TaskDisplayArea
│ │ ├── Task
│ │ │ ├── ActivityRecord
│ │ ├── Task
│ │ │ ├── ActivityRecord
│ ├── TaskDisplayArea
│ │ ├── Task
│ │ │ ├── ActivityRecord
├── DisplayContent
├── TaskDisplayArea
├── Task
├── ActivityRecord
2.1.2 DisplayArea
DisplayArea-Container for grouping WindowContainer below DisplayContent.
Dimmable is inner class in DisplayArea
Tokens is inner class in DisplayArea
WindowContainer
DisplayArea
TaskDisplayArea
Dimmable
Tokens
RootDisplayArea
DisplayContent
DisplayAreaGroup
2.1.3 WindowOrganizer
WindowOrganizer
DisplayAreaOrganizer
TaskFragmentOrganizer
TaskOrganizer
RootDisplayAreaOrganizer
RootTaskDisplayAreaOrganizer
ShellTaskOrganizer
WindowToken 继承自WindowContainer, 其addWindow(windowState) 方法会去创建SurfaceControl, 该过程调用的createSurfaceControl(true) 是WindowContainer内的方法,又牵扯到各级的parent,堆栈较深,最终是在DisplayContent.java 的makeChildSurface(...)方法内调用了WindowManagerService的makeSurfaceBuilder(...)方法创建了一个SurfaceControl.Builder。
dumpsys window windowsdump出的Window #** 其实是WindowState。
一个WindowToken会对应多个WindowState, 特别是当设置了LayoutParams.token后,多个WindowState会用同一个WindowToken, 根据代码注释,他们可以共用一样的policy。
2.1.4 PhoneWindow
PhoneWindow 继承自类android.view.Window ,根据后者的注释,它提供了标准的背景,标题区域和key 处理等。
一个Activity会对应一个PhoneWindow对象; android.app.Dialog中也使用了PhoneWindow。
直接通过 android.view.WindowManager 中的addView(view, layoutParams) 就不会使用到PhoneWindow,但是ViewRootImpl对象还是会创建的。
2.1.5 SurfaceControl对象的创建
SurfaceFlinger Client SurfaceComposerClient android_view_SurfaceControl SurfaceControl SurfaceFlinger Client SurfaceComposerClient android_view_SurfaceControl SurfaceControl nativeCreate() createSurfaceChecked(...) createSurface(..) createLayer(...)
2.1.6 Surface对象的创建
下面是Android 13上面的code, 不管是哪种方式,都需要native层创建BBQSurface对象。
cpp
sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
std::unique_lock _lock{mMutex};
sp<IBinder> scHandle = nullptr;
if (includeSurfaceControlHandle && mSurfaceControl) {
scHandle = mSurfaceControl->getHandle();
}
return new BBQSurface(mProducer, true, scHandle, this);
}
下面是一种创建方式, ViewRootImpl通过Surface.java中的transferFrom(surface)方法给成员变量mSurface作初始化或者说使和native层关联起来:
Surface android_view_Surface BBQSurface BLASTBufferQueue.cpp android_grapics_BLASTBufferQueue BLASTBufferQueue.java ViewRootImpl Surface android_view_Surface BBQSurface BLASTBufferQueue.cpp android_grapics_BLASTBufferQueue BLASTBufferQueue.java ViewRootImpl BBQSurface 继承自Surface mSurface.transferFrom(blastSurface) createSurface() 1 nativeGetSurface(...) 2 getSurface(...) 3 new BBQSurface 4 return sp<Surface> 5 android_view_Surface_createFromSurface(sp<Surface>) 6 return jobject surfaceObj 7 Surface object(Surface.java object) 8 Surface object 9 transferFrom(surface) 10
3. Hardware Composer(HWC)
Android 定义了HAL interface hardware/interfaces/graphics/composer, 从Android 13开始,推荐使用AIDL版本。在参与的高通平台上,高通提供了该HAL interface的实现。
4. SurfaceFlinger native进程
service surfaceflinger是一个native 进程,代码路径是frameworks/native/services/surfaceflinger。 surfaceflinger.rc文件定义了该进程的一些属性。
进程的入口函数main实现在 main_surfaceflinger.cpp中,在该方法中注册了"SurfaceFlinger"和"SurfaceFlingerAIDL"服务:
cpp
// publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
// publish gui::ISurfaceComposer, the new AIDL interface
sp<SurfaceComposerAIDL> composerAIDL = sp<SurfaceComposerAIDL>::make(flinger);
if (FlagManager::getInstance().misc1() &&
!FlagManager::getInstance().disable_sched_fifo_composer()) {
composerAIDL->setMinSchedulerPolicy(SCHED_FIFO, newPriority);
}
sm->addService(String16("SurfaceFlingerAIDL"), composerAIDL, false,
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
SurfaceFlinger中默认使用的render engine是GLESRenderEngine,相关代码是GLESRenderEngine.cpp。
SurfaceFlinger 合成(或准备)的所有数据,最终都必须通过 HWC(Hardware Composer)接口,由 HWC 的实现来与 Linux Kernel 的显示驱动进行通信,并最终将帧送给 Display 显示。
应用程序 → Surface → BufferQueue → SurfaceFlinger → HWC HAL → ioctl() → Linux Kernel 显示驱动 → 显示控制器硬件 → 显示面板
5. BufferQueue
BufferQueue所使用的memory由Galloc memory allocator分配,Google为该分配器定义了两个HAL interface hardware/interfaces/graphics/allocator/ and hardware/interfaces/graphics/mapper/。在参与的高通平台上,高通提供了这两个HAL interface的实现。
"Allocator HAL implementation" Gralloc5Allocator GraphicBufferAllocator GraphicBuffer BBQBufferQueueProducer BBQSurface * "Allocator HAL implementation" Gralloc5Allocator GraphicBufferAllocator GraphicBuffer BBQBufferQueueProducer BBQSurface * BBQBufferQueueProducer 继承自 BufferQueueProducer 继承自GrallocAllocator, 代码文件是Gralloc5.h 和Gralloc5.cpp 是否使用 Gralloc5Allocator,取决于HAL 实现放使用什么版本,比如也可能是Gralloc4Allocator allocateBuffers(...) allocateBuffers(...) new GraphicBuffer(...) initWithSize(...) allocate(...) allocateHelper(...) allocate(...) allocate(...)
Surface对象和BLASTBufferQueue对象运行在Application进程中,调用Surface的
queueBuffer()函数之后,经过BufferQueueProducer和BufferQuqueConsumer的传递,BLASTBufferQueue中的onFrameAvailable()函数会被调用,经由SurfaceComposerClient::Transaction的apply()函数提交到SurfaceFlinger进程。
6. Native so
6.1 libandroid_runtime.so
安装在设备上的system/bin/app_process.bin是zygote进程的入口,代码路径是frameworks/base/cmds/app_process。libandroid_runtime.so是作为shared library被链接的,运行时会被加载。
6.2 libhwui.so
Render thread
render thread的实现代码是 RenderThread.cpp,在libhwui.so中,RenderThread继承了ThreadBase,后者继承了Thread。
ActivityManagerServic.java中的setRenderThread(int tid)可以将render thead的ID保存在ProcessRecord对象中,一个Process对应一个render thread。
RenderThread.cpp的static成员函数getInstance()提供了单例,所以虽然每个ViewRootImpl对象都可能触发RenderThread的创建,但是一旦创建完成,就是单例。
Main thread, main looper
一个进程中,和进程共用一个ID的线程即是主线程,从主线程中创建的Looper对象即是main looper; 主线程也就是UI 线程,UI相关的操作要在该线程中。代码细节,ActivityThread.java中的main()方法作为应用进程的入口函数,会创建Main looper,这个Looper对象就是Main thread中的Looper,而且 sMainThreadHandler会指向这个Looper对象。sMainThreadHandler是ActivityThread.java中的static变量,也就是说该进程中所有Activity对像共用一个Main Looper对象。
android:hardwareAccelerated在Android SDK 14及以上版本默认设置为true。
6.3 libnativewindow.so
代码路径:frameworks/native/libs/nativewindow
会编译成 libnativewindow.so,定义了struct ANativeWindow, Surface.cpp中类Surface继承了ANativeWindow,所以ANativeWindow打通了访问Surface的通道。
包含在NDK中,供第三方Native代码使用。
frameworks/native/libs/nativewindow/include/system/window.h中定义了native_window_set_buffers_smpte2086_metadata inline函数
cpp
static inline int native_window_set_buffers_smpte2086_metadata(
struct ANativeWindow* window,
const struct android_smpte2086_metadata* metadata)
{
return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA,
metadata);
}
6.4 libandroid.so
代码路径:frameworks/base/native/android/
编译生成libandroid.so,是个桥接/glue so,相关功能实现在libandroid_runtime.so等内。
包括在NDK中,供第三方Native代码使用。
6.5 libnativedisplay.so
代码路径:frameworks/native/libs/nativedisplay/
编译生成libnativedisplay.so, 是个桥接/glue so,相关功能实现在安装在系统中的其他so中,比如libgui.so。
包括在NDK中,供第三方Native代码使用。
7. Display
有物理屏(包括built-in 和external;支持热插拔)和虚拟屏。
Display.java: 提供有关逻辑显示的大小和密度的信息。
LogicalDisplay.java
添加Display
下面的流程分了个图,第一个图是SurfaceFlinger native 进程内的处理过程,第二个图是Jave 进程(systemserver)内的处理流程。
BitTube DisplayEventReceiver EventThreadConnection EventThread Scheduler SufraceFlinger AidlComposerHal HWComposer MessageQueue Schedule SurfaceFlinger HWC BitTube DisplayEventReceiver EventThreadConnection EventThread Scheduler SufraceFlinger AidlComposerHal HWComposer MessageQueue Schedule SurfaceFlinger HWC mCurrentState.displays.add(...) 这里和前面是不连贯的,不太确定会从哪里触发这个调用 mPendingEvents.push_back(event) threadMain 方法里面有个while循环,一直在从mPendingEvents中取Event 这里使用参数mChannel,该参数是BitTube类型 sendObjects是static方法 调用的是mChannel对象的write方法, BitTube内用的是SocketPair,在此之前已经将Java进程通过JNI创建的NativeDisplayEventReceiver已经在createDisplayEventConnection后将上面mChannel的fd都拿到了。 onComposerHalHotplug(...) 1 scheduleConfigure() 2 scheduleConfigure() 3 configure() 4 configureLocked() 5 onHotplug(...) 6 onHotplugConnect(hwcDisplayId) 7 addDisplay(display) 8 processHotplug(...) 9 processDisplayAdded(...) 10 dispatchDisplayHotplugEvent(...) 11 onHotplugReceived(...) 12 onHotplugReceived(...) 13 postEvent(event) 14 sendEvents(mChannel, ...) 15 sendObjects(...) 16 write(...) 17
LogicalDisplayMapper DisplayDeviceRepository LocalDisplayAdapter LocalDisplayEventListener ProxyDisplayEventReceiver DisplayEventReceiver NativeDisplayEventReceiver LogicalDisplayMapper DisplayDeviceRepository LocalDisplayAdapter LocalDisplayEventListener ProxyDisplayEventReceiver DisplayEventReceiver NativeDisplayEventReceiver 继承了 DisplayEventDispatcher 来自 Looper.cpp(system/core/libutils)中的回调 in android_view_DisplayEventReceiver.cpp DISPLAY_DEVICE_EVENT_ADDED LocalDisplayAdapter继承了DisplayAdapter handleEvent(...) processPendingEvents(...) dispatchHotplug(...) onHotplug(...) onHotplug(...) tryConnectDisplayLocked(...) sendDisplayDeviceEventLocked(...) onDisplayDeviceEvent(...) handleDisplayDeviceAdded(...) sendEventLocked(...) onDisplayDeviceEventLocked(...) handleDisplayDeviceAddedLocked(...) createNewLogicalDisplayLocked(...)