最近有些忙,切實體驗了一把拖更的羞恥感 ( *︾▽︾)java
本文和上一篇深刻Android系統(十二)Android圖形顯示系統-1-顯示原理與Surface關係比較密切,擼完前篇更易理解本文啦 (๑‾ ꇴ ‾๑)android
瞭解SurfaceFlinger
以前咱們須要先了解下OpenGL
相關的一些知識git
OpenGL ES
與EGL
OpenGL
通常OpenGL
被認爲是一個API
(Application Programming Interface, 應用程序編程接口),包含了一系列能夠操做圖形、圖像的函數。然而,OpenGL
自己並非一個API,它僅僅是一個由Khronos
組織制定並維護的規範(Specification)。github
OpenGL規範
嚴格規定了每一個函數該如何執行,以及它們的輸出值。至於內部具體每一個函數是如何實現的,將由OpenGL
庫的開發者自行決定算法
實際的OpenGL
庫的開發者一般是顯卡的生產商編程
OpenGL ES(OpenGL for Embedded Systems)
是從OpenGL
裁剪的定製而來的,去除了一些複雜圖元等許多非絕對必要的特性markdown
OpenGL
仍是很值得學習的,你們能夠參考:LearnOpenGL教程的中文翻譯app
EGL
咱們知道OpenGL ES
定義了一個渲染圖形的API
,但沒有定義窗口系統。異步
爲了讓OpenGL ES
可以適合各類平臺,OpenGL ES
須要與一個知道如何經過操做系統建立和訪問窗口的庫結合使用socket
在Android
中的這個庫就是EGL
。(沒有什麼問題是不能經過增長一箇中間層來解決的,有的話那就再增長一個。。。。。)
總體結構以下(網上盜圖):
EGL
的用法使用EGL
繪製的通常步驟以下:
Android
中的封裝前面的章節咱們介紹過,不管開發者使用什麼渲染API,一切內容都會渲染到Surface
上
Surface
指的是framework/native/libs/gui/Surface.cpp
對應的業務邏輯當SurfaceFlinger
以消費者的角色獲取到顯示數據後,會開始進行渲染操做,在過程當中也存在一個Surface
framework/native/services/surfaceflinger/RenderEngine/Surface.cpp
Surface
即是對EGL
接口的調用封裝,咱們看下這個類的定義: Surface::Surface(const RenderEngine& engine)
: mEGLDisplay(engine.getEGLDisplay()), mEGLConfig(engine.getEGLConfig()) {
...
}
Surface::~Surface() {
setNativeWindow(nullptr);
}
void Surface::setNativeWindow(ANativeWindow* window) {
...
if (mWindow) {
mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mWindow, nullptr);
}
}
void Surface::swapBuffers() const {
if (!eglSwapBuffers(mEGLDisplay, mEGLSurface)) {
...
}
}
EGLint Surface::queryConfig(EGLint attrib) const {
EGLint value;
if (!eglGetConfigAttrib(mEGLDisplay, mEGLConfig, attrib, &value)) {
value = 0;
}
return value;
}
EGLint Surface::querySurface(EGLint attrib) const {
EGLint value;
if (!eglQuerySurface(mEGLDisplay, mEGLSurface, attrib, &value)) {
value = 0;
}
return value;
}
複製代碼
接口定義結合上面EGL
的知識應該很容易理解,下面咱們開始SurfaceFlinger
學習吧
SurfaceFlinger
的啓動過程從Android 4.4
開始SurfaceFlinger
服務運行在一個獨立的守護進程中(之前在SystemServer
中),這樣系統的圖像繪製性能會獲得必定的提高。frameworks/native/services/surfaceflinger/surfaceflinger.rc
中關於SurfaceFlinger
的定義以下:
service surfaceflinger /system/bin/surfaceflinger
class core animation user system group graphics drmrpc readproc onrestart restart zygote ... 複製代碼
能夠看到surfaceflinger
放到了core
組裏,這個組的服務會在系統初始化時啓動。SurfaceFlinger
啓動的入口函數main()
代碼以下:
int main(int, char**) {
...
// 啓動 Gralloc 服務
startGraphicsAllocatorService();
// 設置當前Binder服務可鏈接最大線程數
ProcessState::self()->setThreadPoolMaxThreadCount(4);
// 經過 startThreadPool 通知 Binder 驅動當前線程已準備完成
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
// 初始化 SurfaceFlinger
sp<SurfaceFlinger> flinger = new SurfaceFlinger();
// 調整進程優先級爲 PRIORITY_URGENT_DISPLAY
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
// 調整調度策略,將其設置爲前臺進程
// 這兩種標誌涉及了內核的 徹底公平調度算法,感興趣的同窗能夠百度一下
// 在這裏的目的是保證 SurfaceFlinger 的較高優先級,方便快速響應更新圖像的請求
set_sched_policy(0, SP_FOREGROUND);
...
// 註冊 Service 前的初始化部分
flinger->init();
// 註冊 SurfaceFlinger 服務
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
// 註冊 GpuService 服務
sp<GpuService> gpuservice = new GpuService();
sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
// 啓動 DisplayService 服務
startDisplayService(); // dependency on SF getting registered above
...
// run surface flinger in this thread
flinger->run();
return 0;
}
複製代碼
main()
方法中註釋比較詳細就不細說了,方法總結下來有三點:
GraphicsAllocatorService
、DisplayService
和GpuService
服務set_sched_policy
和sched_setscheduler
設置進程優先級SurfaceFlinger
對象的初始化以及init
和run
方法的調用SurfaceFlinger
的初始化過程設計的模塊比較多,咱們先簡單看下類關係圖:
SurfaceFlinger
對象初始化SurfaceFlinger
的類定義以下:
class SurfaceFlinger : public BnSurfaceComposer,
public PriorityDumper,
private IBinder::DeathRecipient,
private HWC2::ComposerCallback
{}
複製代碼
BnSurfaceComposer
類:類圖中該類實現的是ISurfaceComposer
接口,而ISurfaceComposer
又是一套定義好的Binder
類
Binder
篇提到過,當出現Bn*
開頭的類就能夠把它看作Binder服務類
了,因此SurfaceFlinger
這裏是做爲一個Binder
服務對象SurfaceSession
初始化時,SurfaceComposerClient
對象就是經過ServiceManager
獲取了SurfaceFlinger
服務createConnection()
方法獲取了ISurfaceComposerClient
對象,也就是上面類圖中提到的Client
類HWC2::ComposerCallback
類:面向底層硬件狀態的監聽回調接口,包括
onHotplugReceived
,顯示屏熱插拔事件回調onRefreshReceived
,通知刷新的回調onVsyncReceived
,VSYNC
信號接收回調SurfaceFlinger
的構造方法以下:
SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) {
ALOGI("SurfaceFlinger is starting");
// 初始化 vsync 信號相關的 offset
vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
sfVsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::vsyncSfEventPhaseOffsetNs>(1000000);
...
// 確認主屏幕方向
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;
...
}
// 初始化主屏幕的 DispSync 對象,這個對象與 vsync 信號分發有關係
mPrimaryDispSync.init(SurfaceFlinger::hasSyncFramework, SurfaceFlinger::dispSyncPresentTimeOffset);
...
// 讀取 Prop 進行一些基礎屬性的設置
// 是否啓動 HWC 虛擬顯示
property_get("debug.sf.enable_hwc_vds", value, "0");
mUseHwcVirtualDisplays = atoi(value);
// 是否開啓三級緩衝
property_get("ro.sf.disable_triple_buffer", value, "1");
mLayerTripleBufferingDisabled = atoi(value);
...
}
複製代碼
構造方法中主要的動做是mPrimaryDispSync.init()
操做,餘下基本都是對一些變量的初始化。mPrimaryDispSync
的類型是DispSync
,這個對象主要是對VSYNC
信號進行調整,而後轉發給app
或sf
,等下完善。
隨着SurfaceFlinger
對象建立後的初次引用,也會調用到對象的onFirstRef()
方法:
void SurfaceFlinger::onFirstRef() {
mEventQueue->init(this);
}
複製代碼
方法中執行了MessageQueue
對象的init()
方法,這個MessageQueue
是SurfaceFlinger
本身定義的消息隊列,MessageQueue
相關的知識對整個SurfaceFlinger
業務邏輯的理解有着關鍵做用,下面細講
瞭解這部分的內容有助於更好的理解
SurfaceFlinger
後面的init()
和run()
方法
MessageQueue
MessageQueue
是SurfaceFlinger
中用與消息和事件分發的對象,先看下主要的成員變量:
class MessageQueue{
...
sp<SurfaceFlinger> mFlinger; // 指向 SurfaceFlinger 對象
sp<Looper> mLooper; // 實現消息機制的 Looper 對象
android::EventThread* mEventThread; // 關聯的 EventThread 對象
sp<IDisplayEventConnection> mEvents;
gui::BitTube mEventTube;
sp<Handler> mHandler; // 消息處理 Handler
...
}
複製代碼
MessageQueue
的成員變量中
mLooper
是一個指向Looper
類的指針,它實現了一套完整的消息處理機制mEventThread
指向一個EventThread
對象,主要做用是分發VSYNC
信號前面提到在SurfaceFlinger
中會調用MessageQueue
對象的init()
方法,代碼以下:
void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
mFlinger = flinger;
mLooper = new Looper(true);
mHandler = new Handler(*this);
}
複製代碼
init()
方法中
建立了Handler
對象。此處的Handler
是MessageQueue
中定義的一個內部類,定義以下:
class MessageQueue final : public android::MessageQueue {
class Handler : public MessageHandler {
enum { eventMaskInvalidate = 0x1, eventMaskRefresh = 0x2, eventMaskTransaction = 0x4 };
MessageQueue& mQueue;
int32_t mEventMask;
...
};
}
複製代碼
Handler
對象中主要處理三種消息:eventMaskInvalidate
、eventMaskRefresh
、eventMaskTransaction
建立了Looper
對象。關於native
層的Looper
對象在Android 消息機制
中已經介紹過,會經過epoll
開啓一個消息監聽,具體能夠看這個直達入口
init()
完成後,MessageQueue
就能夠經過waitMessage()
來等待消息,代碼以下:
void MessageQueue::waitMessage() {
do {
IPCThreadState::self()->flushCommands();
int32_t ret = mLooper->pollOnce(-1); // 嘗試讀取消息,-1 表示永遠阻塞
switch (ret) {
case Looper::POLL_WAKE: // poll 被喚醒
case Looper::POLL_CALLBACK:
continue;
case Looper::POLL_ERROR: // poll 發送錯誤
ALOGE("Looper::POLL_ERROR");
continue;
case Looper::POLL_TIMEOUT: // poll 超時
// timeout (should not happen)
continue;
default:
// should not happen
ALOGE("Looper::pollOnce() returned unknown status %d", ret);
continue;
}
} while (true);
}
複製代碼
waitMessage()
是一個無限循環,它的主要做用是循環調用Looper
類的pollOnce()
從消息隊列中讀取消息
須要注意的是waitMessage()
中並無消息的處理過程,並且沒有明顯的消息處理方法的調用,那麼具體的消息處理在哪裏?
消息的處理涉及EventThread
類,在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);
}
複製代碼
setEventThread()
方法中
EventThread
對象的createEventConnection()
方法來建立一個鏈接
EventThread
是一個線程類,用於分發VSYNC
消息,EventThread
內部會維護一個gui::BitTube mChannel
用於通訊,建立過程以下:sp<BnDisplayEventConnection> EventThread::createEventConnection() const {
// 建立 Connection 對象,同時會調用它的 onFirstRef 方法
return new Connection(const_cast<EventThread*>(this));
}
// Connection 的構造方法,初始化 BitTube mChannel 對象,並設置 mEventThread
EventThread::Connection::Connection(EventThread* eventThread)
: count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {}
// Connection 對象的 onFirstRef 方法會將本身添加到 EventThread 中的 mDisplayEventConnections 中
void EventThread::Connection::onFirstRef() {
// NOTE: mEventThread doesn't hold a strong reference on us
mEventThread->registerDisplayEventConnection(this);
}
// 將 connection 對象添加到 mDisplayEventConnections 監聽集合中
status_t EventThread::registerDisplayEventConnection( const sp<EventThread::Connection>& connection) {
std::lock_guard<std::mutex> lock(mMutex);
// 添加到 mDisplayEventConnections 集合中
mDisplayEventConnections.add(connection);
mCondition.notify_all();
return NO_ERROR;
}
複製代碼
createEventConnection()
方法返回的是一個IDisplayEventConnection
對象mEvents
IDisplayEventConnection
對象的stealReceiveChannel()
方法
mEventTube
對象的mReceiveFd
,mEventTube
的類型是BitTube
BitTube
對象中包含一對Fd
:mReceiveFd
和mSendFd
,初始化時會經過socketpair()
建立全雙工通訊Looper
類的addFd()
方法將mReceiveFd
添加到epoll
監聽列表中,而且傳入了MessageQueue::cb_eventReceiver
做爲事件的回調方法
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;
}
複製代碼
mHandler->dispatchInvalidate();
方法,這就會涉及到Handler
的處理邏輯咱們看下Handler
中的處理邏輯:
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;
}
}
複製代碼
調用了SurfaceFlinger
的onMessageReceived()
方法,這裏纔是真正處理消息的地方,後面細講這個方法哈
咱們先看下EventThread
類
EventThread
EventThread
的繼承關係以下:
class EventThread : public android::EventThread, private VSyncSource::Callback {
}
複製代碼
須要注意的是VSyncSource::Callback
類,它提供了一個onVSyncEvent()
的回調方法
EventThread
的構造方法以下(精簡版):
EventThread::EventThread(...){
...
// 建立線程並開始執行,核心業務經過 threadMain() 方法來完成
mThread = std::thread(&EventThread::threadMain, this);
// 設置一些線程的名稱和優先級
pthread_setname_np(mThread.native_handle(), threadName);
...
// 設置調度策略爲 SP_FOREGROUND
set_sched_policy(tid, SP_FOREGROUND);
}
複製代碼
構造方法中啓動了一個線程,這個線程的執行邏輯在threadMain()
方法中:
void EventThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
std::unique_lock<std::mutex> lock(mMutex);
// mKeepRunning 只會在析構函數中置爲 false
while (mKeepRunning) {
DisplayEventReceiver::Event event;
Vector<sp<EventThread::Connection> > signalConnections;
// 經過 waitForEventLocked() 循環等待事件
// 方法中會經過 mCondition 對象的 wait() 方法進行等待
signalConnections = waitForEventLocked(&lock, &event);
const size_t count = signalConnections.size();
for (size_t i = 0; i < count; i++) {
const sp<Connection>& conn(signalConnections[i]);
// 經過 postEvent() 將事件通知到到 MessageQueue
status_t err = conn->postEvent(event);
...
}
}
}
複製代碼
threadMain()
方法中的重點是:
waitForEventLocked()
方法會循環等待消息(也就是VSYNC
信號),並獲取到註冊的Connection
對象列表Connection
對象的postEvent()
將數據發送到MessageQueue
MessageQueue
中的Looper
會檢測到數據輸入,而後通知回調MessageQueue
的cb_eventReceiver()
方法前面講過VSYNC
信號由HWC
產生,爲了方便接收,HWComposer
提供了一個HW2::ComposerCallback
用於監聽消息
class ComposerCallback {
public:
virtual void onHotplugReceived(...) = 0;
virtual void onRefreshReceived(...) = 0;
virtual void onVsyncReceived(...) = 0;
virtual ~ComposerCallback() = default;
};
複製代碼
SurfaceFlinger
繼承該類,咱們重點關注onVsyncReceived()
方法SurfaceFlinger::onVsyncReceived()
方法以下:
void SurfaceFlinger::onVsyncReceived(...) {
...
bool needsHwVsync = false;
{ // Scope for the lock
Mutex::Autolock _l(mHWVsyncLock);
if (type == DisplayDevice::DISPLAY_PRIMARY && mPrimaryHWVsyncEnabled) {
// 經過 addResyncSample 來進一步分發信號
needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
}
}
...
}
複製代碼
onVsyncReceived()
方法調用mPrimaryDispSync
對象的addResyncSample()
方法來進一步分發VSYNC
信號
mPrimaryDispSync
對象的類型是DispSync
,這個類比較簡單,核心是它的成員變量mThread
,類型是DispSyncThread
DispSyncThread
是一個線程類,在DispSync
對象初始化時進行建立,代碼以下: DispSync::DispSync(const char* name)
: mName(name), mRefreshSkipCount(0), mThread(new DispSyncThread(name)) {}
複製代碼
SurfaceFlinger
的構造方法中會調用DispSync
對象的init()
進行DispSyncThread
線程的啓動 void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) {
...
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
...
}
複製代碼
addResyncSample()
方法中最重要的是執行了DispSyncThread
對象的updateModel()
方法:
void updateModel(nsecs_t period, nsecs_t phase, nsecs_t referenceTime) {
... // 省略和 VSYNC 信號相關的一些賦值操做
// 重點是此處經過 Conditon.signal() 來喚醒 DispSyncThread 線程
mCond.signal();
}
複製代碼
DispSyncThread
線程的執行函數以下:
virtual bool threadLoop() {
...
while (true) {
Vector<CallbackInvocation> callbackInvocations;
nsecs_t targetTime = 0;
{ // Scope for lock
...
if (now < targetTime) {
if (targetTime == INT64_MAX) {
err = mCond.wait(mMutex);
} else {
err = mCond.waitRelative(mMutex, targetTime - now);
}
...
}
now = systemTime(SYSTEM_TIME_MONOTONIC);
...
// 取得 Callback 列表
callbackInvocations = gatherCallbackInvocationsLocked(now);
}
// 經過 fireCallbackInvocations() 調用
if (callbackInvocations.size() > 0) {
fireCallbackInvocations(callbackInvocations);
}
}
return false;
}
複製代碼
threadLoop()
中大部分是比較和計算時間,決定是否要發送信號
mCond
上等待
updateModel()
中須要調用mCond
的signal()
來喚醒的緣由gatherCallbackInvocationsLocked()
獲取本次VSYNC
信號回調通知的監聽對象
addEventListener()
方法進行添加fireCallbackInvocations()
方法一次調用列表中全部對象的onDispSyncEvent()
方法 void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
if (kTraceDetailedInfo) ATRACE_CALL();
for (size_t i = 0; i < callbacks.size(); i++) {
callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
}
}
複製代碼
CallbackInvocation
結構就會發現,回調接口的類型是DispSync::Callback
那麼SurfaceFlinger
中哪幾個類實現了DispSync::Callback
呢?
聰明的咱們會發現,SurfaceFlinger
中的DispSyncSource
繼承了這個類,並且重點是下面部分的代碼:
class DispSyncSource final : public VSyncSource, private DispSync::Callback {
public:
...
void setVSyncEnabled(bool enable) override {
Mutex::Autolock lock(mVsyncMutex);
if (enable) {
status_t err = mDispSync->addEventListener(mName, mPhaseOffset, static_cast<DispSync::Callback*>(this));
...
} else {
status_t err = mDispSync->removeEventListener(static_cast<DispSync::Callback*>(this));
...
}
mEnabled = enable;
}
...
private:
virtual void onDispSyncEvent(nsecs_t when) {
VSyncSource::Callback* callback;
... // 省略 VSYNC 信號處理的一些操做
callback = mCallback;
if (callback != nullptr) {
callback->onVSyncEvent(when);
}
}
...
}
複製代碼
能夠發現:
DispSyncSource
對象的setVSyncEnabled()
方法時會註冊DispSync
的事件監聽onDispSyncEvent()
方法中最終調用了VSyncSource::Callback
對象的onVSyncEvent()
方法VSyncSource::Callback
對象又是和誰關聯呢?
還記得前面的EventThread
麼!!!EventThread
即是繼承了VSyncSource::Callback
類,咱們看下EventThread
中關於onVSyncEvent()
方法的實現:
void EventThread::onVSyncEvent(nsecs_t timestamp) {
std::lock_guard<std::mutex> lock(mMutex);
mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
mVSyncEvent[0].header.id = 0;
mVSyncEvent[0].header.timestamp = timestamp;
mVSyncEvent[0].vsync.count++;
mCondition.notify_all();
}
複製代碼
前面EventThread
部分提到過
threadMain
中的waitForEventLocked()
會經過mCondition.wait()
等待消息,onVSyncEvent()
會經過notify_all()
喚醒threadMain
處理消息conn->postEvent(event);
方法postEvent()
方法會經過BitTube
對象將數據發送到MessageQueue
中MessageQueue
的cb_eventReceiver()
方法前面MessageQueue
章節提到過,cb_eventReceiver()
方法最後會調用的是SurfaceFlinger
的onMessageReceived()
方法,並且消息類型是INVALIDATE
。
咱們看下方法內容:
void SurfaceFlinger::onMessageReceived(int32_t what) {
switch (what) {
case MessageQueue::INVALIDATE: {
...
bool refreshNeeded = handleMessageTransaction();
...
break;
}
case MessageQueue::REFRESH: {
handleMessageRefresh();
break;
}
}
}
複製代碼
INVALIDATE
消息的處理邏輯比較複雜,咱們重點關注的是handleMessageTransaction()
方法,它會建立DisplayDevice
對象。咱們先看下DisplayDevice
對象
DisplayDevice
DisplayDevice
類是顯示設備的抽象,當前Android 9
中定義了3種顯示設備類型:
DISPLAY_PRIMARY
:主顯示設備DISPLAY_EXTERNAL
:擴展顯示設備,經過HDMI
輸出的顯示信號DISPLAY_VIRTUAL
:虛擬顯示設備,經過WIFI
輸出的顯示信號這三種顯示設備,第一種是基本配置,另外兩種須要硬件支持。關於Display
官網有個極其簡單的介紹:傳送門
在SurfaceFlinger
中DisplayDevice
負責與OpenGL ES
交互,即便沒有任何物理顯示設備被檢測到,SurfaceFlinger
都須要一個DisplayDevice
對象才能正常工做
SurfaceFlinger
將須要顯示的圖層Layer
經過DisplayDevice
對象傳遞到OpenGL ES
中進行合成,合成後再經過HWComposer
對象傳送到FrameBuffer
中顯示
DisplayDevice
對象中的成員變量Vector< sp<Layer> > mVisibleLayersSortedByZ;
保存了全部須要在本設備中顯示的Layer
對象
DisplayDevice
比較複雜,先簡單瞭解下它的建立流程。前面提到了handleMessageTransaction()
方法中會建立DisplayDevice
對象,咱們看下具體的建立流程:
handleMessageTransaction()
-->handleTransactionLocked()
-->processDisplayChangesLocked()
void SurfaceFlinger::processDisplayChangesLocked() {
...
if (!curr.isIdenticalTo(draw)) {
...
for (size_t i = 0; i < cc; i++) {
if (draw.indexOfKey(curr.keyAt(i)) < 0) {
const DisplayDeviceState& state(curr[i]);
sp<DisplaySurface> dispSurface;
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferProducer> bqProducer;
sp<IGraphicBufferConsumer> bqConsumer;
// mCreateBufferQueue是一個函數指針,指向的是 BufferQueue::createBufferQueue
// 這就很熟悉了,和咱們前面分析 Surface 時建立的 BufferQueue 同樣
mCreateBufferQueue(&bqProducer, &bqConsumer, false);
int32_t hwcId = -1;
if (state.isVirtualDisplay()) {
... // 省略虛擬屏幕建立的邏輯
} else {
...
hwcId = state.type;
// 建立 FramebufferSurface 用於數據傳輸
dispSurface = new FramebufferSurface(*getBE().mHwc, hwcId, bqConsumer);
producer = bqProducer;
}
const wp<IBinder>& display(curr.keyAt(i));
if (dispSurface != nullptr) {
// 經過 setupNewDisplayDeviceInternal() 建立 DisplayDevice 對象
// 並添加到 mDisplays 集合中
mDisplays.add(display, setupNewDisplayDeviceInternal(display, hwcId, state, dispSurface, producer));
if (!state.isVirtualDisplay()) {
mEventThread->onHotplugReceived(state.type, true);
}
}
}
}
}
mDrawingState.displays = mCurrentState.displays;
}
複製代碼
BufferQueue::createBufferQueue
建立了consumer
和producer
對象(這部分和前面講的BufferQueue
的邏輯是相同的)consumer
對象和一個HWComposer
對象建立了一個FramebufferSurface
對象setupNewDisplayDeviceInternal()
方法建立DisplayDevice
對象,並添加到mDisplays
集合中sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( const wp<IBinder>& display, int hwcId, const DisplayDeviceState& state, const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) {
...
// mCreateNativeWindowSurface 也是一個函數指針,執行的是 NativeWindowSurface::create() 方法
// 該方法利用 IGraphicBufferProducer 生成 NativeWindowSurface 和 NativeWindow 對象
// 其實也是 EGL 相關的接口調用
auto nativeWindowSurface = mCreateNativeWindowSurface(producer);
auto nativeWindow = nativeWindowSurface->getNativeWindow();
// 經過渲染引擎建立 OpenGL 渲染的目標 EGLSurface
std::unique_ptr<RE::Surface> renderSurface = getRenderEngine().createSurface();
renderSurface->setCritical(state.type == DisplayDevice::DISPLAY_PRIMARY);
renderSurface->setAsync(state.type >= DisplayDevice::DISPLAY_VIRTUAL);
// 執行 eglCreateWindowSurface 操做
renderSurface->setNativeWindow(nativeWindow.get());
...
// 建立 DisplayDevice 對象
sp<DisplayDevice> hw = new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow,
dispSurface, std::move(renderSurface), displayWidth, displayHeight,
hasWideColorGamut, hdrCapabilities,
supportedPerFrameMetadata, hwcColorModes, initialPowerMode);
...
return hw;
}
複製代碼
DisplayDevice
對象建立完成,意味着SurfaceFlinger
就能夠利用DisplayDevice
對象寫入圖像數據,並經過
這樣一條路徑到達顯示設備的FrameBuffer
中
SurfaceFlinger
的init()
和run()
有了前面的鋪墊知識,init()
和run()
就很好理解了
SurfaceFlinger::init
void SurfaceFlinger::init() {
// 建立 app 的 DispSyncSource 和 EventThread
mEventThreadSource = std::make_unique<DispSyncSource>(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
mEventThread = std::make_unique<impl::EventThread>(mEventThreadSource.get(), ..., "appEventThread");
// 建立 sf 的 DispSyncSource 和 EventThread
mSfEventThreadSource = std::make_unique<DispSyncSource>(&mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = std::make_unique<impl::EventThread>(mSfEventThreadSource.get(), ..., "sfEventThread");
// 將 mSFEventThread 與 MessageQueue 進行關聯
mEventQueue->setEventThread(mSFEventThread.get());
// 將 mSFEventThread 和 mEventThread 添加到 VSYNC 信號調製器中
mVsyncModulator.setEventThreads(mSFEventThread.get(), mEventThread.get());
// 建立渲染引擎,主要是選擇EGL配置,選擇OpenGL版本,建立OpenGL上下文
getBE().mRenderEngine = RE::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,...);
...
// 初始化 HWC
getBE().mHwc.reset( new HWComposer(std::make_unique<Hwc2::impl::Composer>(getBE().mHwcServiceName)));
// 註冊 HWC 的 Callback 監聽
// VSYNC 信號便會從這裏進行回調通知
getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId);
...
// 建立 VSYNC 事件接收控制對象,enable=true 表示容許 HWC 產生 VSYNC 信號
// sufacefinlger 經過這個對象來控制 HWC 是否產生 VSYNC 信號
mEventControlThread = std::make_unique<impl::EventControlThread>([this](bool enabled) { setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled); });
...
// 該方法會經過 MessageQueue 發送一個異步消息
// 消息處理中會完成 primary DisplayDevice 的建立,並進行 VSYNC 週期的設定
initializeDisplays();
...
// 根據 PresentFenceIsNotReliable 屬性建立 StartPropertySetThread對象
if (getHwComposer().hasCapability(HWC2::Capability::PresentFenceIsNotReliable)) {
mStartPropertySetThread = new StartPropertySetThread(false);
} else {
mStartPropertySetThread = new StartPropertySetThread(true);
}
// 執行 StartPropertySetThread,該線程會經過 setProp 觸發開機動畫,包括設置如下兩個Prop
// property_set("service.bootanim.exit", "0"); 復位動畫退出標記
// property_set("ctl.start", "bootanim"); 啓動開機動畫
if (mStartPropertySetThread->Start() != NO_ERROR) {
ALOGE("Run StartPropertySetThread failed!");
}
...
ALOGV("Done initializing");
}
複製代碼
init()
方法初始化了不少重要的對象:
app
和sf
兩組DispSyncSource
和EventThread
對象
VSYNC
信號的兩個消費者:App
和SurfaceFlinger
sf
對應的信號分發邏輯與鋪墊知識中的一致,由於是經過mEventQueue->setEventThread()
來進行的關聯app
的信號分發邏輯等下細看HWComposer
,並經過registerCallback()
註冊HWC2::ComposerCallback
監聽EventControlThread
對象,SurfaceFlinger
用這個對象來控制HWC
是否須要產生VSYNC
信號
VSYNC
信號StartPropertySetThread
線程,該線程會經過setProp
的方式觸發開機動畫SurfaceFlinger::run
run()
方法比較簡單:
void SurfaceFlinger::run() {
do {
waitForEvent();
} while (true);
}
複製代碼
方法中執行了一個無限循環來調用waitForEvent()
,具體代碼以下:
void SurfaceFlinger::waitForEvent() {
mEventQueue->waitMessage();
}
複製代碼
waitForEvent()
方法又調用了MessageQueue
對象的waitMessage()
方法進入一個無限循環,這個方法在MessageQueue
部分中已經介紹過就不細講啦
因此對於
SurfaceFlinger
進程來講,執行完run()
當前線程就會進入一個無限循環,剩下的業務處理都變成了消息驅動來實現
App
的繪製通知在SurfaceFlinger
的init()
方法中初始化了一個appEventThread
,在接收到VSYNC
信號後,它便會通知到App
去進行繪製操做,咱們看下這個通知流程
onResume()
咱們已經知道,onResume()
方法後纔會進行View
的顯示,這部分體如今ActivityThread
中的handleResumeActivity()
方法中,代碼以下:
public void handleResumeActivity(...) {
...
// TODO Push resumeArgs into the activity for consideration
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
if (r == null) {
// We didn't actually resume the activity, so skipping any follow-up actions.
return;
}
final Activity a = r.activity;
...
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
...
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
} else {
a.onWindowAttributesChanged(l);
}
}
}
...
}
複製代碼
上面performResumeActivity()
會回調應用程序的onResume()
函數。不過本次咱們重點關注的是wm.addView()
方法,最後調用到的是WindowManagerGlobal.java
的addView()
,代碼以下:
public void addView(...) {
...
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
...
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
複製代碼
重點是初始化了ViewRootImpl
對象,咱們看下ViewRootImpl
中的setView()
方法的調用:
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
...
requestLayout();
...
}
}
}
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
複製代碼
執行到scheduleTraversals()
方法就引出來一個最重要的類Choreographer
,整個應用佈局的渲染依賴這個對象的發動。
在scheduleTraversals()
方法中調用了mChoreographer
對象的postCallback()
方法添加了一個回調對象mTraversalRunnable
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
複製代碼
mTraversalRunnable
回調對象的定義以下:
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
複製代碼
doTraversal
內部會調用大名鼎鼎的performTraversal()
方法,到這裏App
就能夠進行measure/layout/draw
三大流程
那麼 mTraversalRunnable
對象是在何時調用的呢?
咱們帶着疑問,先看下應用是如何接收VSYNC
信號的
Choreographer
類App
要求渲染動畫或者更新畫面佈局時都會用到Choreographer
,接收VSYNC
信號也依賴於Choreographer
在上面的scheduleTraversals()
方法中執行了Choreographer
對象的postCallback()
方法
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
複製代碼
這個方法的含義就是應用程序請求VSYNC
信號,接收到VSYNC
信號後執行mTraversalRunnable
回調
那麼接下來咱們看下Choreographer
如何接收vsync
信號
DisplayEventReceiver
類應用層能夠經過
DisplayEventReceiver
類用來接收vsync
信號,當接收到vsync
信號後,會執行DisplayEventReceiver
對象的onVsync()
方法
DisplayEventReceiver
是在Android
的View
體系中定義的一個抽象類,對外隱藏的,核心定義以下
public abstract class DisplayEventReceiver {
...
// 用來表示 APP 的 VSYNC 信號源
public static final int VSYNC_SOURCE_APP = 0;
public DisplayEventReceiver(Looper looper) {
this(looper, VSYNC_SOURCE_APP);
}
public DisplayEventReceiver(Looper looper, int vsyncSource) {
...
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
vsyncSource);
...
}
private static native long nativeInit(WeakReference<DisplayEventReceiver> receiver, MessageQueue messageQueue, int vsyncSource);
private static native void nativeDispose(long receiverPtr);
private static native void nativeScheduleVsync(long receiverPtr);
...
public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
}
...
}
複製代碼
須要關注的是
native
方法nativeInit()
來進行初始化操做onVsync()
方法的空實現,當接收到VSYNC
信號後便會調用該方法先看下nativeInit()
的實現
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject messageQueueObj, jint vsyncSource) {
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
...
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
receiverWeak, messageQueue, vsyncSource);
status_t status = receiver->initialize();
...
}
複製代碼
nativeInit()
方法建立了一個NativeDisplayEventReceiver
對象,並調用了它的initialize()
方法
NativeDisplayEventReceiver
繼承了DisplayEventDispatcher
類,那麼咱們的重點即是DisplayEventDispatcher
,頭文件定義以下:
class DisplayEventDispatcher : public LooperCallback {
public:
DisplayEventDispatcher(const sp<Looper>& looper,
ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp);
status_t initialize();
...
private:
sp<Looper> mLooper;
DisplayEventReceiver mReceiver;
...
};
複製代碼
核心實現以下:
DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
ISurfaceComposer::VsyncSource vsyncSource) :
mLooper(looper), mReceiver(vsyncSource), mWaitingForVsync(false) {
ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}
status_t DisplayEventDispatcher::initialize() {
status_t result = mReceiver.initCheck();
...
int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
this, NULL);
if (rc < 0) {
return UNKNOWN_ERROR;
}
return OK;
}
複製代碼
在鋪墊知識部分已經瞭解到,若是應用要接收
VSYNC
信號,須要將其添加到對應的EventThread
中,SF
中一共建立了兩個
mSFEventThread
是SurfaceFlinger
專用的
- 在
SurfaceFlinger
的init()
中經過mEventQueue->setEventThread()
進行關聯setEventThread()
在鋪墊部分也介紹過(鋪墊內容-消息和事件分發)mEventThread
用來通知App
的
咱們知道mEventQueue->setEventThread()
關聯VSYNC
信號的過程主要分爲了兩步:
對比DisplayEventDispatcher
中咱們會發現
DisplayEventDispatcher
的initialize()
中作了一個mLooper->addFd()
操做
Looper
類的addFd()
方法是將mReceiveFd
添加到epoll
監聽列表DisplayEventDispatcher
中包含一個native
層的DisplayEventReceiver
對象mReceiver
native
層的DisplayEventReceiver
便封裝了建立鏈接
的過程,咱們須要關注的是構造方法部分DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != NULL) {
// createDisplayEventConnection 方法便會調用 mEventThread->createEventConnection() 來建立鏈接
// 而 mEventThread 即是 App 的 VSYNC 分發線程
mEventConnection = sf->createDisplayEventConnection(vsyncSource);
if (mEventConnection != NULL) {
mDataChannel = std::make_unique<gui::BitTube>();
mEventConnection->stealReceiveChannel(mDataChannel.get());
}
}
}
複製代碼
到這裏,DisplayEventReceiver
便和SurfaceFlinger
中的mEventThread
創建了聯繫,當VSYNC
信號產生後,SurfaceFlinger
便會經過mEventThread
通知到DisplayEventReceiver
VSYNC 分發過程已經介紹過了,能夠看這裏
FrameDisplayEventReceiver
類DisplayEventReceiver
是一個抽象類,FrameDisplayEventReceiver
即是這個類的具體實現,在Choreographer
中定義,代碼以下:
private final class FrameDisplayEventReceiver extends DisplayEventReceiver implements Runnable {
private boolean mHavePendingVsync;
private long mTimestampNanos;
private int mFrame;
public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
super(looper, vsyncSource);
}
@Override
public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
// vsync 信號分發時便會回調到這裏
...
mTimestampNanos = timestampNanos;
mFrame = frame;
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
// 這裏發了一個消息,此處並未主動設置 msg.what,默認值應爲 0
// 0 對應的數值爲 MSG_DO_FRAME
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
@Override
public void run() {
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame);
}
}
複製代碼
上面onVsync
會往消息隊列放一個消息,經過下面的FrameHandler
進行處理:
private final class FrameHandler extends Handler {
public FrameHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_DO_FRAME:
doFrame(System.nanoTime(), 0);
break;
case MSG_DO_SCHEDULE_VSYNC:
doScheduleVsync();
break;
case MSG_DO_SCHEDULE_CALLBACK:
doScheduleCallback(msg.arg1);
break;
}
}
}
複製代碼
對於MSG_DO_FRAME
消息,會執行doFrame()
方法,關鍵代碼以下:
void doFrame(long frameTimeNanos, int frame) {
...
mFrameInfo.markInputHandlingStart();
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
mFrameInfo.markAnimationsStart();
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
mFrameInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
...
}
複製代碼
doFrame()
方法經過doCallbacks()
執行了各類類型的Callback
,分爲4類:
CALLBACK_INPUT
: 處理輸入事件處理有關CALLBACK_ANIMATION
: 處理Animation
的處理有關CALLBACK_TRAVERSAL
: 處理和UI
等控件繪製有關CALLBACK_COMMIT
: 處理Commit
相關回調須要注意的是CALLBACK_TRAVERSAL
類型的doCallbacks()
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
複製代碼
這個方法便會執行前面在scheduleTraversals()
方法中添加的mTraversalRunnable
回調。而因爲CALLBACK_INPUT
、CALLBACK_ANIMATION
會修改View
的屬性,因此要先於CALLBACK_TRAVERSAL
執行
狡辯ING:剛接手新平臺比較忙,致使原本清明節計劃學習的章節一直拖到如今,好在磕磕絆絆的學習完了
SurfaceFlinger
這部分涉及的知識不少,很遺憾深刻Android系統(十二)Android圖形顯示系統
系列也僅僅只是記錄一些基礎知識。
View
的繪製部分也並未展開學習,考慮到後面的章節,等了解完整個Android
系統知識後再來補充吧(挖坑ING.....)
最後祝各位同窗五一快樂,你們在求知的道路上一塊兒加油喲 <( ̄︶ ̄)↗[GO!]
下一篇深刻Android系統(十三)Android的窗口系統