深刻Android系統(十二)Android圖形顯示系統-2-SurfaceFlinger與圖像輸出

最近有些忙,切實體驗了一把拖更的羞恥感 ( *︾▽︾)java

本文和上一篇深刻Android系統(十二)Android圖形顯示系統-1-顯示原理與Surface關係比較密切,擼完前篇更易理解本文啦 (๑‾ ꇴ ‾๑)android

瞭解SurfaceFlinger以前咱們須要先了解下OpenGL相關的一些知識git

OpenGL ESEGL

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。(沒有什麼問題是不能經過增長一箇中間層來解決的,有的話那就再增長一個。。。。。)

總體結構以下(網上盜圖): image

EGL的用法

使用EGL繪製的通常步驟以下:

  • 獲取 EGL Display 對象:eglGetDisplay()
  • 初始化與 EGLDisplay 之間的鏈接:eglInitialize()
  • 獲取 EGLConfig 對象:eglChooseConfig()
  • 建立 EGLContext 實例:eglCreateContext()
  • 建立 EGLSurface 實例:eglCreateWindowSurface()
  • 鏈接 EGLContext 和 EGLSurface:eglMakeCurrent()
  • 使用 OpenGL ES API 繪製圖形:gl_*()
  • 切換 front buffer 和 back buffer 送顯:eglSwapBuffer()
  • 斷開並釋放與 EGLSurface 關聯的 EGLContext 對象:eglRelease()
  • 刪除 EGLSurface 對象
  • 刪除 EGLContext 對象
  • 終止與 EGLDisplay 之間的鏈接

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()方法中註釋比較詳細就不細說了,方法總結下來有三點:

  • 初始化GraphicsAllocatorServiceDisplayServiceGpuService服務
  • set_sched_policysched_setscheduler設置進程優先級
  • SurfaceFlinger對象的初始化以及initrun方法的調用

SurfaceFlinger的初始化過程設計的模塊比較多,咱們先簡單看下類關係圖:
image

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,通知刷新的回調
    • onVsyncReceivedVSYNC信號接收回調

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信號進行調整,而後轉發給appsf,等下完善。

隨着SurfaceFlinger對象建立後的初次引用,也會調用到對象的onFirstRef()方法:

void SurfaceFlinger::onFirstRef() {
    mEventQueue->init(this);
}
複製代碼

方法中執行了MessageQueue對象的init()方法,這個MessageQueueSurfaceFlinger本身定義的消息隊列,MessageQueue相關的知識對整個SurfaceFlinger業務邏輯的理解有着關鍵做用,下面細講

鋪墊內容

瞭解這部分的內容有助於更好的理解SurfaceFlinger後面的init()run()方法

消息和事件分發-MessageQueue

MessageQueueSurfaceFlinger中用與消息和事件分發的對象,先看下主要的成員變量:

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對象。此處的HandlerMessageQueue中定義的一個內部類,定義以下:

    class MessageQueue final : public android::MessageQueue {
        class Handler : public MessageHandler {
            enum { eventMaskInvalidate = 0x1, eventMaskRefresh = 0x2, eventMaskTransaction = 0x4 };
            MessageQueue& mQueue;
            int32_t mEventMask;
        ...
        };
    }
    複製代碼
    • Handler對象中主要處理三種消息:eventMaskInvalidateeventMaskRefresheventMaskTransaction
  • 建立了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對象的mReceiveFdmEventTube的類型是BitTube
    • BitTube對象中包含一對FdmReceiveFdmSendFd,初始化時會經過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;
    }
}
複製代碼

調用了SurfaceFlingeronMessageReceived()方法,這裏纔是真正處理消息的地方,後面細講這個方法哈

咱們先看下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會檢測到數據輸入,而後通知回調MessageQueuecb_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()中須要調用mCondsignal()來喚醒的緣由
  • 當確認須要發送信號時,先經過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
  • 接下來便會觸發執行MessageQueuecb_eventReceiver()方法

前面MessageQueue章節提到過,cb_eventReceiver()方法最後會調用的是SurfaceFlingeronMessageReceived()方法,並且消息類型是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官網有個極其簡單的介紹:傳送門

SurfaceFlingerDisplayDevice負責與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建立了consumerproducer對象(這部分和前面講的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對象寫入圖像數據,並經過

  • EGLSurface-->BufferQueue-->FrameBufferSurface-->HWCComposer-->Gralloc

這樣一條路徑到達顯示設備的FrameBuffer

SurfaceFlingerinit()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()方法初始化了不少重要的對象:

  • 初始化appsf兩組DispSyncSourceEventThread對象
    • 這兩個分別表明了VSYNC信號的兩個消費者:AppSurfaceFlinger
    • 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的繪製通知

SurfaceFlingerinit()方法中初始化了一個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.javaaddView(),代碼以下:

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是在AndroidView體系中定義的一個抽象類,對外隱藏的,核心定義以下

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中一共建立了兩個

  • mSFEventThreadSurfaceFlinger專用的
  • mEventThread用來通知App

咱們知道mEventQueue->setEventThread()關聯VSYNC信號的過程主要分爲了兩步:

  • 建立鏈接
  • 註冊監聽

對比DisplayEventDispatcher中咱們會發現

  • DisplayEventDispatcherinitialize()中作了一個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_INPUTCALLBACK_ANIMATION會修改View的屬性,因此要先於CALLBACK_TRAVERSAL執行

結語

狡辯ING:剛接手新平臺比較忙,致使原本清明節計劃學習的章節一直拖到如今,好在磕磕絆絆的學習完了

SurfaceFlinger這部分涉及的知識不少,很遺憾深刻Android系統(十二)Android圖形顯示系統系列也僅僅只是記錄一些基礎知識。

View的繪製部分也並未展開學習,考慮到後面的章節,等了解完整個Android系統知識後再來補充吧(挖坑ING.....)

最後祝各位同窗五一快樂,你們在求知的道路上一塊兒加油喲 <( ̄︶ ̄)↗[GO!]

下一篇深刻Android系統(十三)Android的窗口系統

相關文章
相關標籤/搜索