原址

SurfaceFlinger是一个独立的进程,我们来看下init.rc关于SurfaceFlinger的代码,我们可以看到SurfaceFlinger是属于core服务的。

  1. service surfaceflinger /system/bin/surfaceflinger

  2. class core

  3. user system

  4. group graphics drmrpc

  5. onrestart restart zygote

  6. writepid /dev/cpuset/system-background/tasks

一、SurfaceFlinger的启动过程

SurfaceFlinger的main函数在framework/native/services/surfaceflinger/main_surfaceflinger.cpp中

  1. int main(int, char**) {

  2. // When SF is launched in its own process, limit the number of

  3. // binder threads to 4.

  4. ProcessState::self()->setThreadPoolMaxThreadCount(4);//设置了Binder线程池最大线程为4

  5. // start the thread pool

  6. sp<ProcessState> ps(ProcessState::self());

  7. ps->startThreadPool();

  8. // instantiate surfaceflinger

  9. sp<SurfaceFlinger> flinger = new SurfaceFlinger();//创建SurfaceFlinger对象

  10. setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);

  11. set_sched_policy(0, SP_FOREGROUND);

  12. // initialize before clients can connect

  13. flinger->init();//调用SurfaceFlinger的init函数

  14. // publish surface flinger

  15. sp<IServiceManager> sm(defaultServiceManager());

  16. sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);//像serviceManager注册SurfaceFlinger服务

  17. // run in this thread

  18. flinger->run();//运行

  19. return 0;

  20. }

在主函数中先设置了该进程的binder线程池最大数为4,然后创建了SurfaceFlinger对象,并且调用了其init函数,接着把SurfaceFlinger服务注册到ServiceManager中,然后调用了run方法。

我们先来看下init函数

  1. void SurfaceFlinger::init() {

  2. ALOGI( "SurfaceFlinger's main thread ready to run. "

  3. "Initializing graphics H/W...");

  4. Mutex::Autolock _l(mStateLock);

  5. // initialize EGL for the default display 将EGL初始化成缺省的显示

  6. mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);

  7. eglInitialize(mEGLDisplay, NULL, NULL);

  8. // start the EventThread

  9. sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,

  10. vsyncPhaseOffsetNs, true, "app");

  11. mEventThread = new EventThread(vsyncSrc);

  12. sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,

  13. sfVsyncPhaseOffsetNs, true, "sf");

  14. mSFEventThread = new EventThread(sfVsyncSrc);

  15. mEventQueue.setEventThread(mSFEventThread);

  16. // Initialize the H/W composer object. There may or may not be an

  17. // actual hardware composer underneath.

  18. mHwc = new HWComposer(this,//显示硬件抽象类

  19. *static_cast<HWComposer::EventHandler *>(this));

  20. // get a RenderEngine for the given display / config (can't fail)

  21. mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());

  22. // retrieve the EGL context that was selected/created

  23. mEGLContext = mRenderEngine->getEGLContext();

  24. LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,

  25. "couldn't create EGLContext");

  26. // initialize our non-virtual displays 初始化显示设备

  27. for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {

  28. DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);

  29. // set-up the displays that are already connected

  30. if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {

  31. // All non-virtual displays are currently considered secure.

  32. bool isSecure = true;

  33. createBuiltinDisplayLocked(type);

  34. wp<IBinder> token = mBuiltinDisplays[i];

  35. sp<IGraphicBufferProducer> producer;

  36. sp<IGraphicBufferConsumer> consumer;

  37. BufferQueue::createBufferQueue(&producer, &consumer,

  38. new GraphicBufferAlloc());

  39. sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,

  40. consumer);

  41. int32_t hwcId = allocateHwcDisplayId(type);

  42. sp<DisplayDevice> hw = new DisplayDevice(this,

  43. type, hwcId, mHwc->getFormat(hwcId), isSecure, token,

  44. fbs, producer,

  45. mRenderEngine->getEGLConfig());

  46. if (i > DisplayDevice::DISPLAY_PRIMARY) {

  47. // FIXME: currently we don't get blank/unblank requests

  48. // for displays other than the main display, so we always

  49. // assume a connected display is unblanked.

  50. ALOGD("marking display %zu as acquired/unblanked", i);

  51. hw->setPowerMode(HWC_POWER_MODE_NORMAL);

  52. }

  53. mDisplays.add(token, hw);

  54. }

  55. }

  56. // make the GLContext current so that we can create textures when creating Layers

  57. // (which may happens before we render something)

  58. getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);

  59. mEventControlThread = new EventControlThread(this);

  60. mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);

  61. // set a fake vsync period if there is no HWComposer

  62. if (mHwc->initCheck() != NO_ERROR) {

  63. mPrimaryDispSync.setPeriod(16666667);

  64. }

  65. // initialize our drawing state

  66. mDrawingState = mCurrentState;

  67. // set initial conditions (e.g. unblank default device)

  68. initializeDisplays();//初始化显示设备

  69. // start boot animation

  70. startBootAnim();//启动开机动画

  71. }

init函数主要工作:

1.初始化OpenGL ES图形库。

2. 创建显示设备的抽象代表,负责和显示设备打交道。

