「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」。
SurfaceFlinger启动流程
SurfaceFlinger的启动,此前有说明过,在surfaceflinger.rc配置文件解析出一个SurfaceFlinger服务后,运行其对应的/system/bin/surfaceflinger应用程序,这个程序的入口在main_surfaceflinger.cpp文件中
int main(int, char**) {
// 将忽视SIGPIPE信号
signal(SIGPIPE, SIG_IGN);
// 配置HIDL支持的最大线程数
hardware::configureRpcThreadpool(1 /* maxThreads */,
false /* callerWillJoin */);
// 启动图形系统的内存分配器
startGraphicsAllocatorService();
// ...... binder机制配置流程,本篇不做详细探讨,省略
// instantiate surfaceflinger
// 1. 初始化一个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
// 设置CPU提供更多的cpu core来处理surfaceflinger进程的事件调度
if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM);
// initialize before clients can connect
// 2. 初始化SurfaceFlinger
flinger->init();
// ...... 在ServiceManager中注册surfaceflinger服务的过程,此篇不做讨论,省略
// 启动显示设备服务
startDisplayService(); // dependency on SF getting registered above
// 设置surfaceflinger进程的进程调度策略为SCHED_FIFO
if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
ALOGW("Couldn't set to SCHED_FIFO: %s", strerror(errno));
}
// run surface flinger in this thread
// 3. 运行SurfaceFlinger线程
flinger->run();
return 0;
}
从main函数中可知,在这边主要做了如下的事情
- 设置忽视SIGPIPE信号,LINUX系统中SIGPIPE信号的默认处理方式是直接终止进程
- 设置HIDL支持的最大线程数为1
- Binder机制,设置进程支持的最大线程数为4
- Binder机制,启动线程池
- 通过surfaceflinger::createSurfaceFlinger函数初始化一个SurfaceFlinger指针对象
- 设置surfaceflinger进程的优先级,且设置系统优先为surfaceflinger进程提供服务
- SurfaceFlinger::init函数调用
- ServiceManager中注册surfaceflinger服务
- startDisplayService函数调用
- 设置surfaceflinger进程调度策略为SCHED_FIFO
- SurfaceFlinger::run函数调用
本篇重点分析SurfaceFlinger服务的启动,因此重点分析上述的5/7/11步骤
surfaceflinger::createSurfaceFlinger函数创建SurfaceFlinger指针对象
frameworks/native/services/surfaceflinger/SurfaceFlingerFactory.cpp
sp<SurfaceFlinger> createSurfaceFlinger() {
// 此处的DefaultFactory类定义于frameworks/native/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp文件中
// 其主要目的是为了SurfaceFlinger进程中创建对应的一些默认的接口对象
static DefaultFactory factory;
return new SurfaceFlinger(factory);
}
此处通过new的方式创建一个SurfaceFlinger对象,需要注意的是DefaultFactory对象,这个对象的主要作用是创建一些默认的对应对象
SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) {
// ...... 参数赋值操作,此处不做具体分析,使用的时候使用默认值,省略代码
}
SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
: mFactory(factory),
mInterceptor(mFactory.createSurfaceInterceptor(this)),
mTimeStats(std::make_shared<impl::TimeStats>()),
mFrameTracer(std::make_unique<FrameTracer>()),
mEventQueue(mFactory.createMessageQueue()),
mCompositionEngine(mFactory.createCompositionEngine()),
mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)),
mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)) {}
classDiagram
BnSurfaceComposer <|-- SurfaceFlinger
BnInterface <|-- BnSurfaceComposer
ISurfaceComposer <|-- BnInterface
BpInterface <|-- BpSurfaceComposer
ISurfaceComposer <|-- BpInterface
IInterface <|-- ISurfaceComposer
class SurfaceFlinger {
-Scheduler:mScheduler
-VSyncModulator:mVSyncModulator
-MessageQueue:mEventQueue
-CompositionEngine:mCompositionEngine
-ConnectionHandle:mAppConnectionHandle
-ConnectionHandle:mSfConnectionHandle
-createLayer()
-onTransact(uint32_t, const Parcel&, Parcel*, uint32_t)
}
class BnSurfaceComposer {
+onTransact(uint32_t, const Parcel&, Parcel*, uint32_t)
}
从上述SurfaceFlinger的类图和构造函数中可以看到,在SurfaceFlinger类的父类是BnSurfaceComposer,它与BpSurfaceComposer之间实现了Binder机制的IPC跨进程通信, 而在SurfaceFlinger指针对象的初始化过程中,通过的DefaultFactory对象MessageQueue指针对象,MessageQueue指针对象用作管理消息的接收、分发和处理。
classDiagram
class MessageQueue {
#SurfaceFlinger:mFlinger
#Looper:mLooper
#EventThreadConnection:mEvents
#BitTube:mEventTube
#Handler:mHandler
#cb_eventReceiver(int, int, void*)
#eventReceiver(int fd, int events)
+init(const sp<SurfaceFlinger>& flinger)
+setEventConnection(const sp<EventThreadConnection>&)
+waitMessage()
+postMessage(sp<MessageHandler>&&)
+invalidate()
+refresh()
}
class Handler {
+handleMessage(const Message&)
+dispatchRefresh()
+dispatchInvalidate(nsecs_t)
#MessageQueue&:mQueue
#int32_t:mEventMask
}
class Task {
#handleMessage(const Message&)
}
class MessageHandler{
+handleMessage(const Message&)
}
MessageHandler <|-- Handler
MessageHandler <|-- Task
MessageQueue o-- Handler
SurfaceFlinger的初始化,由于这边初始化的是一个SurfaceFlinger强指针对象,因此在初始化的时候会调用其onFirstRef函数,因此
void SurfaceFlinger::onFirstRef() {
mEventQueue->init(this);
}
void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
mFlinger = flinger;
mLooper = new Looper(true);
mHandler = new Handler(*this);
}
可见,在SurfaceFlinger指针对象初始化中,主要是初始化一些必要的指针对象和必要的默认参数,而SurfaceFlinger::onFirstRef函数的调用,更说明了,在这个服务中,主要通过消息机制来处理数据的流转和信息的交互
SurfaceFlinger初始化
在main函数中,还会调用SurfaceFlinger::init函数,让我们去看看这个函数中具体做了什么呢?
void SurfaceFlinger::init() {
// ......日志打印,省略
// 同步锁
Mutex::Autolock _l(mStateLock);
// Get a RenderEngine for the given display / config (can't fail)
// TODO(b/77156734): We need to stop casting and use HAL types when possible.
// Sending maxFrameBufferAcquiredBuffers as the cache size is tightly tuned to single-display.
// 1. 初始化一个RenderEngine指针对象,然后通过CompositionEngine的setRenderEngine函数设置参数
mCompositionEngine->setRenderEngine(renderengine::RenderEngine::create(
renderengine::RenderEngineCreationArgs::Builder()
.setPixelFormat(static_cast<int32_t>(defaultCompositionPixelFormat))
.setImageCacheSize(maxFrameBufferAcquiredBuffers)
.setUseColorManagerment(useColorManagement)
.setEnableProtectedContext(enable_protected_contents(false))
.setPrecacheToneMapperShaderOnly(false)
.setSupportsBackgroundBlur(mSupportsBlur)
.setContextPriority(useContextPriority
? renderengine::RenderEngine::ContextPriority::HIGH
: renderengine::RenderEngine::ContextPriority::MEDIUM)
.build()));
// CompositionEngine保存TimeStats指针对象地址引用
mCompositionEngine->setTimeStats(mTimeStats);
// ......日志打印,省略
// 3. 初始化一个HWComposer,然后通过CompositionEngine指针对象保存HWComposer指针对象地址引用
mCompositionEngine->setHwComposer(getFactory().createHWComposer(getBE().mHwcServiceName));
// 4. 设置Configuration,这边是一个比较复杂和重要的函数
mCompositionEngine->getHwComposer().setConfiguration(this, getBE().mComposerSequenceId);
// Process any initial hotplug and resulting display changes.
// 5. 运行显示设备热插拔事件,在setConfiguration的调用过程中会触发一次显示设备的热插拔事件
// 添加默认设备后,此处若没有其他人插拔事件的话,会直接跳过运行
processDisplayHotplugEventsLocked();
// 6. 获取默认的显示设备
const auto display = getDefaultDisplayDeviceLocked();
// ...... 判错日志,省略
// ...... 使用的虚拟设备,此处我们暂不考虑虚拟显示设备,先省略这部分代码
// initialize our drawing state
// 初始化送显状态
// 显示设备添加事件完成后,将状态进行转换
mDrawingState = mCurrentState;
// set initial conditions (e.g. unblank default device)
// 8. 初始化显示设备
initializeDisplays();
char primeShaderCache[PROPERTY_VALUE_MAX];
property_get("service.sf.prime_shader_cache", primeShaderCache, "1");
if (atoi(primeShaderCache)) {
getRenderEngine().primeCache();
}
// Inform native graphics APIs whether the present timestamp is supported:
// 9. 创建一个StartPropertySetThread线程并运行
const bool presentFenceReliable =
!getHwComposer().hasCapability(hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE);
mStartPropertySetThread = getFactory().createStartPropertySetThread(presentFenceReliable);
if (mStartPropertySetThread->Start() != NO_ERROR) {
ALOGE("Run StartPropertySetThread failed!");
}
ALOGV("Done initializing");
}
Opengl和EGL的启动
在SurfaceFlinger::init函数的开始,就会通过RenderEngine::create函数来初始化一个GLESRenderEngine,从他们的名称来看,这个指针对象应该是一个绘制引擎,初始化OPENGL ES的一个对象,而事实上也是如此,在这个函数的初始化过程中会对EGL和OPENGL进行初始化,在这个过程中,会加载egl和opengl的库等,这块具体的分析,等后续再来具体的分析 在init函数中,还会调用GLESRenderEngine的primeCache函数,也是一样,主要是设置OPENGL的着色器状态
初始化HWComposer指针对象和设置其配置
HWComposer指针对象的初始化也是通过DefaultFactory对象来初始化的,最终会通过new的方式初始化
// 这边传入参数默认为"default"
std::unique_ptr<HWComposer> DefaultFactory::createHWComposer(const std::string& serviceName) {
return std::make_unique<android::impl::HWComposer>(serviceName);
}
// 同时会初始化一个Composer指针对象
HWComposer::HWComposer(const std::string& composerServiceName)
: mComposer(std::make_unique<Hwc2::impl::Composer>(composerServiceName)) {
}
// 注意,此处传递的第一个参数是SurfaceFlinger对象本身,其实现了HWC2::ComposerCallback接口类
void HWComposer::setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) {
loadCapabilities();
loadLayerMetadataSupport();
// 判断callback是否已经注册,若已经注册,则直接退出
if (mRegisteredCallback) {
ALOGW("Callback already registered. Ignored extra registration attempt.");
return;
}
mRegisteredCallback = true;
sp<ComposerCallbackBridge> callbackBridge(
new ComposerCallbackBridge(callback, sequenceId,
mComposer->isVsyncPeriodSwitchSupported()));
mComposer->registerCallback(callbackBridge);
}
classDiagram
HWComposer o-- Composer
class HWComposer {
-HWC2::Composer : mComposer
+getComposer()
+loadCapabilities()
+loadLayerMetadataSupport()
+allocatePhysicalDisplay()
+setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId)
}
class Composer {
+registerCallback(const sp<IComposerCallback>& callback)
}
这边有一个点需要注意的是,当通过HWComposer::setConfiguration向Hwc2::Composer中注册HWC2::ComposerCallback之后,底层硬件层会检测当前是否已经包含了显示屏幕(当然,在我们正常的手机/平板或者其他设备中,均会默认有一个物理显示屏),因此此处会产生一个显示屏幕设备的信号给到frameworks层,当系统收到这个信号的时候SurfaceFlinger::onHotplugReceived函数即时被调用
void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId,
hal::Connection connection) {
// ...... 功能无关的判断操作,代码省略
// 添加HotplugEvent事件
mPendingHotplugEvents.emplace_back(HotplugEvent{hwcDisplayId, connection});
if (std::this_thread::get_id() == mMainThreadId) {
// Process all pending hot plug events immediately if we are on the main thread.
// 运行显示设备插入事件
processDisplayHotplugEventsLocked();
}
setTransactionFlags(eDisplayTransactionNeeded);
}
void SurfaceFlinger::processDisplayHotplugEventsLocked() {
// 上述的onHotplugReceived函数刚刚添加了一个HotplugEvent事件
for (const auto& event : mPendingHotplugEvents) {
// 这边会判断当前的hwcDisplayID对应的DisplayIdentificationInfo是否存在
// 若不存在,则初始化一个DisplayIdentificationInfo对象,同时会在系统层中分配当前默认Display的内存空间
// 若存在,则更新其参数
const std::optional<DisplayIdentificationInfo> info =
getHwComposer().onHotplug(event.hwcDisplayId, event.connection);
//
if (!info) {
continue;
}
const DisplayId displayId = info->id;
const auto it = mPhysicalDisplayTokens.find(displayId);
if (event.connection == hal::Connection::CONNECTED) {
if (it == mPhysicalDisplayTokens.end()) {
ALOGV("Creating display %s", to_string(displayId).c_str());
if (event.hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
// Scheduler初始化
initScheduler(displayId);
}
// 初始化和配置DisplayDeviceState对象
DisplayDeviceState state;
state.physical = {displayId, getHwComposer().getDisplayConnectionType(displayId),
event.hwcDisplayId};
state.isSecure = true; // All physical displays are currently considered secure.
state.displayName = info->name;
sp<IBinder> token = new BBinder();
mCurrentState.displays.add(token, state);
mPhysicalDisplayTokens.emplace(displayId, std::move(token));
// 提示创建Display对象的Trace
mInterceptor->saveDisplayCreation(state);
}
// ...... 无法进入分支,代码省略
}
// ...... 无法进入分支,代码省略
// 触发Display变化的事件
processDisplayChangesLocked();
}
// 清理事件
mPendingHotplugEvents.clear();
}
可以看到,这边主要做了如下几个工作
- 调用HWComposer对象的onHotplug函数,初始化一个DisplayIdentificationInfo对象,并且在系统层在内存中分配一个Display的内存同驱动层的HWCDisplay对象关联
- 通过initScheduler函数,初始化Scheduler指针对象,同时设置两条连接链路,用作SurfaceFlinger消息的分发和处理,此处将在后续另写一篇做详细的概述
- 初始化和配置DisplayDeviceState对象,并且保存在mPhysicalDisplayTokens中,同时更新mCurrentState当前状态
- 触发Display变化事件,配置设备添加后的一些配置和连接问题
在此后会通过initializeDisplays函数对新初始化的Displays进行初始化,此处我们暂不做详细分析,待后续单独更新详细文档
对显示设备进行初始化
在SurfaceFlinger::init函数的最后,会初始化一个StartPropertySetThread的线程,并运行
sp<StartPropertySetThread> DefaultFactory::createStartPropertySetThread(
bool timestampPropertyValue) {
return new StartPropertySetThread(timestampPropertyValue);
}
StartPropertySetThread::StartPropertySetThread(bool timestampPropertyValue):
Thread(false), mTimestampPropertyValue(timestampPropertyValue) {}
status_t StartPropertySetThread::Start() {
return run("SurfaceFlinger::StartPropertySetThread", PRIORITY_NORMAL);
}
bool StartPropertySetThread::threadLoop() {
// Set property service.sf.present_timestamp, consumer need check its readiness
property_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");
// Clear BootAnimation exit flag
property_set("service.bootanim.exit", "0");
// Start BootAnimation if not started
// 启动bootanim进程
property_set("ctl.start", "bootanim");
// Exit immediately
return false;
}
可以看到,此处通过线程来设置开机动画的属性,那么为何需要在此处设置这个属性呢? 如果看开机动画的bootanim.rc文件可以看到,其默认是disable的,也就是说,开机动画进程,默认是不会自启动的,需要有其他地方来触发 而通过此处的ctl.start属性,能够触发bootanim进程,从而开始显示开机动画
总结
在SurfaceFlinger::init函数中主要是做了
- 初始化GLESRenderEngine指针对象,在这个初始化的过程中,初始化OPENGL和EGL的相关库
- 初始化HWComposer指针对象,这个类跟系统Composer驱动进行关联,并且在通过其函数setConfiguration的时候,设置ComposerCallback回调,并且在过程中初始化显示设备,并启动回调函数onHotplugReceive函数,在这个函数中,初始化系统层的Display相关的对象和配置,同Display驱动层对应的显示设备进行关联
- 初始化和启动StartPropertySetThread线程,在这个线程中判断当前开机动画进程是否已经启动,若未启动,则直接启动该进程
启动SurfaceFlinger的消息处理机制
最后,调用了SurfaceFlinger::run函数,来启动其消息处理机制
void SurfaceFlinger::run() {
// 直接来一个无限循环while,等待消息
while (true) {
mEventQueue->waitMessage();
}
}
void MessageQueue::waitMessage() {
do {
IPCThreadState::self()->flushCommands();
int32_t ret = mLooper->pollOnce(-1);
switch (ret) {
case Looper::POLL_WAKE:
case Looper::POLL_CALLBACK:
continue;
case Looper::POLL_ERROR:
ALOGE("Looper::POLL_ERROR");
continue;
case Looper::POLL_TIMEOUT:
// timeout (should not happen)
continue;
default:
// should not happen
ALOGE("Looper::pollOnce() returned unknown status %d", ret);
continue;
}
} while (true);
}
这样就会在无限循环的等待消息过来后,直接处理