Android回爐系列之Surfaceflinger
文章目錄
前言
很早開始就有想寫寫博客的想法,畢竟好記心不如爛筆頭,這段時間公司業務要求,對音視頻、渲染等要有深度理解,突然之間發現自己腦袋是空空的,沒辦法就只有系統性的回爐一遍,同時也做好存檔,以便於後期的複習、昇華做鋪墊!好了廢話不多說了。我們首先從界面繪製渲染開始,竟然是繪製那麼針對我們Android系統而言我們是怎麼把視圖呈現給用戶的呢?帶着這個疑惑,我們就從surfaceflinger開始一一解析。
1. Surfaceflinger是什麼?
通過查閱源碼發現surfaceflinger幾乎貫通了Android所有領域的知識,從硬件抽象層到framework層,CPU響應處理到OpenGL等等硬件繪製,複雜~。。。所以本文不針對細則邏輯做描述,我們從架構解析開始,來了解它的設計思想。
surfaceflinger是整個Android系統渲染的核心進程,所有的應用的渲染邏輯最後都會來到surfaceflinger進行處理,最有在把處理後的圖像數據交給CPU/GPU繪製在屏幕上。
2. Surfaceflinger
在學習之前給出其總結的五個特點。以便後面的細則理解和設計結構的理解。
2.1 特點一
surfaceflinger在Android系統中並不是擔當渲染角色,而是一個工具(“傳輸機器”),把每個應用傳輸過來的圖元數據處理後交給CPU||GPU做繪製處理。
2.2 特點二
由於針對每個應用而言都是以Surface做爲一個圖元爲傳輸單位,向surfaceflinger傳輸圖元數據。如下圖:
2.3 特點三
通過閱讀發現Surfaceflinger設計核心思想就是以生產者和消費者的模式,會把每一個應用的Surface圖元保存到SufaceflingerQueue隊列中,Surfaceflinger作爲消費者會根據一定的邏輯規則把生產者放入Surface一一處理。如下圖:
2.4 特點四
由於應用進程和Surfaceflinger是兩個獨立的進程,那麼圖元數據是怎麼實現傳輸的呢?這裏就需要跨進程通信,這裏就會連鎖反應想到socket和binder但是由於socket需要拷貝兩次在效率上不可取,binder又有大小限制好像是1M不到還要包括其它的通信也不可取,所以爲了解決這個問題,Android系統使用了共享內存(匿名共享內存ion),匿名共享內存也只需要拷貝一次的進程通信方式,聽大神說比較接近Linux共享內存。具體實現方式後期在學習~如下圖:
2.5 特點五
Surfaceflinger底層有一個時間鍾在不斷循環,從硬件中發出或者從軟件模擬發出記時喚起,每個一段時間(16ms)都會獲取Surfaceflinger中的圖元隊列通過CPU/GPU繪製到屏幕上。這個特點有點繞,因爲此特點應用有辦法通知Surfaceflinger渲染模式,Surfaceflinger繪製屏幕有自身回調自身特點等。如下圖:
PS:對於相位和Vsync(垂直信號)的介紹我們會在後續同步。
3. 小結
上述五點就是Surfaceflinger的設計核心特點,按照這五個特點閱讀可以降低其複雜性。那麼Surfaceflinger和skia有什麼關係呢?和頂層View的繪製又有什麼關係呢?
我們通過層級區分如下:
- framework面向應用開發者的View是便於開發的控件,裏面提供了當前控制的屬性以及功能。
- Skia是Android對於屏幕的畫筆,經過View的onDraw方法回調,把需要繪製的東西通過Skia繪製成像素圖元保存起來。
- Surfaceflinger是最後接收Skia的繪製結果,最後同步到屏幕上。
所以,Skia是Android渲染的核心,最終Skia和系統結合起來纔是一個完整的渲染體系。如下圖:
4. Surfaceflinger初始化
針對初始化我們通過代碼結合形式來分析代碼來至版本9.0。在閱讀源碼做下鋪墊,首先我們先弄清楚EGL/OPENGL ES,Displayhardware,Gralloc,FramcbuffernativeWindow等等之間的關係。如下圖:
- Android HAL層提供了Gralloc,包括fb和gralloc兩個設備。前者負責打開內核中的framebuffer、初始化配置,提供Post,setSwapInsterval等操作接口;後者者管理針緩衝區的分配和釋放。這就意味着上層元素只能通過Gralloc來訪問幀緩衝區,從而保證系統對framebuffer的有序使用和統一管理。
- 另外HAL層的另一個重要模塊Conposer它是爲廠商自制UI合成提供接口,它的直接使用者是surfaceflinger中的HWConposer,同時還負責VSync信號的產生和控制。VSync是一種同步機制,可以是硬件產生,也可以通過軟件來模擬Thread。
- 由於OpenGL ES是一個通用的函數庫,在不同的平臺系統上需要被本地化及就是把它具體的平臺窗口系統聯繫起來。FramebufferNativeWindow主要就是負責OpenGL ES在Android平臺上本地化的中介之一。還有一個本地窗口Surface。爲OpenGL ES配置本地窗口的是EGL。
- OpenGL ES 只是一個接口協議,具體實現既可以採用軟件,也可以依託於硬件。那麼OpenGLES 動態運行時是如何取捨的?這個就是EGL的作用之一,它回去讀取egl.cfg這個配置文件,然後根據設定動態加贊libagl||libhgl。
- surfaceflinger中持有一個數組mDisplays來描述系統中支持的顯示設備及Display,它是由surfaceflinger在readyToRun中判斷並賦值,並且在DisplayDevice在初始化時還將調用eglgetDisplay,eglcreateWindowSurface等,並利用EGL來完成OpenGLES的環境搭建。。。
4.1 初始化涉及文件
- /frameworks/native/services/surfaceflinger/Android.bp
- /frameworks/native/services/surfaceflinger/surfaceflinger.rc
- /frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp
- /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
- /frameworks/native/services/surfaceflinger/DispSync.cpp
- /frameworks/native/services/surfaceflinger/MessageQueue.cpp
- /frameworks/native/services/surfaceflinger/EventThread.cpp
- /frameworks/native/services/surfaceflinger/MessageQueue.cpp
- /frameworks/native/libs/gui/BitTube.cpp
- /frameworks/native/services/surfaceflinger/EventThread.cpp
- /frameworks/native/libs/gui/DisplayEventReceiver.cpp
- /frameworks/native/services/surfaceflinger/MessageQueue.cpp
- /frameworks/native/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
- /frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
- /frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
- /frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.cpp
- /frameworks/native/services/surfaceflinger/EventControlThread.cpp
- /frameworks/native/services/surfaceflinger/MessageQueue.cpp
4.2 Android.bp瀏覽
需要明白Surfaceflinger的啓動需要先了解其涉及的模塊,bp文件路徑: /frameworks/native/services/surfaceflinger/Android.bp
對應代碼如下:
cc_defaults {
name: "libsurfaceflinger_defaults",
defaults: ["surfaceflinger_defaults"],
cflags: [
"-DGL_GLEXT_PROTOTYPES",
"-DEGL_EGLEXT_PROTOTYPES",
],
shared_libs: [
"[email protected]",
"android.hardware.configstore-utils",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"libbase",
"libbinder",
"libbufferhubqueue",
"libcutils",
"libdl",
"libEGL",
"libfmq",
"libGLESv1_CM",
"libGLESv2",
"libgui",
"libhardware",
"libhidlbase",
"libhidltransport",
"libhwbinder",
"liblayers_proto",
"liblog",
"libpdx_default_transport",
"libprotobuf-cpp-lite",
"libsync",
"libtimestats_proto",
"libui",
"libutils",
"libvulkan",
],
static_libs: [
"libserviceutils",
"libtrace_proto",
"libvkjson",
"libvr_manager",
"libvrflinger",
],
header_libs: [
"[email protected]",
"[email protected]",
],
export_static_lib_headers: [
"libserviceutils",
],
export_shared_lib_headers: [
"[email protected]",
"[email protected]",
"[email protected]",
"libhidlbase",
"libhidltransport",
"libhwbinder",
],
}
cc_library_headers {
...
}
filegroup {
name: "libsurfaceflinger_sources",
srcs: [
...
],
}
cc_library_shared {
name: "libsurfaceflinger",
defaults: ["libsurfaceflinger_defaults"],
...
}
cc_binary {
name: "surfaceflinger",
defaults: ["surfaceflinger_defaults"],
init_rc: ["surfaceflinger.rc"],
srcs: ["main_surfaceflinger.cpp"],
...
}
...
Surfaceflinger中涉及的幾個核心:
- [email protected] (圖元生成器抽象硬件層的實現)
- [email protected](hwc圖層合成抽象硬件層實現)
- binder,OpenGL es,hwbinder(抽象硬件層的binder)等等
- 設定了SurfaceFlinger的在Android啓動初期需要加載的init.rc文件:surfaceflinger.rc
- SurfaceFlinger的主函數入口main_surfaceflinger.cpp
PS:針對硬件抽象層不好理解,我們先把這個疑問預留這裏,後期在學習總結。
4.3 Surfaceflinger.rc
文件路徑: /frameworks/native/services/surfaceflinger/surfaceflinger.rc
對應代碼如下:
service surfaceflinger /system/bin/surfaceflinger
class core animation
user system
group graphics drmrpc readproc
onrestart restart zygote
writepid /dev/stune/foreground/tasks
socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_disp
上面代碼在啓動surfaceflinger服務、系統之外,同步還啓動了三個socket-跨進程通信的。具體作用不是當前重點後續在做研究。
4.4 main_surfaceflinger.cpp
Surfaceflinger啓動入口其文件路徑:
/frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp
int main(int, char**) {
//忽略了SIGPIPE信號,因爲在SurfaceFlinger的Client-Server模型中,或者說IPC機制中,很可能會觸發SIGPIPE信號,而這個信號的默認動作是終止進程
//當客戶端/服務端的socket關閉時,防止進程退出
signal(SIGPIPE, SIG_IGN);
hardware::configureRpcThreadpool(1 /* maxThreads */,
false /* callerWillJoin */);
startGraphicsAllocatorService();//初始化Hal層的圖元生成器服務
//設定surfaceflinger進程的binder線程池個數上限爲4,並啓動binder線程池;
ProcessState::self()->setThreadPoolMaxThreadCount(4);
//開啓線程
//大多數程序都是需要IPC的,這裏也需要,但是使用Binder機制是很繁瑣的,所以Android爲程序進程使用Binder機制封裝了兩個實現類:ProcessState、IPCThreadState
//其中ProcessState負責打開Binder驅動,進行mmap等準備工作;IPCThreadState負責具體線程跟Binder驅動進行命令交互。
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
// 實例化
sp<SurfaceFlinger> flinger = new SurfaceFlinger();
//設置surfaceflinger進程爲高優先級以及前臺調度策略;
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
set_sched_policy(0, SP_FOREGROUND);
// Put most SurfaceFlinger threads in the system-background cpuset
// Keeps us from unnecessarily using big cores
// Do this after the binder thread pool init
if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM);
// 執行surfaceflinger初始化方法
flinger->init();
//將surfaceflinger添加到ServiceManager
//sp是strongponiter強指針(sp對象的析構函數調用RefBase的decStrong來減少強弱引用指針計數)
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
// 註冊GPU
sp<GpuService> gpuservice = new GpuService();
sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
startDisplayService(); // 啓動圖形處理相關服務
struct sched_param param = {
0};
param.sched_priority = 2;
if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO");
}
// 運行當前線程
flinger->run();
return 0;
}
在上面方法中我們抽離幾個核心方法解讀:
- startGraphicsAllocatorService初始化hal層的圖元生成器
- 初始化ProcessState,把該進程映射到Binder驅動程序
- Surfaceflinger實例化
- set_sched_policy設置前臺進程
- Surfaceflinger初始化
- 由於Surfaceflinger本質是Binder服務,所以需要添加到ServiceManager進程中
- 初始化GpuService,添加到ServiveManager進程中
- 啓動圖形處理相關服務DisplayService
- sched_setscheduler把進程調度模式設置爲實時進程的FIFO
- 調用Surfaceflinger的run方法
PS:由於Surfaceflinger不像應用進程一樣是前臺應用,它是運行雲後臺的爲了保證它不被幹掉,爲了CPU不斷的優先把資源傳遞給Surfaceflinger,爲了讓得到的渲染機會在16ms完成。
這裏有一個FIFO就是實時調度策略,細則感興趣的桐學可以學習下linux的進程調度。
Surfaceflinger被設置爲SP_FOREGROUND,設置爲前臺進程,加入到前臺進程數組中。接着SCHED_FIFO優先級策略。這樣就能保證Surfaceflinger是在較高優先級下運行,同時保證只要每一次遍歷進程調度類的時候,必定會先讓渡給Surfaceflinger,接着讓調渡給Ap應用。
4.5 Surfaceflinger實例化
創建SurfaceFlinger對象,在其構造函數中,主要是一些成員變量的初始化工作核心是提供的surfaceflinger的binder能力,提供layer創建等能力,系統提供的監聽Binder進程死亡的事件回調,HWComper提供的監聽顯示器變化事件回調以及Hwcomposer中的Vsync信號。
代碼路徑:/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag)
: BnSurfaceComposer(),
mTransactionFlags(0),
mTransactionPending(false),
mAnimTransactionPending(false),
mLayersRemoved(false),
mLayersAdded(false),
mRepaintEverything(0),
mBootTime(systemTime()),
mBuiltinDisplays(),
mVisibleRegionsDirty(false),
mGeometryInvalid(false),
mAnimCompositionPending(false),
mDebugRegion(0),
mDebugDDMS(0),
mDebugDisableHWC(0),
mDebugDisableTransformHint(0),
mDebugInSwapBuffers(0),
mLastSwapBufferTime(0),
mDebugInTransaction(0),
mLastTransactionTime(0),
mBootFinished(false),
mForceFullDamage(false),
mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
mHasPoweredOff(false),
mNumLayers(0),
mVrFlingerRequestsDisplay(false),
mMainThreadId(std::this_thread::get_id()),
mCreateBufferQueue(&BufferQueue::createBufferQueue),
mCreateNativeWindowSurface(&impl::NativeWindowSurface::create) {
}
- BnSurfaceComposer,IBinder::DeathRecipient,HWComposer::EventHandler SurfaceFlinger的父類
- mPrimaryDispSync 主要的信號同步處理器
- BufferQueue 圖元消費隊列
SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) {
ALOGI("SurfaceFlinger is starting");
vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
sfVsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::vsyncSfEventPhaseOffsetNs>(1000000);
hasSyncFramework = getBool< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::hasSyncFramework>(true);
dispSyncPresentTimeOffset = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::presentTimeOffsetFromVSyncNs>(0);
useHwcForRgbToYuv = getBool< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::useHwcForRGBtoYUV>(false);
maxVirtualDisplaySize = getUInt64<ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::maxVirtualDisplaySize>(0);
// Vr flinger is only enabled on Daydream ready devices.
useVrFlinger = getBool< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::useVrFlinger>(false);
maxFrameBufferAcquiredBuffers = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2);
hasWideColorDisplay =
getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
V1_1::DisplayOrientation primaryDisplayOrientation =
getDisplayOrientation< V1_1::ISurfaceFlingerConfigs, &V1_1::ISurfaceFlingerConfigs::primaryDisplayOrientation>(
V1_1::DisplayOrientation::ORIENTATION_0);
switch (primaryDisplayOrientation) {
case V1_1::DisplayOrientation::ORIENTATION_90:
mPrimaryDisplayOrientation = DisplayState::eOrientation90;
break;
case V1_1::DisplayOrientation::ORIENTATION_180:
mPrimaryDisplayOrientation = DisplayState::eOrientation180;
break;
case V1_1::DisplayOrientation::ORIENTATION_270:
mPrimaryDisplayOrientation = DisplayState::eOrientation270;
break;
default:
mPrimaryDisplayOrientation = DisplayState::eOrientationDefault;
break;
}
ALOGV("Primary Display Orientation is set to %2d.", mPrimaryDisplayOrientation);
mPrimaryDispSync.init(SurfaceFlinger::hasSyncFramework, SurfaceFlinger::dispSyncPresentTimeOffset);
// debugging stuff...
char value[PROPERTY_VALUE_MAX];
property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
mGpuToCpuSupported = !atoi(value);
property_get("debug.sf.showupdates", value, "0");
mDebugRegion = atoi(value);
property_get("debug.sf.ddms", value, "0");
mDebugDDMS = atoi(value);
if (mDebugDDMS) {
if (!startDdmConnection()) {
// start failed, and DDMS debugging not enabled
mDebugDDMS = 0;
}
}
ALOGI_IF(mDebugRegion, "showupdates enabled");
ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
property_get("debug.sf.disable_backpressure", value, "0");
mPropagateBackpressure = !atoi(value);
ALOGI_IF(!mPropagateBackpressure, "Disabling backpressure propagation");
property_get("debug.sf.enable_hwc_vds", value, "0");
mUseHwcVirtualDisplays = atoi(value);
ALOGI_IF(!mUseHwcVirtualDisplays, "Enabling HWC virtual displays");
property_get("ro.sf.disable_triple_buffer", value, "1");
mLayerTripleBufferingDisabled = atoi(value);
ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering");
const size_t defaultListSize = MAX_LAYERS;
auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
property_get("debug.sf.early_phase_offset_ns", value, "0");
const int earlyWakeupOffsetOffsetNs = atoi(value);
ALOGI_IF(earlyWakeupOffsetOffsetNs != 0, "Enabling separate early offset");
mVsyncModulator.setPhaseOffsets(sfVsyncPhaseOffsetNs - earlyWakeupOffsetOffsetNs,
sfVsyncPhaseOffsetNs);
//我們應該讀取'persist.sys.sf '。color_saturation‘這
//但是由於/data可能被加密,我們需要等到vold之後
//讀取屬性屬性是
//在啓動動畫之後讀取
if (useTrebleTestingOverride()) {
//如果沒有覆蓋SurfaceFlinger就不能連接到HIDL
//艙單上沒有列出的服務。被認爲是
//從set服務名派生設置,但是它
//如果使用的名稱不是'default',則是易碎的
//用於以後的生產目的。
setenv("TREBLE_TESTING_OVERRIDE", "true", true);
}
}
Surfaceflinger實例化實現如下特點:
- 初始化了vsyncPhaseOffsetNs,sfVsyncPhaseOffsetNs兩個相位差,分別是指app的以及sf的相位差。關於相位差後面在學習
- 設置Surfaceflinger的渲染方向,是哪一個角度
- mPrimaryDispSync 主顯示屏信號同步器初始化
- 根據Android的全局配置,判斷是否需要打開三重緩衝,HWC合成機制
4.5.1 DispSync初始化
void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) {
mIgnorePresentFences = !hasSyncFramework;
mPresentTimeOffset = dispSyncPresentTimeOffset;
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
// set DispSync to SCHED_FIFO to minimize jitter
struct sched_param param = {
0};
param.sched_priority = 2;
if (sched_setscheduler(mThread->getTid(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for DispSyncThread");
}
reset();
beginResync();
if (kTraceDetailedInfo) {
//如果我們沒有得到現在的柵欄,那麼零相位示蹤劑
//將阻止HW垂直同步事件被關閉。
//即使我們只是忽略了柵欄,零相位跟蹤也是
//不需要,因爲任何時候有一個事件註冊我們將
//打開HW垂直同步事件。
if (!mIgnorePresentFences && kEnableZeroPhaseTracer) {
mZeroPhaseTracer = std::make_unique<ZeroPhaseTracer>();
addEventListener("ZeroPhaseTracer", 0, mZeroPhaseTracer.get());
}
}
}
在這個過程中初始化了DispSyncThread這個線程並且運行起來,並且初始化一些簡單的數據。同時設置這個線程調度的優先類爲FIFO。相位計算?
4.5.2 圖元隊列調度
因爲這裏的SurfaceFlinger對象是一個StrongPointer強指針,所以首先會走到RefBase的onFirstRef方法。故
void SurfaceFlinger::onFirstRef()
{
mEventQueue->init(this);
}
查看surfaceFlinger.h,發現mEventQueue是MessqgeQueue創建的對象。
// these are thread safe
mutable std::unique_ptr<MessageQueue> mEventQueue{
std::make_unique<impl::MessageQueue>()};
文件路勁/frameworks/native/services/surfaceflinger/MessageQueue.cpp
所以初始化會創建消息隊列需要的Handler、Looper。
void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
mFlinger = flinger;
mLooper = new Looper(true);
mHandler = new Handler(*this);
}
此處MessageQueue不是常見的消息隊列,在SurfaceFlinger目錄單獨編寫,mEventQueue更像是消息循環機制的管理者,其中包含了一個looper,在looper中的mMessageEnvelopes這個容器纔是真正存儲消息的地方。
waitMessage主要通過調用mLooper的pollOnce方法來監聽消息
void MessageQueue::waitMessage() {
do {
IPCThreadState::self()->flushCommands();
int32_t ret = mLooper->pollOnce(-1);
switch (ret) {
case Looper::POLL_WAKE:
case Looper::POLL_CALLBACK:
continue;
case Looper::POLL_ERROR:
ALOGE("Looper::POLL_ERROR");
continue;
case Looper::POLL_TIMEOUT:
// timeout (should not happen)
continue;
default:
// should not happen
ALOGE("Looper::pollOnce() returned unknown status %d", ret);
continue;
}
} while (true);
}
handler也不是常見的那個Handler,而是Messagequeue中自定義的一個事件處理器,是專門爲Surfaceflinger設計的,handler收到消息,進一步回調Surfaceflinger中的onMessageReceived。
void MessageQueue::Handler::handleMessage(const Message& message) {
switch (message.what) {
case INVALIDATE:
android_atomic_and(~eventMaskInvalidate, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
case REFRESH:
android_atomic_and(~eventMaskRefresh, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
}
}
上面代碼註冊了兩種不同的圖元刷新監聽,一個是invalidate局部刷新,一個是refresh重新刷新。最後都會回調到Surfaceflinger的onMessageReceived中。換句話說,每當我們需要圖元刷新的時候,就會通過mEventQueue的post方法,把數據異步加載到Handler中進行刷新。
4.6 Surfaceflinger初始化
void SurfaceFlinger::init() {
ALOGI( "SurfaceFlinger's main thread ready to run. "
"Initializing graphics H/W...");
ALOGI("Phase offest NS: %" PRId64 "", vsyncPhaseOffsetNs);
Mutex::Autolock _l(mStateLock);
// start the EventThread當應用和sf的vsync偏移量一致時,則只創建一個EventThread線程
// std::make_unique比較新,它是在c++14里加入標準庫的。
//template<typename T, typename... Ts>
//std::unique_ptr<T> make_unique(Ts&&... params)
//{
//return std::unique_ptr<T>(new T(std::forward<Ts>(params)...));
//}
//make_unique只是把參數完美轉發給,要創建對象的構造函數,再從new出來的原生指針,構造std::unique_ptr。
//這種形式的函數,不支持數組和自定義刪除器。
//make_unique函數:把任意集合的參數,完美轉發給動態分配對象的構造函數,
//然後返回一個指向那對象的智能指針。
mEventThreadSource =
std::make_unique<DispSyncSource>(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs,
true, "app");
mEventThread = std::make_unique<impl::EventThread>(mEventThreadSource.get(),
[this]() {
resyncWithRateLimit(); },
impl::EventThread::InterceptVSyncsCallback(),
"appEventThread");
mSfEventThreadSource =
std::make_unique<DispSyncSource>(&mPrimaryDispSync,
SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread =
std::make_unique<impl::EventThread>(mSfEventThreadSource.get(),
[this]() {
resyncWithRateLimit(); },
[this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
},
"sfEventThread");
//設置EventThread
mEventQueue->setEventThread(mSFEventThread.get());
mVsyncModulator.setEventThread(mSFEventThread.get());
//獲取RenderEngine引擎,渲染引擎,通過工廠模式實現對於不同版本的OpenGL分裝. 詳細實現下面接下來再進行分析
getBE().mRenderEngine =
RE::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,
hasWideColorDisplay
? RE::RenderEngine::WIDE_COLOR_SUPPORT
: 0);
LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine");
LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
"Starting with vr flinger active is not currently supported.");
getBE().mHwc.reset(//初始化硬件composer對象, hwcomposer實例化,主要是監聽顯示器硬件變化, hard抽象層。
new HWComposer(std::make_unique<Hwc2::impl::Composer>(getBE().mHwcServiceName)));
//監聽
getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId);
//處理任何初始熱插拔和結果顯示更改。
//該方法第一次進來無效,這是SF重啓發現有屏幕插進來,一般不會走進來
processDisplayHotplugEventsLocked();
LOG_ALWAYS_FATAL_IF(!getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY),
"Registered composer callback but didn't create the default primary display");
//將默認的顯示GLContext設置爲當前,這樣我們就可以創建紋理
//當我們創建圖層時(可能會在渲染之前發生)
//第一次進來還沒有鏈接進來的Display的Binder對象,跳過
getDefaultDisplayDeviceLocked()->makeCurrent();
//打開vr功能相關模塊
if (useVrFlinger) {
auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
//這個回調函數被vr flinger分派線程調用。我們
//需要調用signalTransaction(),它需要持有
//當我們不在主線程時mStateLock。收購
// mStateLock從vr flinger分派線程可能觸發一個
//surface flinger中的死鎖(見b/66916578),因此發佈一個消息
//改爲在主線程上處理。
sp<LambdaMessage> message = new LambdaMessage([=]() {
ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
mVrFlingerRequestsDisplay = requestDisplay;
signalTransaction();
});
postMessageAsync(message);
};
mVrFlinger = dvr::VrFlinger::Create(getBE().mHwc->getComposer(),
getBE().mHwc->getHwcDisplayId(HWC_DISPLAY_PRIMARY).value_or(0),
vrFlingerRequestDisplayCallback);
if (!mVrFlinger) {
ALOGE("Failed to start vrflinger");
}
}
mEventControlThread = std::make_unique<impl::EventControlThread>(
[this](bool enabled) {
setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled); });
// //初始化繪圖狀態
mDrawingState = mCurrentState;
//初始化顯示設備,以Event事件形式發送
initializeDisplays();
getBE().mRenderEngine->primeCache();
//通知本地圖形api是否支持當前的時間戳:
if (getHwComposer().hasCapability(
HWC2::Capability::PresentFenceIsNotReliable)) {
mStartPropertySetThread = new StartPropertySetThread(false);
} else {
mStartPropertySetThread = new StartPropertySetThread(true);
}
if (mStartPropertySetThread->Start() != NO_ERROR) {
ALOGE("Run StartPropertySetThread failed!");
}
mLegacySrgbSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(HWC_DISPLAY_PRIMARY,
Dataspace::SRGB_LINEAR);
ALOGV("Done initializing");
}
在init過程中初始化不少重要的對象:
- DispSyncSource 的初始化
- EventThread 的初始化
- EventQueue 監聽初始化
- RenderEngine渲染引擎的初始化
- 初始化HWComposer監聽顯示器硬件變化
- EventControlThread初始化
- 初始化和鏈接DisplayService
4.6.1 EventThread|DispSyncSource的初始化
文件路徑:/frameworks/native/services/surfaceflinger/EventThread.cpp
mEventThreadSource =std::make_unique<DispSyncSource>(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs,true, "app");
mEventThread = std::make_unique<impl::EventThread>(mEventThreadSource.get(),[this]() {
resyncWithRateLimit(); },impl::EventThread::InterceptVSyncsCallback(),"appEventThread");
能看到實際上mEventThread本質上就是一個DisSyncSource對象,我們看看他的構造函數:
class DispSyncSource final : public VSyncSource, private DispSync::Callback {
public:
DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
const char* name) :
mName(name),
mValue(0),
mTraceVsync(traceVsync),
mVsyncOnLabel(String8::format("VsyncOn-%s", name)),
mVsyncEventLabel(String8::format("VSYNC-%s", name)),
mDispSync(dispSync),
mCallbackMutex(),
mVsyncMutex(),
mPhaseOffset(phaseOffset),
mEnabled(false) {
}
~DispSyncSource() override = default;
...
在這個中設置兩個關鍵參數,一個是上面初始化好的DispSync顯示同步信號,一個是app的DispSyncSource(相位差)
4.6.2 EventThread實例化
其邏輯流程大概如下:
把app的DispSyncSource作爲參數,進行實例化
EventThread::EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback,
InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
: mVSyncSource(src),
mResyncWithRateLimitCallback(resyncWithRateLimitCallback),
mInterceptVSyncsCallback(interceptVSyncsCallback) {
for (auto& event : mVSyncEvent) {
event.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
event.header.id = 0;
event.header.timestamp = 0;
event.vsync.count = 0;
}
mThread = std::thread(&EventThread::threadMain, this);
pthread_setname_np(mThread.native_handle(), threadName);
pid_t tid = pthread_gettid_np(mThread.native_handle());
// Use SCHED_FIFO to minimize jitter
constexpr int EVENT_THREAD_PRIORITY = 2;
struct sched_param param = {
0};
param.sched_priority = EVENT_THREAD_PRIORITY;
if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for EventThread");
}
set_sched_policy(tid, SP_FOREGROUND);
}
能夠看到在這個過程中做的事情和DispSync的方法很相似。首先實例化一個內部線程,並且設置這個線程的啓動後的方法,以及設置該線程爲FIFO策略並且設置爲前臺線程,使用更高的優先級。
void EventThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
std::unique_lock<std::mutex> lock(mMutex);
while (mKeepRunning) {
DisplayEventReceiver::Event event;
Vector<sp<EventThread::Connection> > signalConnections;
signalConnections = waitForEventLocked(&lock, &event);
// dispatch events to listeners...
const size_t count = signalConnections.size();
for (size_t i = 0; i < count; i++) {
const sp<Connection>& conn(signalConnections[i]);
// now see if we still need to report this event
status_t err = conn->postEvent(event);
if (err == -EAGAIN || err == -EWOULDBLOCK) {
// The destination doesn't accept events anymore, it's probably
// full. For now, we just drop the events on the floor.
// FIXME: Note that some events cannot be dropped and would have
// to be re-sent later.
// Right-now we don't have the ability to do this.
ALOGW("EventThread: dropping event (%08x) for connection %p", event.header.type,
conn.get());
} else if (err < 0) {
// handle any other error on the pipe as fatal. the only
// reasonable thing to do is to clean-up this connection.
// The most common error we'll get here is -EPIPE.
removeDisplayEventConnectionLocked(signalConnections[i]);
}
}
}
}
能看到在這個過程中,會通過waitForEventLocked阻塞等待外部鏈接進來的EventThread的Connection,鏈接進來。一般是應用程序註冊了Choreographer之後,就會註冊DisplayEventReceiver,此時會對應DisplayEventReceiverDispatch一個Looper的callback,同時會通過Binder把當前爲當前對象註冊一個Connect給Surfaceflinger進程的EventThread。當喚醒之後,經過檢測將會調用postEvent把同步信號同步給Ap應用。
在waitForEventLocked等待循環的過程中,每一次同步信號的發出都會調用構造函數進來的回調interceptVSyncsCallback,也就是:
resyncWithRateLimit();
同時會根據條件判斷,當前是否打開同步信號。
4.6.3 Surfaceflinger的EventThread初始化
mSfEventThreadSource =
std::make_unique<DispSyncSource>(&mPrimaryDispSync,
SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread =
std::make_unique<impl::EventThread>(mSfEventThreadSource.get(),
[this]() {
resyncWithRateLimit(); },
[this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
},
"sfEventThread");
//設置EventThread
mEventQueue->setEventThread(mSFEventThread.get());
mVsyncModulator.setEventThread(mSFEventThread.get());
Surfaceflinger的EventThread監聽的是本進程的,其先去看看mEventQueue這個Surfaceflinger中的MessageQueue的setEventThread方法
void MessageQueue::setEventThread(android::EventThread* eventThread) {
if (mEventThread == eventThread) {
return;
}
if (mEventTube.getFd() >= 0) {
mLooper->removeFd(mEventTube.getFd());
}
mEventThread = eventThread;
mEvents = eventThread->createEventConnection();
mEvents->stealReceiveChannel(&mEventTube);
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
this);
}
在這個過程中能看到和Ap應用極其相似的邏輯。首先通過eventThread的createEventConnection創建一個Connection,EventThread可以從waitForEventLocked能夠監聽到這個鏈接。
sp<BnDisplayEventConnection> EventThread::createEventConnection() const {
return new Connection(const_cast<EventThread*>(this));
}
EventThread::Connection::Connection(EventThread* eventThread)
: count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {
}
EventThread::Connection::~Connection() {
//這裏什麼都不做——清理將自動發生
//當主線程喚醒時
}
void EventThread::Connection::onFirstRef() {
//注意:mEventThread對我們沒有強引用
mEventThread->registerDisplayEventConnection(this);
}
初始化了一個BitTube對象,以及把當前的Connection註冊到EventThread中,讓waitForEvent可以監聽到新的監聽進來了。
4.6.4 監聽
status_t EventThread::registerDisplayEventConnection(
const sp<EventThread::Connection>& connection) {
std::lock_guard<std::mutex> lock(mMutex);
mDisplayEventConnections.add(connection);
mCondition.notify_all();
return NO_ERROR;
}
4.6.5 BitTube
封裝過的socketpair。是一個全雙工的通道,可以從1號寫入,0號讀取。也可以從0號寫入,1號讀取。在BitTube中設定了0是接受,1是寫入其實就和管道一樣的。
文件路徑:/frameworks/native/libs/gui/BitTube.cpp
static const size_t DEFAULT_SOCKET_BUFFER_SIZE = 4 * 1024;
BitTube::BitTube(size_t bufsize) {
init(bufsize, bufsize);
}
BitTube::BitTube(DefaultSizeType) : BitTube(DEFAULT_SOCKET_BUFFER_SIZE) {
}
BitTube::BitTube(const Parcel& data) {
readFromParcel(&data);
}
void BitTube::init(size_t rcvbuf, size_t sndbuf) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
// since we don't use the "return channel", we keep it small...
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
fcntl(sockets[0], F_SETFL, O_NONBLOCK);
fcntl(sockets[1], F_SETFL, O_NONBLOCK);
mReceiveFd.reset(sockets[0]);
mSendFd.reset(sockets[1]);
} else {
mReceiveFd.reset();
ALOGE("BitTube: pipe creation failed (%s)", strerror(errno));
}
}
4.6.6 事件監聽過程
接着調用EventThread::Connection的stealReceiveChannel
status_t EventThread::Connection::stealReceiveChannel(gui::BitTube* outChannel) {
//重置這個位管的接收文件描述符爲receiveFd
outChannel->setReceiveFd(mChannel.moveReceiveFd());
return NO_ERROR;
}
當waitForEvent接觸等待後,將會調用Connection的postEvent方法:
文件路徑:/frameworks/native/services/surfaceflinger/EventThread.cpp
status_t EventThread::Connection::postEvent(const DisplayEventReceiver::Event& event) {
ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
文件路徑:/frameworks/native/libs/gui/DisplayEventReceiver.cpp
ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
Event const* events, size_t count)
{
return gui::BitTube::sendObjects(dataChannel, events, count);
}
這樣就完成了從發送端到接收端的過程監聽,當有數據喚醒時候就會進入到MessageQueue的回調中。
文件路徑:/frameworks/native/services/surfaceflinger/MessageQueue.cpp
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
MessageQueue* queue = reinterpret_cast<MessageQueue*>(data);
return queue->eventReceiver(fd, events);
}
int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
ssize_t n;
DisplayEventReceiver::Event buffer[8];
while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
for (int i = 0; i < n; i++) {
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
mHandler->dispatchInvalidate();
break;
}
}
}
return 1;
}
此時MessageQueue就會調用Handler中的dispatchInvalidate,也就調用到了Surfaceflinger的onMessageReceived回調。
4.7 RenderEngine初始化
//獲取RenderEngine引擎,渲染引擎,通過工廠模式實現對於不同版本的OpenGL分裝. 詳細實現下面接下來再進行分析
getBE().mRenderEngine =RE::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,hasWideColorDisplay?RE::RenderEngine::WIDE_COLOR_SUPPORT:0);
getBE其實是SurfaceflingerBE,它控制所有硬件接口,理解爲Surfaceflinger縮影。Surfaceflinger是對整個系統的視圖刷新控制。
std::unique_ptr<RenderEngine> RenderEngine::create(int hwcFormat, uint32_t featureFlags) {
//初始化EGL,作爲默認的顯示
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (!eglInitialize(display, nullptr, nullptr)) {
LOG_ALWAYS_FATAL("failed to initialize EGL");
}
//初始化EGL的版本
GLExtensions& extensions = GLExtensions::getInstance();
extensions.initWithEGLStrings(eglQueryStringImplementationANDROID(display, EGL_VERSION),
eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS));
// The code assumes that ES2 or later is available if this extension is
// supported.
//選擇處理EGL的配置
EGLConfig config = EGL_NO_CONFIG;
if (!extensions.hasNoConfigContext()) {
config = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
}
//初始化EGL上下文
EGLint renderableType = 0;
if (config == EGL_NO_CONFIG) {
renderableType = EGL_OPENGL_ES2_BIT;
} else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
}
//設置GL版本號
EGLint contextClientVersion = 0;
if (renderableType & EGL_OPENGL_ES2_BIT) {
contextClientVersion = 2;
} else if (renderableType & EGL_OPENGL_ES_BIT) {
contextClientVersion = 1;
} else {
LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
}
//獲取屬性
std::vector<EGLint> contextAttributes;
contextAttributes.reserve(6);
contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
contextAttributes.push_back(contextClientVersion);
bool useContextPriority = overrideUseContextPriorityFromConfig(extensions.hasContextPriority());
if (useContextPriority) {
contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
}
contextAttributes.push_back(EGL_NONE);
//初始化EGL上下文
EGLContext ctxt = eglCreateContext(display, config, nullptr, contextAttributes.data());
// if can't create a GL context, we can only abort.
LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
// now figure out what version of GL did we actually get
// NOTE: a dummy surface is not needed if KHR_create_context is supported
EGLConfig dummyConfig = config;
if (dummyConfig == EGL_NO_CONFIG) {
dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
}
EGLint attribs[] = {
EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
//創建一個dump的Surface
EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
LOG_ALWAYS_FATAL_IF(dummy == EGL_NO_SURFACE, "can't create dummy pbuffer");
//把EGLDisplay和dump鏈接起來
EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
GlesVersion version = parseGlesVersion(extensions.getVersion());
// initialize the renderer while GL is current
std::unique_ptr<RenderEngine> engine;
switch (version) {
case GLES_VERSION_1_0:
case GLES_VERSION_1_1:
LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run.");
break;
case GLES_VERSION_2_0:
case GLES_VERSION_3_0:
engine = std::make_unique<GLES20RenderEngine>(featureFlags);
break;
}
//設置EGLDisplay
engine->setEGLHandles(display, config, ctxt);
ALOGI("OpenGL ES informations:");
ALOGI("vendor : %s", extensions.getVendor());
ALOGI("renderer : %s", extensions.getRenderer());
ALOGI("version : %s", extensions.getVersion());
ALOGI("extensions: %s", extensions.getExtensions());
ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
//把EGLDisplay設置爲當前OpenGL es的環境
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroySurface(display, dummy);
return engine;
}
- 初始化EGLDisplay ,獲得當前系統默認的顯示屏對象
- 初始化EGL的版本
- chooseEglConfig選擇處理EGL的配置。通過eglGetConfigs查找可返回的EGL配置的數目,接着調用eglChooseConfig從所有配置項中得到最爲推薦的配置數組,最後通過遍歷查詢,把系統中符合當前配置項中所有的配置都添加進來
- eglCreateContext 初始化EGL上下文
- 設置GL版本號
- eglCreatePbufferSurface創建一個dump的Surface,開闢一段可以緩存幀數據的空間,並用eglMakeCurrent把EGLDisplay和dump鏈接起來,其目的就是爲了檢查OpenGL es是否有問題。
- setEGLHandles 設置EGLDisplay,上下文和配置爲全局配置
- eglMakeCurrent 把EGLDisplay設置爲當前OpenGL es的環境,銷燬dump這個Surface
4.8 HWComposer初始化
它聯通的硬件抽象層Conposer,他是被HWComposer直接使用的,HWComposer除了直接管理Composer以外還負責VSync信號的生成和控制。
getBE().mHwc.reset(//初始化硬件composer對象, hwcomposer實例化,主要是監聽顯示器硬件變化, hard抽象層。
new HWComposer(std::make_unique<Hwc2::impl::Composer>(getBE().mHwcServiceName)));
能看到HWComposer中傳入一個Hwc2::impl::Composer對象,先看看這個對象:文件路徑:/frameworks/native/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
Composer::Composer(const std::string& serviceName)
: mWriter(kWriterInitialSize),
mIsUsingVrComposer(serviceName == std::string("vr"))
{
mComposer = V2_1::IComposer::getService(serviceName);
if (mComposer == nullptr) {
LOG_ALWAYS_FATAL("failed to get hwcomposer service");
}
mComposer->createClient(
[&](const auto& tmpError, const auto& tmpClient)
{
if (tmpError == Error::NONE) {
mClient = tmpClient;
}
});
if (mClient == nullptr) {
LOG_ALWAYS_FATAL("failed to create composer client");
}
// 2.2 support is optional
sp<IComposer> composer_2_2 = IComposer::castFrom(mComposer);
if (composer_2_2 != nullptr) {
mClient_2_2 = IComposerClient::castFrom(mClient);
LOG_ALWAYS_FATAL_IF(mClient_2_2 == nullptr, "IComposer 2.2 did not return IComposerClient 2.2");
}
if (mIsUsingVrComposer) {
sp<IVrComposerClient> vrClient = IVrComposerClient::castFrom(mClient);
if (vrClient == nullptr) {
LOG_ALWAYS_FATAL("failed to create vr composer client");
}
}
}
能看到Composer對象中又會持有一個mComposer對象。這個對象可以暫且理解類似爲Binder,從抽象層(hal)服務端傳送過來的IComposer接口對象。之後所有要和硬件層進行交互,只需要操作這個IComposer對象即可。接着調用IComposer的createClient創建開一個Client對象。如果裏面有2.2版本的IComposer對象則會把2.1版本的IComposer轉化過去,這樣軟件層Composer就和硬件抽象層的Composer對應起來,等待HWComposer的操作。
4.8.1 HWComposer初始化
HWComposer::HWComposer(std::unique_ptr<android::Hwc2::Composer> composer)
: mHwcDevice(std::make_unique<HWC2::Device>(std::move(composer))) {
}
初始化一個HWC2::Device對象,hal層的對應的對象。
4.8.2 HWComposer監聽
//監聽
getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId);
註冊SF的監聽到HWC中。
文件路徑:/frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
void HWComposer::registerCallback(HWC2::ComposerCallback* callback,
int32_t sequenceId) {
mHwcDevice->registerCallback(callback, sequenceId);
}
繼續,文件路徑:/frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.cpp
void Device::registerCallback(ComposerCallback* callback, int32_t sequenceId) {
if (mRegisteredCallback) {
ALOGW("Callback already registered. Ignored extra registration "
"attempt.");
return;
}
mRegisteredCallback = true;
sp<ComposerCallbackBridge> callbackBridge(
new ComposerCallbackBridge(callback, sequenceId));
mComposer->registerCallback(callbackBridge);
}
能看到HWC會藉助一callbackBridge對象把對象註冊到hal層中進行監聽…
4.8 Surfaceflinger的run