3. 创建显示设备对象。

4. 启动EventThread。监听和处理SurfaceFlinger中的事件。

5.设置软件VSync信号周期。

6.初始化显示设备,调用initializeDisplays完成。

7.启动开机动画,调用了startBootAnim函数,只是设置了两个属性,其中一个ctl.start是启动了bootanim进程。

  1. void SurfaceFlinger::startBootAnim() {

  2. // start boot animation

  3. property_set("service.bootanim.exit", "0");

  4. property_set("ctl.start", "bootanim");

  5. }

二、消息和事件分发 MessageQueue和EventThread

MessageQueue和用于消息和事件的分发,这个和之前博客分析过得消息机制原理差不多。

我们先来看看MessageQueue的主要成员变量

  1. class MessageQueue {

  2. ......

  3. sp<SurfaceFlinger> mFlinger;//指向SurfaceFlinger

  4. sp<Looper> mLooper;//消息机制Looper对象

  5. sp<EventThread> mEventThread;//关联的EventThread

  6. sp<IDisplayEventConnection> mEvents;

  7. sp<BitTube> mEventTube;

  8. sp<Handler> mHandler;//消息处理器

其中mEventThread主要是用来分析VSync信号的。

在SurfaceFlinger中有一个类型为MessageQueue的成员变量mEventQueue,在SurfaceFlinger的onFirstRef函数中会调用其init函数

  1. void SurfaceFlinger::onFirstRef()

  2. {

  3. mEventQueue.init(this);

  4. }

在这个函数中创建了Looper和Handler对象,并且把flinger保存在mFlinger中。

  1. void MessageQueue::init(const sp<SurfaceFlinger>& flinger)

  2. {

  3. mFlinger = flinger;

  4. mLooper = new Looper(true);

  5. mHandler = new Handler(*this);

  6. }

我们来看下Handler这个类,它是MessageQueue类的一个内部类,这个类主要处理3个消息。

  1. class Handler : public MessageHandler {

  2. enum {

  3. eventMaskInvalidate = 0x1,//invalidate消息

  4. eventMaskRefresh = 0x2,//刷新消息

  5. eventMaskTransaction = 0x4

  6. };

  7. MessageQueue& mQueue;

  8. int32_t mEventMask;

  9. public:

  10. Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) { }

  11. virtual void handleMessage(const Message& message);

  12. void dispatchRefresh();

  13. void dispatchInvalidate();

  14. void dispatchTransaction();

  15. };

我们再来看在SurfaceFlinger主函数最后调用了下面方法。

    flinger->run();

SurfaceFlinger::run代码如下

  1. void SurfaceFlinger::run() {

  2. do {

  3. waitForEvent();

  4. } while (true);

  5. }

waitForEvent函数如下:

  1. void SurfaceFlinger::waitForEvent() {

  2. mEventQueue.waitMessage();

  3. }

然后又调用了EventQueue的waitMessage方法,记住这里是在主线程中循环调用的。

下面我们来看下waitMessage方法,flushCommands之前在分析Binder的博客中有提到,主要是清理工作的,和Binder驱动的交互关了。而pollOnce是消息机制,主要调用了epoll_wait函数,会阻塞,阻塞完了会分发消息队列中的消息。这里的消息只有自己在Handler中发的消息,还有在setEventThread中自己添加的fd。

  1. void MessageQueue::waitMessage() {

  2. do {

  3. IPCThreadState::self()->flushCommands();

  4. int32_t ret = mLooper->pollOnce(-1);

  5. switch (ret) {

  6. case Looper::POLL_WAKE:

  7. case Looper::POLL_CALLBACK:

  8. continue;

  9. case Looper::POLL_ERROR:

  10. ALOGE("Looper::POLL_ERROR");

  11. case Looper::POLL_TIMEOUT:

  12. // timeout (should not happen)

  13. continue;

  14. default:

  15. // should not happen

  16. ALOGE("Looper::pollOnce() returned unknown status %d", ret);

  17. continue;

  18. }

  19. } while (true);

  20. }

下面是Handler中发送消息,这个会在pollOnce中处理。

  1. void MessageQueue::Handler::dispatchRefresh() {

  2. if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {

  3. mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));

  4. }

  5. }

  6. void MessageQueue::Handler::dispatchInvalidate() {

  7. if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {

  8. mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));

  9. }

  10. }

  11. void MessageQueue::Handler::dispatchTransaction() {

  12. if ((android_atomic_or(eventMaskTransaction, &mEventMask) & eventMaskTransaction) == 0) {

  13. mQueue.mLooper->sendMessage(this, Message(MessageQueue::TRANSACTION));

  14. }

  15. }

在SurfaceFlinger的init函数还调用了如下函数

  1. mSFEventThread = new EventThread(sfVsyncSrc);

  2. mEventQueue.setEventThread(mSFEventThread);

