Android graphics - 框架摘要

Android graphics


1. Graphics框图

下图从binary level总结了Graphic相关的代码,不注重细节,主要目的是展示Android实现的思路和大框架,角度有区别于Android官网的文档,算是一个补充。

图中绿色的线主要展示渲染相关的流程;紫色的线主要展示合成和显示的流程;红色的线展示了BLASTBufferQueue分配内存的流程。


2. Frameworks

framework.jarservices.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(...)

相关推荐
AC赳赳老秦4 小时前
DeepSeek优化多智能体指令:避免协同冲突,提升自动化流程稳定性
android·大数据·运维·人工智能·自然语言处理·自动化·deepseek
峥嵘life7 小时前
Android16 【CTS】CtsWindowManagerDeviceAnimations存在fail项
android·linux·学习
阿拉斯攀登8 小时前
第 7 篇 安卓驱动开发的灵魂:字符设备驱动框架,从原理到最简实战
android·驱动开发·rk3568·嵌入式驱动·安卓驱动
阿拉斯攀登8 小时前
第 1 篇 入坑不亏!瑞芯微 RK 平台 + 安卓驱动开发,小白全维度扫盲
android·驱动开发·rk3568·嵌入式驱动
Android系统攻城狮8 小时前
Android tinyalsa深度解析之pcm_params_get调用流程与实战(一百六十二)
android·pcm·tinyalsa·android hal·audio hal
zh路西法8 小时前
【C语言简明教程提纲】(四):结构体与文件定义和操作
android·c语言·redis
常利兵9 小时前
Jetpack Compose 1.8 新特性来袭,打造丝滑开发体验
android
牢七9 小时前
百家cms 审计 未完成
android·ide·android studio
hjxu20169 小时前
【 MySQL 速记5】插入
android·数据库·mysql