Android 顯示系統:SurfaceFlinger詳解

1、Android系統啓動java

  Android設備從按下開機鍵到桌面顯示畫面,大體過程以下圖流程:android

  開機顯示桌面、從桌面點擊 App 圖標到 Activity顯示在屏幕上的過程又是怎樣的呢?下面介紹Android系統中的「畫家」 - SurfaceFlinger.
  SurfaceFlinger 啓動過程:算法

 

 

 2、SurfaceFlinger代碼剖析[Android 8.0]json

  代碼路徑:/frameworks/native/services/surfaceflinger/
  SurfaceFlinger二進制分紅surfaceflinger可執行文件(main入口)和libsurfaceflinger.so庫文件(功能實現),由main_surfaceflinger.cpp文件編譯而成,Android.mk代碼模塊編譯配置以下:canvas

 1.【執行文件-surfaceflinger】數組

###############################################################
# build surfaceflinger's executable
include $(CLEAR_VARS)

LOCAL_CLANG := true

LOCAL_LDFLAGS_32 := -Wl,--version-script,art/sigchainlib/version-script32.txt -Wl,--export-dynamic
LOCAL_LDFLAGS_64 := -Wl,--version-script,art/sigchainlib/version-script64.txt -Wl,--export-dynamic
LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"

LOCAL_INIT_RC := surfaceflinger.rc

ifeq ($(TARGET_USES_HWC2),true)
    LOCAL_CFLAGS += -DUSE_HWC2
endif

LOCAL_SRC_FILES := \
    main_surfaceflinger.cpp

LOCAL_SHARED_LIBRARIES := \
    android.frameworks.displayservice@1.0 \
    android.hardware.configstore@1.0 \
    android.hardware.configstore-utils \
    android.hardware.graphics.allocator@2.0 \
    libsurfaceflinger \
    libcutils \
    libdisplayservicehidl \
    liblog \
    libbinder \
    libhidlbase \
    libhidltransport \
    libutils \
    libui \
    libgui \
    libdl

LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain
LOCAL_STATIC_LIBRARIES := libtrace_proto

LOCAL_MODULE := surfaceflinger

ifdef TARGET_32_BIT_SURFACEFLINGER
LOCAL_32_BIT_ONLY := true
endif

LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code

include $(BUILD_EXECUTABLE)

  SurfaceFlinger可執行二進制文件surfaceflinger由main_surfaceflinger.cpp文件獨立編譯而成,主要負責搭建進程啓動環境:session

