本文主要是介绍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, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO");
}
// run surface flinger in this thread
flinger->run();
return 0;
}
下面将main函数里主要函数进行剖析讲解。
-
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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!