我们来看setEventThread函数会调用Looper的addFd,这个最终也会在pollOnce中执行。mEventThread是一个EventThread对象,调用createEventConnection来创建一个连接。EventThread是一个线程类用来分发VSync消息。这个我们后面讲解VSync信号的时候还会详细分析。

  1. void MessageQueue::setEventThread(const sp<EventThread>& eventThread)

  2. {

  3. mEventThread = eventThread;

  4. mEvents = eventThread->createEventConnection();

  5. mEventTube = mEvents->getDataChannel();

  6. mLooper->addFd(mEventTube->getFd(), 0, Looper::EVENT_INPUT,

  7. MessageQueue::cb_eventReceiver, this);

  8. }

三、显示设备  DisplayDevice类

DisplayDevice是显示设备的抽象,定义了3中类型的显示设备。

1.DISPLAY_PRIMARY:主显示设备,通常是LCD屏

2.DISPLAY_EXTERNAL:扩展显示设备。通过HDMI输出的显示信号

3.DISPLAY_VIRTUAL:虚拟显示设备,通过WIFI输出信号
这3钟设备,第一种是基本配置,另外两种需要硬件支持。这里我们主要讲解第一种。

SurfaceFlinger中需要显示的图层(layer)将通过DisplayDevice对象传递到OpenGLES中进行合成,合成之后的图像再通过HWComposer对象传递到Framebuffer中显示。DisplayDevice对象中的成员变量mVisibleLayersSortedByZ保存了所有需要显示在本显示设备中显示的Layer对象,同时DisplayDevice对象也保存了和显示设备相关的显示方向、显示区域坐标等信息。

上节在SurfaceFlinger的init函数中有一段代码来创建DisplayDevice对象

  1. for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {

  2. DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);

  3. // set-up the displays that are already connected

  4. if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {

  5. // All non-virtual displays are currently considered secure.

  6. bool isSecure = true;

  7. createBuiltinDisplayLocked(type);//给显示设备分配一个token

  8. wp<IBinder> token = mBuiltinDisplays[i];

  9. sp<IGraphicBufferProducer> producer;

  10. sp<IGraphicBufferConsumer> consumer;

  11. BufferQueue::createBufferQueue(&producer, &consumer,

  12. new GraphicBufferAlloc());

  13. sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,

  14. consumer);

  15. int32_t hwcId = allocateHwcDisplayId(type);

  16. sp<DisplayDevice> hw = new DisplayDevice(this,

  17. type, hwcId, mHwc->getFormat(hwcId), isSecure, token,

  18. fbs, producer,

  19. mRenderEngine->getEGLConfig());

  20. if (i > DisplayDevice::DISPLAY_PRIMARY) {

  21. // FIXME: currently we don't get blank/unblank requests

  22. // for displays other than the main display, so we always

  23. // assume a connected display is unblanked.

  24. ALOGD("marking display %zu as acquired/unblanked", i);

  25. hw->setPowerMode(HWC_POWER_MODE_NORMAL);

  26. }

  27. mDisplays.add(token, hw);//把显示设备对象保存在mDisplays列表中

  28. }

  29. }

所有显示设备的输出都要通过HWComposer对象完成,因此上面这段代码先调用了HWComposer的isConnected来检查显示设备是否已连接,只有和显示设备连接的DisplayDevice对象才会被创建出来。即使没有任何物理显示设备被检测到,SurfaceFlinger都需要一个DisplayDevice对象才能正常工作,因此,DISPLAY_PRIMARY类型的DisplayDevice对象总是会被创建出来。

createBuiltinDisplayLocked函数就是为显示设备对象创建一个BBinder类型的Token而已。

  1. void SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type) {

  2. ALOGW_IF(mBuiltinDisplays[type],

  3. "Overwriting display token for display type %d", type);

  4. mBuiltinDisplays[type] = new BBinder();

  5. DisplayDeviceState info(type);

  6. // All non-virtual displays are currently considered secure.

  7. info.isSecure = true;

  8. mCurrentState.displays.add(mBuiltinDisplays[type], info);

  9. }

然后会调用createBufferQueue函数创建一个producer和consumer,这个之前分析过。然后又创建了一个FramebufferSurface对象。这里我们看到在新建FramebufferSurface对象时把consumer参数传入了代表是一个消费者。而在DisplayDevice的构造函数中,会创建一个Surface对象传递给底层的OpenGL ES使用,而这个Surface是一个生产者。在OpenGl ES中合成好了图像之后会将图像数据写到Surface对象中,这将触发consumer对象的onFrameAvailable函数被调用:

这就是Surface数据好了就通知消费者来拿数据做显示用,在onFrameAvailable函数汇总,通过nextBuffer获得图像数据,然后调用HWComposer对象mHwc的fbPost函数输出。

  1. void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {

  2. sp<GraphicBuffer> buf;

  3. sp<Fence> acquireFence;

  4. status_t err = nextBuffer(buf, acquireFence);

  5. if (err != NO_ERROR) {

  6. ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",

  7. strerror(-err), err);

  8. return;

  9. }

  10. err = mHwc.fbPost(mDisplayType, acquireFence, buf);

  11. if (err != NO_ERROR) {

  12. ALOGE("error posting framebuffer: %d", err);

  13. }

  14. }

fbPost函数最后通过调用Gralloc模块的post函数来输出图像。