int main(int, char**) {

        // 從8.0開始,Android提供了hidl機制,將原先直接由JNI->Native->HAL的接口調用形式,統一規範成hidl service/client交互形式。
     // 該方式從一方面規範和統一了Android Framework和HAL的調用機制,但實際上,從項目維度,這種調用方式對性能上開銷,將比直接調用的方式要花費更多的時間。
startHidlServices(); signal(SIGPIPE, SIG_IGN); // When SF is launched in its own process, limit the number of // binder threads to 4. ProcessState::self()->setThreadPoolMaxThreadCount(4); // start the thread pool sp<ProcessState> ps(ProcessState::self()); ps->startThreadPool(); // 初始化SurfaceFlinger對象,由強指針指向。SurfaceFlinger繼承RefBase類,因此此處一旦new出對象賦給sp指針後,將馬上出發SurfaceFlinger類的onFirstRef方法的調用。 // instantiate surfaceflinger sp<SurfaceFlinger> flinger = new 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類正式初始化 // initialize before clients can connect flinger->init(); // SurfaceFlinger向ServiceManager註冊Binder服務,這樣在其餘進程中,能夠經過getService+SERVICE_NAME來獲取SurfaceFlinger服務,繼而能夠和SurfaceFlinger類進行Binder通訊。 // publish surface flinger sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false); // publish GpuService sp<GpuService> gpuservice = new GpuService(); sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false); struct sched_param param = {0}; param.sched_priority = 2; if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) { ALOGE("Couldn't set SCHED_FIFO"); } // SurfaceFlinger類進入主循環(此處注意SurfaceFlinger類未繼承Threads類,不遵循Threads類的接口執行順序) // run surface flinger in this thread flinger->run(); return 0; }

  startHidlServices();內容以下app

static status_t startHidlServices() {
    using android::frameworks::displayservice::V1_0::implementation::DisplayService;
    using android::frameworks::displayservice::V1_0::IDisplayService;
    using android::hardware::configstore::getBool;
    using android::hardware::configstore::getBool;
    using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
    hardware::configureRpcThreadpool(1 /* maxThreads */,
            false /* callerWillJoin */);

    status_t err;

    if (getBool<ISurfaceFlingerConfigs,
            &ISurfaceFlingerConfigs::startGraphicsAllocatorService>(false)) {
        err = startGraphicsAllocatorService();
        if (err != OK) {
           return err;
        }
    }

    sp<IDisplayService> displayservice = new DisplayService(); //裏面調用HIDL定義接口 Return<sp<IDisplayEventReceiver >> getEventReceiver() override;
    err = displayservice->registerAsService();

    if (err != OK) {
        ALOGE("Could not register IDisplayService service.");
    }

    return err;
}

  HIDL接口介紹能夠參考:https://source.android.google.cn/reference/hidl/
composer

 2.【動態庫-libsurfaceflinger.so】框架

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_CLANG := true LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_SRC_FILES := \ Client.cpp \ DisplayDevice.cpp \ DispSync.cpp \ EventControlThread.cpp \ StartBootAnimThread.cpp \ EventThread.cpp \ FrameTracker.cpp \ GpuService.cpp \ Layer.cpp \ LayerDim.cpp \ LayerRejecter.cpp \ LayerVector.cpp \ MessageQueue.cpp \ MonitoredProducer.cpp \ SurfaceFlingerConsumer.cpp \ SurfaceInterceptor.cpp \ Transform.cpp \ DisplayHardware/ComposerHal.cpp \ DisplayHardware/FramebufferSurface.cpp \ DisplayHardware/HWC2.cpp \ DisplayHardware/HWComposerBufferCache.cpp \ DisplayHardware/PowerHAL.cpp \ DisplayHardware/VirtualDisplaySurface.cpp \ Effects/Daltonizer.cpp \ EventLog/EventLogTags.logtags \ EventLog/EventLog.cpp \ RenderEngine/Description.cpp \ RenderEngine/Mesh.cpp \ RenderEngine/Program.cpp \ RenderEngine/ProgramCache.cpp \ RenderEngine/GLExtensions.cpp \ RenderEngine/RenderEngine.cpp \ RenderEngine/Texture.cpp \ RenderEngine/GLES20RenderEngine.cpp \ LOCAL_MODULE := libsurfaceflinger LOCAL_C_INCLUDES := \ frameworks/native/vulkan/include \ external/vulkan-validation-layers/libs/vkjson \ system/libhwbinder/fast_msgq/include \ LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES ifeq ($(TARGET_USES_HWC2),true) LOCAL_CFLAGS += -DUSE_HWC2 LOCAL_SRC_FILES += \ SurfaceFlinger.cpp \ DisplayHardware/HWComposer.cpp else LOCAL_SRC_FILES += \ SurfaceFlinger_hwc1.cpp \ DisplayHardware/HWComposer_hwc1.cpp endif LOCAL_CFLAGS += -fvisibility=hidden -Werror=format LOCAL_STATIC_LIBRARIES := \ libhwcomposer-command-buffer \ libtrace_proto \ libvkjson \ libvr_manager \ libvrflinger LOCAL_SHARED_LIBRARIES := \ android.frameworks.vr.composer@1.0 \ android.hardware.graphics.allocator@2.0 \ android.hardware.graphics.composer@2.1 \ android.hardware.configstore@1.0 \ android.hardware.configstore-utils \ libcutils \ liblog \ libdl \ libfmq \ libhardware \ libhidlbase \ libhidltransport \ libhwbinder \ libutils \ libEGL \ libGLESv1_CM \ libGLESv2 \ libbinder \ libui \ libgui \ libpowermanager \ libvulkan \ libsync \ libprotobuf-cpp-lite \ libbase \ android.hardware.power@1.0 LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \ android.hardware.graphics.allocator@2.0 \ android.hardware.graphics.composer@2.1 \ libhidlbase \ libhidltransport \ libhwbinder LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code include $(BUILD_SHARED_LIBRARY)

  new SurfaceFlinger(); 會執行到:onFirstRef()

void SurfaceFlinger::onFirstRef()
{
    mEventQueue.init(this);
}

  onFirstRef() 中會建立 Handler 並初始化:

//MessageQueue.cpp
void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
{
    mFlinger = flinger;
    mLooper = new Looper(true);
    mHandler = new Handler(*this);
}

  而後會執行到 SurfaceFlinger::init(),該方法主要功能是:

  • 初始化 EGL
  • 建立 HWComposer
  • 初始化非虛擬顯示屏
  • 啓動 EventThread 線程
  • 啓動開機動畫
void SurfaceFlinger::init() {
    ALOGI(  "SurfaceFlinger's main thread ready to run. "
            "Initializing graphics H/W...");

    Mutex::Autolock _l(mStateLock);

    // initialize EGL for the default display
    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(mEGLDisplay, NULL, NULL);

    // start the EventThread
    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
            vsyncPhaseOffsetNs, true, "app");
    mEventThread = new EventThread(vsyncSrc, *this, false);
    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
            sfVsyncPhaseOffsetNs, true, "sf");
    mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
    mEventQueue.setEventThread(mSFEventThread);

    // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
    struct sched_param param = {0};
    param.sched_priority = 2;
    if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, &param) != 0) {
        ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
    }
    if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, &param) != 0) {
        ALOGE("Couldn't set SCHED_FIFO for EventThread");
    }

    // Initialize the H/W composer object.  There may or may not be an
    // actual hardware composer underneath.
    mHwc = new HWComposer(this,
            *static_cast<HWComposer::EventHandler *>(this));

    // get a RenderEngine for the given display / config (can't fail)
    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());

    // retrieve the EGL context that was selected/created
    mEGLContext = mRenderEngine->getEGLContext();

    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
            "couldn't create EGLContext");

    // Inform native graphics APIs that the present timestamp is NOT supported:
    property_set(kTimestampProperty, "0");

    // initialize our non-virtual displays
    for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
        // set-up the displays that are already connected
        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
            // All non-virtual displays are currently considered secure.
            bool isSecure = true;
            createBuiltinDisplayLocked(type);
            wp<IBinder> token = mBuiltinDisplays[i];

            sp<IGraphicBufferProducer> producer;
            sp<IGraphicBufferConsumer> consumer;
            BufferQueue::createBufferQueue(&producer, &consumer);

            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
                    consumer);
            int32_t hwcId = allocateHwcDisplayId(type);
            sp<DisplayDevice> hw = new DisplayDevice(this,
                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
                    fbs, producer,
                    mRenderEngine->getEGLConfig(), false);
            if (i > DisplayDevice::DISPLAY_PRIMARY) {
                // FIXME: currently we don't get blank/unblank requests
                // for displays other than the main display, so we always
                // assume a connected display is unblanked.
                ALOGD("marking display %zu as acquired/unblanked", i);
                hw->setPowerMode(HWC_POWER_MODE_NORMAL);
            }
            mDisplays.add(token, hw);
        }
    }

    // make the GLContext current so that we can create textures when creating Layers
    // (which may happens before we render something)
    getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);

    mEventControlThread = new EventControlThread(this);
    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);

    // set a fake vsync period if there is no HWComposer
    if (mHwc->initCheck() != NO_ERROR) {
        mPrimaryDispSync.setPeriod(16666667);
    }

    // initialize our drawing state
    mDrawingState = mCurrentState;

    // set initial conditions (e.g. unblank default device)
    initializeDisplays();

    mRenderEngine->primeCache();

    mStartBootAnimThread = new StartBootAnimThread();
    if (mStartBootAnimThread->Start() != NO_ERROR) {
        ALOGE("Run StartBootAnimThread failed!");
    }

    ALOGV("Done initializing");
}

  建立 HWComposer:

