Android UI架构(四)--SurfaceFlinger的初始化.md
参考:
-
Vsync虚拟化
-
Android SurfaceFlinger SW Vsync模型
-
Android SurfaceFlinger服务的消息队列创建过程分析
-
Android6.0 显示系统(六) 图像的输出过程
-
Android图形显示系统(一)
文章目录
- 一、SurfaceFlinger的启动
- 1.1 surfaceflinger.rc
- 1.2 main_surfaceflinger.cpp:main()
- 1.3 实例化SurfaceFlinger
- 1.3.1 SurfaceFlinger:onFirstRef()
- 1.3.2 MessageQueue:init()
- 1.4 SurfaceFlinger:init()
- 1.4.1 EventThread
- 1.4.1.1 DispSyncSource
- 1.4.1.2 new EventThread()
- 1.4.1.3 MessageQueue:setEventThread(sf)
- 1.4.1.4 EventThread.run()
- 1.4.2.1 HWComposer.setEventHandler(EventHandler*)
- 1.4.2.2 HWC2:registerVsyncCallback(VsyncCallback)
- 1.4.3 启动EventControlThread
- 1.4.3.1 EventControlThread(const sp&)
- 1.4.3.2 EventControlThread.run()
- 1.4.4 mDrawingState = mCurrentState;
- 1.5 SurfaceFlinger:run()
- 1.5.1 MessageQueue.waitMessage()
- 1.5.2 MessageQueue.cb_eventReceiver()
- 1.5.3 MessageQueue:eventReceiver
- 1.5.4 MessageQueue.handler:dispatchInvalidate()
- 1.5.5 MessageQueue.handler:handleMessage
- 1.5.6 SurfaceFlinger:onMessageReceived()
- 1.5.6.1 SurfaceFlinger:signalLayerUpdate
- 1.5.8 SurfaceFlinger:handleMessageInvalidate()
- 1.5.9 SurfaceFlinger:signalRefresh()
- 1.5.9.1 SurfaceFlinger:handleMessageRefresh()
- 二、VSync信号的启动与处理
- 2.1 DisplayEventReceiver
- 2.1 EventThread:waitForEvent
一、SurfaceFlinger的启动
要理解SurfaceFlinger的工作机制,必须要理解SF所有线程的工作内容。从SF的启动流程入手分析整个SF的工作机制~ PS. 这篇笔记写的时间较早,基于Andorid 8.0(O). 不过大致流程没有变化,凑合看。
1.1 surfaceflinger.rc
Android7.0以后的版本对init.rc脚本进行了重构,将各种服务进行归类拆分,而其中的SurfaceFlinger服务作为独立进程由surfaceflinger.rc脚本启动。
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
这里的 /system/bin/surfaceflinger 可以从Android.mk文件中看到具体启动的代码:
LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"LOCAL_INIT_RC := surfaceflinger.rcifeq ($(TARGET_USES_HWC2),true) LOCAL_CFLAGS += -DUSE_HWC2endifLOCAL_SRC_FILES := \ main_surfaceflinger.cpp ......LOCAL_MODULE := surfaceflinger
重点来了:main_surfaceflinger.cpp
1.2 main_surfaceflinger.cpp:main()
int main(int, char**) { // 从8.0开始,Android提供了hidl机制,将原先直接由 // JNI->Native->HAL的接口调用形式,统一规范成hidl service/client // 交互形式。该方式从一方面规范和统一了Android Framework和HAL // 的调用机制,这个是Android O的Treble计划核心,mark一下,有空研究 startHidlServices(); // 忽略SIGPIPE信息,IPC机制中如果客户端关闭了,可能会产生SIGPIPE信号 // 该信号是进程终止信号,SF进程不应该响应这个信号 signal(SIGPIPE, SIG_IGN); // 设置进程最大线程数为4(主线程不计入),线程过多会影响性能 ProcessState::self()->setThreadPoolMaxThreadCount(4); // 开启线程池 sp<ProcessState> ps(ProcessState::self()); ps->startThreadPool(); // 1.3 实例化SurfaceFlinger,注意这里的flinger是一个强引用指针 sp<SurfaceFlinger> flinger = new SurfaceFlinger(); // 设置SF进程的优先级为高优先级(PRIORITY_URGENT_DISPLAY = -8) setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY); // 设置为前台调度策略 set_sched_policy(0, SP_FOREGROUND); // 将SF的大多数线程优先级设为SP_SYSTEM if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM); // 1.4 初始化SurfaceFlinger flinger->init(); // 将SF服务添加至ServiceManager中 sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false); // 添加GpuService至ServiceManager sp<GpuService> gpuservice = new GpuService(); sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false); struct sched_param param = {0}; param.sched_priority = 2; if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) { ALOGE("Couldn't set SCHED_FIFO"); } // 1.5 SF运行在当前线程中 flinger->run(); return 0;}
1.3 实例化SurfaceFlinger
先看一下SurfaceFlinger的定义:
class SurfaceFlinger : public BnSurfaceComposer, private IBinder::DeathRecipient, private HWComposer::EventHandler{ ......}
可以看到SF是继承了BnSurfaceComposer、DeathRecipient和 HWComposer::EventHandler的。
-
BnSurfaceComposer继承了BnInterface,提供onTranscat(SF实现)接口供客户端调用
-
DeathRecipient是Android的Binder机制提供的死亡监听
-
HWComposer::EventHandler,这个用来处理来自硬件或软件产生的Vsync信号,包括其他各种消息
SurfaceFlinger::SurfaceFlinger() : BnSurfaceComposer(), mTransactionFlags(0), mTransactionPending(false), mAnimTransactionPending(false), mLayersRemoved(false), mLayersAdded(false), mRepaintEverything(0), mHwc(nullptr), // mHwc = nullptr mRealHwc(nullptr), // mRealHwc = nullptr mVrHwc(nullptr), mRenderEngine(nullptr), mBootTime(systemTime()), mBuiltinDisplays(), mVisibleRegionsDirty(false), mGeometryInvalid(false), mAnimCompositionPending(false), mDebugRegion(0), mDebugDDMS(0), mDebugDisableHWC(0), mDebugDisableTransformHint(0), mDebugInSwapBuffers(0), mLastSwapBufferTime(0), mDebugInTransaction(0), mLastTransactionTime(0), mBootFinished(false), mForceFullDamage(false), mInterceptor(this), mPrimaryDispSync("PrimaryDispSync"), mPrimaryHWVsyncEnabled(false), //mPrimaryHWVsyncEnabled = false mHWVsyncAvailable(false), mHasColorMatrix(false), mHasPoweredOff(false), mFrameBuckets(), mTotalTime(0), mLastSwapTime(0), mNumLayers(0), mVrFlingerRequestsDisplay(false){ ALOGI("SurfaceFlinger is starting"); vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000); sfVsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::vsyncSfEventPhaseOffsetNs>(1000000); hasSyncFramework = getBool< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasSyncFramework>(true); useContextPriority = getBool< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::useContextPriority>(false); dispSyncPresentTimeOffset = getInt64< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::presentTimeOffsetFromVSyncNs>(0); useHwcForRgbToYuv = getBool< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::useHwcForRGBtoYUV>(false); maxVirtualDisplaySize = getUInt64(0); // VrFlinger仅支持DayDream设备 useVrFlinger = getBool< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::useVrFlinger>(false); maxFrameBufferAcquiredBuffers = getInt64< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2); hasWideColorDisplay = getBool(false); // debugging stuff... char value[PROPERTY_VALUE_MAX]; property_get("ro.bq.gpu_to_cpu_unsupported", value, "0"); mGpuToCpuSupported = !atoi(value); property_get("debug.sf.showupdates", value, "0"); mDebugRegion = atoi(value); property_get("debug.sf.ddms", value, "0"); mDebugDDMS = atoi(value); if (mDebugDDMS) { if (!startDdmConnection()) { // start failed, and DDMS debugging not enabled mDebugDDMS = 0; } } ALOGI_IF(mDebugRegion, "showupdates enabled"); ALOGI_IF(mDebugDDMS, "DDMS debugging enabled"); property_get("debug.sf.disable_backpressure", value, "0"); mPropagateBackpressure = !atoi(value); ALOGI_IF(!mPropagateBackpressure, "Disabling backpressure propagation"); property_get("debug.sf.enable_hwc_vds", value, "0"); mUseHwcVirtualDisplays = atoi(value); ALOGI_IF(!mUseHwcVirtualDisplays, "Enabling HWC virtual displays"); property_get("ro.sf.disable_triple_buffer", value, "1"); mLayerTripleBufferingDisabled = atoi(value); ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering");}
实例化过程中中会启动DDMS调试工具,这里重点注意:mHwc,mRealHwc均为nullptr;且mPrimaryHWVsyncEnabled=false。
1.3.1 SurfaceFlinger:onFirstRef()
智能指针第一被引用时会调用该方法。
void SurfaceFlinger::onFirstRef(){ // 1.3.2 初始化Looper和Handler mEventQueue.init(this);}
先看下mEventQueue究竟是什么:
class SurfaceFlinger : public BnSurfaceComposer, private IBinder::DeathRecipient, private HWComposer::EventHandler{ ...... private: // 线程安全 mutable MessageQueue mEventQueue;}
MessageQueue的定义:
class MessageQueue { class Handler : public MessageHandler { enum { eventMaskInvalidate = 0x1, // Invalidate消息 eventMaskRefresh = 0x2, // Refresh消息 eventMaskTransaction = 0x4 // Transaction消息 }; MessageQueue& mQueue; int32_t mEventMask; public: explicit Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) { } virtual void handleMessage(const Message& message); void dispatchRefresh(); void dispatchInvalidate(); }; friend class Handler; sp mFlinger; sp mLooper; sp mEventThread; sp mEvents; gui::BitTube mEventTube; // BitTube对象,用于Socket监听VSYNC信号 sp mHandler; static int cb_eventReceiver(int fd, int events, void* data); int eventReceiver(int fd, int events);public: enum { INVALIDATE = 0, REFRESH = 1, }; MessageQueue(); ~MessageQueue(); void init(const sp& flinger); void setEventThread(const sp& events); void waitMessage(); status_t postMessage(const sp& message, nsecs_t reltime=0); // 下一次接收到 VSYNC 时发送INVALIDATE 消息 void invalidate(); // 下一次接收到 VSYNC 时发送 REFRESH 消息 void refresh();};
1.3.2 MessageQueue:init()
这里的MessageQueue是native层实现的,位于:frameworks/native/services/surfaceflinger/MessageQueue.cpp
void MessageQueue::init(const sp& flinger){ mFlinger = flinger; mLooper = new Looper(true); //绑定到SF主线程 mHandler = new Handler(*this);}
1.4 SurfaceFlinger:init()
这个方法比较长,主要做了如下工作:
-
为OpenGL渲染准备环境;
-
启动App EventThread和SF EventThread;
-
初始化HWComposer;
-
启动EventControlThread;
-
初始化图层状态,显示状态,最后启动开机动画线程!
重点关注2,3,4步骤。
void SurfaceFlinger::init() { ALOGI( "SurfaceFlinger's main thread ready to run. " "Initializing graphics H/W..."); ALOGI("Phase offest NS: %" PRId64 "", vsyncPhaseOffsetNs); { // Autolock scope Mutex::Autolock _l(mStateLock); // 初始化EGL作为默认显示,为OpenGL渲染准备环境 mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(mEGLDisplay, NULL, NULL); // 1.4.1 启动App EventThread,该线程用于接收vsync信号并且上报给App进程,App开始画图 sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true, "app"); mEventThread = new EventThread(vsyncSrc, *this, false); // 启动SF EventThread,该线程用于SurfaceFlinger接收vsync信号用于渲染 sp sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, true, "sf"); mSFEventThread = new EventThread(sfVsyncSrc, *this, true); // 1.4.1.3 创建BitTube并监听其文件描述符 mEventQueue.setEventThread(mSFEventThread); // 设置App EventThread和SF EventThread线程的调度策略为SCHED_FIFO(实时调度策略,先到先服务) // 这样可以优化阻塞,更流畅 struct sched_param param = {0}; param.sched_priority = 2; if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) { ALOGE("Couldn't set SCHED_FIFO for SFEventThread"); } if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != 0) { ALOGE("Couldn't set SCHED_FIFO for EventThread"); } // 创建渲染引擎,主要是选择EGL配置,选择OpenGL版本,创建OpenGL上下文 // 后续有时间跟进瞅一下 mRenderEngine = RenderEngine::create(mEGLDisplay, HAL_PIXEL_FORMAT_RGBA_8888); } // 暂时不支持vr flinger LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay, "Starting with vr flinger active is not currently supported."); // 1.4.2 初始化Hwc,这里的参数控制vr Composer mRealHwc = new HWComposer(false); mHwc = mRealHwc; // 1.4.2.1 由SF主线程处理event mHwc->setEventHandler(static_cast(this)); Mutex::Autolock _l(mStateLock); // 通知本地图形API是否支持当前时间戳 if (getHwComposer().hasCapability( HWC2::Capability::PresentFenceIsNotReliable)) { property_set(kTimestampProperty, "0"); } else { property_set(kTimestampProperty, "1"); } if (useVrFlinger) { // 不考虑Vr Flinger auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) { ALOGI("VR request display mode: requestDisplay=%d", requestDisplay); mVrFlingerRequestsDisplay = requestDisplay; signalTransaction(); }; mVrFlinger = dvr::VrFlinger::Create(mHwc->getComposer(), vrFlingerRequestDisplayCallback); if (!mVrFlinger) { ALOGE("Failed to start vrflinger"); } } // 获取EGL上下文 mEGLContext = mRenderEngine->getEGLContext(); LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT, "couldn't create EGLContext"); // 设置当前GL上下文以便创建图层时创建纹理 getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext); // 1.4.3 启动EventControlThread,VSync信号闸刀控制线程 mEventControlThread = new EventControlThread(this); mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY); // 1.4.4 初始化绘图状态 // mDrawingState : 上一次绘图图层状态 // mCurrentState : 当前图层状态 mDrawingState = mCurrentState; // 初始化显示状态 initializeDisplays(); // 内存缓存增强 mRenderEngine->primeCache(); // 启动开机动画线程! mStartBootAnimThread = new StartBootAnimThread(); if (mStartBootAnimThread->Start() != NO_ERROR) { ALOGE("Run StartBootAnimThread failed!"); } ALOGV("Done initializing");}
1.4.1 EventThread
App EventThread和SF EventThread的区别除了名称,只在于相移phase offset。
名称|作用|相移
—|---|—
app|用于接收vsync信号并且上报给App进程,App开始画图|VSYNC_EVENT_PHASE_OFFSET_NS
sf|用于SurfaceFlinger接收vsync信号用于渲染|SF_VSYNC_EVENT_PHASE_OFFSET_NS
这两个值都可配,这两个一般用来调节performance. 具体可在 BoardConfig.mk里配置。
这里要解释下相移的作用。Android 4.1(Jelly Bean)引入了Vsync(Vertical Syncronization)用于渲染同步,使得App UI和SurfaceFlinger可以按硬件产生的VSync节奏来进行工作。
但新的问题产生了,App UI和SurfaceFlinger的工作都是流水线模型,对应一帧内容,AppUI先绘制完毕后由SurfaceFlinger合成渲染放入FrameBuffer,最终显示到屏幕上。这样从AppUI接收到Vsync信号到最终显示过去了2个Vsync周期(2 * 16.6ms),严重影响体验。针对这个问题Android4.4引入了虚拟Vsync,也就是将硬件产生的Vsync信号同步到本地Vsync模型后一分为二,引出两个Vsync线程,如下图:
为了好理解,做个假设:产生Vsync信号,先通知AppUI绘制,一段时间后通知SurfaceFlinger合成。如果AppUI绘制速度够快,SurfaceFlinger就可以不用等待而直接渲染合成图像了。
理解这个,app和sf EventThread我们就看其中一个的初始化即可。
先瞅瞅DispSyncSource,该类继承了VSyncSource,实现了其虚函数,主要功能恰如其名:设置相移、Vsync开关和提供接收Vsync事件的回调。
1.4.1.1 DispSyncSource
// 定义在SurfaceFlinger.cpp中class DispSyncSource : public VSyncSource, private DispSync::Callback {public: DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync, const char* name) : mName(name), mValue(0), mTraceVsync(traceVsync), mVsyncOnLabel(String8::format("VsyncOn-%s", name)), mVsyncEventLabel(String8::format("VSYNC-%s", name)), mDispSync(dispSync), mCallbackMutex(), mCallback(), mVsyncMutex(), mPhaseOffset(phaseOffset), mEnabled(false) {} // 默认mEnable为false ......};// 定义在EventThread.h文件中 class VSyncSource : public virtual RefBase {public: class Callback: public virtual RefBase { public: virtual ~Callback() {} virtual void onVSyncEvent(nsecs_t when) = 0; }; virtual ~VSyncSource() {} virtual void setVSyncEnabled(bool enable) = 0; virtual void setCallback(const sp& callback) = 0; virtual void setPhaseOffset(nsecs_t phaseOffset) = 0;};
1.4.1.2 new EventThread()
照惯例,初始化之前看看EventThread的定义:
class EventThread : public Thread, private VSyncSource::Callback { class Connection : public BnDisplayEventConnection { public: explicit Connection(const sp& eventThread); status_t postEvent(const DisplayEventReceiver::Event& event); // count >= 1 : 连续vsync事件,count为vsync频次 // count == 0 : 一次vsync事件 // count ==-1 : one-shot event that fired this round / disabled int32_t count; private: virtual ~Connection(); virtual void onFirstRef(); status_t stealReceiveChannel(gui::BitTube* outChannel) override; // 设置BitTube通道 status_t setVsyncRate(uint32_t count) override; // 设置Vsync频率 void requestNextVsync() override; // 异步请求Vsync sp const mEventThread; gui::BitTube mChannel; // 用于Vsync信号传输的BitTube };public: EventThread(const sp& src, SurfaceFlinger& flinger, bool interceptVSyncs); sp createEventConnection() const; status_t registerDisplayEventConnection(const sp& connection); void setVsyncRate(uint32_t count, const sp& connection); void requestNextVsync(const sp& connection); // called before the screen is turned off from main thread void onScreenReleased(); // called after the screen is turned on from main thread void onScreenAcquired(); // called when receiving a hotplug event void onHotplugReceived(int type, bool connected); Vector< sp > waitForEvent( DisplayEventReceiver::Event* event); void dump(String8& result) const; void sendVsyncHintOff(); void setPhaseOffset(nsecs_t phaseOffset);private: virtual bool threadLoop(); virtual void onFirstRef(); virtual void onVSyncEvent(nsecs_t timestamp); void removeDisplayEventConnection(const wp& connection); void enableVSyncLocked(); void disableVSyncLocked(); void sendVsyncHintOnLocked(); // constants sp mVSyncSource; PowerHAL mPowerHAL; SurfaceFlinger& mFlinger; mutable Mutex mLock; mutable Condition mCondition; // protected by mLock SortedVector< wp > mDisplayEventConnections; Vector< DisplayEventReceiver::Event > mPendingEvents; DisplayEventReceiver::Event mVSyncEvent[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; bool mUseSoftwareVSync; bool mVsyncEnabled; // for debugging bool mDebugVsyncEnabled; bool mVsyncHintSent; const bool mInterceptVSyncs; timer_t mTimerId;};
不难发现,EventThread除了继承Thread,同时还是VSyncSource的内部类Callback的子类。并且还有一个继承了BnDisplayEventConnection的内部类Connection。
这个Connection的作用是作为服务端分发Vsync信号给app或者sf进程,后面详细介绍。
// 初始化EventThread::EventThread(const sp& src, SurfaceFlinger& flinger, bool interceptVSyncs) : mVSyncSource(src), // Vsync事件源:1、app;2、sf mFlinger(flinger), mUseSoftwareVSync(false), mVsyncEnabled(false), mDebugVsyncEnabled(false), mVsyncHintSent(false), mInterceptVSyncs(interceptVSyncs) { // DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES默认为2,也就是默认最多支持双屏显示 // 初始化 mVSyncEvent for (int32_t i=0 ; i
1.4.1.3 MessageQueue:setEventThread(sf)
void MessageQueue::setEventThread(const sp& eventThread){ mEventThread = eventThread; // 创建BitTube连接 mEvents = eventThread->createEventConnection(); // 获取BitTube文件描述符 mEvents->stealReceiveChannel(&mEventTube); // SF主线程监听该文件描述符,重点注意这里传入 // 的回调函数:cb_eventReceiver,后续会遇到的 mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver, this);}
1.4.1.4 EventThread.run()
上面的初始化过程很完美,但总感觉少了什么。EventThread线程是什么时候run的呢?仔细看SurfaceFlinger.h中关于EventThread的定义。
// SurfaceFlinger.h:两个强引用类型 sp mEventThread; sp mSFEventThread;
所以看EventThread:onFirstRef
void EventThread::onFirstRef() { // 这里运行该线程,设置调度策略 run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);}bool EventThread::threadLoop() { DisplayEventReceiver::Event event; Vector< sp > signalConnections; // 2.1 等待Vsync事件,其实也将本线程注册进监听了DispSync signalConnections = waitForEvent(&event); // 分发事件给监听者 const size_t count = signalConnections.size(); for (size_t i=0 ; i& conn(signalConnections[i]); // 上报该事件 status_t err = conn->postEvent(event); if (err == -EAGAIN || err == -EWOULDBLOCK) { // 目标不接收事件,可能队列已满,现在直接丢弃 ALOGW("EventThread: dropping event (%08x) for connection %p", event.header.type, conn.get()); } else if (err < 0) { // 处理pipe错误 removeDisplayEventConnection(signalConnections[i]); } } return true;}
#### 1.4.1.5 EventThread.Connection:postEvent() ```c++ status_t EventThread::Connection::postEvent( const DisplayEventReceiver::Event& event) {// 通过BitTube发送Vsync事件。这里Send的事件,会被SurfaceFlinger主线程// 响应,也就是MessageQueue.hanlder,1.4.1.3:MessageQueue:setEventThread(sf)ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
### 1.4.2 初始化HWComposer回到1.4 SurfaceFlinger.init()方法,初始化的HWComposer是负责接收并转发来自硬件的VSync信号。```c++HWComposer::HWComposer(bool useVrComposer) : mHwcDevice(), mDisplayData(2), mFreeDisplaySlots(), mHwcDisplaySlots(), mCBContext(), mEventHandler(nullptr), mVSyncCounts(), mRemainingHwcVirtualDisplays(0){ // HWC_NUM_PHYSICAL_DISPLAY_TYPES = 2 for (size_t i=0 ; i
1.4.2.1 HWComposer.setEventHandler(EventHandler*)
设置HWC的EventHandler,这里传入的handler就是继承了EventHandler的SurfaceFlinger本身。
void HWComposer::setEventHandler(EventHandler* handler){ if (handler == nullptr) { ALOGE("setEventHandler: Rejected attempt to clear handler"); return; } bool wasNull = (mEventHandler == nullptr); mEventHandler = handler; // 第一次设置EventHandler时进入 if (wasNull) { // 注册热插拔回调 auto hotplugHook = std::bind(&HWComposer::hotplug, this, std::placeholders::_1, std::placeholders::_2); mHwcDevice->registerHotplugCallback(hotplugHook); // 注册刷新回调 auto invalidateHook = std::bind(&HWComposer::invalidate, this, std::placeholders::_1); mHwcDevice->registerRefreshCallback(invalidateHook); // 1.4.2.2 注册Vsync回调,注意这里传入的参数 &HWComposer::vsync auto vsyncHook = std::bind(&HWComposer::vsync, this, std::placeholders::_1, std::placeholders::_2); mHwcDevice->registerVsyncCallback(vsyncHook); }}
1.4.2.2 HWC2:registerVsyncCallback(VsyncCallback)
这里为display注册监听了vsync,这里稍稍注意下传入的参数类型:
VsyncCallback : typedef std::function
这是个函数指针,c++11引入的标准,暂时只要明确这是一个回调。
void Device::registerVsyncCallback(VsyncCallback vsync){ mVsync = vsync; for (auto& pending : mPendingVsyncs) { auto& display = pending.first; auto timestamp = pending.second; mVsync(std::move(display), timestamp); // 传入display }}
这里已经准备好接收Vsync信号了,但接下来我们继续分析SurfaceFlinger的启动。
1.4.3 启动EventControlThread
Andorid5.0以后,专门启用一个线程控制Vsync信号,这个线程就是EventControlThread,先看下定义:
class EventControlThread: public Thread {public: explicit EventControlThread(const sp& flinger); virtual ~EventControlThread() {} void setVsyncEnabled(bool enabled); virtual bool threadLoop();private: sp mFlinger; bool mVsyncEnabled; Mutex mMutex; Condition mCond;};
定义很简单,继承了Thread类,持有一个SurfaceFlinger的强引用。
1.4.3.1 EventControlThread(const sp&)
EventControlThread::EventControlThread(const sp& flinger): mFlinger(flinger), mVsyncEnabled(false) { // 默认禁止Vsync信号,当然了,原因SF现在还没准备好嘛}
1.4.3.2 EventControlThread.run()
android native中的Thread.run就是不断运行threadLoop()。
这里通过Condition来控制SurfaceFlinger是否接收Vsync信号。
bool EventControlThread::threadLoop() { Mutex::Autolock lock(mMutex); //持锁 bool vsyncEnabled = mVsyncEnabled;#ifdef USE_HWC2 mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, mVsyncEnabled);#else mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, mVsyncEnabled);#endif while (true) { // mCond阻塞,通过信号量控制 status_t err = mCond.wait(mMutex); if (err != NO_ERROR) { ALOGE("error waiting for new events: %s (%d)", strerror(-err), err); return false; } // 解除阻塞后,如果开关状态发生变化,调用mFlinger->eventControl // 之后保存当前开关状态 if (vsyncEnabled != mVsyncEnabled) {#ifdef USE_HWC2 mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, mVsyncEnabled);#else mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, mVsyncEnabled);#endif vsyncEnabled = mVsyncEnabled; } } return false;}
看完这个函数自然有两个疑问,谁控制mCond?SF->eventControl的作用?先不着急,回到SurfaceFlinger.init()继续分析SF的启动流程。
1.4.4 mDrawingState = mCurrentState;
需要看这个State的定义–在SurfaceFlinger.h文件中;State是个私有内部类,主要功能是按照Z轴顺序储存了一组layer。
private: class State { public: explicit State(LayerVector::StateSet set) : stateSet(set) {} State& operator=(const State& other) { // We explicitly don't copy stateSet so that, e.g., mDrawingState // always uses the Drawing StateSet. layersSortedByZ = other.layersSortedByZ; displays = other.displays; return *this; } const LayerVector::StateSet stateSet = LayerVector::StateSet::Invalid; LayerVector layersSortedByZ; DefaultKeyedVector< wp, DisplayDeviceState> displays; void traverseInZOrder(const LayerVector::Visitor& visitor) const; void traverseInReverseZOrder(const LayerVector::Visitor& visitor) const; }; // 必须被mStateLock锁保护 State mCurrentState{LayerVector::StateSet::Current}; // 只能被SF主线程访问,不需要同步 State mDrawingState{LayerVector::StateSet::Drawing};
1.5 SurfaceFlinger:run()
在初始化所有资源和状态后,SF开始处理。
void SurfaceFlinger::run() { do { // 死循环一直执行。 waitForEvent(); } while (true);}void SurfaceFlinger::waitForEvent() { // 1.5.1 上面分析得知,mEventQueue是MessageQueue类型 mEventQueue.waitMessage();}
1.5.1 MessageQueue.waitMessage()
void MessageQueue::waitMessage() { do { IPCThreadState::self()->flushCommands(); // 1.5.2 重点在这里,Looper接收消息给主线程的handler处理 //([1.3.2]MessageQueue.init & [1.4.1.3]MessageQueue:setEventThread)。 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); // 双重死循环??}
1.5.2 MessageQueue.cb_eventReceiver()
从1.4.1.3MessageQueue:setEventThread 可知对应Fd有事件,会调用这个回调函数。
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) { MessageQueue* queue = reinterpret_cast(data); //1.5.3 return queue->eventReceiver(fd, events);}
1.5.3 MessageQueue:eventReceiver
int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) { ssize_t n; DisplayEventReceiver::Event buffer[8]; // 从BitTube读取事件 while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) { for (int i=0 ; idispatchInvalidate(); break; } } } return 1;}
1.5.4 MessageQueue.handler:dispatchInvalidate()
void MessageQueue::Handler::dispatchInvalidate() { // 给mEventMask标上eventMaskInvalidate标识,表明SurfaceFlinger正在处理Invalidate事件 // 这也说明了如果SF正在处理消息时,会忽略重复的消息 if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) { // 通过Looper发送INVALIDATE消息 mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE)); }}
这里就有个问题,为什么通过BitTube读取的事件不直接处理,反而要多此一举重新进入消息队列处理呢?:
1.5.5 MessageQueue.handler:handleMessage
void MessageQueue::Handler::handleMessage(const Message& message) { switch (message.what) { case INVALIDATE: // 移除标识,表明可以接收处理下一次事件 android_atomic_and(~eventMaskInvalidate, &mEventMask); // 1.5.6 转交给SF处理咯 mQueue.mFlinger->onMessageReceived(message.what); break; case REFRESH: android_atomic_and(~eventMaskRefresh, &mEventMask); mQueue.mFlinger->onMessageReceived(message.what); break; }}
1.5.6 SurfaceFlinger:onMessageReceived()
void SurfaceFlinger::onMessageReceived(int32_t what) { ATRACE_CALL(); switch (what) { case MessageQueue::INVALIDATE: { // 这个frameMissed 暂时还没看出是什么意思,涉及到Fence机制 // 先从字面意思理解,这里判断是否跳过该帧 bool frameMissed = !mHadClientComposition && mPreviousPresentFence != Fence::NO_FENCE && (mPreviousPresentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING); ATRACE_INT("FrameMissed", static_cast(frameMissed)); if (mPropagateBackpressure && frameMissed) { ALOGD("Backpressure trigger, skipping transaction & refresh!"); // 1.5.6.1 请求Vsync信号 // Backpressure被触发,frameMissed = true,跳过此次的Transaction和refresh signalLayerUpdate(); break; } // 目前忽略VrFlinger updateVrFlinger(); // 1.5.7 处理Transaction消息,每个layer处理(doTransaction) bool refreshNeeded = handleMessageTransaction(); // 1.5.8 处理Invalidate消息,重绘 refreshNeeded |= handleMessageInvalidate(); refreshNeeded |= mRepaintEverything; if (refreshNeeded) { // 1.5.9 如果事务修改了窗口状态,锁定了新的缓冲区, // 或者HWC请求完全重新绘制,则发出刷新信号 signalRefresh(); } break; } case MessageQueue::REFRESH: { // 1.5.9.1 刷新 handleMessageRefresh(); break; } }}
1.5.6.1 SurfaceFlinger:signalLayerUpdate
这个方法最终是通过SurfaceFlinger请求Vsync信号,为什么绕个圈子请求?注意 mCondition.broadcast
void SurfaceFlinger::signalLayerUpdate() { // 通过MessageQueue使EventThread请求下一次Vsync信号 mEventQueue.invalidate();}// MessageQueue.cppvoid MessageQueue::invalidate() { // 1.5.6.2 这里的 mEvents 是EventThread.Connection mEvents->requestNextVsync();}
#### 1.5.6.2 EventThread::Connection::requestNextVsync() ```c++ void EventThread::Connection::requestNextVsync() {
mEventThread->requestNextVsync(this);
}
void EventThread::requestNextVsync(
const sp& connection) {Mutex::Autolock _l(mLock);// SF向硬件请求Vsync,两次请求间隔必须大于500ns,否则忽略mFlinger.resyncWithRateLimit();if (connection->count < 0) { connection->count = 0; // 通知有Vsync信号来了,1.4.1.4:EventThread:threadLoop()中 // waitForEvent 终于等到事件了。 mCondition.broadcast();}
}
### 1.5.7 SurfaceFlinger:handleMessageTransaction()```c++void SurfaceFlinger::handleTransaction(uint32_t transactionFlags){ ATRACE_CALL(); // 拷贝mDrawingState副本,避免死锁 State drawingState(mDrawingState); Mutex::Autolock _l(mStateLock); const nsecs_t now = systemTime(); mDebugInTransaction = now; // 标记Transaction transactionFlags = getTransactionFlags(eTransactionMask); // 这部分代码过长,稍后分析。主要功能是调用每个 Layer // 的 doTransaction,处理系统在两次刷新期间的各种变化 handleTransactionLocked(transactionFlags); mLastTransactionTime = systemTime() - now; mDebugInTransaction = 0; invalidateHwcGeometry();}
1.5.8 SurfaceFlinger:handleMessageInvalidate()
bool SurfaceFlinger::handleMessageInvalidate() { ATRACE_CALL(); // 重绘,更新每个layer状态,后续分析 return handlePageFlip();}
1.5.9 SurfaceFlinger:signalRefresh()
这里的流程是通过MessageQueue将Refresh消息添加至消息队列后,回到SurfaceFlinger处理。
MessageQueue.handler收到REFRESH消息,转交给SurfaceFlinger:onMessageReceived处理。
void SurfaceFlinger::signalRefresh() { mEventQueue.refresh();}// MessageQueue.cppvoid MessageQueue::refresh() { mHandler->dispatchRefresh();}void MessageQueue::Handler::dispatchRefresh() { if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) { mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH)); }}void MessageQueue::Handler::handleMessage(const Message& message) { switch (message.what) { case INVALIDATE: android_atomic_and(~eventMaskInvalidate, &mEventMask); mQueue.mFlinger->onMessageReceived(message.what); break; case REFRESH: android_atomic_and(~eventMaskRefresh, &mEventMask); // 1.5.6 回到SF处理该消息 mQueue.mFlinger->onMessageReceived(message.what); break; }}
1.5.9.1 SurfaceFlinger:handleMessageRefresh()
处理刷新,SF的消息处理流程复杂。这刷新操作后续分析。
void SurfaceFlinger::handleMessageRefresh() { ATRACE_CALL(); nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); preComposition(refreshStartTime); rebuildLayerStacks(); setUpHWComposer(); doDebugFlashRegions(); doComposition(); postComposition(refreshStartTime); mPreviousPresentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY); mHadClientComposition = false; for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { const sp& displayDevice = mDisplays[displayId]; mHadClientComposition = mHadClientComposition || mHwc->hasClientComposition(displayDevice->getHwcDisplayId()); } mLayersWithQueuedFrames.clear();}
好了,SF启动流程分析完了。
二、VSync信号的启动与处理
SF启动完成了,万事俱备就等着硬件设备的Vsync信号了~等一下,Vsync信号是怎么传递给SF的呢?
1.4.1.4 EventThread.run()中等待Vsync信号,我们从这里开始分析,在分析之前先看一下DisplayEventReceiver这个类。
2.1 DisplayEventReceiver
这个类其实就是传输VSync信号,也包括Hotplug事件。先看定义:
class DisplayEventReceiver {public: enum { DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'), // vsyn DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'), // plug }; struct Event { struct Header { uint32_t type; // 事件类型:1、vsyn;2、plug uint32_t id; // 0:vsyn plug:plug nsecs_t timestamp __attribute__((aligned(8))); // 时间戳 }; struct VSync { uint32_t count; }; struct Hotplug { bool connected; }; Header header; union { VSync vsync; Hotplug hotplug; }; };public: // DisplayEventReceiver创建并注册了SF的一个事件连接,默认禁止VSync // 通过调用setVSyncRate、requestNextVsync开始接受。其他事件则即刻分发 DisplayEventReceiver( ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp); ~DisplayEventReceiver(); status_t initCheck() const; // 获取用于接收事件的文件描述符,该描述符由本类持有,不得关闭 int getFd() const; // 从队列中读取事件并返回事件个数如果返回NOT_ENOUGH_DATA // 表示这个对象永远无效,不能继续调用本方法 ssize_t getEvents(Event* events, size_t count); static ssize_t getEvents(gui::BitTube* dataChannel, Event* events, size_t count); // 向队列中写入事件并返回写入的数量 static ssize_t sendEvents(gui::BitTube* dataChannel, Event const* events, size_t count); // 设置VSync分发频率,每次VSync事件返回1,其他事件返回2,没有事件返回0。 status_t setVsyncRate(uint32_t count); // 请求下一次Vsync status_t requestNextVsync();private: sp mEventConnection; std::unique_ptr mDataChannel;};
2.1 EventThread:waitForEvent
Vector< sp > EventThread::waitForEvent( DisplayEventReceiver::Event* event){ Mutex::Autolock _l(mLock); Vector< sp > signalConnections; do { bool eventPending = false; bool waitForVSync = false; size_t vsyncCount = 0; nsecs_t timestamp = 0; // 从mVSyncEvent数组中读取timestamp // 其实只有mVSyncEvent[0]中存入了Vsync事件信息 for (int32_t i=0 ; i connection(mDisplayEventConnections[i].promote()); if (connection != NULL) { bool added = false; if (connection->count >= 0) { // we need vsync events because at least // one connection is waiting for it waitForVSync = true; if (timestamp) { // we consume the event only if it's time // (ie: we received a vsync event) if (connection->count == 0) { // fired this time around connection->count = -1; signalConnections.add(connection); added = true; } else if (connection->count == 1 || (vsyncCount % connection->count) == 0) { // continuous event, and time to report it signalConnections.add(connection); added = true; } } } if (eventPending && !timestamp && !added) { // we don't have a vsync event to process // (timestamp==0), but we have some pending // messages. signalConnections.add(connection); } } else { // we couldn't promote this reference, the connection has // died, so clean-up! mDisplayEventConnections.removeAt(i); --i; --count; } } // Here we figure out if we need to enable or disable vsyncs if (timestamp && !waitForVSync) { // we received a VSYNC but we have no clients // don't report it, and disable VSYNC events disableVSyncLocked(); } else if (!timestamp && waitForVSync) { // we have at least one client, so we want vsync enabled // (TODO: this function is called right after we finish // notifying clients of a vsync, so this call will be made // at the vsync rate, e.g. 60fps. If we can accurately // track the current state we could avoid making this call // so often.) enableVSyncLocked(); } // note: !timestamp implies signalConnections.isEmpty(), because we // don't populate signalConnections if there's no vsync pending if (!timestamp && !eventPending) { // wait for something to happen if (waitForVSync) { // This is where we spend most of our time, waiting // for vsync events and new client registrations. // // If the screen is off, we can't use h/w vsync, so we // use a 16ms timeout instead. It doesn't need to be // precise, we just need to keep feeding our clients. // // We don't want to stall if there's a driver bug, so we // use a (long) timeout when waiting for h/w vsync, and // generate fake events when necessary. bool softwareSync = mUseSoftwareVSync; nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000); if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) { if (!softwareSync) { ALOGW("Timed out waiting for hw vsync; faking it"); } // FIXME: how do we decide which display id the fake // vsync came from ? mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY; mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC); mVSyncEvent[0].vsync.count++; } } else { // Nobody is interested in vsync, so we just want to sleep. // h/w vsync should be disabled, so this will wait until we // get a new connection, or an existing connection becomes // interested in receiving vsync again. mCondition.wait(mLock); } } } while (signalConnections.isEmpty()); // here we're guaranteed to have a timestamp and some connections to signal // (The connections might have dropped out of mDisplayEventConnections // while we were asleep, but we'll still have strong references to them.) return signalConnections;}
这里是初动力,来自硬件的vsync信号:
void HWComposer::vsync(const std::shared_ptr& display, int64_t timestamp) { auto displayType = HWC2::DisplayType::Invalid; auto error = display->getType(&displayType); if (error != HWC2::Error::None) { ALOGE("vsync: Failed to determine type of display %" PRIu64, display->getId()); return; } if (displayType == HWC2::DisplayType::Virtual) { ALOGE("Virtual display %" PRIu64 " passed to vsync callback", display->getId()); return; } if (mHwcDisplaySlots.count(display->getId()) == 0) { ALOGE("Unknown physical display %" PRIu64 " passed to vsync callback", display->getId()); return; } int32_t disp = mHwcDisplaySlots[display->getId()]; { Mutex::Autolock _l(mLock); // There have been reports of HWCs that signal several vsync events // with the same timestamp when turning the display off and on. This // is a bug in the HWC implementation, but filter the extra events // out here so they don't cause havoc downstream. if (timestamp == mLastHwVSync[disp]) { ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")", timestamp); return; } mLastHwVSync[disp] = timestamp; } char tag[16]; snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp); ATRACE_INT(tag, ++mVSyncCounts[disp] & 1); // 收到Vsync,发送给mEventHandler,也就是SurfaceFlinger mEventHandler->onVSyncReceived(this, disp, timestamp);}
Vsync信号不仅仅只有来自HWC的硬件Vsync,也有使用软件模拟的Vsync,甚至大多数情况下app收到的vsync信号都是来自软件模拟的。更多请关注DispSync探秘。
更多相关文章
- Android-防止事件导致的oncreate的多次调用
- 基于TCP和多线程实现无线鼠标键盘-Socket(2)
- cocos2dx android平台事件系统解析
- android中在子线程中更新UI的几种方法
- android利用handler线程间的通信
- 关于Android在非UI线程更新UI的问题。
- android 线程通信Handler Bundle