SurfaceFlinger启动流程
好久没有看源码,恰好接触到SurfaceFlinger,简单了解一下SurfaceFlinger。SurfaceFlinger是一个系统服务,接受来自多个来源的数据缓冲区,对它们进行合成,然后发送到显示设备进行显示。
在Zygote进程的启动一文中,了解到:在系统启动时,init进程读取位于/android/platform/system/core/rootdir目录下的init.rc文件,启动所有核心服务。其中,init进程入口是位于/system/core/init目录中的main.cpp:
int main(int argc, char** argv) {
...
if (argc > 1) {
...
if (!strcmp(argv[1], "second_stage")) {
return SecondStageMain(argc, argv); //第二阶段
}
}
return FirstStageMain(argc, argv); //第一阶段
}
当启动参数为"second_stage"时,走这里的SecondStageMain(argc, argv)方法,至于哪里传入先不管:
int SecondStageMain(int argc, char** argv) {
...
property_init(); //初始化属性服务
...
LoadBootScripts(am, sm); //加载启动脚本
..
return 0;
}
再调用LoadBootScripts(am, sm)方法中加载解析前面提到的init.rc文件:
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
Parser parser = CreateParser(action_manager, service_list);
std::string bootscript = GetProperty("ro.boot.init_rc", "");
if (bootscript.empty()) {
parser.ParseConfig("/init.rc");
if (!parser.ParseConfig("/system/etc/init")) {
late_import_paths.emplace_back("/system/etc/init");
}
if (!parser.ParseConfig("/product/etc/init")) {
late_import_paths.emplace_back("/product/etc/init");
}
if (!parser.ParseConfig("/product_services/etc/init")) {
late_import_paths.emplace_back("/product_services/etc/init");
}
if (!parser.ParseConfig("/odm/etc/init")) {
late_import_paths.emplace_back("/odm/etc/init");
}
if (!parser.ParseConfig("/vendor/etc/init")) {
late_import_paths.emplace_back("/vendor/etc/init");
}
} else {
parser.ParseConfig(bootscript);
}
}
init.rc是用Android初始化语言(Android Init Language)编写的脚本配置文件,启动了所有核心服务:
on boot
# basic network init
ifup lo
hostname localhost
domainname localdomain
...
# Start standard binderized HAL daemons
class_start hal
class_start core
其中就包括在/frameworks/native/services/surfaceflinger目录下的surfaceflinger.rc,而这正是SurfaceFlinger服务:
service surfaceflinger /system/bin/surfaceflinger
class core animation
user system
group graphics drmrpc readproc
capabilities SYS_NICE
onrestart restart --only-if-running zygote
task_profiles HighPerformance
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服务由 init 进程创建,之后独立的运行在 SurfaceFlinger进程中。
SurfaceFlinger对应的可执行文件在/system/bin/surfaceflinger,其源码则位于/frameworks/native/services/surfaceflinger目录中。程序入口是main_surfaceflinger.cpp中的main()方法:
int main(int, char**) {
signal(SIGPIPE, SIG_IGN);
//配置线程池:设置binder的线程池,用于设置 当前进程用于hwbinder通信的最大线程数:
hardware::configureRpcThreadpool(1 /* maxThreads */, false /* callerWillJoin */);
//启动图形分配器服务
startGraphicsAllocatorService();
// 当 SF 在自己的进程中启动时,将 binder 线程数限制为 4。
ProcessState::self()->setThreadPoolMaxThreadCount(4);
// Set uclamp.min setting on all threads, maybe an overkill but we want
// to cover important threads like RenderEngine.
if (SurfaceFlinger::setSchedAttr(true) != NO_ERROR) {
ALOGW("Couldn't set uclamp.min: %s\n", strerror(errno));
}
// The binder threadpool we start will inherit sched policy and priority
// of (this) creating thread. We want the binder thread pool to have
// SCHED_FIFO policy and priority 1 (lowest RT priority)
// Once the pool is created we reset this thread's priority back to
// original.
int newPriority = 0;
int origPolicy = sched_getscheduler(0);
struct sched_param origSchedParam;
int errorInPriorityModification = sched_getparam(0, &origSchedParam);
if (errorInPriorityModification == 0) {
int policy = SCHED_FIFO;
newPriority = sched_get_priority_min(policy);
struct sched_param param;
param.sched_priority = newPriority;
errorInPriorityModification = sched_setscheduler(0, policy, ¶m);
}
// 启动线程池
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
// Reset current thread's policy and priority
if (errorInPriorityModification == 0) {
errorInPriorityModification = sched_setscheduler(0, origPolicy, &origSchedParam);
} else {
ALOGE("Failed to set SurfaceFlinger binder threadpool priority to SCHED_FIFO");
}
// 创建surfaceflinger实例
sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
// Set the minimum policy of surfaceflinger node to be SCHED_FIFO.
// So any thread with policy/priority lower than {SCHED_FIFO, 1}, will run
// at least with SCHED_FIFO policy and priority 1.
if (errorInPriorityModification == 0) {
flinger->setMinSchedulerPolicy(SCHED_FIFO, newPriority);
}
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
////设置调度策略,SP_FOREGROUND优先级
set_sched_policy(0, SP_FOREGROUND);
// CPU 策略,限制SF在了小核
if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM);
// 在客户端可以连接之前初始化
flinger->init();
// 发布并注册SurfaceFlinger服务
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
//依赖于SF在上面注册,启动DisplayService
startDisplayService();
if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
ALOGW("Couldn't set to SCHED_FIFO: %s", strerror(errno));
}
// 在当前这个线程运行SurfaceFlinger
flinger->run();
return 0;
}
从上面的main()方法可以看到,在SurfaceFlinger进程启动时,主要是执行初始化binder线程池、设定进程优先级和cgroup、创建SurfaceFlinger、启动SurfaceFlinger服务并添加到ServiceManager等操作。
①初始化binder线程池:调用的configureRpcThreadpool(size_t maxThreads, bool callerWillJoin)方法在/system/libhidl/transport中的HidlTransportSupport.cpp中。
void configureRpcThreadpool(size_t maxThreads, bool callerWillJoin) {
// TODO(b/32756130) this should be transport-dependent
configureBinderRpcThreadpool(maxThreads, callerWillJoin);
}
内部调用了HidlBinderSupport.cpp中的:
void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin) {
status_t ret = ProcessState::self()->setThreadPoolConfiguration(
maxThreads, callerWillJoin /*callerJoinsPool*/);
LOG_ALWAYS_FATAL_IF(ret != OK, "Could not setThreadPoolConfiguration: %d", ret);
gThreadPoolConfigured = true;
}
②启动线程池:ProcessState.cpp在/system/libhwbinder目录下。
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != nullptr) {
return gProcess;
}
gProcess = new ProcessState(DEFAULT_BINDER_VM_SIZE);
return gProcess;
}
使用DEFAULT_BINDER_VM_SIZE作为默认参数即Binder底层共享内存大小,构造ProcessState实例:
sp<ProcessState> ProcessState::initWithMmapSize(size_t mmap_size) {
Mutex::Autolock _l(gProcessMutex);
if (gProcess != nullptr) {
LOG_ALWAYS_FATAL_IF(mmap_size != gProcess->getMmapSize(),
"ProcessState already initialized with a different mmap size.");
return gProcess;
}
gProcess = new ProcessState(mmap_size);
return gProcess;
}
随后调用startThreadPool()开启线程池:
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
if (mSpawnThreadOnStart) {
spawnPooledThread(true);
}
}
}
③创建SurfaceFlinger实例:借助/frameworks/native/services/surfaceflinger里的SurfaceFlingerFactory.cpp工厂构造一个SurfaceFlinger实例。
sp<SurfaceFlinger> createSurfaceFlinger(){
static DefaultFactory factory;
return new SurfaceFlinger(factory);
}
④SurfaceFlinger初始化:/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中的init()方法,初始化 EGL、创建 HWComposer、初始化非虚拟显示屏、启动 EventThread 线程、启动开机动画。
// Do not call property_set on main thread which will be blocked by init
// Use StartPropertySetThread instead.
void SurfaceFlinger::init() {
ALOGI( "SurfaceFlinger's main thread ready to run. "
"Initializing graphics H/W...");
ALOGI("Phase offset NS: %" PRId64 "", mPhaseOffsets->getCurrentAppOffset());
Mutex::Autolock _l(mStateLock);
// start the EventThread
mScheduler =
getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
mRefreshRateConfigs);
auto resyncCallback =
mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
mAppConnectionHandle =
mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
resyncCallback,
impl::EventThread::InterceptVSyncsCallback());
mSfConnectionHandle = mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),
resyncCallback, [this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
});
...
mRefreshRateConfigs.populate(getHwComposer().getConfigs(*display->getId()));
mRefreshRateStats.setConfigMode(getHwComposer().getActiveConfigIndex(*display->getId()));
ALOGV("Done initializing");
}
⑤SurfaceFlinger运行:SurfaceFlinger.cpp中的run()方法进入主循环。
void SurfaceFlinger::run() {
do {
waitForEvent();
} while (true);
}
之前在绘制性能分析一文中介绍了Systrace,通过Systrace可以判断是否出现掉帧,看的就是SurfaceFlinger部分。推荐阅读 Systrace 基础知识 这篇博客,在Triple Buffer 解读 > 掉帧检测 章节有非常详细的解读。
对于SurfaceFlinger能了解到这些就行了,主要涉及底层的C++,这部分由专业的图形图像框架团队维护,应用开发者不用往下卷的很深。
相关资料:
SurfaceFlinger 和 Hardware Composer
Android 显示系统:SurfaceFlinger详解
Android图形显示-专题
Android P 图形显示系统硬件合成
Android Q SurfaceFlinger合成
SurfaceFlinger分析文档