HWComposer::HWComposer(
        const sp<SurfaceFlinger>& flinger,
        EventHandler& handler)
    : mFlinger(flinger),
      mFbDev(0), mHwc(0), mNumDisplays(1),
      mCBContext(new cb_context),
      mEventHandler(handler),
      mDebugForceFakeVSync(false)
{
    for (size_t i =0 ; i<MAX_HWC_DISPLAYS ; i++) {
        mLists[i] = 0;
    }

    for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
        mLastHwVSync[i] = 0;
        mVSyncCounts[i] = 0;
    }

    char value[PROPERTY_VALUE_MAX];
    property_get("debug.sf.no_hw_vsync", value, "0");
    mDebugForceFakeVSync = atoi(value);

    bool needVSyncThread = true;

    // Note: some devices may insist that the FB HAL be opened before HWC.
    int fberr = loadFbHalModule(); //加載 framebuffer 的 HAL 層模塊
    loadHwcModule(); //加載 HWComposer 模塊 

    if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
        // close FB HAL if we don't needed it.
        // FIXME: this is temporary until we're not forced to open FB HAL
        // before HWC.
        framebuffer_close(mFbDev);
        mFbDev = NULL;
    }

    // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
    if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
            && !mFbDev) {
        ALOGE("ERROR: failed to open framebuffer (%s), aborting",
                strerror(-fberr));
        abort();
    }

    // these display IDs are always reserved
    for (size_t i=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
        mAllocatedDisplayIDs.markBit(i);
    }

    if (mHwc) {
        ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
              (hwcApiVersion(mHwc) >> 24) & 0xff,
              (hwcApiVersion(mHwc) >> 16) & 0xff);
        if (mHwc->registerProcs) {
            mCBContext->hwc = this;
            mCBContext->procs.invalidate = &hook_invalidate;
        // VSYNC 信號的回調方法
            mCBContext->procs.vsync = &hook_vsync;
            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
                mCBContext->procs.hotplug = &hook_hotplug;
            else
                mCBContext->procs.hotplug = NULL;
            memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
       // 註冊回調函數
            mHwc->registerProcs(mHwc, &mCBContext->procs);
        }

        // don't need a vsync thread if we have a hardware composer
        needVSyncThread = false;
        // always turn vsync off when we start
        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);

        // the number of displays we actually have depends on the
        // hw composer version
        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
            // 1.3 adds support for virtual displays
            mNumDisplays = MAX_HWC_DISPLAYS;
        } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
            // 1.1 adds support for multiple displays
            mNumDisplays = NUM_BUILTIN_DISPLAYS;
        } else {
            mNumDisplays = 1;
        }
    }

    if (mFbDev) {
        ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
                "should only have fbdev if no hwc or hwc is 1.0");

        DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
        disp.connected = true;
        disp.format = mFbDev->format;
        DisplayConfig config = DisplayConfig();
        config.width = mFbDev->width;
        config.height = mFbDev->height;
        config.xdpi = mFbDev->xdpi;
        config.ydpi = mFbDev->ydpi;
        config.refresh = nsecs_t(1e9 / mFbDev->fps);
        disp.configs.push_back(config);
        disp.currentConfig = 0;
    } else if (mHwc) {
        // here we're guaranteed to have at least HWC 1.1
        for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
            queryDisplayProperties(i);
        }
    }

    if (needVSyncThread) {
        // we don't have VSYNC support, we need to fake it : 不支持硬件的 VSYNC,則會建立線程來模擬定時 VSYNC 信號
        mVSyncThread = new VSyncThread(*this);
    }
}

  HWComposer 表明着硬件顯示設備,註冊了 VSYNC 信號的回調。VSYNC 信號自己是由顯示驅動產生的,在不支持硬件的 VSYNC,則會建立「VSyncThread」線程來模擬定時 VSYNC 信號。當硬件產生VSYNC信號時,則會發送消息,handler 收到消息進行處理。當 SurfaceFlinger 進程收到 VSync 信號後經層層調用,最終調用到該對象的 handleMessageRefresh() 方法。

  • HSYNC 信號用於告訴電子槍該掃描下一行了, 即要轉到下一行起始處了;
  • VSYNC 信號告訴電子槍該顯示下一幀了, 即該轉回左上角起始處了;
// SurfaceFlinger.cpp
void SurfaceFlinger::handleMessageRefresh() {
    ATRACE_CALL();
    preComposition();//處理顯示設備與 layers 的改變,更新光標
    rebuildLayerStacks();//重建全部可見 Layer 列表,根據Z軸排序
    setUpHWComposer();//更新 HWComposer 圖層
    doDebugFlashRegions();
    doComposition();//生成 OpenGL 紋理圖像
    postComposition();//將圖像傳遞到物理屏幕
}

