一篇文章看明白 Android 圖形系統 Surface 與 SurfaceFlinger 之間的關係
Android - SurfaceFlinger 圖形系統
概述
Android 系統啟動過程
Activity 建立過程
Activity 與 Window 與 View 之間的關係
通過前面的知識我們知道了,Android 系統從按下開機鍵到桌面,從桌面點選 App 圖示到 Activity 顯示的過程。但是 Activity 是怎麼顯示在螢幕上的呢?下面我們就來討論下這一過程。
SurfaceFlinger 啟動過程
SurfaceFlinger 程序是由 init 程序建立的,執行在獨立的 SurfaceFlinger 程序中。init 程序讀取 init.rc 檔案啟動 SurfaceFlinger。
service surfaceflinger /system/bin/surfaceflinger
class core
user system
group graphics drmrpc
onrestart restart zygote
writepid /dev/cpuset/system-background/tasks
SurfaceFlinger 的建立會執行 main() 方法:
main_surfaceflinger.cpp
int main(int, char**) {
ProcessState::self()->setThreadPoolMaxThreadCount(4);
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
//例項化 surfaceflinger
sp<SurfaceFlinger> flinger = new SurfaceFlinger();
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
set_sched_policy(0, SP_FOREGROUND);
//初始化
flinger->init();
//釋出 surface flinger,註冊到 ServiceManager
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
// 執行在當前執行緒
flinger->run();
return 0;
}
SurfaceFlinger 的例項化會執行到:onFirstRef()
void SurfaceFlinger::onFirstRef() {
mEventQueue.init(this);
}
onFirstRef() 中會建立 Handler 並初始化。
MessageQueue.cpp:
void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
mFlinger = flinger;
mLooper = new Looper(true);
mHandler = new Handler(*this);
}
然後會執行到 SurfaceFlinger::init():
void SurfaceFlinger::init() {
Mutex::Autolock _l(mStateLock);
//初始化 EGL,作為預設的顯示
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(mEGLDisplay, NULL, NULL);
// 初始化硬體 composer 物件
mHwc = new HWComposer(this, *static_cast<HWComposer::EventHandler *>(this));
//獲取 RenderEngine 引擎
mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());
//檢索建立的 EGL 上下文
mEGLContext = mRenderEngine->getEGLContext();
//初始化非虛擬顯示屏
for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
//建立已連線的顯示裝置
if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
bool isSecure = true;
createBuiltinDisplayLocked(type);
wp<IBinder> token = mBuiltinDisplays[i];
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
//建立 BufferQueue 的生產者和消費者
BufferQueue::createBufferQueue(&producer, &consumer,
new GraphicBufferAlloc());
sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i, consumer);
int32_t hwcId = allocateHwcDisplayId(type);
//建立顯示裝置
sp<DisplayDevice> hw = new DisplayDevice(this,
type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
fbs, producer,
mRenderEngine->getEGLConfig());
if (i > DisplayDevice::DISPLAY_PRIMARY) {
hw->setPowerMode(HWC_POWER_MODE_NORMAL);
}
mDisplays.add(token, hw);
}
}
getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
//當應用和 sf 的 vsync 偏移量一致時,則只建立一個 EventThread 執行緒
if (vsyncPhaseOffsetNs != sfVsyncPhaseOffsetNs) {
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
mEventThread = new EventThread(vsyncSrc);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc);
mEventQueue.setEventThread(mSFEventThread);
} else {
//建立 DispSyncSource 物件
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "sf-app");
//建立執行緒 EventThread
mEventThread = new EventThread(vsyncSrc);
//設定 EventThread
mEventQueue.setEventThread(mEventThread);
}
//建立 EventControl
mEventControlThread = new EventControlThread(this);
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
//當不存在 HWComposer 時,則設定軟體 vsync
if (mHwc->initCheck() != NO_ERROR) {
mPrimaryDispSync.setPeriod(16666667);
}
//初始化繪圖狀態
mDrawingState = mCurrentState;
//初始化顯示裝置
initializeDisplays();
//啟動開機動畫
startBootAnim();
}
該方法主要功能是:
1. 初始化 EGL
2. 建立 HWComposer
3. 初始化非虛擬顯示屏
4. 啟動 EventThread 執行緒
5. 啟動開機動畫
建立 HWComposer:
HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger, EventHandler& handler):mFlinger(flinger), mFbDev(0), mHwc(0), mNumDisplays(1), mCBContext(new cb_context), mEventHandler(handler), mDebugForceFakeVSync(false) {
...
bool needVSyncThread = true;
int fberr = loadFbHalModule(); //載入 framebuffer 的 HAL 層模組
loadHwcModule(); //載入 HWComposer 模組
//標記已分配的 display ID
for (size_t i=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
mAllocatedDisplayIDs.markBit(i);
}
if (mHwc) {
if (mHwc->registerProcs) {
mCBContext->hwc = this;
mCBContext->procs.invalidate = &hook_invalidate;
//VSYNC 訊號的回撥方法
mCBContext->procs.vsync = &hook_vsync;
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
mCBContext->procs.hotplug = &hook_hotplug;
else
mCBContext->procs.hotplug = NULL;
memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
//註冊回撥函式
mHwc->registerProcs(mHwc, &mCBContext->procs);
}
//進入此處,說明已成功開啟硬體 composer 裝置,則不再需要 vsync 執行緒
needVSyncThread = false;
eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
...
}
...
if (needVSyncThread) {
//不支援硬體的 VSYNC,則會建立執行緒來模擬定時 VSYNC 訊號
mVSyncThread = new VSyncThread(*this);
}
}
HWComposer 代表著硬體顯示裝置,註冊了 VSYNC 訊號的回撥。VSYNC 訊號本身是由顯示驅動產生的,在不支援硬體的 VSYNC,則會建立“VSyncThread”執行緒來模擬定時 VSYNC 訊號。
當硬體產生VSYNC訊號時,則會發送訊息,handler 收到訊息進行處理。當 SurfaceFlinger 程序收到 VSync 訊號後經層層呼叫,最終呼叫到該物件的 handleMessageRefresh() 方法。
SurfaceFlinger.cpp:
void SurfaceFlinger::handleMessageRefresh() {
ATRACE_CALL();
preComposition();//處理顯示裝置與 layers 的改變,更新游標
rebuildLayerStacks();//重建所有可見 Layer 列表,根據Z軸排序
setUpHWComposer();//更新 HWComposer 圖層
doDebugFlashRegions();
doComposition();//生成 OpenGL 紋理影象
postComposition();//將影象傳遞到物理螢幕
}
Surface 建立過程
Surface 建立的過程就是 Activity 顯示的過程,在 ActivityThread.handleResumeActivity() 中呼叫了 Activity.makeVisible(),我們接著看下 Activity 是怎麼顯示出來的。
Activity.makeVisible:
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();//此處 getWindowManager 獲取的是 WindowManagerImpl 物件
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
WindowManagerImpl.java:
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
WindowManagerGlobal.java:
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) {
...
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
//建立 ViewRootImpl
ViewRootImpl root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
//設定 View
root.setView(view, wparams, panelParentView);
...
}
建立 ViewRootImpl:
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
...
final Surface mSurface = new Surface(); //建立 Surface,此時 Surface 建立完什麼都沒有,詳見下面分析
...
public ViewRootImpl(Context context, Display display) {
mContext = context;
//獲取 IWindowSession 的代理類
mWindowSession = WindowManagerGlobal.getWindowSession();
mDisplay = display;
mThread = Thread.currentThread(); //主執行緒
mWindow = new W(this);
mChoreographer = Choreographer.getInstance();
...
}
}
WindowManagerGlobal.java:
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
//獲取 IMS 的代理類
InputMethodManager imm = InputMethodManager.getInstance();
//獲取 WMS 的代理類
IWindowManager windowManager = getWindowManagerService();
//經過 Binder 呼叫,最終呼叫 WMS
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {...},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
...
}
}
return sWindowSession
}
}
WindowManagerService.openSession:
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, IInputContext inputContext) {
//建立 Session 物件
Session session = new Session(this, callback, client, inputContext);
return session;
}
再次經過 Binder 將資料寫回 app 程序,則獲取的便是 Session 的代理物件 IWindowSession。
建立完 ViewRootImpl 物件後,接下來呼叫該物件的 setView() 方法。
ViewRootImpl:
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
requestLayout(); //詳見下面分析
...
//通過 Binder呼叫,進入 system 程序的 Session
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
...
}
}
final class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel) {
//呼叫 WMS.addWindow
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outStableInsets, outOutsets, outInputChannel);
}
}
WindowManagerService.java:
public int addWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel) {
...
WindowToken token = mTokenMap.get(attrs.token);
//建立 WindowState
WindowState win = new WindowState(this, session, client, token,
attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
...
//調整 WindowManager 的 LayoutParams 引數
mPolicy.adjustWindowParamsLw(win.mAttrs);
res = mPolicy.prepareAddWindowLw(win, attrs);
addWindowToListInOrderLocked(win, true);
// 設定 input
mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
//詳見下面分析
win.attach();
mWindowMap.put(client.asBinder(), win);
if (win.canReceiveKeys()) {
//當該視窗能接收按鍵事件,則更新聚焦視窗
focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
false /*updateInputWindows*/);
}
assignLayersLocked(displayContent.getWindowList());
...
}
//WindowState.java
void attach() {
mSession.windowAddedLocked();
}
建立 SurfaceSession 物件,並將當前 Session 新增到 WMS.mSessions 成員變數。
Session.java:
void windowAddedLocked() {
if (mSurfaceSession == null) {
mSurfaceSession = new SurfaceSession();
mService.mSessions.add(this);
if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
mService.dispatchNewAnimatorScaleLocked(this);
}
}
mNumWindow++;
}
SurfaceSession 的建立會呼叫 JNI,在 JNI 呼叫 nativeCreate()。
android_view_SurfaceSession.cpp:
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
SurfaceComposerClient* client = new SurfaceComposerClient();
client->incStrong((void*)nativeCreate);
return reinterpret_cast<jlong>(client);
}
建立 SurfaceComposerClient 物件, 作為跟 SurfaceFlinger 通訊的代理物件。
SurfaceComposerClient::SurfaceComposerClient() {
//getComposerService() 將返回 SF 的 Binder 代理端的 BpSurfaceFlinger 物件
sp<ISurfaceComposer> sm(getComposerService());
//先呼叫 SF 的 createConnection(),再呼叫_init
_init(sm, sm->createConnection());
if(mClient != 0) {
Mutex::Autolock _l(gLock);
//gActiveConnections 是全域性變數,把剛才建立的 client 儲存到這個 map 中去
gActiveConnections.add(mClient->asBinder(), this);
}
}
SurfaceFlinger.cpp:
sp<ISurfaceFlingerClient>SurfaceFlinger::createConnection() {
Mutex::Autolock _l(mStateLock);
uint32_t token = mTokens.acquire();
//先建立一個Client
sp<Client> client = new Client(token, this);
//把這個Client物件儲存到mClientsMap中,token是它的標識。
status_t err = mClientsMap.add(token, client);
/*
建立一個用於 Binder 通訊的 BClient,BClient 派生於 ISurfaceFlingerClient,
它的作用是接受客戶端的請求,然後把處理提交給 SF,注意,並不是提交給 Client。
Client 會建立一塊共享記憶體,該記憶體由 getControlBlockMemory 函式返回。
*/
sp<BClient> bclient = new BClient(this, token,client->getControlBlockMemory());
return bclient;
}
Client::Client(ClientID clientID, constsp<SurfaceFlinger>& flinger):ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger) {
const int pgsize = getpagesize();
//下面這個操作會使 cblksize 為頁的大小,目前是4096位元組
constint cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
mCblkHeap = new MemoryHeapBase(cblksize, 0, "SurfaceFlinger Clientcontrol-block");
ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
if(ctrlblk) {
new(ctrlblk) SharedClient;//原來 Surface 的 CB 物件就是在共享記憶體中建立的這個 SharedClient 物件
}
}
SharedClient:
class SharedClient {
public:
SharedClient();
~SharedClient();
status_t validate(size_t token) const;
uint32_t getIdentity(size_t token) const;
private:
Mutexlock;
Condition cv; //支援跨程序的同步物件
//NUM_LAYERS_MAX 為 31,SharedBufferStack 是什麼?
SharedBufferStack surfaces[ NUM_LAYERS_MAX ];
};
//SharedClient的建構函式,沒什麼新意,不如Audio的CB物件複雜
SharedClient::SharedClient():lock(Mutex::SHARED), cv(Condition::SHARED) {
}
一個 Client 最多支援 31 個顯示層。每一個顯示層的生產/消費步調都由會對應的 SharedBufferStack 來控制。而它內部就用了幾個成員變數來控制讀寫位置。
SharedBufferStack.h:
class SharedBufferStack{
......
//Buffer 是按塊使用的,每個 Buffer 都有自己的編號,其實就是陣列中的索引號。
volatile int32_t head; //FrontBuffer 的編號
volatile int32_t available; //空閒 Buffer 的個數
volatile int32_t queued; //髒 Buffer 的個數,髒 Buffer 表示有新資料的 Buffer
volatile int32_t inUse; //SF 當前正在使用的 Buffer 的編號
volatilestatus_t status; //狀態碼
......
}
SF 的一個 Client 分配一個跨程序共享的 SharedClient 物件。這個物件有31個 SharedBufferStack 元素,每一個 SharedBufferStack 對應於一個顯示層。
一個顯示層將建立兩個 Buffer,後續的 PageFlipping 就是基於這兩個 Buffer 展開的。
接著看 SurfaceComposerClient 中這個_init函式:
void SurfaceComposerClient::_init(
const sp<ISurfaceComposer>& sm, constsp<ISurfaceFlingerClient>& conn) {
mPrebuiltLayerState = 0;
mTransactionOpen = 0;
mStatus = NO_ERROR;
mControl = 0;
mClient = conn;// mClient 就是 BClient 的客戶端
mControlMemory =mClient->getControlBlock();
mSignalServer = sm;// mSignalServer 就是 BpSurfaceFlinger
//mControl 就是那個創建於共享記憶體之中的 SharedClient
mControl = static_cast<SharedClient*>(mControlMemory->getBase());
}
建立完 ViewRootImpl 物件後,接下來呼叫該物件的 setView() 方法。在 setView() 中呼叫了 requestLayout() 方法我們來看下這個方法:
public void requestLayout() {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
public void scheduleTraversals() {
if(!mTraversalScheduled) {
mTraversalScheduled = true;
sendEmptyMessage(DO_TRAVERSAL); //傳送 DO_TRAVERSAL 訊息
}
}
public void handleMessage(Message msg) {
switch (msg.what) {
......
case DO_TRAVERSAL:
......
performTraversals();//呼叫 performTraversals()
......
break;
......
}
}
private void performTraversals() {
finalView host = mView;//還記得這mView嗎?它就是 DecorView
booleaninitialized = false;
booleancontentInsetsChanged = false;
booleanvisibleInsetsChanged;
try {
relayoutResult= // 1. 關鍵函式relayoutWindow
relayoutWindow(params, viewVisibility,insetsPending);
}
......
draw(fullRedrawNeeded);// 2. 開始繪製
......
}
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility, boolean insetsPending)throws RemoteException {
//原來是呼叫 IWindowSession 的 relayout(),暫且記住這個呼叫
int relayoutResult = sWindowSession.relayout(mWindow, params, (int) (mView.mMeasuredWidth * appScale + 0.5f), (int) (mView.mMeasuredHeight * appScale + 0.5f), viewVisibility, insetsPending, mWinFrame, mPendingContentInsets, mPendingVisibleInsets, mPendingConfiguration, mSurface); //mSurface 做為引數傳進去了。
}
......
}
private void draw(boolean fullRedrawNeeded) {
Surface surface = mSurface;//mSurface 是 ViewRoot 的成員變數
......
Canvascanvas;
try {
int left = dirty.left;
int top = dirty.top;
int right = dirty.right;
int bottom = dirty.bottom;
//從 mSurface 中 lock 一塊 Canvas
canvas = surface.lockCanvas(dirty);
......
mView.draw(canvas);//呼叫 DecorView 的 draw 函式,canvas 就是畫布
......
//unlock 畫布,螢幕上馬上就能看到 View 的樣子了
surface.unlockCanvasAndPost(canvas);
}
......
}
在 ViewRoot 構造時,會建立一個 Surface,它使用無參建構函式,程式碼如下所示:
final Surface mSurface = new Surface();
1
此時建立完的 Surface 是空的,什麼都沒有。接著繼續分析 relayoutWindow(),在 relayoutWindow() 中會呼叫 IWindowSession 的 relayout(),這是一個跨程序方法會呼叫到 WMS 中的 Session.relayout(),最後呼叫到 WindowManagerService.relayoutWindow()。
public int relayoutWindow(Session session,IWindow client,
WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, boolean insetsPending,
Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
Configuration outConfig, SurfaceoutSurface){
.....
try {
//win 就是 WinState,這裡將建立一個本地的 Surface 物件
Surfacesurface = win.createSurfaceLocked();
if(surface != null) {
//先建立一個本地 surface,然後在 outSurface 的物件上呼叫 copyFrom
//將本地 Surface 的資訊拷貝到 outSurface 中,為什麼要這麼麻煩呢?
outSurface.copyFrom(surface);
......
}
WindowManagerService.java::WindowState:
Surface createSurfaceLocked() {
......
try {
//mSurfaceSession 就是在 Session 上建立的 SurfaceSession 物件
//這裡,以它為引數,構造一個新的 Surface 物件
mSurface = new Surface(mSession.mSurfaceSession, mSession.mPid, mAttrs.getTitle().toString(), 0, w, h, mAttrs.format, flags);
}
Surface.openTransaction();//開啟一個事務處理
......
Surface.closeTransaction();//關閉一個事務處理
......
}
構造 Surface 物件:
public Surface(SurfaceSession s,//傳入一個SurfaceSession物件
int pid, String name, int display, int w, int h, int format, int flags) throws OutOfResourcesException {
......
mCanvas = new CompatibleCanvas();
//又一個 native 函式
init(s,pid,name,display,w,h,format,flags);
mName = name;
}
static void Surface_init(JNIEnv*env, jobject clazz, jobject session, jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jintflags) {
//從 SurfaceSession 物件中取出之前建立的那個 SurfaceComposerClient 物件
SurfaceComposerClient* client = (SurfaceComposerClient*)env->GetIntField(session, sso.client);
sp<SurfaceControl> surface;//注意它的型別是 SurfaceControl
if (jname == NULL) {
//呼叫 SurfaceComposerClient 的 createSurface 函式,返回的 surface 是一個 SurfaceControl 型別
surface = client->createSurface(pid, dpy, w, h, format, flags);
} else{
......
}
//把這個 surfaceControl 物件設定到 Java 層的 Surface 物件中
setSurfaceControl(env, clazz, surface);
}
在 createSurface 內部會使用 Binder 通訊將請求發給 SurfaceFlinger:
sp<ISurface>SurfaceFlinger::createSurface(ClientID clientId, int pid, const String8& name, ISurfaceFlingerClient::surface_data_t* params, DisplayID d, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) {
sp<LayerBaseClient> layer;//LayerBaseClient 是 Layer 家族的基類
//這裡又冒出一個 LayerBaseClient 的內部類,它也叫Surface
sp<LayerBaseClient::Surface> surfaceHandle;
Mutex::Autolock _l(mStateLock);
//根據 clientId 找到 createConnection 時加入的那個 Client 物件
sp<Client> client = mClientsMap.valueFor(clientId);
......
//注意這個 id,它的值表示 Client 建立的是第幾個顯示層
//同時也表示將使用 SharedBufferStatck 陣列的第 id 個元素
int32_t id = client->generateId(pid);
//一個 Client 不能建立多於 NUM_LAYERS_MAX 個的Layer
if(uint32_t(id) >= NUM_LAYERS_MAX) {
return surfaceHandle;
}
//根據 flags 引數來建立不同型別的顯示層
switch(flags & eFXSurfaceMask) {
case eFXSurfaceNormal:
if (UNLIKELY(flags & ePushBuffers)) {
//建立 PushBuffer 型別的顯示層
layer = createPushBuffersSurfaceLocked(client, d, id, w, h, flags);
} else {
//建立 Normal 型別的顯示層
layer = createNormalSurfaceLocked(client, d, id, w, h, flags, format);
}
break;
case eFXSurfaceBlur:
//建立 Blur 型別的顯示層
layer = createBlurSurfaceLocked(client, d, id, w, h, flags);
break;
case eFXSurfaceDim:
//建立 Dim 型別的顯示層
layer = createDimSurfaceLocked(client, d, id, w, h, flags);
break;
}
if(layer != 0) {
layer->setName(name);
setTransactionFlags(eTransactionNeeded);
//從顯示層物件中取出一個 ISurface 物件賦值給 SurfaceHandle
surfaceHandle = layer->getSurface();
if(surfaceHandle != 0) {
params->token = surfaceHandle->getToken();
params->identity = surfaceHandle->getIdentity();
params->width = w;
params->height = h;
params->format = format;
}
}
return surfaceHandle;//ISurface 的 Bn 端就是這個物件
}
sp<LayerBaseClient>SurfaceFlinger::createNormalSurfaceLocked(const sp<Client>& client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format) {
switch(format) { //一些影象方面的引數設定,可以不去管它
case PIXEL_FORMAT_TRANSPARENT:
case PIXEL_FORMAT_TRANSLUCENT:
format = PIXEL_FORMAT_RGBA_8888;
break;
case PIXEL_FORMAT_OPAQUE:
format = PIXEL_FORMAT_RGB_565;
break;
}
//建立一個 Layer 型別的物件
sp<Layer> layer = new Layer(this, display,client, id);
//設定 Buffer
status_t err = layer->setBuffers(w, h, format, flags);
if (LIKELY(err == NO_ERROR)) {
//初始化這個新 layer 的一些狀態
layer->initStates(w, h, flags);
//下面這個函式把這個 layer 加入到 Z 軸集合中
addLayer_l(layer);
}
......
return layer;
}
createNormalSurfaceLocked 函式有三個關鍵點,它們是:
構造一個Layer物件。
呼叫Layer物件的setBuffers函式。
呼叫SF的addLayer_l函式。
當跨程序的 createSurface() 執行完返回一個 ISurface 物件,接下來會建立 SurfaceControl 物件:
SurfaceControl::SurfaceControl(
const sp<SurfaceComposerClient>& client,
const sp<ISurface>& surface,
const ISurfaceFlingerClient::surface_data_t& data,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
//mClient 為 SurfaceComposerClient,而 mSurface 指向跨程序 createSurface() 呼叫返回的 ISurface 物件
:mClient(client), mSurface(surface),
mToken(data.token), mIdentity(data.identity),
mWidth(data.width), mHeight(data.height), mFormat(data.format),
mFlags(flags){
......
}
SurfaceControl 類可以看作是一個 wrapper 類,它封裝了一些函式,通過這些函式可以方便地呼叫 mClient 或 ISurface 提供的函式。
最後會執行 copyFrom() 返回給 App 客戶端:
static void Surface_copyFrom(JNIEnv* env,jobject clazz, jobject other) {
//根據JNI函式的規則,clazz 是 copyFrom 的呼叫物件,而 other 是 copyFrom 的引數。
//目標物件此時還沒有設定 SurfaceControl,而源物件在前面已經建立了 SurfaceControl
constsp<SurfaceControl>& surface = getSurfaceControl(env, clazz);
constsp<SurfaceControl>& rhs = getSurfaceControl(env, other);
if (!SurfaceControl::isSameSurface(surface, rhs)) {
//把源 SurfaceControl 物件設定到目標 Surface 中
setSurfaceControl(env, clazz, rhs);
}
}
copyFrom 期間一共有三個關鍵物件,它們分別是:
SurfaceComposerClient
SurfaceControl
Surface,這個 Surface 物件屬於 Native 層,和 Java 層的 Surface 相對應
其中轉移到 ViewRoot 成員變數 mSurface 中的,就是最後這個 Surface 物件了。
在 SurfaceFlinger 程序中,Client 的一個 Layer 將使用 SharedBufferStack 陣列中的一個成員,並通過 SharedBufferServer 結構來控制這個成員,我們知道 SurfaceFlinger 是消費者,所以可由 SharedBufferServer 來控制資料的讀取。
與之相對應,客戶端的程序也會有一個物件來使用這個 SharedBufferStack,可它是通過另外一個叫 SharedBufferClient 的結構來控制的。客戶端為 SurfaceFlinger 提供資料,所以可由 SharedBufferClient 控制資料的寫入。
Surface 顯示過程
如圖所示,在 App 程序中建立 PhoneWindow 後會建立 ViewRoot。ViewRoot 的建立會建立一個 Surface,這個 Surface 其實是空的,通過與 WindowManagerService 通訊 copyFrom() 一個 NativeSurface。在與 SurfaceFlinger 通訊時,會建立 SharedClient 一段共享記憶體,裡面存放的是 SharedBufferStack 對應 SurfaceFlinger 中的 SurfaceLayer 每個 Layer 其實是一個 FrameBuffer,每個 FrameBuffer 中有兩個 GraphicBuffer 記作 FrontBuffer 和 BackBuffer。
在 SurfaceFlinger 中 SharedBufferServer 來管理 FrameBuffer。同時在 App 端 copyFrom() 出來 NativeSurface 時會建立一個 SharedBufferClient 與 SharedClient 這塊共享記憶體關聯。當客戶端 addView() 或者需要更新 View 時,會通過 SharedBufferClient 寫入資料到 ShareClient 中,SurfaceFlinger 中的 SharedBufferServer 接收到通知會將 FrameBuffer 中的資料傳輸到螢幕上。
HWComposer 是基於硬體來產生 VSync 訊號的,來通知 SurfaceFlinger 重繪控制顯示的幀率。
以上理解屬於個人觀點,能力有限,若有錯誤歡迎指出,歡迎交流學習,共同進步。