- Surface 到底是什么?它和 View/Window 的關(guān)系是什么?
- App 繪制的像素?cái)?shù)據(jù)是如何存儲(chǔ)在 Surface 中的?
- Surface 是如何跨進(jìn)程把數(shù)據(jù)傳遞給 SurfaceFlinger 的?
Surface 的定義
Surface 不是 “顯示組件”,而是 「一塊可繪制的內(nèi)存緩沖區(qū)(Buffer)的抽象封裝」。
通俗理解:Surface 是 App 寫(xiě)給 “畫(huà)布” 的 “畫(huà)板”,App 只負(fù)責(zé)往畫(huà)板上畫(huà)畫(huà)(寫(xiě)入像素?cái)?shù)據(jù)),但不負(fù)責(zé)把畫(huà)板掛到墻上(顯示到屏幕);
技術(shù)本質(zhì):Surface 內(nèi)部持有 BufferQueue 的「生產(chǎn)者(Producer)」端,通過(guò)它向緩沖區(qū)寫(xiě)入數(shù)據(jù)。
Surface 與 Window/View 的關(guān)系
1 個(gè) Window 對(duì)應(yīng) 1 個(gè) Surface:每個(gè) Activity/Dialog/ 狀態(tài)欄都對(duì)應(yīng)一個(gè) Window,每個(gè) Window 會(huì)創(chuàng)建一個(gè)專屬的 Surface(通過(guò) WindowManager 申請(qǐng));
View 依賴 Surface 繪制:所有 View 的 onDraw() 最終都是通過(guò) Canvas 把數(shù)據(jù)寫(xiě)入所屬 Window 的 Surface 緩沖區(qū);
Surface 與 ViewRootImpl 綁定:ViewRootImpl 是 Surface 和 View 樹(shù)的橋梁,負(fù)責(zé)把 View 繪制的內(nèi)容同步到 Surface 中。
Activity 啟動(dòng) → WindowManager 創(chuàng)建 Window
↓
WindowManager 向 SurfaceFlinger 申請(qǐng) Surface
↓
SurfaceFlinger 創(chuàng)建 BufferQueue,并返回「生產(chǎn)者」給 App 層
↓
App 層封裝生產(chǎn)者為 Surface 對(duì)象,綁定到 ViewRootImpl
↓
ViewRootImpl 把 Surface 傳遞給 Canvas,供 View 繪制
- 關(guān)鍵結(jié)論:Surface 的創(chuàng)建是跨進(jìn)程的,由 SurfaceFlinger 主導(dǎo),App 層只持有 “寫(xiě)入數(shù)據(jù)的權(quán)限”。
BufferQueue - 緩沖區(qū)的「生產(chǎn)者 - 消費(fèi)者」模型
BufferQueue 是連接 App 和 SurfaceFlinger 的核心機(jī)制,本質(zhì)是 「環(huán)形緩沖區(qū)隊(duì)列」,遵循生產(chǎn)者 - 消費(fèi)者設(shè)計(jì)模式:
生產(chǎn)者(Producer):App 層(Surface 持有),負(fù)責(zé)往緩沖區(qū)寫(xiě)入繪制好的像素?cái)?shù)據(jù);
消費(fèi)者(Consumer):SurfaceFlinger 層,負(fù)責(zé)從緩沖區(qū)讀取數(shù)據(jù),進(jìn)行圖層合成。
BufferQueue 的核心作用
解耦 App 繪制和 SurfaceFlinger 合成:App 繪制的速度和 SurfaceFlinger 合成的速度可以不一致,通過(guò)緩沖區(qū)隊(duì)列緩沖;
復(fù)用緩沖區(qū):避免頻繁創(chuàng)建 / 銷(xiāo)毀內(nèi)存緩沖區(qū),減少內(nèi)存抖動(dòng)和性能消耗;
同步數(shù)據(jù):保證 SurfaceFlinger 讀取的緩沖區(qū)是 “完整繪制完成” 的,避免讀取到半拉子數(shù)據(jù)。
BufferQueue 的工作流程(60Hz 屏幕為例)
1. 初始狀態(tài):BufferQueue 有 N 個(gè)空緩沖區(qū)(通常 2-3 個(gè));
2. App 向 BufferQueue 請(qǐng)求一個(gè)空緩沖區(qū)(dequeueBuffer);
3. App 通過(guò) Canvas 把繪制內(nèi)容寫(xiě)入該緩沖區(qū);
4. App 把寫(xiě)好的緩沖區(qū)送回隊(duì)列(queueBuffer),標(biāo)記為“就緒”;
5. SurfaceFlinger 從隊(duì)列取出就緒的緩沖區(qū)(acquireBuffer);
6. SurfaceFlinger 合成該緩沖區(qū)的數(shù)據(jù)到最終幀;
7. SurfaceFlinger 把用完的緩沖區(qū)放回隊(duì)列(releaseBuffer),標(biāo)記為“空”;
8. 重復(fù)步驟 2-7,每 16.6ms 執(zhí)行一次(60Hz 屏幕)。
雙緩沖 / 三緩沖機(jī)制
雙緩沖:BufferQueue 有 2 個(gè)緩沖區(qū),一個(gè)供 App 寫(xiě)入,一個(gè)供 SurfaceFlinger 讀取,避免 “寫(xiě)一半被讀” 的問(wèn)題;
三緩沖:當(dāng) App 繪制耗時(shí)超過(guò) 16.6ms 時(shí),第三個(gè)緩沖區(qū)可以承接下一次繪制,減少掉幀(比如 120Hz 屏幕常用三緩沖)。
Surface + BufferQueue 核心
// Surface 中的生產(chǎn)者邏輯(App 層)
public class Surface {
private final SurfaceControl mSurfaceControl;
private final BufferQueueProducer mProducer; // 生產(chǎn)者
// 申請(qǐng)空緩沖區(qū)
public long dequeueBuffer(BufferItem item, long timeout) {
return mProducer.dequeueBuffer(item, timeout);
}
// 提交寫(xiě)好的緩沖區(qū)
public int queueBuffer(long bufferId, int flags) {
return mProducer.queueBuffer(bufferId, flags);
}
}
// SurfaceFlinger 中的消費(fèi)者邏輯(Native 層簡(jiǎn)化)
class SurfaceFlinger {
private BufferQueueConsumer mConsumer; // 消費(fèi)者
// 獲取就緒的緩沖區(qū)
status_t acquireBuffer(BufferItem* item, nsecs_t timeout) {
return mConsumer->acquireBuffer(item, timeout);
}
// 釋放用完的緩沖區(qū)
status_t releaseBuffer(int slot, uint64_t frameNumber) {
return mConsumer->releaseBuffer(slot, frameNumber);
}
}
Surface → SurfaceFlinger 的數(shù)據(jù)傳遞
跨進(jìn)程通信的核心:Binder
Surface 持有的 BufferQueueProducer 是 Binder 接口,SurfaceFlinger 持有的 BufferQueueConsumer 是 Binder 服務(wù)端:
App 層調(diào)用 queueBuffer() 時(shí),通過(guò) Binder 把緩沖區(qū)的「句柄(Handle)」傳遞給 SurfaceFlinger(而非直接傳遞像素?cái)?shù)據(jù),避免內(nèi)存拷貝);
SurfaceFlinger 通過(guò)句柄直接訪問(wèn)緩沖區(qū)內(nèi)存(基于共享內(nèi)存 Ashmem),無(wú)需拷貝,效率極高。
數(shù)據(jù)傳遞完整流程
App 層:View.onDraw() → Canvas 寫(xiě)入像素?cái)?shù)據(jù)
↓
Canvas 把數(shù)據(jù)寫(xiě)入 Surface 持有的 BufferQueue 緩沖區(qū)
↓
Surface.queueBuffer() → 通過(guò) Binder 把緩沖區(qū)句柄發(fā)給 SurfaceFlinger
↓
SurfaceFlinger.acquireBuffer() → 獲取緩沖區(qū)句柄,訪問(wèn)共享內(nèi)存
↓
SurfaceFlinger 合成該緩沖區(qū)(與其他 Surface 的緩沖區(qū))→ 輸出到屏幕
- 關(guān)鍵結(jié)論:像素?cái)?shù)據(jù)存儲(chǔ)在共享內(nèi)存中,只傳遞句柄,不拷貝數(shù)據(jù),這是 Android 渲染性能的核心優(yōu)化點(diǎn)。
SurfaceView vs TextureView
普通 View 依賴 Window 的 Surface 繪制,而高頻繪制場(chǎng)景(視頻、游戲、直播)需要更高效的 Surface 載體:

問(wèn)題
為什么 SurfaceFlinger 不直接讀取 App 內(nèi)存中的像素?cái)?shù)據(jù),而是通過(guò) BufferQueue 共享內(nèi)存?
為什么 SurfaceView 適合高頻繪制場(chǎng)景,而普通 View 不適合?