相關問題:

  ① 屏幕刷新速率比系統幀速率快:
    此時,在前緩衝區內容所有映射到屏幕上以後,後緩衝區還沒有準備好下一幀,屏幕將沒法讀取下一幀,因此只能繼續顯示當前一幀的圖形,形成一幀顯示屢次,也就是卡頓。 
  ② 系統幀速率比屏幕刷新率快 
    此時,屏幕未徹底把前緩衝區的一幀映射到屏幕,而系統已經在後緩衝區準備好了下一幀,並要求讀取下一幀到屏幕,將會致使屏幕上半部分是上一幀的圖形,而下半部分是下一幀的圖形,形成屏幕上顯示多幀,也就是屏幕撕裂。

  爲了解決上述問題,Android顯示系統通常會有多級緩衝,即在屏幕刷新的同時在另一個buffer準備下一幀數據,以此提升性能:

  


  前緩衝區:用來顯示內容到屏幕的幀緩衝區 
  後緩衝區:用於後臺合成下一幀圖形的幀緩衝區

  垂直同步(VSync):當屏幕從緩衝區掃描完一幀到屏幕上以後,開始掃描下一幀以前,發出的一個同步信號,該信號用來切換前緩衝區和後緩衝區。

  屏幕刷新率(HZ):表明屏幕在一秒內刷新屏幕的次數,Android手機通常爲60HZ(也就是1秒刷新60幀,大約16.67毫秒刷新1幀) 
  系統幀速率(FPS):表明了系統在一秒內合成的幀數,該值的大小由系統算法和硬件決定。

 

3. 服務啓動配置文件:/frameworks/native/services/surfaceflinger/surfaceflinger.rc
 上面發現服務配置文件也在Android.mk中被加載:LOCAL_INIT_RC := 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_display_vsync_endpoint_socket:s0


4. Surface 建立過程

 

 Surface 建立的過程就是 Activity 顯示的過程,在 ActivityThread.handleResumeActivity() 中調用了 Activity.makeVisible()具體實現:

void makeVisible() {
    if (!mWindowAdded) {
        ViewManager wm = getWindowManager();//此處 getWindowManager 獲取的是 WindowManagerImpl 對象
        wm.addView(mDecor, getWindow().getAttributes());
        mWindowAdded = true;
    }
    mDecor.setVisibility(View.VISIBLE);
}

 WindowManagerImpl.java:

public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyDefaultToken(params);
    mGlobal.addView(view, params, mDisplay, mParentWindow);
}

 WindowManagerGlobal.java:

public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) {
    ...
    final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
    //建立 ViewRootImpl
    ViewRootImpl root = new ViewRootImpl(view.getContext(), display);
    view.setLayoutParams(wparams);
    mViews.add(view);
    mRoots.add(root);
    mParams.add(wparams);
    //設置 View
    root.setView(view, wparams, panelParentView);
    ...
}

 建立 ViewRootImpl:

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
    ...
    final Surface mSurface = new Surface(); //建立 Surface,此時 Surface 建立完什麼都沒有,詳見下面分析
    ...
    public ViewRootImpl(Context context, Display display) {
        mContext = context;
        //獲取 IWindowSession 的代理類
        mWindowSession = WindowManagerGlobal.getWindowSession();
        mDisplay = display;
        mThread = Thread.currentThread(); //主線程
        mWindow = new W(this);
        mChoreographer = Choreographer.getInstance();
        ...
    }
}

 WindowManagerGlobal.java:

public static IWindowSession getWindowSession() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowSession == null) {
            try {
                //獲取 IMS 的代理類
                InputMethodManager imm = InputMethodManager.getInstance();
                //獲取 WMS 的代理類
                IWindowManager windowManager = getWindowManagerService();
                //通過 Binder 調用,最終調用 WMS
                sWindowSession = windowManager.openSession(
                        new IWindowSessionCallback.Stub() {...},
                        imm.getClient(), imm.getInputContext());
            } catch (RemoteException e) {
                ...
            }
        }
        return sWindowSession
    }
}

 WindowManagerService.openSession:

public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, IInputContext inputContext) {
    //建立 Session 對象
    Session session = new Session(this, callback, client, inputContext);
    return session;
}

 再次通過 Binder 將數據寫回 app 進程,則獲取的即是 Session 的代理對象 IWindowSession。
 建立完 ViewRootImpl 對象後,接下來調用該對象的 setView() 方法:
 ViewRootImpl:

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
  synchronized (this) {
 
    requestLayout(); //詳見下面分析
    ...
    //經過 Binder調用,進入 system 進程的 Session
    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
          getHostVisibility(), mDisplay.getDisplayId(),
          mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
          mAttachInfo.mOutsets, mInputChannel);
    ...
  }
}
final class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {

    public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel) {
        //調用 WMS.addWindow
        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                outContentInsets, outStableInsets, outOutsets, outInputChannel);
    }
}

 WindowManagerService.java:

public int addWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel) {
    ...
    WindowToken token = mTokenMap.get(attrs.token);
    //建立 WindowState
    WindowState win = new WindowState(this, session, client, token,
                attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
    ...
    //調整 WindowManager 的 LayoutParams 參數
    mPolicy.adjustWindowParamsLw(win.mAttrs);
    res = mPolicy.prepareAddWindowLw(win, attrs);
    addWindowToListInOrderLocked(win, true);
    // 設置 input
    mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
    //詳見下面分析
    win.attach();
    mWindowMap.put(client.asBinder(), win);
    
    if (win.canReceiveKeys()) {
        //當該窗口能接收按鍵事件,則更新聚焦窗口
        focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                false /*updateInputWindows*/);
    }
    assignLayersLocked(displayContent.getWindowList());
    ...
}

