參考原文鏈接:[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)

在我們之前的代碼中,對于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);
}
~~~
終于回到我們的主線了。。。

我們劃線這部分也算是打通了。剩下得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)
- 前言
- Android系統的體系結構
- Dalvik VM 和 JVM 的比較
- Android 打包應用程序并安裝的過程
- Android ADB工具
- Android應用開發
- Android UI相關知識總結
- Android 中window 、view、 Activity的關系
- Android應用界面
- Android中的drawable和bitmap
- AndroidUI組件adapterView及其子類和Adapter的關系
- Android四大組件
- Android 數據存儲
- SharedPreference
- Android應用的資源
- 數組資源
- 使用Drawable資源
- Material Design
- Android 進程和線程
- 進程
- 線程
- Android Application類的介紹
- 意圖(Intent)
- Intent 和 Intent 過濾器(Google官網介紹)
- Android中關于任務棧的總結
- 任務和返回棧(官網譯文)
- 總結
- Android應用安全現狀與解決方案
- Android 安全開發
- HTTPS
- 安卓 代碼混淆與打包
- 動態注入技術(hook技術)
- 一、什么是hook技術
- 二、常用的Hook 工具
- Xposed源碼剖析——概述
- Xposed源碼剖析——app_process作用詳解
- Xposed源碼剖析——Xposed初始化
- Xposed源碼剖析——hook具體實現
- 無需Root也能Hook?——Depoxsed框架演示
- 三、HookAndroid應用
- 四、Hook原生應用程序
- 五、Hook 檢測/修復
- Android 應用的逆向與加固保護技術
- OpenCV在Android中的開發
- Android高級開發進階
- 高級UI
- UI繪制流程及原理
- Android新布局ConstraintLayout約束布局
- 關鍵幀動畫
- 幀動畫共享元素變換
- Android異步消息處理機制完全解析,帶你從源碼的角度徹底理解
- Android中為什么主線程不會因為Looper.loop()里的死循環卡死?
- 為什么 Android 要采用 Binder 作為 IPC 機制?
- JVM 中一個線程的 Java 棧和寄存器中分別放的是什么?
- Android源碼的Binder權限是如何控制?
- 如何詳解 Activity 的生命周期?
- 為什么Android的Handler采用管道而不使用Binder?
- ThreadLocal,你真的懂了嗎?
- Android屏幕刷新機制