一,VSync機制的作用及VSync在SurfaceFlinger服務中的位置:
VSync信号通常都來自硬體控制器,在Android中也可以采用軟體模拟;
VSync的作用,如下圖(以雙緩沖為例,為了提高流暢性有時也采用triple三緩沖):LCD控制器在讀取每一幀資料的開始都會産生一個VSync信号(垂直同步信号或幀同步信号);
LCD的頻率是60Hz,顯示每一幀的間隔是16ms,是以每一個VSync信号的時間間隔是16ms,上圖中的A和B都是幀緩沖區framebuffer,每一個framebuffer由CPU和GPU共同完成;
在硬體晶片中,晶振産生的時鐘脈沖驅動整個硬體電路連續運作;在Surfaceflinger中,VSync信号就好像晶振電路産生的時鐘信号一樣驅動Surfaceflinger中所有子產品和諧的運作,如下圖;
二,VSync流程及重要代碼:
1,整體流程概覽,如下圖:
重點介紹如下過程:
2,App繪制請求發送流程(過程1(App)):
App程序調用invalidate或postinvalidate方法發送繪制請求;
invalidate方法最終會調用的BpDisplayEventConnection的requestNextVsync方法,在該方法中通過Binder IPC通路服務端的requestNextSync方法;
BpDisplayEventConnection方法的執行個體化過程如下:
1>,在ViewRootImpl的構造函數中會執行個體化Choreographer對象,
public ViewRootImpl(Context context, Display display) {
. . . . .
mChoreographer = Choreographer.getInstance();
}
2>,在mChoreographer 的構造函數中執行個體化FrameDisplayEventReceiver對象:
private Choreographer(Looper looper) {
. . . . . .
mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
}
3>,在FrameDisplayEventReceiver的父類構造函數中會調用到,android_view_DisplayEventReceiver.cpp中的nativeInit方法,
4>,在nativeInit方法中有如下過程:
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject messageQueueObj) {
. . . . . .
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
receiverWeak, messageQueue);
status_t status = receiver->initialize();
. . . . . .
1),建立NativeDisplayEventReceiver類類型指針,
在NativeDisplayEventReceiver的構造函數中會調用DisplayEventReceiver類的無參構造函數執行個體化成員mReceiver;
DisplayEventReceiver::DisplayEventReceiver() {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != NULL) {
mEventConnection = sf->createDisplayEventConnection();
if (mEventConnection != NULL) {
mDataChannel = mEventConnection->getDataChannel();
}
}
}
在這段代碼中擷取Surfaceflinger服務的代理對象,然後通過Binder IPC建立BpDisplayEventConnection對象,然後mEventConnection->getDataChannel()方法再次通過Binder IPC建立 BitTube對象mDataChannel ,在Binder IPC建立mDataChannel 過程中會從服務端EventThread::Connection::Connection中(在EventThread類中定義)接收一個socketpair建立的FIFO檔案描述符;
EventThread::Connection::Connection建立描述符的代碼:
Connection構造函數調用BitTube的無參構造函數,在BitTube的構造函數中調用init函數;
void BitTube::init(size_t rcvbuf, size_t sndbuf) {
int sockets[];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, , sockets) == ) {
size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
setsockopt(sockets[], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
setsockopt(sockets[], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
// sine we don't use the "return channel", we keep it small...
setsockopt(sockets[], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
setsockopt(sockets[], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
fcntl(sockets[], F_SETFL, O_NONBLOCK);
fcntl(sockets[], F_SETFL, O_NONBLOCK);
mReceiveFd = sockets[];
mSendFd = sockets[];
} else {
mReceiveFd = -errno;
ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
}
}
2)調用到NativeDisplayEventReceiver類的父類DisplayEventDispatcher中的initialize()方法,
将BpDisplayEventConnection對象擷取到的mDataChannel (BitTube類型)中的檔案描述符添加到UI主線程Looper的epoll中,
當檔案描述符中被寫入資料時,該epoll_wait會被喚醒;
3,Vsync信号驅動App程序繪制流程(過程4(App)):
4,Surfaceflinger圖冊合成請求發送流程(過程1(sf)):
5,Vsync信号驅動Surfaceflinger合成流程(過程4(sf)):