//WindowState.java
void attach() {
    mSession.windowAddedLocked();
}

 建立 SurfaceSession 對象,並將當前 Session 添加到 WMS.mSessions 成員變量。
 Session.java:

void windowAddedLocked() {
    if (mSurfaceSession == null) {
        mSurfaceSession = new SurfaceSession();
        mService.mSessions.add(this);
        if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
            mService.dispatchNewAnimatorScaleLocked(this);
        }
    }
    mNumWindow++;
}

 SurfaceSession 的建立會調用 JNI,在 JNI 調用 nativeCreate()。
 android_view_SurfaceSession.cpp:

static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient();
    client->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(client);
}

 建立 SurfaceComposerClient 對象, 做爲跟 SurfaceFlinger 通訊的代理對象。

SurfaceComposerClient::SurfaceComposerClient() {
    //getComposerService() 將返回 SF 的 Binder 代理端的 BpSurfaceFlinger 對象
    sp<ISurfaceComposer> sm(getComposerService());
    
    //先調用 SF 的 createConnection(),再調用_init
    _init(sm, sm->createConnection());
    if(mClient != 0) {
       Mutex::Autolock _l(gLock);
       
       //gActiveConnections 是全局變量,把剛纔建立的 client 保存到這個 map 中去
       gActiveConnections.add(mClient->asBinder(), this);
    }
}

 SurfaceFlinger.cpp:

sp<ISurfaceFlingerClient>SurfaceFlinger::createConnection() {
    Mutex::Autolock _l(mStateLock);
    uint32_t token = mTokens.acquire();

    //先建立一個Client
    sp<Client> client = new Client(token, this);

    //把這個Client對象保存到mClientsMap中,token是它的標識。
    status_t err = mClientsMap.add(token, client);

    /*
    建立一個用於 Binder 通訊的 BClient,BClient 派生於 ISurfaceFlingerClient,
    它的做用是接受客戶端的請求,而後把處理提交給 SF,注意,並非提交給 Client。
    Client 會建立一塊共享內存,該內存由 getControlBlockMemory 函數返回。
    */
    sp<BClient> bclient = new BClient(this, token,client->getControlBlockMemory());
    return bclient;
}
Client::Client(ClientID clientID, constsp<SurfaceFlinger>& flinger):ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger) {
const int pgsize = getpagesize();
    //下面這個操做會使 cblksize 爲頁的大小,目前是4096字節
    constint cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
    mCblkHeap = new MemoryHeapBase(cblksize, 0, "SurfaceFlinger Clientcontrol-block");

    ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
    if(ctrlblk) {
       new(ctrlblk) SharedClient;//原來 Surface 的 CB 對象就是在共享內存中建立的這個 SharedClient 對象
    }
}

 SharedClient:

class SharedClient {

public:
   SharedClient();
   ~SharedClient();
   status_t validate(size_t token) const;
   uint32_t getIdentity(size_t token) const;

private:
    Mutexlock;
    Condition cv; //支持跨進程的同步對象

    //NUM_LAYERS_MAX 爲 31,SharedBufferStack 是什麼?
    SharedBufferStack surfaces[ NUM_LAYERS_MAX ];

};

//SharedClient的構造函數,沒什麼新意,不如Audio的CB對象複雜
SharedClient::SharedClient():lock(Mutex::SHARED), cv(Condition::SHARED) {
}

 一個 Client 最多支持 31 個顯示層。每個顯示層的生產/消費步調都由會對應的 SharedBufferStack 來控制。而它內部就用了幾個成員變量來控制讀寫位置。
 SharedBufferStack.h:

class  SharedBufferStack{
     ......
    //Buffer 是按塊使用的,每一個 Buffer 都有本身的編號,其實就是數組中的索引號。
    volatile int32_t head;     //FrontBuffer 的編號
    volatile int32_t available; //空閒 Buffer 的個數
    volatile int32_t queued;  //髒 Buffer 的個數,髒 Buffer 表示有新數據的 Buffer
    volatile int32_t inUse; //SF 當前正在使用的 Buffer 的編號   
    volatilestatus_t status; //狀態碼
     ......
  }

 SF 的一個 Client 分配一個跨進程共享的 SharedClient 對象。這個對象有31個 SharedBufferStack 元素,每個 SharedBufferStack 對應於一個顯示層。
 一個顯示層將建立兩個 Buffer,後續的 PageFlipping 就是基於這兩個 Buffer 展開的。
 接着看 SurfaceComposerClient 中這個_init函數:

void SurfaceComposerClient::_init(
       const sp<ISurfaceComposer>& sm, constsp<ISurfaceFlingerClient>& conn) {
    mPrebuiltLayerState = 0;
    mTransactionOpen = 0;
    mStatus = NO_ERROR;
    mControl = 0;

    mClient = conn;// mClient 就是 BClient 的客戶端
    mControlMemory =mClient->getControlBlock();
    mSignalServer = sm;// mSignalServer 就是 BpSurfaceFlinger
    //mControl 就是那個建立於共享內存之中的 SharedClient
    mControl = static_cast<SharedClient*>(mControlMemory->getBase());
}

 建立完 ViewRootImpl 對象後,接下來調用該對象的 setView() 方法。在 setView() 中調用了 requestLayout() 方法咱們來看下這個方法:

public void requestLayout() {
   checkThread();
   mLayoutRequested = true;
   scheduleTraversals();
}

public void scheduleTraversals() {
    if(!mTraversalScheduled) {
       mTraversalScheduled = true;
       sendEmptyMessage(DO_TRAVERSAL); //發送 DO_TRAVERSAL 消息
    }
}