我们再来看看DisplayDevice的构造函数

  1. DisplayDevice::DisplayDevice(

  2. const sp<SurfaceFlinger>& flinger,

  3. DisplayType type,

  4. int32_t hwcId,

  5. int format,

  6. bool isSecure,

  7. const wp<IBinder>& displayToken,

  8. const sp<DisplaySurface>& displaySurface,

  9. const sp<IGraphicBufferProducer>& producer,

  10. EGLConfig config)

  11. : lastCompositionHadVisibleLayers(false),

  12. mFlinger(flinger),

  13. mType(type), mHwcDisplayId(hwcId),

  14. mDisplayToken(displayToken),

  15. mDisplaySurface(displaySurface),

  16. mDisplay(EGL_NO_DISPLAY),

  17. mSurface(EGL_NO_SURFACE),

  18. mDisplayWidth(), mDisplayHeight(), mFormat(),

  19. mFlags(),

  20. mPageFlipCount(),

  21. mIsSecure(isSecure),

  22. mSecureLayerVisible(false),

  23. mLayerStack(NO_LAYER_STACK),

  24. mOrientation(),

  25. mPowerMode(HWC_POWER_MODE_OFF),

  26. mActiveConfig(0)

  27. {

  28. mNativeWindow = new Surface(producer, false);//创建Surface对象

  29. ANativeWindow* const window = mNativeWindow.get();

  30. /*

  31. * Create our display's surface

  32. */

  33. EGLSurface surface;

  34. EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

  35. if (config == EGL_NO_CONFIG) {

  36. config = RenderEngine::chooseEglConfig(display, format);

  37. }

  38. surface = eglCreateWindowSurface(display, config, window, NULL);

  39. eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth);

  40. eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);

  41. // Make sure that composition can never be stalled by a virtual display

  42. // consumer that isn't processing buffers fast enough. We have to do this

  43. // in two places:

  44. // * Here, in case the display is composed entirely by HWC.

  45. // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the

  46. // window's swap interval in eglMakeCurrent, so they'll override the

  47. // interval we set here.

  48. if (mType >= DisplayDevice::DISPLAY_VIRTUAL)//虚拟设备不支持图像合成

  49. window->setSwapInterval(window, 0);

  50. mConfig = config;

  51. mDisplay = display;

  52. mSurface = surface;

  53. mFormat = format;

  54. mPageFlipCount = 0;

  55. mViewport.makeInvalid();

  56. mFrame.makeInvalid();

  57. // virtual displays are always considered enabled 虚拟设备屏幕认为是不关闭的

  58. mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?

  59. HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;

  60. // Name the display. The name will be replaced shortly if the display

  61. // was created with createDisplay().

  62. switch (mType) {//显示设备名称

  63. case DISPLAY_PRIMARY:

  64. mDisplayName = "Built-in Screen";

  65. break;

  66. case DISPLAY_EXTERNAL:

  67. mDisplayName = "HDMI Screen";

  68. break;

  69. default:

  70. mDisplayName = "Virtual Screen"; // e.g. Overlay #n

  71. break;

  72. }

  73. // initialize the display orientation transform.

  74. setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);

  75. }

上面构造函数主要功能是创建了一个Surface对象mNativeWindow,同时用它作为参数创建EGLSurface对象,这个EGLSurface对象是OpenGL ES中绘图需要的。

这样,在DisplayDevice中就建立了一个通向Framebuffer的通道,只要向DisplayDevice的mSurface写入数据。就会到消费者FrameBufferSurface的onFrameAvailable函数,然后到HWComposer在到Gralloc模块,最后输出到显示设备。

swapBuffers函数将内部缓冲区的图像数据刷新到显示设备的Framebuffer中,它通过调用eglSwapBuffers函数来完成缓冲区刷新工作。但是注意调用swapBuffers输出图像是在显示设备不支持硬件composer的情况下。

  1. void DisplayDevice::swapBuffers(HWComposer& hwc) const {

  2. // We need to call eglSwapBuffers() if:

  3. // (1) we don't have a hardware composer, or

  4. // (2) we did GLES composition this frame, and either

  5. // (a) we have framebuffer target support (not present on legacy

  6. // devices, where HWComposer::commit() handles things); or

  7. // (b) this is a virtual display

  8. if (hwc.initCheck() != NO_ERROR ||

  9. (hwc.hasGlesComposition(mHwcDisplayId) &&

  10. (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {

  11. EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);

  12. if (!success) {

  13. EGLint error = eglGetError();

  14. if (error == EGL_CONTEXT_LOST ||

  15. mType == DisplayDevice::DISPLAY_PRIMARY) {

  16. LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",

  17. mDisplay, mSurface, error);

  18. } else {

  19. ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",

  20. mDisplay, mSurface, error);

  21. }

  22. }

  23. }

  24. else if(hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL)

  25. {

  26. EGLBoolean success = eglSwapBuffersVIV(mDisplay, mSurface);

  27. if (!success) {

  28. EGLint error = eglGetError();

  29. ALOGE("eglSwapBuffersVIV(%p, %p) failed with 0x%08x",

  30. mDisplay, mSurface, error);

  31. }

  32. }

  33. status_t result = mDisplaySurface->advanceFrame();

  34. if (result != NO_ERROR) {

  35. ALOGE("[%s] failed pushing new frame to HWC: %d",

  36. mDisplayName.string(), result);

  37. }

  38. }

