Android 10 SurfaceFlinger

2024-02-24 22:58
文章标签 android surfaceflinger

本文主要是介绍Android 10 SurfaceFlinger,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

               

 

 

                                                                           Andorid 10 SurfaceFlinger

模块介绍

 

源码介绍

startGraphicsAllocatorService()函数解析


               

Andorid 10 SurfaceFlinger

 

 

  • 模块介绍

SurfaceFlinger 接受来自多个源的数据缓冲区,然后将它们进行合成并发送到显示屏。WindowManager 为 SurfaceFlinger 提供缓冲区和窗口元数据,而 SurfaceFlinger 可使用这些信息将 Surface 合成到屏幕。

SurfaceFlinger 可通过两种方式接受缓冲区:通过 BufferQueue 和 SurfaceControl,或通过 ASurfaceControl。

SurfaceFlinger 接受缓冲区的一种方式是通过 BufferQueue 和 SurfaceControl。当应用进入前台时,它会从 WindowManager 请求缓冲区。然后,WindowManager 会从 SurfaceFlinger 请求层。层是 surface(包含 BufferQueue)和 SurfaceControl(包含屏幕框架等层元数据)的组合。SurfaceFlinger 创建层并将其发送至 WindowManager。然后,WindowManager 将 Surface 发送至应用,但会保留 SurfaceControl 来操控应用在屏幕上的外观。

Android 10 新增了 ASurfaceControl,这是 SurfaceFlinger 接受缓冲区的另一种方式。ASurfaceControl 将 Surface 和 SurfaceControl 组合到一个事务包中,该包会被发送至 SurfaceFlinger。ASurfaceControl 与层相关联,应用可通过 ASurfaceTransactions 更新该层。然后,应用可通过回调(用于传递包含锁定时间、获取时间等信息的 ASurfaceTransactionStats)获取有关 ASurfaceTransactions 的信息。

下表包含有关 ASurfaceControl 及其相关组件的更多详细信息。

组件说明
ASurfaceControl对 SurfaceControl 进行包装并使应用能够创建与屏幕上的各层相对应的 SurfaceControl。

可作为 ANativeWindow 的一个子级或者另一个 ASurfaceControl 的子级创建。
ASurfaceTransaction对事务进行包装,以使客户端能够修改层的描述性属性(比如几何图形),并将经过更新的缓冲区发送至 SurfaceFlinger。
ASurfaceTransactionStats通过预先注册的回调将有关已显示事务的信息(比如锁定时间、获取时间和上一个释放栅栏)发送至应用。

虽然应用可以随时提交缓冲区,但 SurfaceFlinger 仅能在屏幕处于两次刷新之间时唤醒,以接受缓冲区,这会因设备而异。这样可以最大限度地减少内存使用量,并避免屏幕上出现可见的撕裂现象(如果显示内容在刷新期间更新,则会出现此现象)。

在屏幕处于两次刷新之间时,屏幕会向 SurfaceFlinger 发送 VSYNC 信号。VSYNC 信号表明可对屏幕进行刷新而不会产生撕裂。当 SurfaceFlinger 接收到 VSYNC 信号后,SurfaceFlinger 会遍历其层列表,以查找新的缓冲区。如果 SurfaceFlinger 找到新的缓冲区,SurfaceFlinger 会获取缓冲区;否则,SurfaceFlinger 会继续使用上一次获取的那个缓冲区。SurfaceFlinger 必须始终显示内容,因此它会保留一个缓冲区。如果在某个层上没有提交缓冲区,则该层会被忽略。

SurfaceFlinger 在收集可见层的所有缓冲区之后,便会询问硬件混合渲染器 (HWC) 应如何进行合成。如果 HWC 将层合成类型标记为客户端合成,则 SurfaceFlinger 将合成这些层。然后,SurfaceFlinger 会将输出缓冲区传递给 HWC。

 

  • 源码介绍

源代码主要位于

frameworks\native\services\surfaceflinger\

其中看Android.bp以及SurfaceFlinger.rc可知

cc_binary {
    name: "surfaceflinger",
    defaults: ["libsurfaceflinger_binary"],
    init_rc: ["surfaceflinger.rc"],
    srcs: [":surfaceflinger_binary_sources"],
    shared_libs: [
        "libsurfaceflinger",
        "libSurfaceFlingerProp",
    ],
}

 

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:s0

可见surfaceflinger会伴随系统启动,并且重启会导致zygote的重启。

我们知道一个bin文件的入口函数肯定为main函数所以我们从main函数入手找到main_surfaceflinger.cpp。

分析从这个文件的main函数开始

int main(int, char**) {
    signal(SIGPIPE, SIG_IGN);//当断开连接时,禁止退出交由系统处理

    hardware::configureRpcThreadpool(1 /* maxThreads */,
            false /* callerWillJoin */);//创建hildl的线程池

    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 = surfaceflinger::createSurfaceFlinger();

    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 | IServiceManager::DUMP_FLAG_PROTO);

    startDisplayService(); // dependency on SF getting registered above

    struct sched_param param = {0};
    param.sched_priority = 2;
    if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
        ALOGE("Couldn't set SCHED_FIFO");
    }

    // run surface flinger in this thread
    flinger->run();

    return 0;
}

