Choreographer應(yīng)用最廣泛的是其postCallback()方法可以提供在vsync信號來到時進(jìn)行回調(diào),本篇的就是為了說明其原理脉课。
- Choreographer的初始化
private final Looper mLooper;
private final FrameHandler mHandler;
private final FrameDisplayEventReceiver mDisplayEventReceiver;
private Choreographer(Looper looper, int vsyncSource){
mLooper = looper;
mHandler = new FrameHandler(looper);
nDisplayEventReceiver = USE_VSYNC? new FrameDisplayEventReceiver(looper, vsyncSource):null;
mLastFrameTimeNanos = Long.MIN_VALUE;
mFrameIntervalNanos = (long)(1000000000/getRefreshRate());
mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
for(int i=0;i<=CALLBACK_LAST;i++){
mCallbackQueuesi[i] = new CallbackQueue();
}
setFPSDivisor(SystemProperties.getInt(ThreadRender.DEBUG_FPS_DIVISOR,1));
}
其他的都沒有什么內(nèi)容倘零,這里的關(guān)鍵是這個FrameDisplayEventReceiver;我們目前在這里分析的是ViewRootImpl中的Choreographer呈驶,所以認(rèn)為這里的looper為MainLooper(不影響整體分析疫鹊,在Choreographer中可以看到有兩個ThreadLocal提供線程單例)。
- FrameDisplayEventReceiver繼承自DisplayEventReceiver聋迎,重寫了onVsync與run
//DisplayEventReceiver.java
public DisplayEventReceiver(Looper looper, int vsyncSource){
mMessageQueue = looper.getQueue();
mReceiverPtr=nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue, vsyncSource);
}
//messageQueue可以認(rèn)為是主線程的MessageQueue枣耀,
//該方法的native實現(xiàn)在../framework/base/core/jni/android_view_DisplayEventReceiver.cpp
private static native long nativeInit(WeakReference<DisplayEventReceiver> receiver, MessageQueue messageQueue, int vsyncSource);
//android_view_DisplayEventReceiver.cpp
static jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj, jobject messageQueueObj){
//Java層的MessageQueue還是依托native層的MessageQueue去實現(xiàn)的
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
//創(chuàng)建一個NativeDisplayEventReceiver對象
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env, receiverObj, messageQueue);
status_t status = receiver->initialize();
receiver->incStrong(gDisplayEventReceiverClassInfo.clazz);
return reinterpret_cast<jnit>(receiver.get());
}
class NativeDisplayEventReceiver : public LooperCallback{
...
private:
...
DisplayEventReceiver mReceiver;
}
//保存成員變量
NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, jobject receiverObj, const sp<MessageQueue>& messageQueue):
mReceiverObjGlobal(env->NewGlobalRef(receiverObj)), mMessageQueue(mMessageQueue), mWaitingForVsync(false){}
status_t NativeDisplayEventReceiver::initialize(){
status_t result = mReceiver.initCheck();
int rc = mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, ALOOPER_EVENT_INPUT, this, NULL);
}
在這里佩微,mReceiver是DisplayEventReceiver對象
- DisplayEventReceiver.cpp
DisplayEventReceiver::DisplayEventReceiver(){
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if(sf != NULL){
mEventConnection = sf->createDisplayEventConnection();
if(mEventConnection != NULL){
mDataChannel = mEventConnection->getDataChannel();
}
}
}
//定義在DisplayEventReciver.h
sp<IDisplayEventConnection> mEventConnection;
sp<BitTube> mDataChannel;
從另外一篇SurfaceFlinger可以找到這里的mDataChannel為一個BitTube對象缝彬,內(nèi)部為管道。并且在其創(chuàng)建的時候會注冊在EventThread中扒俯,在接受到vsync信號后,會在EventThread中進(jìn)行寫入注冊的BitTube的管道中撼玄。
int DisplayEventReceiver::getFd() const {
return mDataChannel->getFd();
}
- 結(jié)論
聯(lián)系Handler的阻塞分析掌猛,在底層收到vsync信號后,EventThread會往注冊的BitTube中寫入數(shù)據(jù)荔茬,而這里Choreographer在底層正是將這個BitTube注冊到MessageQueue的Looper竹海,于是收到一個vsync后慕蔚,對應(yīng)的MessageQueue就會被喚醒斋配,從而進(jìn)行下一步孔飒。
如何利用BitTube的
//EventThread.cpp
void EventThread::Connection::onFirstRef(){
mEventThread->registerDisplayConnection(this);
}
status_t EventThread::registerDisplayEventConnection(const sp<EventThread::Connection>& connection){
mDisplayEventConnections.add(connection);
}
bool EventThread::threadLoop(){
...
status_t err = conn->postEvent(event);
...
}
status_t EventThread::Connection::postEvent(const DisplayEventReceiver::Event& event){
ssize_t size = DisplayEventReceiver::sendEvent(mChannel, &event, 1);
}
//DisplayEventReceiver.cpp
ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel, Event const* events, size_t count){
return BitTube::sendObject(dataChannel,events,count);
}
//BitTube.cpp
ssize_t BitTube::sendObjects(const sp<BitTube>& tube, void const* events, size_t count, size_t objSize){
...
const char* vaddr = reinterpret_cast<const char*>(events) + objSize*i;
ssize_t size = tube->write(vaddr, objsize);
...
}
ssize_t BitTube::write(void const* vaddr, size_t size){
...
len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
...
}
同時在Looper中的添加的fd為mReceiveFd,與mSendFd相對應(yīng)艰争,此時Looper就會被喚醒了。
因此每次收到vsync信號甩卓,對應(yīng)的Looper中的MessageQueue都會在阻塞中被喚醒(如果被阻塞的話)。
//Choreographer
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){
postCallbackDelayInternal(callbackType, action, token, delayMillis);
}
private void postCallbackDelayInternal(int callbackType, Object action, Object token, long delayMillis){
synchronized(mLock){
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
mCallbackQueues[callbackType].addCallbackLocked(dueTime,action,token);
if(dueTime <= now){
scheduleFrameLocked(now);
}else{
Message msg=mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1=callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg,dueTime);
}
}
}
//todo