四、VSync信号的分发过程

在之前的博客分析过,当VSync信号到来时会调用HWComposer类中的vsync函数

  1. void HWComposer::vsync(int disp, int64_t timestamp) {

  2. if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {

  3. {

  4. Mutex::Autolock _l(mLock);

  5. // There have been reports of HWCs that signal several vsync events

  6. // with the same timestamp when turning the display off and on. This

  7. // is a bug in the HWC implementation, but filter the extra events

  8. // out here so they don't cause havoc downstream.

  9. if (timestamp == mLastHwVSync[disp]) {

  10. ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",

  11. timestamp);

  12. return;

  13. }

  14. mLastHwVSync[disp] = timestamp;

  15. }

  16. char tag[16];

  17. snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);

  18. ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);

  19. mEventHandler.onVSyncReceived(disp, timestamp);

  20. }

  21. }

这个函数主要是调用了mEventHandler.onVSyncReceived函数,让我们先来看下mEventHandler的构造,看HWComposer的构造函数,mEventHandler是传入的参数handler。

  1. HWComposer::HWComposer(

  2. const sp<SurfaceFlinger>& flinger,

  3. EventHandler& handler)

  4. : mFlinger(flinger),

  5. mFbDev(0), mHwc(0), mNumDisplays(1),

  6. mCBContext(new cb_context),

  7. mEventHandler(handler),

  8. mDebugForceFakeVSync(false)

那么我们就要看新建HWComposer的地方了,是在SurfaceFlinger的init函数中新建的,这handler就是SurfaceFlinger对象。

  1. mHwc = new HWComposer(this,

  2. *static_cast<HWComposer::EventHandler *>(this));

因此上面的mEventHandler.onVSyncReceived函数,就是调用了SurfaceFlinger的onVSyncReceived函数

  1. void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {

  2. bool needsHwVsync = false;

  3. { // Scope for the lock

  4. Mutex::Autolock _l(mHWVsyncLock);

  5. if (type == 0 && mPrimaryHWVsyncEnabled) {

  6. needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);

  7. }

  8. }

  9. if (needsHwVsync) {

  10. enableHardwareVsync();

  11. } else {

  12. disableHardwareVsync(false);

  13. }

  14. }

4.1 DispSync类

上面函数我们主要看下DispSync的addResyncSample函数,看这个函数之前先看下DispSync的构造函数,在构造函数中启动了DispSyncThread线程

  1. DispSync::DispSync() :

  2. mRefreshSkipCount(0),

  3. mThread(new DispSyncThread()) {

  4. mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);

我们再来看addResyncSample函数,将VSync信号的时间戳保存大搜了数组mResyncSamples中。然后调用了updateModelLocked函数继续分发VSync信号。

  1. bool DispSync::addResyncSample(nsecs_t timestamp) {

  2. Mutex::Autolock lock(mMutex);

  3. size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;

  4. mResyncSamples[idx] = timestamp;

  5. if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {

  6. mNumResyncSamples++;

  7. } else {

  8. mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES;

  9. }

  10. updateModelLocked();

  11. if (mNumResyncSamplesSincePresent++ > MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) {

  12. resetErrorLocked();

  13. }

  14. if (kIgnorePresentFences) {

  15. // If we don't have the sync framework we will never have

  16. // addPresentFence called. This means we have no way to know whether

  17. // or not we're synchronized with the HW vsyncs, so we just request

  18. // that the HW vsync events be turned on whenever we need to generate

  19. // SW vsync events.

  20. return mThread->hasAnyEventListeners();

  21. }

  22. return mPeriod == 0 || mError > kErrorThreshold;

  23. }

updateModelLocked主要显示利用数组mResyncSamples中的值计算mPeriod和mPhase这两个时间值。然后最后调用了mThread的updateModel函数。mThread是DispSyncThread类。

  1. void DispSync::updateModelLocked() {

  2. if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) {

  3. ......

  4. //计算mPeriod和mPhase

  5. mThread->updateModel(mPeriod, mPhase);

  6. }

  7. }

我们来看下DispSyncThread的updateModel函数,这个函数只是保存了参数,然后调用了Condition的signal唤醒线程。

  1. void updateModel(nsecs_t period, nsecs_t phase) {

  2. Mutex::Autolock lock(mMutex);

  3. mPeriod = period;

  4. mPhase = phase;

  5. mCond.signal();

  6. }

我们再来看DispSyncThread的threadLoop函数,主要这个函数比较计算时间来决定是否要发送信号。如果没有信号发送就会在mCond等待,有信号发送前面会在updateModel中调用mCond的singal函数,这里线程就唤醒了。gatherCallbackInvocationsLocked函数获取本次VSync信号的回调函数列表,这些回调函数是通过DispSync类的addEventListener函数加入的。接着就调用fireCallbackInvocations来依次调用列表中所有对象的onDispSyncEvent函数。

  1. virtual bool threadLoop() {

  2. ......

  3. while (true) {

  4. Vector<CallbackInvocation> callbackInvocations;

  5. nsecs_t targetTime = 0;

  6. { // Scope for lock

  7. ......

  8. if (now < targetTime) {

  9. err = mCond.waitRelative(mMutex, targetTime - now);

  10. ......

  11. }

  12. now = systemTime(SYSTEM_TIME_MONOTONIC);

  13. ......

  14. callbackInvocations = gatherCallbackInvocationsLocked(now);

  15. }

  16. if (callbackInvocations.size() > 0) {

  17. fireCallbackInvocations(callbackInvocations);

  18. }

  19. }

  20. return false;

  21. }

