Android显示系统(09)- SurfaceFlinger的使用

Android显示系统(01)- 架构分析
Android显示系统(02)- OpenGL ES - 概述
Android显示系统(03)- OpenGL ES - GLSurfaceView的使用
Android显示系统(04)- OpenGL ES - Shader绘制三角形
Android显示系统(05)- OpenGL ES - Shader绘制三角形(使用glsl文件)
Android显示系统(06)- OpenGL ES - VBO和EBO和VAO
Android显示系统(07)- OpenGL ES - 纹理Texture
Android显示系统(08)- OpenGL ES - 图片拉伸
Android显示系统(09)- SurfaceFlinger的使用
Android显示系统(10)- SurfaceFlinger内部结构
Android显示系统(11)- 向SurfaceFlinger申请Surface
Android显示系统(12)- 向SurfaceFlinger申请Buffer
Android显示系统(13)- 向SurfaceFlinger提交Buffer

一、前言:

之前文章讲解了Android显示系统的架构,并且花了大量时间介绍了OpenGL ES,以及为了保证OpenGL ES的平台无关性,Android引入的EGL。不过我们都是借助于GLSurfaceView来学习的,而我们构建GLSurfaceView对象的时候,在Native层做了很多的事情,其中,大多数逻辑都是SurfaceFlinger辅助我们完成的,它才是整个Android显示系统的核心。

SurfaceFlinger最重要的职责就是合成各个App传递过来的Surface。本文先学会在Native层使用SurfaceFlinger,后续根据代码一点点引入不同知识。

**说明:**后续文章如果出现SF那就是我对SurfaceFlinger的缩写。

二、BootAnimation:

读者可能很郁闷,讲SF的使用,怎么突然蹦出来这么一个东西。其实,BootAnimation是 Android 系统启动时显示的动画,通常包括启动画面、动画效果和加载过程中的图形展示。要学习Native层显示系统,它是最好的程序之一,因为,此时AMS、WMS那些复杂的服务还没有启动,干扰项少!

1、启动:

  • Android.bp当中启动bootanim.rc
  • 解析文件内容启动BootAnimation进程;
  • 启动之后,就会调用BootAnimation的main函数;

这是base\cmds\bootanimation\bootanim.rc内容,我都贴心的加了注释。

# 这行定义了一个名为 bootanim 的服务,服务的可执行文件是 /system/bin/bootanimation。
service bootanim /system/bin/bootanimation
    # 这行指定了服务的类别。将其归类为 core 和 animation 意味着该服务属于系统的核心服务及动画服务类别,可能影响其调度和优先级
    class core animation
    # 这行指定了运行该服务的用户身份是 graphics
    user graphics
    # 这行指定该服务属于 graphics 和 audio 组。这样做是为了允许该服务访问所需的资源和设备,因此图形和音频相关的权限会得到支持。
    group graphics audio
    # 这表示该服务在系统启动时不会自动启动。
    disabled
    # 这个关键字指明该服务是一种一次性服务。它在启动后会运行一次并退出,而不是保持在后台持续运行
    oneshot
    # 这行设置了 I/O 调度优先级,rt 表示实时优先级,0 是优先级值。设置为 0 表示它具有较低的实时优先级
    ioprio rt 0
    # 这一行表示将该服务的进程 ID(PID)写入到特定路径 /dev/stune/top-app/tasks 中
    writepid /dev/stune/top-app/tasks

注意,其中这一行disabled表示这个服务不会自己启动,为什么呢?因为它要渲染开机画面,离不开大佬SurfaceFlingerSurfaceFlinger启动之后,会将这个改成enable,然后,bootanimation服务就启动了,启动后当然就要执行main函数了。

2、流程概述:

我们假设自己没有阅读过BootAnimation,但是,我们对SurfaceFlinger比较熟悉,我们觉得应该怎么做?

  • 获得SurfaceFlinger服务;
  • 通过SurfaceFlinger创建Surface;
  • 开始循环:
    • 得到surface里面的buffer;
    • 设置给渲染引擎(比如之前的OpenGL ES),往buffer填充数据;
    • 提交填充好的buffer;

后续我们阅读完开机动画代码之后再总结,只是会详细很多,透过现象看本质,大体思路不会变。

3、main函数:

文件路径:base\cmds\bootanimation\bootanimation_main.cpp

代码如下:

int main()
{
   
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);

    bool noBootAnimation = bootAnimationDisabled();
    ALOGI_IF(noBootAnimation,  "boot animation disabled");
    if (!noBootAnimation) {
   

        sp<ProcessState> proc(ProcessState::self());
        ProcessState::self()->startThreadPool();

        // create the boot animation object (may take up to 200ms for 2MB zip)
        sp<BootAnimation> boot = new BootAnimation(audioplay::createAnimationCallbacks());

        waitForSurfaceFlinger();

        boot->run("BootAnimation", PRIORITY_DISPLAY);

        ALOGV("Boot animation set up. Joining pool.");

        IPCThreadState::self()->joinThreadPool();
    }
    return 0;
}

总体来看:

负责设置进程的优先级,检查是否禁用 BootAnimation,启动并设置 BootAnimation 相关的状态和资源,同时确保在 SurfaceFlinger 可用后开始播放动画。通过这样的结构,系统能够顺利地处理BootAnimation的显示,确保用户在设备开机时有良好的视觉体验。

详细看看:

  • 设置进程优先级:

    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
    
    • PRIO_PROCESS 指定要修改的是进程的优先级。
    • 0 表示当前进程(即当前执行的 main 函数)。
    • ANDROID_PRIORITY_DISPLAY 是一个常量,通常是在 Android 中用于设置与显示相关的进程优先级,确保 Boot Animation 在显示时有足够的资源进行渲染。
  • 检查是否禁用 BootAnimation:

    bool noBootAnimation = bootAnimationDisabled();
    

    如果没有禁用,才会执行主要逻辑;

  • 打开Binder,并启动线程池:

    因为SF就是一个Binder服务,要想访问SF,必须先打开Binder;

    sp<ProcessState> proc(ProcessState::self());
    ProcessState::self()->startThreadPool();
    

    其实ProcessState::self()主要作用就是打开binder,并将进程和线程的相关信息设置进binder的binder_proc,binder_thread结构当中。接着通过startThreadPool()启动线程池,主要处理 IPC(进程间通信)请求。这样可以在后台异步处理工作而不阻塞主线程。

  • 创建 BootAnimation 对象,并设置音频回调函数:

    sp<BootAnimation> boot = new BootAnimation(audioplay::createAnimationCallbacks());
    

    这回调函数应该是播放那个开机完了噔噔噔噔的,我没看!!

  • 等待 SurfaceFlinger可用:

    waitForSurfaceFlinger();
    
  • 运行BootAnimation

    boot->run("BootAnimation", PRIORITY_DISPLAY);
    

    传入“BootAnimation”的名称和显示优先级 PRIORITY_DISPLAY。

  • 加入线程池:

    IPCThreadState::self()->joinThreadPool()

你可能感兴趣的:(Android显示系统,Android,android,媒体,音视频)