下面将main函数里主要函数进行剖析讲解。

  1. startGraphicsAllocatorService()函数解析

从字面上来看是要启动一个图形内存收集器的服务,我们进入深入探究一下

  • static status_t startGraphicsAllocatorService() {

        using android::hardware::configstore::getBool;
        using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
        if (!android::sysprop::start_graphics_allocator_service(false)) {
            return OK;
        }

        status_t result = hardware::registerPassthroughServiceImplementation<
                android::hardware::graphics::allocator::V3_0::IAllocator>();
        if (result == OK) {
            return OK;
        }

        result = hardware::registerPassthroughServiceImplementation<
                android::hardware::graphics::allocator::V2_0::IAllocator>();
        if (result != OK) {
            ALOGE("could not start graphics allocator service");
            return result;
        }

        return OK;
    }

     这里遇到的第一个函数是android::sysprop::start_graphics_allocator_service(false)这个函数定义在frameworks\native\services\surfaceflinger\SurfaceFlingerProperties.cpp

     函数源码如下:

    bool start_graphics_allocator_service(bool defaultValue) {
    auto temp = SurfaceFlingerProperties::start_graphics_allocator_service();
    if (temp.has_value()) {
        return *temp;
    }
    return getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::startGraphicsAllocatorService>(
            defaultValue);
}

这个函数的第一个函数遇到一点疑问,在源码中搜不到这个函数的定义,后来才发现是Android10新添加的新特性叫做将系统属性作为 API 实现在这篇博客将这个功能进行了介绍。

通过链接里的知识我们可以知道SurfaceFlingerProperties::start_graphics_allocator_service()这个函数的定义是在frameworks\native\services\surfaceflinger\sysprop\SurfaceFlingerProperties.sysprop

定义如下:

# Returns true if surface flinger should start
# hardware.graphics.allocator@2.0::IAllocator service.
prop {
    api_name: "start_graphics_allocator_service"
    type: Boolean
    scope: System
    access: Readonly
    prop_name: "ro.surface_flinger.start_graphics_allocator_service"
}

从这里我看可以看到这里主要是获取ro.surface_flinger.start_graphics_allocator_service这个属性值。返回之前的start_graphics_allocator_service(bool defaultValue)函数,将属性值赋予temp

如果temp有值则返回这个值,没有值得话则返回getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::startGraphicsAllocatorService>(defaultValue)

getBool还有一个专有名称叫做效用函数。

关于这个函数的定义则位于hidl的ConfigStore中configstore/utils/include/configstore/Utils.h代码如下:

template<typename I, android::hardware::Return<void> (I::* func)
        (std::function<void(const OptionalBool&)>)>
bool getBool(const bool defValue) {
    return get<OptionalBool, I, func>(defValue);
}

这里使用模板函数进行定义并且调用get函数此函数定义如下:

// arguments V: type for the value (i.e., OptionalXXX)
//           I: interface class name
//           func: member function pointer
template<typename V, typename I, android::hardware::Return<void> (I::* func)
        (std::function<void(const V&)>)>
decltype(V::value) get(const decltype(V::value) &defValue) {
    using namespace android::hardware::details;
    // static initializer used for synchronizations
    auto getHelper = []()->V {
        V ret;
        sp<I> configs = getService<I>();

        if (!configs.get()) {
            // fallback to the default value
            ret.specified = false;
        } else {
            auto status = (*configs.*func)([&ret](V v) {
                ret = v;
            });
            if (!status.isOk()) {
                std::ostringstream oss;
                oss << "HIDL call failed for retrieving a config item from "
                       "configstore : "
                    << status.description().c_str();
                logAlwaysError(oss.str());
                ret.specified = false;
            }

        }

        return ret;
    };
    static V cachedValue = getHelper();

    if (wouldLogVerbose()) {
        std::string iname = __PRETTY_FUNCTION__;
        // func name starts with "func = " in __PRETTY_FUNCTION__
        auto pos = iname.find("func = ");
        if (pos != std::string::npos) {
            iname = iname.substr(pos + sizeof("func = "));
            iname.pop_back();  // remove trailing ']'
        } else {
            iname += " (unknown)";
        }

        std::ostringstream oss;
        oss << iname << " retrieved: "
            << (cachedValue.specified ? cachedValue.value : defValue)
            << (cachedValue.specified ? "" : " (default)");
        logAlwaysVerbose(oss.str());
    }

    return cachedValue.specified ? cachedValue.value : defValue;
}

这个函数略长,总体分析下来的意思就是先获取一个Helpler用来访问数据,然后去查询数据。

对应到我们之前getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::startGraphicsAllocatorService>(defaultValue)的调用就是获取ISurfaceFlingerConfigs这个类下startGraphicsAllocatorService

