目录

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相关推荐

  1. Android 10 SurfaceView 奔溃报错signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4

    最近在Android 10 系统上发现SurfaceView 测试的时候奔溃了,10以前的系统测试都会奔溃,在Android 11之后的设备上是正常的. 上错误日志 Native 报错信息 signa ...

  2. Android 10亮屏、熄屏和自动调光

    前言 Android设备与用户进行交互往往通过屏幕进行,目前市场手机设备对于屏幕越来月看重,oled.高刷.大尺寸.全色域等都是各大厂商的pk项,目的都是为了提高设备的交互体验,同时现在大多数设备都已 ...

  3. Android 开机动画启动、播放、退出流程(android 10)

    Android 开机动画启动流程 (android 10) 1 开机动画启动流程 我们先来看一下开机动画是如何启动,并开始播放的. 通过系统启动流程分析可以得知,在系统内核启动后,会启动第一个init ...

  4. Android 10 新增的功能

    个人表示看了2个多小时 ,基本了解如下 android 10 对应的API 版本为29  好像名字就是android 10 没看到什么甜品的名称了 可以在官网上看到android 对应的版本如下 an ...

  5. Android 10 vivo,更快更安全,vivo产品经理宣布:iQOO将首批适配Android 10正式版

    今天,谷歌一年一度的I/O 2019开发者大会如期举行.此次大会除了多款重磅新产品,新一代系统Android Q(10)beta版本的更多新功能也被揭开.除了支持5G网络.针对折叠屏这样的大屏设备进行 ...

  6. Android10剪贴板,剪纸堆 Clip Stack - 轻量级剪贴板管理程序(支持 Android 10)

    编辑点评 剪贴板的历史记录这么看 剪纸堆 Clip Stack - 轻量级剪贴板管理程序(支持 Android 10) 介绍 剪纸堆 Clip Stack - 轻量级剪贴板管理程序(支持 Androi ...

  7. Android 10.0 PackageManagerService(三)APK扫描-[Android取经之路]

    摘要:上一节讲解了PKMS的 权限扫描,扫描/system/etc/permissions中的xml,存入相应的结构体中,供之后权限管理使用. 这一节主要来讲讲APK的扫描. 阅读本文大约需要花费15 ...

  8. Android 10.0 PackageManagerService(二)权限扫描-[Android取经之路]

    摘要:PackageManagerService在systemReady()后,进行了/system/etc/permissions中的各种xml进行扫描,进行相应的权限存储,供以后使用 阅读本文大约 ...

  9. Android 10.0 PackageManagerService(一)工作原理及启动流程-[Android取经之路]

    摘要:PackageManagerService是Android系统核心服务之一,在Android中的非常重要,主要负责APK.jar包等的管理. 阅读本文大约需要花费50分钟. 文章的内容主要还是从 ...

最新文章

  1. 求1-2+3-4+5......99的所有数的和
  2. matlab r2007课后答案,《MATLAB R2007基础教程》习题答案.doc
  3. 科园贸易:帆软助力其推动数据应用落地,打造自主可控数据平台
  4. 单位阶跃信号是周期信号吗_vivoS7e是5G手机吗-支持5G吗-5G信号怎么样
  5. C++ 类对象和 指针的区别
  6. 小区物业收费管理系统
  7. 计算机功能转动怎么设定,怎么旋转电脑屏幕
  8. 快速复制文件地址——无任何安装
  9. Chap1_基础理论+Chap2_数据准备和数据模型
  10. 我从校园出来的这几年
  11. 2021爱智先行者—人体存在感传感器
  12. 如何压缩视频而不降低画质?
  13. 详解ENet | CPU可以实时的道路分割网络
  14. TensorFlow Lite 开发手册(5)——TensorFlow Lite模型使用实例(分类模型)
  15. CSS一个摇摆的大红灯笼
  16. Windows无线网“无法连接到这个网络”的解决办法
  17. 《操作系统真象还原》第二章
  18. 企业为何要认定高新技术企业,都有哪些好处?
  19. 接口调用失败重试方案
  20. PAT甲级官网 刷题(3)

热门文章

  1. 原型链prototype和__proto__
  2. 前端学习日志之复刻百度新闻百家号专栏
  3. linux 双网卡主备,CentOS下双网卡主备模式配置
  4. 中海达智能驾驶定位方案白皮书
  5. 什么是静态变量 举例 C语言入门
  6. 计算机考研400分能上清华吗,考研400分能上清华吗 400分是什么水平
  7. linux netlink 机制,Linux Netlink 编程
  8. Python 学习笔记-第9讲:面向对象练习-猜拳游戏
  9. Linux系统占用cpu病毒处理记录
  10. 婚恋交友平台小程序制作开发代码案例