fireCallbackInvocations函数就是遍历回调列表调用其onDispSyncEvent函数。

  1. void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {

  2. for (size_t i = 0; i < callbacks.size(); i++) {

  3. callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);

  4. }

  5. }

4.2 EventThread和DispSync的关系

这里我们先不往下分析DispSync遍历调用回调,我们先来看看EventThread的threadLoop函数,这个函数逻辑很简单。调用waitForEvent来获取事件,然后调用每个连接的postEvent来发送Event。

  1. bool EventThread::threadLoop() {

  2. DisplayEventReceiver::Event event;

  3. Vector< sp<EventThread::Connection> > signalConnections;

  4. signalConnections = waitForEvent(&event);//获取Event

  5. // dispatch events to listeners...

  6. const size_t count = signalConnections.size();

  7. for (size_t i=0 ; i<count ; i++) {

  8. const sp<Connection>& conn(signalConnections[i]);

  9. // now see if we still need to report this event

  10. status_t err = conn->postEvent(event);//发送Event

  11. if (err == -EAGAIN || err == -EWOULDBLOCK) {

  12. // The destination doesn't accept events anymore, it's probably

  13. // full. For now, we just drop the events on the floor.

  14. // FIXME: Note that some events cannot be dropped and would have

  15. // to be re-sent later.

  16. // Right-now we don't have the ability to do this.

  17. ALOGW("EventThread: dropping event (%08x) for connection %p",

  18. event.header.type, conn.get());

  19. } else if (err < 0) {

  20. // handle any other error on the pipe as fatal. the only

  21. // reasonable thing to do is to clean-up this connection.

  22. // The most common error we'll get here is -EPIPE.

  23. removeDisplayEventConnection(signalConnections[i]);

  24. }

  25. }

  26. return true;

  27. }

我们再来看下waitForEvent函数中下面代码段,timestamp为0表示没有时间,waitForSync为true表示至少有一个客户和EventThread建立了连接。这段代码一旦有客户连接,就调用enableVSyncLocked接收DispSyncSource的VSync信号。如果在接受信号中,所有客户都断开了连接,则调用disableVSyncLocked函数停止接受DispSyncSource对象的信号。

  1. // Here we figure out if we need to enable or disable vsyncs

  2. if (timestamp && !waitForVSync) {

  3. // we received a VSYNC but we have no clients

  4. // don't report it, and disable VSYNC events

  5. disableVSyncLocked();

  6. } else if (!timestamp && waitForVSync) {

  7. // we have at least one client, so we want vsync enabled

  8. // (TODO: this function is called right after we finish

  9. // notifying clients of a vsync, so this call will be made

  10. // at the vsync rate, e.g. 60fps. If we can accurately

  11. // track the current state we could avoid making this call

  12. // so often.)

  13. enableVSyncLocked();

  14. }

我们先来看下enableVSyncLocked函数

  1. void EventThread::enableVSyncLocked() {

  2. if (!mUseSoftwareVSync) {

  3. // never enable h/w VSYNC when screen is off

  4. if (!mVsyncEnabled) {

  5. mVsyncEnabled = true;

  6. mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this));

  7. mVSyncSource->setVSyncEnabled(true);

  8. }

  9. }

  10. mDebugVsyncEnabled = true;

  11. sendVsyncHintOnLocked();

  12. }

我们先来看看mVSyncSource->setCallback函数。先要知道这个mVSyncSource是在SurfaceFlinger的init函数中。

  1. sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,

  2. vsyncPhaseOffsetNs, true, "app");

  3. mEventThread = new EventThread(vsyncSrc);

  4. sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,

  5. sfVsyncPhaseOffsetNs, true, "sf");

  6. mSFEventThread = new EventThread(sfVsyncSrc);

  7. mEventQueue.setEventThread(mSFEventThread);

看到上面这段代码,我们知道这个mVsyncSource是DispSyncSource类,我们先来看起setCallback函数,就是把callback保存起来

  1. virtual void setCallback(const sp<VSyncSource::Callback>& callback) {

  2. Mutex::Autolock lock(mCallbackMutex);

  3. mCallback = callback;

  4. }

