• Android SurfaceFlinger导读(02)MessageQueue


    该系列文章总纲链接:Android GUI系统之SurfaceFlinger 系列文章目录

    说明:

    • 关于导读:导读部分主要是方便初学者理解SurfaceFlinger代码中的机制,为后面分析代码打下一个更好的基础,这样就可以把更多的精力放在surfaceFlinger的业务逻辑分析上。
    • 关于代码分支:以下代码分析均在android5.1.1_r3分支上 目录frameworks/native/services/surfaceflinger为root目录

    1 MessageQueue解读

    在surfaceflinger中,基于最原始的Message handler机制,构建了自己的MessageQueue队列,代码具体实现如下:

    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. }
    16. void MessageQueue::Handler::handleMessage(const Message& message) {
    17. switch (message.what) {
    18. case INVALIDATE:
    19. android_atomic_and(~eventMaskInvalidate, &mEventMask);
    20. mQueue.mFlinger->onMessageReceived(message.what);
    21. break;
    22. case REFRESH:
    23. android_atomic_and(~eventMaskRefresh, &mEventMask);
    24. mQueue.mFlinger->onMessageReceived(message.what);
    25. break;
    26. case TRANSACTION:
    27. android_atomic_and(~eventMaskTransaction, &mEventMask);
    28. mQueue.mFlinger->onMessageReceived(message.what);
    29. break;
    30. }
    31. }
    32. // ---------------------------------------------------------------------------
    33. MessageQueue::MessageQueue(){}
    34. MessageQueue::~MessageQueue() {}
    35. void MessageQueue::init(const sp& flinger)
    36. {
    37. mFlinger = flinger;
    38. mLooper = new Looper(true);
    39. mHandler = new Handler(*this);
    40. }
    41. void MessageQueue::setEventThread(const sp& eventThread)
    42. {
    43. mEventThread = eventThread;
    44. mEvents = eventThread->createEventConnection();
    45. mEventTube = mEvents->getDataChannel();
    46. mLooper->addFd(mEventTube->getFd(), 0, Looper::EVENT_INPUT,
    47. MessageQueue::cb_eventReceiver, this);
    48. }
    49. void MessageQueue::waitMessage() {
    50. do {
    51. IPCThreadState::self()->flushCommands();
    52. int32_t ret = mLooper->pollOnce(-1);
    53. switch (ret) {
    54. case Looper::POLL_WAKE:
    55. case Looper::POLL_CALLBACK:
    56. continue;
    57. case Looper::POLL_ERROR:
    58. ALOGE("Looper::POLL_ERROR");
    59. case Looper::POLL_TIMEOUT:
    60. // timeout (should not happen)
    61. continue;
    62. default:
    63. // should not happen
    64. ALOGE("Looper::pollOnce() returned unknown status %d", ret);
    65. continue;
    66. }
    67. } while (true);
    68. }
    69. status_t MessageQueue::postMessage(
    70. const sp& messageHandler, nsecs_t relTime)
    71. {
    72. const Message dummyMessage;
    73. if (relTime > 0) {
    74. mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage);
    75. } else {
    76. mLooper->sendMessage(messageHandler, dummyMessage);
    77. }
    78. return NO_ERROR;
    79. }
    80. #define INVALIDATE_ON_VSYNC 1
    81. void MessageQueue::invalidateTransactionNow() {
    82. mHandler->dispatchTransaction();
    83. }
    84. void MessageQueue::invalidate() {
    85. #if INVALIDATE_ON_VSYNC
    86. mEvents->requestNextVsync();
    87. #else
    88. mHandler->dispatchInvalidate();
    89. #endif
    90. }
    91. void MessageQueue::refresh() {
    92. #if INVALIDATE_ON_VSYNC
    93. mHandler->dispatchRefresh();
    94. #else
    95. mEvents->requestNextVsync();
    96. #endif
    97. }
    98. int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
    99. MessageQueue* queue = reinterpret_cast(data);
    100. return queue->eventReceiver(fd, events);
    101. }
    102. int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
    103. ssize_t n;
    104. DisplayEventReceiver::Event buffer[8];
    105. while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
    106. for (int i=0 ; i
    107. if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
    108. #if INVALIDATE_ON_VSYNC
    109. mHandler->dispatchInvalidate();
    110. #else
    111. mHandler->dispatchRefresh();
    112. #endif
    113. break;
    114. }
    115. }
    116. }
    117. return 1;
    118. }

    2 MessageQueue在SurfaceFlinger中的使用

    2.1 分析mEventQueue.init

    2.1.1 mEventQueue.init执行的上下文解读

    在SurfaceFlinger第一次被创建时会调用mEventQueue的init方法,如下所示:

    1. void SurfaceFlinger::onFirstRef()
    2. {
    3.     mEventQueue.init(this);
    4. }

    2.1.2 mEventQueue.init内部实现

    在这个init函数中,主要做了一些初始化工作,包括handler、looper和mFlinger成员变量的初始化,如下所示:

    1. void MessageQueue::init(const sp& flinger)
    2. {
    3.     mFlinger = flinger;
    4.     mLooper = new Looper(true);
    5.     mHandler = new Handler(*this);
    6. }

    2.2 分析mEventQueue.setEventThread

    2.2.1 mEventQueue.setEventThread执行的上下文解读

    该部分代码主要在SurfaceFlinger::init()中使用,启动EventThread的过程中,如下所示:

    1. // start the EventThread
    2.     sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync,vsyncPhaseOffsetNs, true, "app");
    3.     mEventThread = new EventThread(vsyncSrc);
    4.     sp sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,sfVsyncPhaseOffsetNs, true, "sf");
    5.     mSFEventThread = new EventThread(sfVsyncSrc);
    6.     mEventQueue.setEventThread(mSFEventThread);

    在这段代码中,创建了两个不同的 EventThread 对象,并使用 DispSyncSource 类作为事件源来处理事件。代码详细解读如下:

    1. vsyncSrc 对象的创建:通过 new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true, "app") 创建了一个 DispSyncSource 对象,作为应用程序相关事件的事件源。vsyncPhaseOffsetNs 是传递的垂直同步相位偏移值,用于控制应用程序事件的触发时机相对于显示刷新。参数中的 "app" 表示该事件源与应用程序相关。
    2. mEventThread 对象的创建:通过 new EventThread(vsyncSrc) 创建了一个 EventThread 对象,并将上述的 vsyncSrc 对象作为参数传递给它。这个 EventThread 对象用于处理应用程序相关的事件。
    3. sfVsyncSrc 对象的创建:通过 new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, true, "sf") 创建了另一个 DispSyncSource 对象,作为 SurfaceFlinger 相关事件的事件源。sfVsyncPhaseOffsetNs 是传递的垂直同步相位偏移值,用于控制 SurfaceFlinger 事件的触发时机相对于显示刷新。参数中的 "sf" 表示该事件源与 SurfaceFlinger 相关。
    4. mSFEventThread 对象的创建:通过 new EventThread(sfVsyncSrc) 创建了另一个 EventThread 对象,并将上述的 sfVsyncSrc 对象作为参数传递给它。这个 EventThread 对象用于处理 SurfaceFlinger 相关的事件。
    5. mEventQueue 的设置:通过 mEventQueue.setEventThread(mSFEventThread) 将 mSFEventThread 对象设置为 mEventQueue 的事件线程。这意味着 SurfaceFlinger 相关的事件将由 mSFEventThread 处理。

    通过这段代码,为应用程序事件和 SurfaceFlinger 事件创建了独立的 EventThread 对象,并使用不同的 DispSyncSource 对象来控制它们的触发时机。这样可以实现事件的隔离和优先级控制,提高系统的稳定性和响应性。

    2.2.2 mEventQueue.setEventThread内部实现

    代码如下所示:

    1. void MessageQueue::setEventThread(const sp& 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. }

    这里MessageQueue::setEventThread 方法的主要作用是将事件线程(EventThread)与消息队列相关联,并设置事件接收器。这段代码详细解读如下:

    1. 设置事件线程:通过将传入的 eventThread 对象赋值给成员变量 mEventThread,将事件线程与消息队列相关联。事件线程负责接收和处理消息队列中的事件。
    2. 创建事件连接:调用事件线程的 createEventConnection 方法,创建一个事件连接(EventConnection)。事件连接用于将消息队列中的事件传递给事件线程进行处理。
    3. 获取数据通道:通过事件连接的 getDataChannel 方法,获取与事件线程通信的数据通道(EventTube)。数据通道用于传输消息队列中的事件数据。
    4. 注册事件接收器:使用事件循环(Looper)的 addFd 方法,将数据通道的文件描述符(mEventTube->getFd())注册到事件循环中。这样,当事件数据可读时,事件循环会调用 MessageQueue::cb_eventReceiver 方法处理事件。

    总结起来,MessageQueue::setEventThread 方法的目的是将事件线程与消息队列关联起来,并设置事件接收器,以便将消息队列中的事件传递给事件线程进行处理。这样可以实现消息队列的异步事件处理机制,提高系统的性能和响应性。

    2.3 分析mEventQueue.waitMessage

    2.3.1 mEventQueue.waitMessage执行的上下文解读

    在SurfaceFlinger执行run方法时,会调用到waitForEvent()方法,进而调用到mEventQueue的waitMessage方法。相关代码整理如下:

    1. void SurfaceFlinger::run() {
    2.     do {
    3.         waitForEvent();
    4.     } while (true);
    5. }
    6. void SurfaceFlinger::waitForEvent() {
    7.     mEventQueue.waitMessage();
    8. }

    2.3.2 MessageQueue::waitMessage内部实现

    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. }

    该部分代码主要是用于等待和处理消息。代码详细解读如下:

    1. 进入循环:代码进入一个无限循环,通过 do-while 结构实现。
    2. IPCThreadState::self()->flushCommands():在每次循环开始时,调用 IPCThreadState::self()->flushCommands() 来刷新命令队列。这是为了确保在等待消息期间处理任何挂起的 IPC 命令。
    3. mLooper->pollOnce(-1):调用 mLooper->pollOnce(-1) 来等待消息的到达。-1 表示无限等待,直到有消息到达才会返回。
    4. switch 语句:根据 pollOnce 的返回值进行不同的处理。
      1. Looper::POLL_WAKE 或 Looper::POLL_CALLBACK:如果返回值是 POLL_WAKE 或 POLL_CALLBACK,表示有消息到达或有回调触发,代码会继续下一次循环,继续等待和处理消息。
      2. Looper::POLL_ERROR:如果返回值是 POLL_ERROR,打印错误日志信息。
      3. Looper::POLL_TIMEOUT:如果返回值是 POLL_TIMEOUT,表示发生了超时,这里注释写着 "should not happen",意味着理论上不应该发生超时。
      4. 其他情况:如果返回值是其他未知状态,打印错误日志信息。
    5. 继续循环:在 switch 语句的 continue 语句下,继续下一次循环,等待和处理下一条消息。

    这段代码的作用是不断等待和处理消息,确保SurfaceFlinger能够及时响应和处理来自系统和应用程序的消息。它使用Looper的pollOnce函数来等待消息的到达,并根据不同的返回状态进行相应的处理。

    2.4 分析mEventQueue.invalidate和mEventQueue.refresh

    2.4.1 mEventQueue.invalidate和mEventQueue.refresh

    使用上下文相关代码如下所示:

    1. void SurfaceFlinger::signalTransaction() {
    2.     mEventQueue.invalidate();
    3. }
    4. void SurfaceFlinger::signalLayerUpdate() {
    5.     mEventQueue.invalidate();
    6. }
    7. void SurfaceFlinger::signalRefresh() {
    8.     mEventQueue.refresh();
    9. }

    3个方法的简要说明如下:

    • signalTransaction()方法的目的是发出事务信号。当有新的事务要应用于SurfaceFlinger时,例如添加、删除或修改图层属性,调用此方法会使事件队列无效。通过使事件队列无效,可以触发对应的事件处理,确保新的事务能够及时地被处理(invalidate是废弃、使无效的意思。Android中需要重绘某个视图时就可以调用该函数,表示view的某个显示区域内容变脏了,该显示区域需要被重新绘制)。
    • signalLayerUpdate()方法的目的是发出图层更新信号。当某个图层的内容发生更改时,例如图层的绘制内容更新,调用此方法会使事件队列无效。这将通知 SurfaceFlinger 有图层内容需要更新,从而触发相应的渲染和显示操作。
    • signalRefresh() 方法的目的是发出刷新信号。调用此方法会直接触发事件队列的刷新操作,而不是简单地使其无效。这通常用于强制立即刷新事件队列,并处理所有待处理的事件。这对于某些需要及时响应的情况非常有用,例如在某些显示刷新时机敏感的应用场景中。

    总结来说,这3个方法都与事件队列的处理和刷新相关。signalTransaction和 signalLayerUpdate在发生特定事件时使事件队列无效,以触发相应的事件处理。而 signalRefresh则直接触发对事件队列的立即刷新。这些方法的调用可以保证事件的及时处理和刷新,以确保 SurfaceFlinger 的正常运行和图层的正确显示。

    2.4.2 mEventQueue的invalidate和refresh的实现

    @1 mEventQueue.invalidate的实现

    invalidate是废弃、使无效的意思。Android中需要重绘某个视图时就可以调用该函数,表示view的某个显示区域内容变脏了,该显示区域需要被重新绘制。代码实现如下:

    1. #define INVALIDATE_ON_VSYNC 1
    2. void MessageQueue::invalidate() {
    3. #if INVALIDATE_ON_VSYNC
    4.     mEvents->requestNextVsync();
    5. #else
    6.     mHandler->dispatchInvalidate();
    7. #endif
    8. }

    这里的mEvents->requestNextVsync中mEvents是EventThread::Connection类型的,因此这里直接调用EventThread::Connection里的requestNextVsync方法,如下所示:

    1. void EventThread::Connection::requestNextVsync() {
    2.     mEventThread->requestNextVsync(this);
    3. }
    4. void EventThread::requestNextVsync(
    5.         const sp& connection) {
    6.     Mutex::Autolock _l(mLock);
    7.     if (connection->count < 0) {
    8.         connection->count = 0;
    9.         mCondition.broadcast();
    10.     }
    11. }

    这里的mCondition.broadcast()如果被执行,则会导致mCondition.wait或mCondition.waitRelative被执行,会直接导致EventThread::waitForEvent()方法不再阻塞。

    两者在 EventThread 类的上下文中用于实现事件的同步和处理。它们之间的关系如下:

    • EventThread::requestNextVsync() 方法通过请求下一次垂直同步事件,通知系统在下一次垂直同步时发送事件。
    • EventThread::waitForEvent() 方法在事件队列中等待事件的到来,并保持线程阻塞状态。当 EventThread 类接收到新的事件连接对象时,会唤醒等待的线程,使其从阻塞状态返回。

    通过这种方式,EventThread 类可以与系统的垂直同步信号和事件队列进行同步,以及在事件到来时及时处理和分发事件。

    @2 mEventQueue.refresh的实现

    相关代码实现和调用关系如下所示:

    1. #define INVALIDATE_ON_VSYNC 1
    2. void MessageQueue::refresh() {
    3. #if INVALIDATE_ON_VSYNC
    4.     mHandler->dispatchRefresh();
    5. #else
    6.     mEvents->requestNextVsync();
    7. #endif
    8. }
    9. //dispatchRefresh实现如下:
    10. void MessageQueue::Handler::dispatchRefresh() {
    11.     if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
    12.         mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
    13.     }
    14. }
    15. //消息处理如下:
    16. void MessageQueue::Handler::handleMessage(const Message& message) {
    17.     switch (message.what) {
    18.         case REFRESH:
    19.             android_atomic_and(~eventMaskRefresh, &mEventMask);
    20.             mQueue.mFlinger->onMessageReceived(message.what);
    21.             break;
    22.     //...
    23.     }
    24. }
    25. //onMessageReceived实现如下:
    26. void SurfaceFlinger::onMessageReceived(int32_t what) {
    27.     ATRACE_CALL();
    28.     switch (what) {
    29.         //...
    30.         case MessageQueue::REFRESH: {
    31.             handleMessageRefresh();
    32.             break;
    33.         }
    34.     }
    35. //handleMessageRefresh实现如下:
    36. void SurfaceFlinger::handleMessageRefresh() {
    37.     ATRACE_CALL();
    38.     preComposition();
    39.     rebuildLayerStacks();
    40.     setUpHWComposer();
    41.     doDebugFlashRegions();
    42.     doComposition();
    43.     postComposition();
    44. }

    2.5 分析mEventQueue.invalidateTransactionNow

    2.5.1 mEventQueue.invalidateTransactionNow上下文

    该部分代码主要是在SurfaceFlinger::captureScreen中进行调用的,使用上下文相关代码如下所示:

    1. status_t SurfaceFlinger::captureScreen(const sp& display,
    2. const sp& producer,
    3. Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
    4. uint32_t minLayerZ, uint32_t maxLayerZ,
    5. bool useIdentityTransform, ISurfaceComposer::Rotation rotation) {
    6. //...
    7. class MessageCaptureScreen : public MessageBase {
    8. SurfaceFlinger* flinger;
    9. sp display;
    10. sp producer;
    11. Rect sourceCrop;
    12. uint32_t reqWidth, reqHeight;
    13. uint32_t minLayerZ,maxLayerZ;
    14. bool useIdentityTransform;
    15. Transform::orientation_flags rotation;
    16. status_t result;
    17. public:
    18. MessageCaptureScreen(SurfaceFlinger* flinger,
    19. const sp& display,
    20. const sp& producer,
    21. Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
    22. uint32_t minLayerZ, uint32_t maxLayerZ,
    23. bool useIdentityTransform, Transform::orientation_flags rotation)
    24. : flinger(flinger), display(display), producer(producer),
    25. sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight),
    26. minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
    27. useIdentityTransform(useIdentityTransform),
    28. rotation(rotation),
    29. result(PERMISSION_DENIED)
    30. {
    31. }
    32. status_t getResult() const {
    33. return result;
    34. }
    35. virtual bool handler() {
    36. Mutex::Autolock _l(flinger->mStateLock);
    37. sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
    38. result = flinger->captureScreenImplLocked(hw, producer,
    39. sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
    40. useIdentityTransform, rotation);
    41. static_cast(producer->asBinder().get())->exit(result);
    42. return true;
    43. }
    44. };
    45. mEventQueue.invalidateTransactionNow();
    46. sp wrapper = new GraphicProducerWrapper(producer);
    47. sp msg = new MessageCaptureScreen(this,
    48. display, IGraphicBufferProducer::asInterface( wrapper ),
    49. sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
    50. useIdentityTransform, rotationFlags);
    51. status_t res = postMessageAsync(msg);
    52. if (res == NO_ERROR) {
    53. res = wrapper->waitForResponse();
    54. }
    55. return res;
    56. }

    2.5.2 mEventQueue.invalidateTransactionNow内部实现

    相关代码和调用流程流程实现如下:

    1. void MessageQueue::invalidateTransactionNow() {
    2.     mHandler->dispatchTransaction();
    3. }
    4. //handler的dispatchTransaction实现如下:
    5. void MessageQueue::Handler::dispatchTransaction() {
    6.     if ((android_atomic_or(eventMaskTransaction, &mEventMask) & eventMaskTransaction) == 0) {
    7.         mQueue.mLooper->sendMessage(this, Message(MessageQueue::TRANSACTION));
    8.     }
    9. }
    10. //消息处理如下:
    11. void MessageQueue::Handler::handleMessage(const Message& message) {
    12.     switch (message.what) {
    13.         //...
    14.         case TRANSACTION:
    15.             android_atomic_and(~eventMaskTransaction, &mEventMask);
    16.             mQueue.mFlinger->onMessageReceived(message.what);
    17.             break;
    18.     }
    19. }
    20. //onMessageReceived实现如下:
    21. void SurfaceFlinger::onMessageReceived(int32_t what) {
    22.     ATRACE_CALL();
    23.     switch (what) {
    24.         case MessageQueue::TRANSACTION: {
    25.             handleMessageTransaction();
    26.             break;
    27.         }
    28.         //...
    29.     }
    30. }
    31. //handleMessageTransaction实现如下:
    32. bool SurfaceFlinger::handleMessageTransaction() {
    33.     uint32_t transactionFlags = peekTransactionFlags(eTransactionMask);
    34.     if (transactionFlags) {
    35.         handleTransaction(transactionFlags);
    36.         return true;
    37.     }
    38.     return false;
    39. }

    至于mEventQueue.postMessage,在上一章节MessageBase中已经进行相关的解读,这里不再赘述。

  • 相关阅读:
    【无标题】
    .NET Worker Service 作为 Windows 服务运行及优雅退出改进
    使用python统计jira bug数据
    MYSQL的下载与配置 mysql远程操控
    悟了!阿里p9专家强推的《java虚拟机并发编程》后悔没早看到!
    计算机视觉基础
    【牛牛前端面试每天练】一,HTML与CSS专项
    2020银川B - The Great Wall dp 1383A - String Transformation 1 并查集
    如何拥有自己的私有docker仓库
    2024 年天津专升本招生实施办法(天津专升本文化报名考试时间)
  • 原文地址:https://blog.csdn.net/vviccc/article/details/132892603