public void handleMessage(Message msg) {
   switch (msg.what) {
    ......
    case DO_TRAVERSAL:
        ......
        performTraversals();//調用 performTraversals()
        ......
        break;
    ......
    }
}

private void performTraversals() {
    finalView host = mView;//還記得這mView嗎?它就是 DecorView
    booleaninitialized = false;
    booleancontentInsetsChanged = false;
    booleanvisibleInsetsChanged;
    
    try {
        relayoutResult= // 1. 關鍵函數relayoutWindow
        relayoutWindow(params, viewVisibility,insetsPending);
    }
    ......
    draw(fullRedrawNeeded);// 2. 開始繪製
    ......
}

private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility, boolean insetsPending)throws RemoteException {
       //原來是調用 IWindowSession 的 relayout(),暫且記住這個調用
       int relayoutResult = sWindowSession.relayout(mWindow, params, (int) (mView.mMeasuredWidth * appScale + 0.5f),  (int) (mView.mMeasuredHeight * appScale + 0.5f), viewVisibility, insetsPending, mWinFrame, mPendingContentInsets, mPendingVisibleInsets, mPendingConfiguration, mSurface); //mSurface 作爲參數傳進去了。
       }
   ......
}

private void draw(boolean fullRedrawNeeded) {
    Surface surface = mSurface;//mSurface 是 ViewRoot 的成員變量
    ......
    Canvascanvas;

    try {
       int left = dirty.left;
       int top = dirty.top;
       int right = dirty.right;
       int bottom = dirty.bottom;

       //從 mSurface 中 lock 一塊 Canvas
       canvas = surface.lockCanvas(dirty);
       ......
       mView.draw(canvas);//調用 DecorView 的 draw 函數,canvas 就是畫布
       ......
       //unlock 畫布,屏幕上立刻就能看到 View 的樣子了
       surface.unlockCanvasAndPost(canvas);
    }
    ......
}


 在 ViewRoot 構造時,會建立一個 Surface,它使用無參構造函數,代碼以下所示:

final Surface mSurface = new Surface();

 此時建立完的 Surface 是空的,什麼都沒有。接着繼續分析 relayoutWindow(),在 relayoutWindow() 中會調用 IWindowSession 的 relayout(),這是一個跨進程方法會調用到 WMS 中的 Session.relayout(),最後調用到 WindowManagerService.relayoutWindow()。