再来看setVSyncEnabled函数,这里参数enable是true,就是调用了DispSync的addEventListenter。这里就回到了上一小节了,这里我们就在DispSync中注册了回调了

  1. virtual void setVSyncEnabled(bool enable) {

  2. Mutex::Autolock lock(mVsyncMutex);

  3. if (enable) {

  4. status_t err = mDispSync->addEventListener(mPhaseOffset,

  5. static_cast<DispSync::Callback*>(this));

  6. if (err != NO_ERROR) {

  7. ALOGE("error registering vsync callback: %s (%d)",

  8. strerror(-err), err);

  9. }

  10. //ATRACE_INT(mVsyncOnLabel.string(), 1);

  11. } else {

  12. status_t err = mDispSync->removeEventListener(

  13. static_cast<DispSync::Callback*>(this));

  14. if (err != NO_ERROR) {

  15. ALOGE("error unregistering vsync callback: %s (%d)",

  16. strerror(-err), err);

  17. }

  18. //ATRACE_INT(mVsyncOnLabel.string(), 0);

  19. }

  20. mEnabled = enable;

  21. }

这样回想上一节在fireCallbackInvocations中遍历所有的回调时,就调用了DispSyncSource类的onDispSyncEvent函数,而这个函数主要是调用了其成员变量mCallback的onVSyncEvent,这个mCallback就是之前在EventThread中的waitForEvent注册的,就是EventThread自己。

  1. virtual void onDispSyncEvent(nsecs_t when) {

  2. sp<VSyncSource::Callback> callback;

  3. {

  4. Mutex::Autolock lock(mCallbackMutex);

  5. callback = mCallback;

  6. if (mTraceVsync) {

  7. mValue = (mValue + 1) % 2;

  8. ATRACE_INT(mVsyncEventLabel.string(), mValue);

  9. }

  10. }

  11. if (callback != NULL) {

  12. callback->onVSyncEvent(when);

  13. }

  14. }

因此最后到了EventThread的onVsyncEvent函数,这个函数把数据放在mVSyncEvent数组第一个,然后调用了Condition的broadcast函数。

  1. void EventThread::onVSyncEvent(nsecs_t timestamp) {

  2. Mutex::Autolock _l(mLock);

  3. mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;

  4. mVSyncEvent[0].header.id = 0;

  5. mVSyncEvent[0].header.timestamp = timestamp;

  6. mVSyncEvent[0].vsync.count++;

  7. mCondition.broadcast();

  8. }

最后之前在EventThread的threadLoop函数中调用waitForEvent会阻塞,当这里调用Condition的broadcast之后,waitForEvent就唤醒,并且得到了mVsynEvent中的数据。紧接着就是在EventThread中的threadLoop调用conn->postEvent来发送Event。这里是通过BitTube对象中的socket发送到MessageQueue中。这个我们在第二节中分析过了。

4.3 MessageQueue分发VSync信号

我们来回顾下,在MessageQueue中有下面这个函数。这样当EventThread通过BitTube传送数据的话,pollOnce会唤醒epoll_wait然后就到这个cb_eventReceiver这个回调函数

  1. void MessageQueue::setEventThread(const sp<EventThread>& eventThread)

  2. {

  3. mEventThread = eventThread;

  4. mEvents = eventThread->createEventConnection();

  5. mEventTube = mEvents->getDataChannel();

  6. mLooper->addFd(mEventTube->getFd(), 0, Looper::EVENT_INPUT,

  7. MessageQueue::cb_eventReceiver, this);

  8. }

cb_eventReceiver就是调用了eventReceiver函数。

  1. int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {

  2. MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);

  3. return queue->eventReceiver(fd, events);

  4. }

  5. int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {

  6. ssize_t n;

  7. DisplayEventReceiver::Event buffer[8];

  8. while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {

  9. for (int i=0 ; i<n ; i++) {

  10. if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {

  11. #if INVALIDATE_ON_VSYNC

  12. mHandler->dispatchInvalidate();

  13. #else

  14. mHandler->dispatchRefresh();

  15. #endif

  16. break;

  17. }

  18. }

  19. }

  20. return 1;

  21. }

这里我们支持VSync信号就会调用mHandler的dispatchRefresh函数。

  1. void MessageQueue::Handler::dispatchRefresh() {

  2. if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {

  3. mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));

  4. }

  5. }

而在Hander的处理中,最终是调用了SurfaceFlinger的onMessageReceived函数

  1. case REFRESH:

  2. android_atomic_and(~eventMaskRefresh, &mEventMask);

  3. mQueue.mFlinger->onMessageReceived(message.what);

  4. break;

而在SurfaceFlinger的onMessageReceived函数最终会调用了handleMessageRefresh函数。

  1. void SurfaceFlinger::onMessageReceived(int32_t what) {

  2. ATRACE_CALL();

  3. switch (what) {

  4. ......

  5. case MessageQueue::REFRESH: {

  6. handleMessageRefresh();

  7. break;

  8. }

  9. }

  10. }

handleMessageRefresh函数负责刷新系统的显示。这样我们就分析了从底层发送VSync信号最终到达SurfaceFlinger的handleMessageRefresh函数。

4.4 VSync信号分发总结

我们回顾下整个流程,VSync信号从底层产生后,经过几个函数,保存到了SurfaceFlinger的mPrimaryDispSync变量(DisySync类)的数组中,这样设计的目的让底层的调用尽快结束,否则会耽搁下次VSync信号的发送。然后在mPrimaryDispSync变量关联的线程开始分发数组中的VSync信号,分发的过程也调用了几个回调函数,最终结果是放在EventThread对象的数组中。EventThread是转发VSync信号的中心。不但会把VSync信号发给SurfaceFlinger,还会把信号发送到用户进程中去。EventThread的工作比较重,因此SurfaceFlinger中使用了两个EventThread对象来转发VSync信号。确保能及时转发。SurfaceFlinger中的MessageQueue收到Event后,会将Event转化成消息发送,这样最终就能在主线程调用SurfaceFlinger的函数处理VSync信号了。

