<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                參考原文鏈接:[Android屏幕刷新機制](https://juejin.im/post/6874483682699132935#comment) 參考文章: [渲染應用程序UI的過程分析](http://www.hmoore.net/alex_wsc/androids/473761) [20講UI優化(上):UI渲染的幾個關鍵概念](http://www.hmoore.net/alex_wsc/android_master/1572085) [21講UI優化(下):如何優化UI渲染](http://www.hmoore.net/alex_wsc/android_master/1572086) [Android操作系統架構開篇之圖形系統系列](http://gityuan.com/android/#45-%E5%9B%BE%E5%BD%A2%E7%B3%BB%E7%BB%9F%E7%B3%BB%E5%88%97) ## Android屏幕刷新機制 之前我們講過布局優化中提到Android系統每16ms發出一個VSYNC信號,然后執行一次UI的渲染工作。如果渲染成功,那么界面基本就是流暢的。 我們看看Android系統是如何做屏幕刷新機制,如果做到16ms執行一次繪制工作,又如何保證我們每次點擊或者觸摸屏幕的時候,快速的處理對應的事件。 VSync來源自底層硬件驅動程序的上報,對于Android能看到的接口來說,它是來自HAL層的hwc\_composer\_device的抽象硬件設備 ### 基礎知識 #### View繪制 這部分在之前的文章有過專門的說明[Android的View繪制機制](https://mp.weixin.qq.com/s/ic__vhXRdVlzDt3cXP3JPw) ![](https://img.kancloud.cn/29/a7/29a7ad2651069b07899dd6f72de40fbf_2019x1703.png) 在我們之前的代碼中,對于15-17這部分并沒有進行任何的詳解,那么底層是如何產生Vsync的信號,然后又是如何通知到我們的應用進行屏幕刷新呢?這不分就是我們這篇文章的關注點。 ### 入口 ``` mChoreographer = Choreographer.getInstance(); //Choreographer.java frameworks\base\core\java\android\view public static Choreographer getInstance() { return sThreadInstance.get(); } private static final ThreadLocal<Choreographer> sThreadInstance = new ThreadLocal<Choreographer>() { @Override protected Choreographer initialValue() { //獲取對應的looper Looper looper = Looper.myLooper(); if (looper == null) { throw new IllegalStateException("The current thread must have a looper!"); } //注意這里使用的VSYNC_SOURCE_APP Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP); if (looper == Looper.getMainLooper()) { mMainInstance = choreographer; } return choreographer; } }; private Choreographer(Looper looper, int vsyncSource) { //FrameDisplayEventReceiver創建的信號是VSYNC_SOURCE_APP,APP層請求的VSYNC mDisplayEventReceiver = USE_VSYNC? new FrameDisplayEventReceiver(looper, vsyncSource): null; ... } ``` 這里初始化的**FrameDisplayEventReceiver**類繼承自**DisplayEventReceiver**類 ~~~java public DisplayEventReceiver(Looper looper, int vsyncSource) { if (looper == null) { throw new IllegalArgumentException("looper must not be null"); } mMessageQueue = looper.getQueue(); //調用底層初始化,并將本身以及對應的mMessageQueue傳入進去 //對應frameworks\base\core\jni\android_view_DisplayEventReceiver.cpp mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,vsyncSource); mCloseGuard.open("dispose"); } ~~~ 這里會調用Native層的方法,并將當前的**DisplayEventReceiver**以及隊列**mMessageQueue**和**vsyncSource(VSYNC\_SOURCE\_APP)**傳遞給底層 ### nativeInit ~~~c //frameworks\base\core\jni\android_view_DisplayEventReceiver.cpp static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject messageQueueObj, jint vsyncSource) { //申請對應的MessageQueue sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); ... //重點方法1 創建NativeDisplayEventReceiver sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env, receiverWeak, messageQueue, vsyncSource); //重點方法2 進行初始化NativeDisplayEventReceiver,并返回對應的初始化結果 status_t status = receiver->initialize(); if (status) {//初始化出現異常 String8 message;led to initialize display event receiver. status message.appendFormat("Fai=%d", status); jniThrowRuntimeException(env, message.string()); return 0; } receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object return reinterpret_cast<jlong>(receiver.get()); } 復制代碼 ~~~ 我們這里先看一下**NativeDisplayEventReceiver**的創建過程。 #### \[NativeDisplayEventReceiver的創建\] ~~~c NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak, const sp<MessageQueue>& messageQueue, jint vsyncSource) : //繼承了DisplayEventDispatcher,并傳入了對應的messagequeue,將vsyncSource轉化為了底層使用的變量 DisplayEventDispatcher(messageQueue->getLooper(), static_cast<ISurfaceComposer::VsyncSource>(vsyncSource)), mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)), mMessageQueue(messageQueue) { ALOGV("receiver %p ~ Initializing display event receiver.", this); } //DisplayEventDispatcher構造函數 DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,ISurfaceComposer::VsyncSource vsyncSource) : //Vsync的來源傳遞給了mReceiver。這里相當于調用了mReceiver(DisplayEventReceiver)的構造函數 mLooper(looper), mReceiver(vsyncSource), mWaitingForVsync(false) { ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this); } 復制代碼 ~~~ 這里會創建**DisplayEventReceiver** ~~~c++ //DisplayEventReceiver構造函數 frameworks\native\libs\gui\DisplayEventReceiver.cpp DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::ConfigChanged configChanged) { //方法1 獲取SurfaceFling服務,并保存在ComposerService中 sp<ISurfaceComposer> sf(ComposerService::getComposerService()); if (sf != nullptr) { //方法2 通過binder,最后跨進程調用surfaceFling的createDisplayEventConnection方法 //方法位置 ISurfaceComposer.cpp frameworks\native\libs\gui 66331 2020/3/22 1379 mEventConnection = sf->createDisplayEventConnection(vsyncSource, configChanged); if (mEventConnection != nullptr) { //方法3 mDataChannel = std::make_unique<gui::BitTube>(); //方法4 mEventConnection->stealReceiveChannel(mDataChannel.get()); } } } 復制代碼 ~~~ DisplayEventReceiver**結構體是一個比較重要的類,其主要作用是建立與**SurfaceFlinger\*\*的連接。我們這里將對其每一個調用的方法都來進行一個自習的分析 * 方法1:獲取SurfaceFlinger服務 sp sf(ComposerService::getComposerService()); ##### ComposerService::getComposerService() ~~~c // frameworks\native\libs\gui\SurfaceComposerClient.cpp /*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() { ComposerService& instance = ComposerService::getInstance(); Mutex::Autolock _l(instance.mLock);//加鎖 if (instance.mComposerService == nullptr) { //獲取SurfaceFling服務,并保存在ComposerService中 ComposerService::getInstance().connectLocked(); assert(instance.mComposerService != nullptr); ALOGD("ComposerService reconnected"); } return instance.mComposerService; } void ComposerService::connectLocked() { const String16 name("SurfaceFlinger"); //通過getService方法獲取SurfaceFlinger服務,并將獲取到的服務保存到mComposerService變量中 while (getService(name, &mComposerService) != NO_ERROR) { usleep(250000); } //創建死亡回調 ... mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this)); IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver); } 復制代碼 ~~~ 通過**getService**方法來獲取對應的**SurfaceFlinger**服務。這里會將獲取到的服務保存到mComposerService變量中. * 創建事件連接 ##### sf->createDisplayEventConnection ~~~c virtual sp<IDisplayEventConnection> createDisplayEventConnection(VsyncSource vsyncSource,ConfigChanged configChanged) { Parcel data, reply; sp<IDisplayEventConnection> result; //binder機制調用SurfaceFling的createDisplayEventConnection方法 //SurfaceFlinger.cpp frameworks\native\services\surfaceflinger int err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeInt32(static_cast<int32_t>(vsyncSource)); data.writeInt32(static_cast<int32_t>(configChanged)); err = remote()->transact( BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION, data, &reply); ... result = interface_cast<IDisplayEventConnection>(reply.readStrongBinder()); return result; } 復制代碼 ~~~ 可以看到,該方法使用的是**Binder機制**,而服務的提供方則是**SurfaceFlinger**。 ~~~c //創建顯示事件連接 sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection( ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::ConfigChanged configChanged) { //makeResyncCallback是一個方法,定義在EventThread.h中。using ResyncCallback = std::function<void()>; //創建一個resyncCallback auto resyncCallback = mScheduler->makeResyncCallback([this] { Mutex::Autolock lock(mStateLock); return getVsyncPeriod(); }); //根據傳入的Vsync類型,返回不同的Handler。如果是應用中注冊的,則返回mAppConnectionHandle const auto& handle = vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle; //調用createDisplayEventConnection,傳入了對應的handle,mScheduler是Scheduler.cpp結構體 return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback), configChanged); } 復制代碼 ~~~ 根據傳入的**vsyncSource**類型來返回具體的Handler。因為我們這里使用過的應用類型,所以這里的handle是**mAppConnectionHandle**。 然后通過mScheduler創建對應的連接。 這里我們需要對handle進行一個**補充說明** 補充說明: 對于Handler的創建是在SurfaceFlinger的初始化方法init()中進行創建的 ~~~c++ void SurfaceFlinger::init() { ... mAppConnectionHandle = mScheduler->createConnection("app", mVsyncModulator.getOffsets().app, mPhaseOffsets->getOffsetThresholdForNextVsync(), resyncCallback, impl::EventThread::InterceptVSyncsCallback()); ... } sp<Scheduler::ConnectionHandle> Scheduler::createConnection( const char* connectionName, nsecs_t phaseOffsetNs, nsecs_t offsetThresholdForNextVsync, ResyncCallback resyncCallback, impl::EventThread::InterceptVSyncsCallback interceptCallback) { //對應的id,累加的 const int64_t id = sNextId++; //創建一個EventThread,名稱為傳入的connectionName std::unique_ptr<EventThread> eventThread = makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs, offsetThresholdForNextVsync, std::move(interceptCallback)); //創建EventThreadConnection auto eventThreadConnection = createConnectionInternal(eventThread.get(), std::move(resyncCallback), ISurfaceComposer::eConfigChangedSuppress); //創建ConnectionHandle,入參是id, //然后將創建的connection并存入到map中。key是id。 mConnections.emplace(id, std::make_unique<Connection>(new ConnectionHandle(id), eventThreadConnection, std::move(eventThread))); return mConnections[id]->handle; } 復制代碼 ~~~ 這里創建的Handler,持有了對應的**EventThread**,而**eventThreadConnection**是通過**EventThread**來進行創建。創建**eventThreadConnection**以后,會將其保存到map中,對應的key則是id信息。 而連接處理器:**ConnectionHandle**則是一個持有id的對象。 我們回到主線。。。。 ##### mScheduler->createDisplayEventConnection ~~~c++ // frameworks\native\services\surfaceflinger\Scheduler\Scheduler.cpp sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection( const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) { RETURN_VALUE_IF_INVALID(nullptr); //傳入了handle.id。能夠表明連接是app還是surfaceFlinger return createConnectionInternal(mConnections[handle->id]->thread.get(), std::move(resyncCallback), configChanged); } sp<EventThreadConnection> Scheduler::createConnectionInternal( EventThread* eventThread, ResyncCallback&& resyncCallback, ISurfaceComposer::ConfigChanged configChanged) { //調用EventThread的方法,創建事件連接器 return eventThread->createEventConnection(std::move(resyncCallback), configChanged); } 復制代碼 ~~~ 我們看看事件連接器**EventThreadConnection**的創建過程 ~~~c++ sp<EventThreadConnection> EventThread::createEventConnection( ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) const { return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback), configChanged); } EventThreadConnection::EventThreadConnection(EventThread* eventThread, ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) : resyncCallback(std::move(resyncCallback)), configChanged(configChanged), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {} 復制代碼 ~~~ **EventThreadConnection**的構造方法中最重要的是創建了**mChannel**,而它是gui::BitTube類型的 ~~~c++ // frameworks\native\libs\gui\BitTube.cpp BitTube::BitTube(size_t bufsize) { init(bufsize, bufsize); } void BitTube::init(size_t rcvbuf, size_t sndbuf) { int sockets[2]; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) { size_t size = DEFAULT_SOCKET_BUFFER_SIZE; //創建對應一對socket:0和1,一個用來讀,一個用來寫。 setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)); // since we don't use the "return channel", we keep it small... setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); fcntl(sockets[0], F_SETFL, O_NONBLOCK); fcntl(sockets[1], F_SETFL, O_NONBLOCK); //將mReceiveFd文件和socket進行綁定。當Vsync到來的時候,會通過mSendFd文件來寫入消息,通過對文件的消息寫入監聽,完成了對Vsync信號的監聽 mReceiveFd.reset(sockets[0]); mSendFd.reset(sockets[1]); } else { mReceiveFd.reset(); } } 復制代碼 ~~~ 在初始化方法中,創建了一對socket,然后將**mReceiveFd**和**mSendFd**進行了綁定。當Vsync到來的時候通過mSendFd寫入消息,然后APP就可以監聽文件的變化。 在創建**EventThreadConnection**對象的時候,會自動調用**onFirstRef**方法。 ~~~c++ void EventThreadConnection::onFirstRef() { mEventThread->registerDisplayEventConnection(this); } status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) { std::lock_guard<std::mutex> lock(mMutex); // this should never happen auto it = std::find(mDisplayEventConnections.cbegin(), mDisplayEventConnections.cend(), connection); if (it != mDisplayEventConnections.cend()) { ALOGW("DisplayEventConnection %p already exists", connection.get()); mCondition.notify_all(); return ALREADY_EXISTS; } //將連接放入到需要通知的列表中。 mDisplayEventConnections.push_back(connection); //有新的連接了,就需要喚醒AppEventThread線程使能Vsync信號了。 mCondition.notify_all(); return NO_ERROR; } 復制代碼 ~~~ 會將我們創建的連接放入到**EventThread**管理的**mDisplayEventConnections**中,然后喚醒**AppEventThread**線程使能Vsync信號 整個步驟二,其實是根據傳入的vsyncSource,指導對應的監聽者是來自APP,然后創建一對socket連接,來進行進程間的通信。 我們繼續回到主線進行跟蹤處理 ~~~c++ DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::ConfigChanged configChanged) { //方法1 獲取SurfaceFling服務,并保存在ComposerService中 sp<ISurfaceComposer> sf(ComposerService::getComposerService()); if (sf != nullptr) { //方法2 通過binder,最后跨進程調用surfaceFling的createDisplayEventConnection方法 //方法位置 ISurfaceComposer.cpp frameworks\native\libs\gui mEventConnection = sf->createDisplayEventConnection(vsyncSource, configChanged); if (mEventConnection != nullptr) { //方法3 獲取方法二中創建的gui::BitTube對象 mDataChannel = std::make_unique<gui::BitTube>(); //方法4 mEventConnection->stealReceiveChannel(mDataChannel.get()); } } } 復制代碼 ~~~ 方法3是獲取了對應的gui::BitTube對象。我們主要來分析一下方法四。 方法四調用了**EventThreadConnect**的**stealReceiveChannel** ~~~c++ status_t EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) { outChannel->setReceiveFd(mChannel.moveReceiveFd()); return NO_ERROR; } 復制代碼 ~~~ 這的mChannel是gui::BitTube。這里將事件連接器**EventThreadConnection**中創建的Fd復制給了outChannel。也就是DisplayEventReceiver的mDataChannel。 所以**這時候app進程就有了mReceivedFd,surfaceFlinger進程有了mSendFd。這時候通過socket就能夠進行通信了**。 > 整個DisplayEventReceiver的作用是創建一個socket以及對應的文件,然后實現和SurfaceFlinger的雙向通訊。 這里我們為止,我們只是創建NativeDisplayEventReceiver。 那么后續還有 #### receiver->initialize() ~~~c++ status_t DisplayEventDispatcher::initialize() { //異常檢測 status_t result = mReceiver.initCheck(); if (result) { ALOGW("Failed to initialize display event receiver, status=%d", result); return result; } //這里的Looper就是應用app進程的主線程Looper,這一步就是將創建的BitTube信道的 //fd添加到Looper的監聽。 int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL); if (rc < 0) { return UNKNOWN_ERROR; } return OK; } 復制代碼 ~~~ 這里之所以能夠加入到監聽,是因為我們的 這里整個方法比較簡單,就是進行異常的檢測,讓后將在步驟一中創建的fd文件加入到Looper的監聽中。 到這里為止,整個流程算是打通了。 **java層通過DisplayEventReceive的nativeInit函數,創建了應用層和SurfaceFlinger的連接,通過一對socket,對應mReceiveFd和mSendFd,應用層通過native層Looper將mReceiveFd加入監聽,等待mSendFd的寫入。** 那么mSendFd什么時候寫入,又是如何傳遞到應用層的呢? 當我們進行頁面刷新繪制的時候,看一下如何注冊對于Vsync的監聽的 ~~~java @UnsupportedAppUsage void scheduleTraversals() { ... mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); ... } public void postCallback(int callbackType, Runnable action, Object token) { postCallbackDelayed(callbackType, action, token, 0); } public void postCallbackDelayed(int callbackType,Runnable action, Object token, long delayMillis) { postCallbackDelayedInternal(callbackType, action, token, delayMillis); } private void postCallbackDelayedInternal(int callbackType,Object action, Object token, long delayMillis) { ... //需要立即進行繪制 scheduleFrameLocked(now); ... } private void scheduleFrameLocked(long now) { ... scheduleVsyncLocked(); ... } private void scheduleVsyncLocked() { //執行同步功能,進行一次繪制。這里會進行一個VSYNC事件的監聽注冊,如果有有 mDisplayEventReceiver.scheduleVsync(); } public void scheduleVsync() { .. nativeScheduleVsync(mReceiverPtr); ... } 復制代碼 ~~~ 這里的**nativeScheduleVsync()**就是應用層向native層注冊監聽下一次Vsync信號的方法。 ### nativeScheduleVsync ~~~c++ //base\core\jni\android_view_DisplayEventReceiver.cpp 8492 2020/9/14 96 static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) { sp<NativeDisplayEventReceiver> receiver = reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr); //調用Recivier的調度方法 status_t status = receiver->scheduleVsync(); } 復制代碼 ~~~ 這里的receiver,是**NativeDisplayEventReceiver**。而**NativeDisplayEventReceiver**是繼承自**DisplayEventDispatcher** #### DisplayEventDispatcher->scheduleVsync(); ~~~c++ //調度Vsync status_t DisplayEventDispatcher::scheduleVsync() { //如果當前正在等待Vsync信號,那么直接返回 if (!mWaitingForVsync) { nsecs_t vsyncTimestamp; PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; //重點方法1 處理對應的準備事件,如果獲取到了Vsync信號的話,這里會返回true if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) { ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this, ns2ms(static_cast<nsecs_t>(vsyncTimestamp))); } //重點方法2 請求下一個Vsync信號 status_t status = mReceiver.requestNextVsync(); ... //設置正在等待Vsync信號 mWaitingForVsync = true; } return OK; } 復制代碼 ~~~ 這里我們跟蹤一下方法1 ##### DisplayEventDispatcher::processPendingEvents ~~~c++ bool DisplayEventDispatcher::processPendingEvents( nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount) { bool gotVsync = false; DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE]; ssize_t n; //獲取對應的事件 while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) { ALOGV("dispatcher %p ~ Read %d events.", this, int(n)); for (ssize_t i = 0; i < n; i++) { const DisplayEventReceiver::Event& ev = buf[i]; switch (ev.header.type) { case DisplayEventReceiver::DISPLAY_EVENT_VSYNC://Vsync類型 //獲取到最新的Vsync信號,然后將時間戳等信息保存下來 gotVsync = true; *outTimestamp = ev.header.timestamp; *outDisplayId = ev.header.displayId; *outCount = ev.vsync.count; break; ... return gotVsync; } 復制代碼 ~~~ 會通過**getEvents**方法獲取到對應的事件類型,然后返回是否為Vsync信號。 ##### DisplayEventReceiver::getEvents ~~~c++ // native\libs\gui\DisplayEventReceiver.cpp ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,size_t count) { //這里的mDataChannel是在init中創建的,用來接收Vsync信號 return DisplayEventReceiver::getEvents(mDataChannel.get(), events, count); } ssize_t DisplayEventReceiver::getEvents(gui::BitTube* dataChannel, Event* events, size_t count) { return gui::BitTube::recvObjects(dataChannel, events, count); } //native\libs\gui\BitTube.cpp static ssize_t recvObjects(BitTube* tube, T* events, size_t count) { return recvObjects(tube, events, count, sizeof(T)); } ssize_t BitTube::recvObjects(BitTube* tube, void* events, size_t count, size_t objSize) { char* vaddr = reinterpret_cast<char*>(events); //通過socket讀取數據 ssize_t size = tube->read(vaddr, count * objSize); return size < 0 ? size : size / static_cast<ssize_t>(objSize); } //讀取數據 ssize_t BitTube::read(void* vaddr, size_t size) { ssize_t err, len; do { //將mReceiveFd接收到的數據,放入到size大小的vaddr緩沖區。并返回實際接收到的數據大小len len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT); err = len < 0 ? errno : 0; } while (err == EINTR); if (err == EAGAIN || err == EWOULDBLOCK) { //如果接收出現異常,返回0 return 0; } return err == 0 ? len : -err; } 復制代碼 ~~~ 這里將接收到的數據放入到對應的緩沖區,并返回數據之后,會校驗返回的具體的數據類型。 ~~~c++ status_t DisplayEventReceiver::requestNextVsync() { //校驗當前連接存在 if (mEventConnection != nullptr) { //通過連接請求下一個Vsync信號。這個mEventConnection。是在DisplayEventReceiver初始化的時候創建的 //具體的是EventThreadConnection(位于EventThread中) mEventConnection->requestNextVsync(); return NO_ERROR; } return NO_INIT; } void EventThreadConnection::requestNextVsync() { ATRACE_NAME("requestNextVsync"); mEventThread->requestNextVsync(this); } void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) { if (connection->resyncCallback) { connection->resyncCallback(); } //線程鎖機制 std::lock_guard<std::mutex> lock(mMutex); //vsyncRequest默認值是None.定義在EventThread.h文件中 if (connection->vsyncRequest == VSyncRequest::None) { //之所以Vsync是一次性的,是因為,當我們當前是None之后,會將這個字段設置為Single。 //后續硬件再有Vsync信號過來的時候,不會再執行這個方法 connection->vsyncRequest = VSyncRequest::Single; mCondition.notify_all(); } } 復制代碼 ~~~ 這里當有Vsync的信號過來的時候,會調用一個**notify\_all()**。這個方法會喚醒所有執行了**wait()**方法的線程。 那么這個到底會喚醒誰呢? 這里就不得不說一下**EventThread**創建過程中了。 ~~~c++ EventThread::EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc, InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName) : mVSyncSource(src), mVSyncSourceUnique(std::move(uniqueSrc)), mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)), mThreadName(threadName) { ... //創建了mThread線程 mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS { std::unique_lock<std::mutex> lock(mMutex); //創建線程的時候調用了threadMain函數 threadMain(lock); }); ... } 復制代碼 ~~~ 在**EventThread**創建時,會創建一個線程,然后調用threadMain方法。 ~~~c++ //在創建EventThread的時候會調用該方法。會不斷的遍歷 void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { DisplayEventConsumers consumers; //只要沒有退出,則一直遍歷循環 while (mState != State::Quit) { std::optional<DisplayEventReceiver::Event> event; ... //是否有Vsync請求 bool vsyncRequested = false; ... //查詢所有的連接,其實這里一個連接就是一個監聽 auto it = mDisplayEventConnections.begin(); while (it != mDisplayEventConnections.end()) { if (const auto connection = it->promote()) { vsyncRequested |= connection->vsyncRequest != VSyncRequest::None; //遍歷,將需要通知的監聽放入到consumers中 if (event && shouldConsumeEvent(*event, connection)) { consumers.push_back(connection); } ++it; } else { it = mDisplayEventConnections.erase(it); } } if (!consumers.empty()) { //進行事件的分發。最終會調用gui::BitTube::sendObjects函數 dispatchEvent(*event, consumers); consumers.clear(); } State nextState; if (mVSyncState && vsyncRequested) { nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync; } else { ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected"); nextState = State::Idle; } if (mState != nextState) { if (mState == State::VSync) { mVSyncSource->setVSyncEnabled(false); } else if (nextState == State::VSync) { mVSyncSource->setVSyncEnabled(true); } mState = nextState; } if (event) { continue; } //空閑狀態,則等待事件請求 if (mState == State::Idle) { mCondition.wait(lock); } else { ... } } } 復制代碼 ~~~ **threadMain**函數會不斷的循環。如果找到了能夠消耗事件的EventThreadConnection,則調用dispatchEvent分發事件。如果當前為空閑狀態,則會讓線程進入到等待,等待喚醒。 也就是我們在前面所說的喚醒。 當有Vsync信號到來的時候,會調用**dispatchEvent**方法進行分發 ~~~c++ void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event, const DisplayEventConsumers& consumers) { //這里的DisplayEventConsumers是vector,內部保存的是EventThreadConnection。 for (const auto& consumer : consumers) { switch (consumer->postEvent(event)) { case NO_ERROR: break; case -EAGAIN: ALOGW("Failed dispatching %s for %s", toString(event).c_str(), toString(*consumer).c_str()); break; default: // Treat EPIPE and other errors as fatal. removeDisplayEventConnectionLocked(consumer); } } } 復制代碼 ~~~ 我們看一下**postEvent**方法 ~~~c++ //EventThread.cpp frameworks\native\services\surfaceflinger\Scheduler status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) { ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1); return size < 0 ? status_t(size) : status_t(NO_ERROR); } //DisplayEventReceiver.cpp frameworks\native\libs\gui ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel, Event const* events, size_t count) { return gui::BitTube::sendObjects(dataChannel, events, count); } ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel, Event const* events, size_t count) { //這里會發送Vsync信號,往BitTube所對應的 return gui::BitTube::sendObjects(dataChannel, events, count); } //BitTube.h frameworks\native\libs\gui\include\private\gui static ssize_t sendObjects(BitTube* tube, T const* events, size_t count) { return sendObjects(tube, events, count, sizeof(T)); } ssize_t BitTube::sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize) { const char* vaddr = reinterpret_cast<const char*>(events); //往vaddr中寫數據。當mSendFd寫入文件以后以后,與之對應的mReceiveFd則能接收到數據。 //然后mReceiveFd則會調用對應的回調函數 ssize_t size = tube->write(vaddr, count * objSize); ... return size < 0 ? size : size / static_cast<ssize_t>(objSize); } 復制代碼 ~~~ 當sendObjects像mSendFd寫入數據以后,mReceiveFd能夠接收到消息。而在nativeInit過程中,會將mReceiveFd添加到handler的epoll進行監聽。所以當寫入數據以后,就會回調對應的handleEvent回調函數。而這個回調在添加mReceiveFd的時候,是一起注冊的 ### 回調流程 ~~~c++ //mReceiveFd能接收到對應寫入的數據,然后調用此方法。 int DisplayEventDispatcher::handleEvent(int, int events, void*) { if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) { ALOGE("Display event receiver pipe was closed or an error occurred. " "events=0x%x", events); return 0; // remove the callback } nsecs_t vsyncTimestamp; PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) { ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", count=%d", this, ns2ms(vsyncTimestamp), vsyncDisplayId, vsyncCount); //這里已經獲取到一個Vsync信息,所以將正在等待Vsync標志位置為false。 mWaitingForVsync = false; //進行分發。這個的具體是現在DisplayEventDispater(android_view_DisplayEventReceiver中定義的)的子類NativeDisplayEventReceiver中 dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount); } return 1; // keep the callback } //android_view_DisplayEventReceiver.cpp frameworks\base\core\jni void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) { //JNI的上下文環境 JNIEnv* env = AndroidRuntime::getJNIEnv(); //這里的mReceiverWeakGlobal ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal)); if (receiverObj.get()) { ALOGV("receiver %p ~ Invoking vsync handler.", this); //通過JNI方法,調用dispatchVsync方法,參數傳入了對應的時間戳、顯示屏和對應的Vsync的個數 //實際上就是DisplayEventReceiver的dispatchVsync方法 env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, displayId, count); ALOGV("receiver %p ~ Returned from vsync handler.", this); } mMessageQueue->raiseAndClearException(env, "dispatchVsync"); } ~~~ 最終會調用我們Java中的**dispatchVsync**方法。 ~~~JAVA //DisplayEventReceiver.java frameworks\base\core\java\android\view private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame) { onVsync(timestampNanos, physicalDisplayId, frame); } ~~~ 終于回到我們的主線了。。。 ![](https://img.kancloud.cn/10/6d/106d9a207b64c7667d7bcb9ee4a456f3_1532x1234.png) 我們劃線這部分也算是打通了。剩下得Java層的回調處理,我們在之前的View繪制講解過,有興趣的可以了解一下。 ### 引用 [dandanlove.com/2018/04/25/…](http://dandanlove.com/2018/04/25/android-source-choreographer/) [blog.csdn.net/stven\_king/…](https://blog.csdn.net/stven_king/article/details/80098798) [blog.csdn.net/litefish/ar…](https://blog.csdn.net/litefish/article/details/53939882) [Android垂直同步信號VSync的產生及傳播結構詳解](https://blog.csdn.net/houliang120/article/details/50908098) [blog.csdn.net/qq\_34211365…](https://blog.csdn.net/qq_34211365/article/details/105123790) [blog.csdn.net/qq\_34211365…](https://blog.csdn.net/qq_34211365/article/details/105155801)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看