public int relayoutWindow(Session session,IWindow client,
           WindowManager.LayoutParams attrs, int requestedWidth,
           int requestedHeight, int viewVisibility, boolean insetsPending,
           Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
            Configuration outConfig, SurfaceoutSurface){
        .....

    try {
         //win 就是 WinState,這裏將建立一個本地的 Surface 對象
        Surfacesurface = win.createSurfaceLocked();
        if(surface != null) {
            //先建立一個本地 surface,而後在 outSurface 的對象上調用 copyFrom
            //將本地 Surface 的信息拷貝到 outSurface 中,爲何要這麼麻煩呢?
            outSurface.copyFrom(surface);
        ......
}

WindowManagerService.java::WindowState:

Surface createSurfaceLocked() {
    ......
    try {
        //mSurfaceSession 就是在 Session 上建立的 SurfaceSession 對象
        //這裏,以它爲參數,構造一個新的 Surface 對象
        mSurface = new Surface(mSession.mSurfaceSession, mSession.mPid, mAttrs.getTitle().toString(), 0, w, h, mAttrs.format, flags);
    }
    Surface.openTransaction();//打開一個事務處理
    ......
    Surface.closeTransaction();//關閉一個事務處理
    ......
}

構造 Surface 對象:

 public Surface(SurfaceSession s,//傳入一個SurfaceSession對象
    int pid, String name, int display, int w, int h, int format, int flags) throws OutOfResourcesException {
        ......
        mCanvas = new CompatibleCanvas();
        //又一個 native 函數
        init(s,pid,name,display,w,h,format,flags);
        mName = name;
    }
static void Surface_init(JNIEnv*env, jobject clazz, jobject session, jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jintflags) {

    //從 SurfaceSession 對象中取出以前建立的那個 SurfaceComposerClient 對象
    SurfaceComposerClient* client = (SurfaceComposerClient*)env->GetIntField(session, sso.client);
    sp<SurfaceControl> surface;//注意它的類型是 SurfaceControl
    if (jname == NULL) {
        //調用 SurfaceComposerClient 的 createSurface 函數,返回的 surface 是一個 SurfaceControl 類型
        surface = client->createSurface(pid, dpy, w, h, format, flags);
    } else{
        ......
    }

   //把這個 surfaceControl 對象設置到 Java 層的 Surface 對象中
   setSurfaceControl(env, clazz, surface);
}

 在 createSurface 內部會使用 Binder 通訊將請求發給 SurfaceFlinger:

sp<ISurface>SurfaceFlinger::createSurface(ClientID clientId, int pid, const String8& name, ISurfaceFlingerClient::surface_data_t* params, DisplayID d, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) {
    sp<LayerBaseClient> layer;//LayerBaseClient 是 Layer 家族的基類
    //這裏又冒出一個 LayerBaseClient 的內部類,它也叫Surface
    sp<LayerBaseClient::Surface> surfaceHandle;
    Mutex::Autolock _l(mStateLock);

    //根據 clientId 找到 createConnection 時加入的那個 Client 對象
    sp<Client> client = mClientsMap.valueFor(clientId);
    ......
    //注意這個 id,它的值表示 Client 建立的是第幾個顯示層
    //同時也表示將使用 SharedBufferStatck 數組的第 id 個元素
    int32_t id = client->generateId(pid);
    
    //一個 Client 不能建立多於 NUM_LAYERS_MAX 個的Layer
    if(uint32_t(id) >= NUM_LAYERS_MAX) {
       return surfaceHandle;
    }

    //根據 flags 參數來建立不一樣類型的顯示層
    switch(flags & eFXSurfaceMask) {
        case eFXSurfaceNormal:
           if (UNLIKELY(flags & ePushBuffers)) {
             //建立 PushBuffer 類型的顯示層
            layer = createPushBuffersSurfaceLocked(client, d, id, w, h, flags);
            } else {
               //建立 Normal 類型的顯示層
               layer = createNormalSurfaceLocked(client, d, id, w, h, flags, format);
           }
           break;
        case eFXSurfaceBlur:
            //建立 Blur 類型的顯示層
           layer = createBlurSurfaceLocked(client, d, id, w, h, flags);
           break;
        case eFXSurfaceDim:
            //建立 Dim 類型的顯示層
           layer = createDimSurfaceLocked(client, d, id, w, h, flags);
           break;
    }

    if(layer != 0) {
        layer->setName(name);
        setTransactionFlags(eTransactionNeeded);
        //從顯示層對象中取出一個 ISurface 對象賦值給 SurfaceHandle
        surfaceHandle = layer->getSurface();
        if(surfaceHandle != 0) {
           params->token = surfaceHandle->getToken();
           params->identity = surfaceHandle->getIdentity();
           params->width = w;
           params->height = h;
           params->format = format;
        }
    }
    return surfaceHandle;//ISurface 的 Bn 端就是這個對象
}
sp<LayerBaseClient>SurfaceFlinger::createNormalSurfaceLocked(const sp<Client>& client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format) {
    switch(format) { //一些圖像方面的參數設置,能夠不去管它
    case PIXEL_FORMAT_TRANSPARENT:
    case PIXEL_FORMAT_TRANSLUCENT:
       format = PIXEL_FORMAT_RGBA_8888;
       break;
    case PIXEL_FORMAT_OPAQUE:
       format = PIXEL_FORMAT_RGB_565;
       break;
    }

    //建立一個 Layer 類型的對象
    sp<Layer> layer = new Layer(this, display,client, id);

    //設置 Buffer
    status_t err = layer->setBuffers(w, h, format, flags);
    if (LIKELY(err == NO_ERROR)) {
        //初始化這個新 layer 的一些狀態
        layer->initStates(w, h, flags);
        //下面這個函數把這個 layer 加入到 Z 軸集合中
        addLayer_l(layer);
    }
......
    return layer;
}


 createNormalSurfaceLocked 函數有三個關鍵點,它們是:

  •     構造一個Layer對象。
  •     調用Layer對象的setBuffers函數。
  •     調用SF的addLayer_l函數。

 當跨進程的 createSurface() 執行完返回一個 ISurface 對象,接下來會建立 SurfaceControl 對象:

SurfaceControl::SurfaceControl(
       const sp<SurfaceComposerClient>& client,
       const sp<ISurface>& surface,
       const ISurfaceFlingerClient::surface_data_t& data,
       uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
    //mClient 爲 SurfaceComposerClient,而 mSurface 指向跨進程 createSurface() 調用返回的 ISurface 對象
    :mClient(client), mSurface(surface),
     mToken(data.token), mIdentity(data.identity),
     mWidth(data.width), mHeight(data.height), mFormat(data.format),
     mFlags(flags){
     ......
}

 SurfaceControl 類能夠看做是一個 wrapper 類,它封裝了一些函數,經過這些函數能夠方便地調用 mClient 或 ISurface 提供的函數。
 最後會執行 copyFrom() 返回給 App 客戶端:

static void Surface_copyFrom(JNIEnv* env,jobject clazz, jobject other) {
    //根據JNI函數的規則,clazz 是 copyFrom 的調用對象,而 other 是 copyFrom 的參數。
    //目標對象此時尚未設置 SurfaceControl,而源對象在前面已經建立了 SurfaceControl
    constsp<SurfaceControl>& surface = getSurfaceControl(env, clazz);
    constsp<SurfaceControl>& rhs = getSurfaceControl(env, other);
    if (!SurfaceControl::isSameSurface(surface, rhs)) {
        //把源 SurfaceControl 對象設置到目標 Surface 中
        setSurfaceControl(env, clazz, rhs);
    }
}

 copyFrom 期間一共有三個關鍵對象,它們分別是:

  •     SurfaceComposerClient
  •     SurfaceControl
  •     Surface,這個 Surface 對象屬於 Native 層,和 Java 層的 Surface 相對應

 其中轉移到 ViewRoot 成員變量 mSurface 中的,就是最後這個 Surface 對象了。

 在 SurfaceFlinger 進程中,Client 的一個 Layer 將使用 SharedBufferStack 數組中的一個成員,並經過 SharedBufferServer 結構來控制這個成員, SurfaceFlinger 是消費者,因此可由 SharedBufferServer 來控制數據的讀取。與之相對應,客戶端的進程也會有一個對象來使用這個 SharedBufferStack,可它是經過另一個叫 SharedBufferClient 的結構來控制的。客戶端爲 SurfaceFlinger 提供數據,因此可由 SharedBufferClient 控制數據的寫入。

Surface 顯示過程總結:

  

  如圖所示,在 App 進程中建立 PhoneWindow 後會建立 ViewRoot。ViewRoot 的建立會建立一個 Surface,這個 Surface 實際上是空的,經過與 WindowManagerService 通訊 copyFrom() 一個NativeSurface。在與 SurfaceFlinger 通訊時,會建立 SharedClient 一段共享內存,裏面存放的是 SharedBufferStack 對應 SurfaceFlinger 中的 SurfaceLayer 每一個 Layer 實際上是一個 FrameBuffer,每一個 FrameBuffer 中有兩個 GraphicBuffer 記做 FrontBuffer 和 BackBuffer。
  在SurfaceFlinger 中 SharedBufferServer 來管理 FrameBuffer。同時在 App 端 copyFrom() 出來 NativeSurface 時會建立一個 SharedBufferClient 與 SharedClient 這塊共享內存關聯。當客戶端 addView() 或者須要更新 View 時,會經過 SharedBufferClient 寫入數據到 ShareClient 中,SurfaceFlinger 中的 SharedBufferServer 接收到通知會將 FrameBuffer 中的數據傳輸到屏幕上。

 

5.本地窗口(Native Window)

  Native Window爲OpenGL與本地窗口系統之間搭建了橋樑。整個GUI系統至少須要兩種本地窗口:
  (1)面向管理者(SurfaceFlinger)
    SurfaceFlinger是系統中全部UI界面的管理者,須要直接或間接的持有「本地窗口」,此本地窗口是FramebufferNativeWindow。
  (2)面向應用程序
    這類本地窗口是Surface。

  正常狀況按照SDK嚮導生成APK應用程序,是採用Skia等第三方圖形庫,而對於但願使用OpenGL ES來完成複雜界面渲染的應用開發者來講,Android也提供封裝的GLSurfaceView(或其餘方式)來實現圖形顯示。

  ①FramebufferNativeWindow
    EGL須要經過本地窗口來爲OpenGL/OpenGL ES建立環境。因爲OpenGL/ES對多平臺支持,考慮到兼容性和移植性。不一樣平臺的本地窗口EGLNativeWindowType數據類型不一樣。
    Android平臺的數據類型是ANativeWindow,像是一份「協議」,規定了一個本地窗口的形態和功能。ANativeWindow是FramebufferNativeWindow的父類。
    Android中,因爲多緩衝技術,EGLNativeWindowType所管理的緩衝區最少2個,最大3個。
    FramebufferNativeWindow初始化須要Golloc支持,步驟以下:

    • 加載GRALLOC_HARDWARE_MODULE_ID模塊,參見上節。
    • 分別打開fb和gralloc設備,打開後的設備由全局變量fbDev和grDev管理。
    • 根據設備的屬性來給FramebufferNativeWindow賦初值。
    • 根據FramebufferNativeWindow的實現來填充ANativeWindow中的「協議」
    • 其餘一些必要的初始化

  ②應用程序的本地窗口 - Surface
    Surface也繼承了ANativeWindow

 class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase>

     Surface是面向Android系統中全部UI應用程序的,即它承擔着應用進程中的UI顯示需求。
    須要面向上層實現(主要是Java層)提供繪製圖像的畫板。SurfaceFlinger須要收集系統中全部應用程序繪製的圖像數據,而後集中顯示到物理屏幕上。Surface須要扮演相應角色,本質上仍是由SurfaceFlinger服務統一管理的,涉及到不少跨進程的通訊細節。

  ③Surface的建立
    Surface將經過mGraphicBufferProducer來獲取buffer,這些緩衝區會被記錄在mSlots中數據中。mGraphicBufferProducer這一核心成員的初始化流程以下:
      ViewRootImpl持有一個Java層的Surface對象(mSurface)。
      ViewRootImpl向WindowManagerService發起relayout請求,此時mSurface被賦予真正的有效值,將展轉生成的SurfaceControl經過Surface.copyFrom()函數複製到mSurface中。
    由此,Surface由SurfaceControl管理,SurfaceControl由SurfaceComposerClient建立。SurfaceComposerClient得到的匿名Binder是ISurfaceComposer,其服務端實現是SurfaceFlinger。而Surface依賴的IGraphicBufferProducer對象在Service端的實現是BufferQueue。

class SurfaceFlinger : 
  public BinderService<SurfaceFlinger>, //在ServiceManager中註冊爲SurfaceFlinger
  public BnSurfaceComposer,//實現的接口卻叫ISurfaceComposer

  ④SurfaceFlinger服務框架:
    Buffer,Consumer,Producer是「生產者-消費者」模型中的3個參與對象,如何協調好它們的工做是應用程序可否正常顯示UI的關鍵。
    Buffer是BufferQueue,Producer是應用程序,Consumer是SurfaceFlinger。

 Surface內部提供一個BufferQueue,與上層和SurfaceFlinger造成一個生產者消費者模型,上層對應Producer,SurfaceFlinger對應Consumer。三者經過Buffer產生聯繫,每一個Buffer都有四種狀態:

  • Free:可被上層使用;
  • Dequeued:出列,正在被上層使用;
  • Queued:入列,已完成上層繪製,等待SurfaceFlinger合成;
  • Acquired:被獲取,SurfaceFlinger正持有該Buffer進行合成;

  如此循環,造成一個Buffer被循環使用的過程(FREE-> DEQUEUED->QUEUED->ACQUIRED->FREE)。

  BufferQueue中的mSlots數組用於管理期內的緩衝區,最大容器是32。數據緩衝區的空間是動態分配的,應用程序與SurfaceFlinger都是使用OpenGL ES來完成UI顯示。Layer類在SurfaceFlinger中表示「層」,通俗地講就是表明了一個「畫面」,最終物理屏幕上的顯示結果就是經過對系統中同時存在的全部「畫面」進行處理疊加而成.

相關文章
相關標籤/搜索