--------------------- 作者:kc专栏 来源:CSDN 原文:https://blog.csdn.net/kc58236582/article/details/52763534?utm_source=copy 版权声明:本文为博主原创文章,转载请附上博文链接!

Android6.0显示系统(五) SurfaceFlinger服务相关推荐

  1. Android 9.0 显示系统导航栏(左/右/底部)

    Android 9.0 显示系统导航栏(左/右/底部) 显示系统导航栏 一般有:HOME  BACK  最近应用列表 等组成. 先看下效果图: 显示在底部(最常见的做法): 显示在右边(平板): (请 ...

  2. GUI显示系统之SurfaceFlinger

    第1章  GUI系统之SurfaceFlinger 在进入GUI系统的学习前,建议大家可以先阅读本书应用篇中的"OpenGLES"章节,并参阅OpenGL ES官方指南.因为And ...

  3. GUI显示系统之 SurfaceFlinger

    转载自http://blog.csdn.net/uiop78uiop78/article/details/8954508 介绍了Surface, SurfaceTexture, BufferQueue ...

  4. ]GUI显示系统之SurfaceFlinger

    转载自http://blog.csdn.net/uiop78uiop78/article/details/8954508 介绍了Surface, SurfaceTexture, BufferQueue ...

  5. Android6.0以上系统搜索不到 蓝牙BLE 设备问题

    最近开发一款软件,一开始一切顺利,但是在连接外围BLE 设备时,发现需要Location的权限, <uses-permission android:name="android.perm ...

  6. 红米4A Android 版本,红米4A评测:4A搭载深度定制基于Android6.0.1系统MIUI 8 - 红米4A评测:双11手机单品销量第一 怎么样好不好用?...

    标签: 系统方面,红米4A搭载了小米今年刚推出的MIUI 8,这是基于Android 6.0.1深度定制的ROM.内置的默认主题风格很有小米的味道,非常简洁. 手机主界面 默认锁屏的界面下,底部左侧右 ...

  7. Android6.0以下系统判断相机权限

    参考博文 http://blog.csdn.net/jm_beizi/article/details/51728495 关于Android权限检测问题 在6.0系统以后由于使用的是动态权限 很好判断 ...

  8. Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析

    出自:http://blog.csdn.net/luoshengyang/article/details/8079456 在前面的一系列文章中,我们学习了Android应用程序与SurfaceFlin ...

  9. Android系统Surface机制的SurfaceFlinger服务的启动过程分析

    在前面一篇文章中,我们简要介绍了Android系统Surface机制中的SurfaceFlinger服务.SurfaceFlinger服务是在System进程中启动的,并且负责统一管理设备的帧缓冲区. ...

最新文章

  1. Java中常见的锁简述
  2. 345 所开设人工智能本科专业高校名单大全
  3. 拯救“没常识”的GPT-3得靠它了,交大ACM班校友提出“Voken” 无监督学习 | EMNLP 2020...
  4. Win10上rabbitmq 安装
  5. C#中JSON和对象之间互相转换功能示例
  6. 从源代码角度看Struts2返回JSON数据的原理
  7. 采用install.sh安装脚本进行快速安装astercc
  8. tcp服务端无故死掉了linux,TCP服务端socket会丢连接的诡异问题及思考
  9. python修改html,Python爬虫精简步骤 HTML基础
  10. 前端性能优化分析(雅虎军规)
  11. 《QTreeView中嵌入QPushButton实现命令操作》:系列教程之八(第8小节)
  12. excel vba 字典使用方法学习
  13. R语言使用pROC包绘制ROC曲线并在ROC曲线上显示特异度和敏感度的置信区间(通过阴影区域以及线条显示)
  14. zabbix 监控81端口
  15. 学计算机要高智商吗,这7大高智商专业,很容易挂科,如果不是学霸级人物,最好不要报考...
  16. 2019最全大数据学习资源整理(值得收藏)
  17. linux 下oracle11g卸载干净,linux系统Oracle11g R2完整卸载教程
  18. React16、17、18版本新特性
  19. CAD快捷键记不全怎么办?快来自定义CAD快捷键吧!
  20. 求数组中的最大值和次大值

热门文章

  1. 自定义高效支持点击监听的RecyclerView
  2. JDBC-简单连接Oracle Database
  3. Sql Server 2005如何导入DBF文件?
  4. sql 去除数据表中一列中字符串后边的空格...
  5. 虚拟环境下配置拨号接入的×××
  6. 论大学毕业后是否适合创业
  7. IronPython 小试牛角
  8. 谷歌开源 VR 应用
  9. 未能正确加载“ProviderPackage”包。
  10. pytorch图片数据归一化,通常传入transforms.Normalize(mean,std,inplace=False)中的mean和std是如何获取的?