該系列文章總綱連結:Android GUI系統之SurfaceFlinger 系列文章目錄
本章關鍵點總結 & 說明:

本章節思維導圖如上。主要講述了SurfaceFlinger 處理Vsync機制的流程。主要分析handleMessageTransaction 處理方法。
繼續上一節(Android GUI系統之SurfaceFlinger(06)服務端分析1-處理VSYNC)的分析,這裡的INVALIDATE對應mQueue.mFlinger->onMessageReceived(message.what)方法的執行,onMessageReceived代碼實作如下:
void SurfaceFlinger::onMessageReceived(int32_t what) {
switch (what) {
case MessageQueue::TRANSACTION: {
handleMessageTransaction();
break;
}
case MessageQueue::INVALIDATE: {
//關鍵語句
bool refreshNeeded = handleMessageTransaction();//1
refreshNeeded |= handleMessageInvalidate();//2
refreshNeeded |= mRepaintEverything;
if (refreshNeeded) {
signalRefresh();//3
}
break;
}
case MessageQueue::REFRESH: {
handleMessageRefresh();
break;
}
}
}
針對INVALIDATE消息,關鍵執行代碼中辨別的幾句話。我們對其分别技能型詳細的分析
handleMessageTransaction
handleMessageTransaction的代碼實作如下:
bool SurfaceFlinger::handleMessageTransaction() {
uint32_t transactionFlags = peekTransactionFlags(eTransactionMask);
if (transactionFlags) {
handleTransaction(transactionFlags);
return true;
}
return false;
}
繼續分析這裡的handleTransaction,代碼如下:
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
State drawingState(mDrawingState);
Mutex::Autolock _l(mStateLock);
const nsecs_t now = systemTime();
mDebugInTransaction = now;
//産生一個新的transactionFlags變量
transactionFlags = getTransactionFlags(eTransactionMask);
handleTransactionLocked(transactionFlags);
mLastTransactionTime = systemTime() - now;
mDebugInTransaction = 0;
invalidateHwcGeometry();
}
繼續分析handleTransactionLocked,這也是本部分分析的重點,因為handleTransactionLocked的代碼比較長,這類分成5個部分進行解讀。
1 處理Layer的事務
抽取第一部分代碼,實作如下:
void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
const size_t count = currentLayers.size();
if (transactionFlags & eTraversalNeeded) {
for (size_t i=0 ; i<count ; i++) {
const sp<Layer>& layer(currentLayers[i]);
uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
if (!trFlags) continue;
const uint32_t flags = layer->doTransaction(0);
if (flags & Layer::eVisibleRegion)
mVisibleRegionsDirty = true;
}
}
//...
}
這裡周遊每一個Layer,根據eTraversalNeeded标志來決定是否要檢查Layer對象。如果Layer中有eTransactionNeeded标志,則傳回非0值,然後調用它的doTransaction函數。Layer的doTransaction函數傳回的flags如果有eVisibleRegion,則說明該Layer需要更新,mVisibleRegionsDirty設定為true。這裡繼續分析Layer的doTransaction函數,代碼如下:
uint32_t Layer::doTransaction(uint32_t flags) {
const Layer::State& s(getDrawingState());//上次繪制使用的State對象
const Layer::State& c(getCurrentState());//目前繪制使用的State對象
const bool sizeChanged = (c.requested.w != s.requested.w) ||
(c.requested.h != s.requested.h);
//如果兩個對象的大小不相等,說明Layer的尺寸發生變化
if (sizeChanged) {
mSurfaceFlingerConsumer->setDefaultBufferSize(
c.requested.w, c.requested.h);
}
if (!isFixedSize()) {
const bool resizePending = (c.requested.w != c.active.w) ||
(c.requested.h != c.active.h);
//如果兩者不一樣,flags加上不更新Geometry标志
if (resizePending) {
flags |= eDontUpdateGeometryState;
}
}
if (flags & eDontUpdateGeometryState) {
} else {
//如果沒有eDontUpdateGeometryState标志,更新active的值為request
Layer::State& editCurrentState(getCurrentState());
editCurrentState.active = c.requested;
}
if (s.active != c.active) {
// 如果目前state的active和以前的State的active不等,設定更新标志
flags |= Layer::eVisibleRegion;
}
if (c.sequence != s.sequence) {
//如果目前state的sequence和以前state的sequence不等,設定更新标志
flags |= eVisibleRegion;
this->contentDirty = true;
// we may use linear filtering, if the matrix scales us
const uint8_t type = c.transform.getType();
mNeedsFiltering = (!c.transform.preserveRects() ||
(type >= Transform::SCALE));
}
//将mCurrentState的值賦給mDrawingState
commitTransaction();
return flags;
}
這裡留意:Layer類中的兩個類型為Layer::State的成員變量mDrawingState、mCurrentState,Layer::State類型代碼如下:
struct State {
Geometry active; //實際大小
Geometry requested; //使用者大小
uint32_t z; //Z軸值
uint32_t layerStack;//和顯示裝置的關聯值
uint8_t alpha;
uint8_t flags;
uint8_t reserved[2];
int32_t sequence; //序列值,Layer的屬性變化一次,這個值就加1
Transform transform;
Region activeTransparentRegion;//實際的透明區域
Region requestedTransparentRegion;//使用者層的透明區域
};
Layer對象在繪制圖形時,使用的是mDrawingState變量,使用者調用接口設定Layer對象屬性是,設定的值儲存在mCurrentState對象中,這樣就不會因為使用者的操作而幹擾Layer對象的繪制了。是以這裡有兩個對象。
接下來對State 結構體中的一些變量進行說明:
- Geometry字段:State的結構中有兩個Geometry字段,active和requested。他們表示layer的尺寸,其中requested儲存是使用者設定的尺寸,而active儲存的值通過計算後的實際尺寸。
- layerStack字段:它是使用者指定的一個值,使用者可以給DisplayDevice也指定一個layerStack值,隻有Layer對象和DisplayDevice對象的layerStack相等,這個Layer才能在這個顯示裝置上輸出,這樣的好處是可以讓顯示裝置隻顯示某個Surface的内容。例如,可以讓HDMI顯示裝置隻顯示手機上播放視訊的Surface視窗,但不顯示Activity視窗。
- sequence字段:它是一個序列值,每當使用者調用了Layer的接口,例如setAlpha、setSize或者setLayer等改變Layer對象屬性的哈數,這個值都會加1。是以在doTransaction函數中能通過比較sequence值來判斷Layer的屬性值有沒有變化。
可以看到Layer::State中的layerStack中會對比DisplayDeviceState對象的layerStack,是以分析下DisplayDeviceState,代碼如下:
struct DisplayDeviceState {
DisplayDeviceState();
DisplayDeviceState(DisplayDevice::DisplayType type);
bool isValid() const { return type >= 0; }
bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; }
bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
DisplayDevice::DisplayType type;
sp<IGraphicBufferProducer> surface;
uint32_t layerStack;//關鍵點
Rect viewport;
Rect frame;
uint8_t orientation;
uint32_t width, height;
String8 displayName;
bool isSecure;
};
可以說這裡的layerStack和Layer的State中的layerStack如果相等,則Layer可以在該State對應的DisplayDevice中顯示。
2 處理顯示裝置的變化
抽取第二部分代碼,實作如下:
//...
if (transactionFlags & eDisplayTransactionNeeded) {
//得到目前顯示裝置清單和之前使用的顯示裝置清單
const KeyedVector< wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays);
const KeyedVector< wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
if (!curr.isIdenticalTo(draw)) {
mVisibleRegionsDirty = true;
const size_t cc = curr.size();//現在顯示裝置的數量
size_t dc = draw.size();//以前顯示裝置的數量
for (size_t i=0 ; i<dc ; i++) {
const ssize_t j = curr.indexOfKey(draw.keyAt(i));
if (j < 0) {//裝置被删除
// in drawing state but not in current state
if (!draw[i].isMainDisplay()) {
const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
if (hw != NULL)
hw->disconnect(getHwComposer());
if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
mEventThread->onHotplugReceived(draw[i].type, false);
//如果不是主裝置移除它
mDisplays.removeItem(draw.keyAt(i));
} else {
ALOGW("trying to remove the main display");
}
} else {裝置還在,再檢查有沒有其他變化
// this display is in both lists. see if something changed.
const DisplayDeviceState& state(curr[j]);
const wp<IBinder>& display(curr.keyAt(j));
if (state.surface->asBinder() != draw[i].surface->asBinder()) {
sp<DisplayDevice> hw(getDisplayDevice(display));
if (hw != NULL)
hw->disconnect(getHwComposer());
mDisplays.removeItem(display);
mDrawingState.displays.removeItemsAt(i);
dc--; i--;
// at this point we must loop to the next item
continue;
}
const sp<DisplayDevice> disp(getDisplayDevice(display));
if (disp != NULL) {
//兩個對象layerStack不等,使用目前對象的
if (state.layerStack != draw[i].layerStack) {
disp->setLayerStack(state.layerStack);
}
if ((state.orientation != draw[i].orientation)
|| (state.viewport != draw[i].viewport)
|| (state.frame != draw[i].frame))
{
disp->setProjection(state.orientation,
state.viewport, state.frame);
}
if (state.width != draw[i].width || state.height != draw[i].height) {
disp->setDisplaySize(state.width, state.height);
}
}
}
}
//處理顯示裝置增加的情況。。。
}
}
//...
這段代碼主要是處理顯示裝置的變化:
- 移除不需要的顯示裝置,将其對應的DisplayDevice移除
- 對于發生變化的顯示裝置(設定Surface、重置layerStack、旋轉。。。),就需要重置顯示對象的屬性
- 對于新增加的顯示裝置,建立DisplayDevice并加入到系統
3 設定TransfromHit
抽取第三部分代碼,實作如下:
//...
if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
sp<const DisplayDevice> disp;
uint32_t currentlayerStack = 0;
for (size_t i=0; i<count; i++) {
const sp<Layer>& layer(currentLayers[i]);
uint32_t layerStack = layer->getDrawingState().layerStack;
if (i==0 || currentlayerStack != layerStack) {
currentlayerStack = layerStack;
disp.clear();
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
if (hw->getLayerStack() == currentlayerStack) {
if (disp == NULL) {
disp = hw;
} else {
disp = NULL;
break;
}
}
}
}
if (disp == NULL) {
disp = getDefaultDisplayDevice();
}
//設定Layer對象的TransformHint
layer->updateTransformHint(disp);
}
}
//...
這段代碼根據每種顯示裝置的不同,設定和顯示裝置關聯在一起的Layer(主要看Layer的layerStack是否和DisplayDevice的layerStack一緻)的TransformHint(主要指裝置的顯示方向orientation)
4 處理Layer增減情況
抽取第四部分代碼,實作如下:
//...
const LayerVector& layers(mDrawingState.layersSortedByZ);
if (currentLayers.size() > layers.size()) {
//如果有Layer加入,設定需要更新
mVisibleRegionsDirty = true;
}
if (mLayersRemoved) {//有Layer删除
mLayersRemoved = false;
mVisibleRegionsDirty = true;
const size_t count = layers.size();
for (size_t i=0 ; i<count ; i++) {
const sp<Layer>& layer(layers[i]);
//如果這個Layer不存在,則把它的所在區域設定為需要更新的區域
if (currentLayers.indexOf(layer) < 0) {
const Layer::State& s(layer->getDrawingState());
Region visibleReg = s.transform.transform(
Region(Rect(s.active.w, s.active.h)));
invalidateLayerStack(s.layerStack, visibleReg);
}
}
}
//...
這段代碼處理Layer的增減情況:
- 如果有Layer增加,需要重新計算裝置的更新區域,mVisibleRegionsDirty設定為true
- 如果有Layer被删除,需要把Layer的可見區域加入到系統需要更新的區域中
5 設定mDrawingState
抽取第五部分代碼,實作如下:
//...
commitTransaction();
updateCursorAsync();
}
分别對commitTransaction和updateCursorAsync進行簡單的分析。
5.1 commitTransaction
代碼實作如下:
void SurfaceFlinger::commitTransaction()
{
if (!mLayersPendingRemoval.isEmpty()) {
// Notify removed layers now that they can't be drawn from
for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
mLayersPendingRemoval[i]->onRemoved();
}
mLayersPendingRemoval.clear();
}
mAnimCompositionPending = mAnimTransactionPending;
mDrawingState = mCurrentState;//關鍵點
mTransactionPending = false;
mAnimTransactionPending = false;
mTransactionCV.broadcast();
}
commitTransaction函數最關鍵的作用是把mDrawingState的值設定成mCurrentState的值。
5.2 updateCursorAsync
代碼實作如下:
void SurfaceFlinger::updateCursorAsync()
{
HWComposer& hwc(getHwComposer());
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id < 0) {
continue;
}
const Vector< sp<Layer> >& currentLayers(
hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id);
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
if (cur->getCompositionType() != HWC_CURSOR_OVERLAY) {
continue;
}
const sp<Layer>& layer(currentLayers[i]);
Rect cursorPos = layer->getPosition(hw);
hwc.setCursorPositionAsync(id, cursorPos);
break;
}
}
}
updateCursorAsync函數會更新所有顯示裝置中光标的位置。
6 總結
該部分代碼主要是處理事物:
- 周遊每一個Layer,根據條件執行對應的doTransaction,根據傳回值設定mVisibleRegionsDirty
- 處理顯示裝置的變化:增加/删除/變化
- 對Layer的TransfromHit(旋轉角度)進行設定
- 處理SurfaceFlinger本身的事物:Layer的增減情況
總結下,雖然處理了很多事物,但主要是設定一些flag,但并未對相關的Buffer進行實際的操作。handleTransaction函數的作用的就是處理系統在兩次重新整理期間的各種變化。SurfaceFlinger子產品 中不管是SurfaceFlinger類還是Layer類,都采用了雙緩沖的方式來儲存他們的屬性,這樣的好處是剛改變SurfaceFlinger對象或者Layer類對象的屬性時不需要上鎖,這很大程度上提高了系統效率。隻有在最後的圖像輸出才會進行一次上鎖,并将記憶體的屬性變化進行處理。正是以,應用程序必須收到VSync信号才開始改變Surface中Buffer的内容。