这个函数的值。写到此处心中万马奔腾,就为了调用一个函数获取一个值,绕了一大圈。

这个函数的定义在hardware/interfaces/configstore/1.1/default/SurfaceFlingerConfigs.cpp代码如下:

Return<void> SurfaceFlingerConfigs::startGraphicsAllocatorService(
        startGraphicsAllocatorService_cb _hidl_cb) {
    bool value = false;
#ifdef START_GRAPHICS_ALLOCATOR_SERVICE
    value = true;
#endif
    _hidl_cb({true, value});
    return Void();
}

这么一大堆的调用实际上是使用了ConfigStore HAL但是这东西特别占用内存,从上面的一大堆函数调用就可以看出。

为什么出这么万恶的东西官方的回答如下:

Android 8.0 将整个 Android 操作系统拆分为通用分区 (system.img) 和硬件专用分区(vendor.img 和 odm.img)。受这种变更的影响,必须从安装到系统分区的模块中移除条件编译,而且此类模块必须在运行时确定系统的配置(并根据相应配置表现出不同的行为)。

然后官方又说了:

Android 10 因 ConfigStore HAL 内存耗用量高且难以使用而将其弃用,并用系统属性替换了这个 HAL。在 Android 10 中:

  • ConfigStore 使用构建标记在供应商分区中存储配置值,系统分区中的服务使用 HIDL 访问这些值(在 Android 9 中也是如此)。
  • 系统属性使用 PRODUCT_DEFAULT_PROPERTY_OVERRIDES 在供应商分区的 default.prop 中存储系统属性,服务使用 sysprop 读取这些属性。

ConfigStore HAL 保留在 AOSP 中以支持旧版供应商分区。在搭载 Android 10 的设备上,surfaceflinger 首先读取系统属性;如果没有为 SurfaceFlingerProperties.sysprop 中的配置项定义任何系统属性,则 surfaceflinger 会回退到 ConfigStore HAL。

这是安卓自己给自己挖坑,然后带大家都跳进去了,然后出不来了。后来又挖了一个新坑,这让我们这些开发猝不及防啊。

这里也就完美解释了为啥出现了下面这段代码:

    if (temp.has_value()) {
        return *temp;
    }
    return getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::startGraphicsAllocatorService>(
            defaultValue);

我们这是被逼进入了老版本的ConfigStore HAL这个坑里了。

 

回到之前的调用函数SurfaceFlingerConfigs::startGraphicsAllocatorService(
        startGraphicsAllocatorService_cb _hidl_cb)首先查看是否定义了全局变量 START_GRAPHICS_ALLOCATOR_SERVICE这个全局变量的定义在

surfaceflinger.mk:50:ifneq ($(SF_START_GRAPHICS_ALLOCATOR_SERVICE),)
surfaceflinger.mk:51:    LOCAL_CFLAGS += -DSTART_GRAPHICS_ALLOCATOR_SERVICE

看来还有一个全局变量SF_START_GRAPHICS_ALLOCATOR_SERVICE,如果这些变量都没有那么我们就给 _hidl_cb({true, value});

 

 

 

 

 


 

 

 

这篇关于Android 10 SurfaceFlinger的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/743638

相关文章

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

Android DataBinding 与 MVVM使用详解

《AndroidDataBinding与MVVM使用详解》本文介绍AndroidDataBinding库,其通过绑定UI组件与数据源实现自动更新,支持双向绑定和逻辑运算,减少模板代码,结合MV... 目录一、DataBinding 核心概念二、配置与基础使用1. 启用 DataBinding 2. 基础布局

Android ViewBinding使用流程

《AndroidViewBinding使用流程》AndroidViewBinding是Jetpack组件,替代findViewById,提供类型安全、空安全和编译时检查,代码简洁且性能优化,相比Da... 目录一、核心概念二、ViewBinding优点三、使用流程1. 启用 ViewBinding (模块级

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

Android NDK版本迭代与FFmpeg交叉编译完全指南

《AndroidNDK版本迭代与FFmpeg交叉编译完全指南》在Android开发中,使用NDK进行原生代码开发是一项常见需求,特别是当我们需要集成FFmpeg这样的多媒体处理库时,本文将深入分析A... 目录一、android NDK版本迭代分界线二、FFmpeg交叉编译关键注意事项三、完整编译脚本示例四

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I

Android 实现一个隐私弹窗功能

《Android实现一个隐私弹窗功能》:本文主要介绍Android实现一个隐私弹窗功能,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 效果图如下:1. 设置同意、退出、点击用户协议、点击隐私协议的函数参数2. 《用户协议》、《隐私政策》设置成可点击的,且颜色要区分出来res/l

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整

Android 12解决push framework.jar无法开机的方法小结

《Android12解决pushframework.jar无法开机的方法小结》:本文主要介绍在Android12中解决pushframework.jar无法开机的方法,包括编译指令、框架层和s... 目录1. android 编译指令1.1 framework层的编译指令1.2 替换framework.ja