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 WebView无法加载H5页面的常见问题和解决方法

《AndroidWebView无法加载H5页面的常见问题和解决方法》AndroidWebView是一种视图组件,使得Android应用能够显示网页内容,它基于Chromium,具备现代浏览器的许多功... 目录1. WebView 简介2. 常见问题3. 网络权限设置4. 启用 JavaScript5. D

Android如何获取当前CPU频率和占用率

《Android如何获取当前CPU频率和占用率》最近在优化App的性能,需要获取当前CPU视频频率和占用率,所以本文小编就来和大家总结一下如何在Android中获取当前CPU频率和占用率吧... 最近在优化 App 的性能,需要获取当前 CPU视频频率和占用率,通过查询资料,大致思路如下:目前没有标准的

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影