Android P 圖形顯示系統(五) 上層Client和SurfaceFlinger的交互

[TOC]

上層Client和SurfaceFlinger的交互

為了很好的切入主題,我們這里基于Native的Framework進行應用的開發呢,不是指的NDK應用。我們直接用系統接口,進行開發。Native應用直接拋棄掉Android的Java上層,AMS,WMS,View等,直接在Native開發,這樣便于我們理解顯示系統。

Native應用建立

在顯示子系統中,Surface是一個很重要的類,通過Surface我們就能獲取到Buffer,我們就能夠和Android Native窗口系統建立連接。我們就基于Surface來寫一個Native的應用。

首先,我們先定義一個封裝類WindowSurfaceWrapper,WindowSurfaceWrapper和Surface進行交互。

class WindowSurfaceWrapper : public RefBase {
public:
    // Creates the window.
    WindowSurfaceWrapper(const String8& name);

    virtual ~WindowSurfaceWrapper() {}

    virtual void onFirstRef();

    // Retrieves a handle to the window.
    sp<ANativeWindow>  getSurface() const;

    int width() {
        return mWidth;
    }

    int height() {
        return mHeight;
    }

private:
    WindowSurfaceWrapper(const WindowSurfaceWrapper&);
    WindowSurfaceWrapper& operator=(const WindowSurfaceWrapper&);

    sp<SurfaceControl> mSurfaceControl;

    int mWidth;
    int mHeight;
    String8 mName;
};

WindowSurfaceWrapper對應的實現如下:

WindowSurfaceWrapper::WindowSurfaceWrapper(const String8& name) {
    mName = name;
}

void WindowSurfaceWrapper::onFirstRef() {
    status_t err;

    sp<SurfaceComposerClient> surfaceComposerClient = new SurfaceComposerClient;
    err = surfaceComposerClient->initCheck();
    if (err != NO_ERROR) {
        fprintf(stderr, "SurfaceComposerClient::initCheck error: %#x\n", err);
        return;
    }

    // Get main display parameters.
    sp<IBinder> mainDisplay = SurfaceComposerClient::getBuiltInDisplay(
            ISurfaceComposer::eDisplayIdMain);
    DisplayInfo mainDisplayInfo;
    err = SurfaceComposerClient::getDisplayInfo(mainDisplay, &mainDisplayInfo);
    if (err != NO_ERROR) {
        fprintf(stderr, "ERROR: unable to get display characteristics\n");
        return;
    }

    uint32_t width, height;
    if (mainDisplayInfo.orientation != DISPLAY_ORIENTATION_0 &&
            mainDisplayInfo.orientation != DISPLAY_ORIENTATION_180) {
        // rotated
        width = mainDisplayInfo.h;
        height = mainDisplayInfo.w;
    } else {
        width = mainDisplayInfo.w;
        height = mainDisplayInfo.h;
    }

    sp<SurfaceControl> surfaceControl = surfaceComposerClient->createSurface(
            mName, width, height,
            PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque);
    if (surfaceControl == NULL || !surfaceControl->isValid()) {
        fprintf(stderr, "Failed to create SurfaceControl\n");
        return;
    }

    SurfaceComposerClient::Transaction{}
            .setLayer(surfaceControl, 0x7FFFFFFF)
            .show(surfaceControl)
            .apply();

    mSurfaceControl = surfaceControl;
    mWidth = width;
    mHeight = height;

}

sp<ANativeWindow> WindowSurfaceWrapper::getSurface() const {
    sp<ANativeWindow> anw = mSurfaceControl->getSurface();
    return anw;
}

getSurface獲取Native 窗口,這個窗口能夠和Native的窗口系統建立聯系,我們直接往這個窗口里面繪制我們需要的界面就OK了。

int main(int argc, char *argv[]) {
    unsigned samples = 0;
    printf("usage: %s [samples]\n", argv[0]);
    if (argc == 2) {
        samples = atoi( argv[1] );
        printf("Multisample enabled: GL_SAMPLES = %u\n", samples);
    }

    sp<ProcessState> proc(ProcessState::self());
    ProcessState::self()->startThreadPool();

    sp<WindowSurfaceWrapper> windowSurface(new WindowSurfaceWrapper(String8("NativeBinApp")));

    drawNativeWindow(windowSurface->getSurface().get(), windowSurface->width(), windowSurface->height());

    IPCThreadState::self()->joinThreadPool();

    return EXIT_SUCCESS;
}

解釋一下代碼中的關鍵點:

  • 創建一個SurfaceComposerClient,這是應用端,是SurfaceFlinger的Client端,它將建立和SurfaceFlinger服務的通信
  • getDisplayInfo,獲取手機屏幕的信息
  • createSurface,創建SurfaceControl,在SurfaceFlinger創建對應的Layer等~
  • setLayer,設置窗口的z-Oder,SurfaceFlinger根據z-Oder決定窗口的可見性及可見大小
  • show,讓當前窗口可見
  • apply,這時,上面的設置的屬性才真正生效,傳給SurfaceFlinger

至于怎么畫界面,我們接來下再介紹,稍后再給出drawNativeWindow的代碼。我們先來看,目前都干了什么。

應用和SurfaceFlinger的鏈接建立

應用和SurfaceFlinger是兩個不同的進程,他們采用Binder通信,應用是Client端,SurfaceFlinger是服務端。在Android中ProcessState是客戶端和服務端公共的部分,作為Binder通信的基礎,ProcessState是一個singleton類,每個進程只有一個對象,這個對象負責打開Binder驅動,建立線程池,讓其進程里面的所有線程都能通過Binder通信。與之相關的是IPCThreadState,每個線程都有一個IPCThreadState實例登記在Linux線程的上下文附屬數據中,主要負責Binder的讀取,寫入和請求處理框架。IPCThreadState在構造的時候獲取進程的ProcessState并記錄在自己的成員變量mProcess中,通過mProcess可以獲得Binder的句柄。

我們這里將不詳細的介紹Binder。有需求的可以提,我們開一個專題。

SurfaceComposerClient的 定義非常簡單,繼承RefBase~,這樣我們就可以直接用智能指針sp,wp管理SurfaceComposerClient對象,不用擔心SurfaceComposerClient對象的回收問題。

智能指針sp,wp,我們這里也不做詳細的介紹,有需求的可以提,我們開一個專題。

在SurfaceComposerClient的構造函數中,只初始化了一個裝mStatus。

SurfaceComposerClient::SurfaceComposerClient()
    : mStatus(NO_INIT)
{
}

第一次引用的時候,才真正的建立連接:

*frameworks/native/libs/gui/SurfaceComposerClient.cpp

void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != 0 && mStatus == NO_INIT) {
        auto rootProducer = mParent.promote();
        sp<ISurfaceComposerClient> conn;
        conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
                sf->createConnection();
        if (conn != 0) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

ComposerService繼承模板類Singleton,ComposerService是一個單例。

ComposerService::ComposerService()
: Singleton<ComposerService>() {
    Mutex::Autolock _l(mLock);
    connectLocked();
}

ComposerService在構建時,創建鏈接:

void ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");
    while (getService(name, &mComposerService) != NO_ERROR) {
        usleep(250000);
    }
    assert(mComposerService != NULL);

    // Create the death listener.
    class DeathObserver : public IBinder::DeathRecipient {
        ComposerService& mComposerService;
        virtual void binderDied(const wp<IBinder>& who) {
            ALOGW("ComposerService remote (surfaceflinger) died [%p]",
                  who.unsafe_get());
            mComposerService.composerServiceDied();
        }
     public:
        explicit DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }
    };

    mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this));
    IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver);
}

建立連接時,采用輪循的方式,getService時,如果SurfaceFlinger服務還沒有啟動,等待250000后再查詢,知道等到SurffaceFlinger進程啟動。DeathObserver是監聽SurfaceFlinger進程是否死掉,做善后處理的。

getComposerService直接返回單實例mComposerService。

/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
    ComposerService& instance = ComposerService::getInstance();
    Mutex::Autolock _l(instance.mLock);
    if (instance.mComposerService == NULL) {
        ComposerService::getInstance().connectLocked();
        assert(instance.mComposerService != NULL);
        ALOGD("ComposerService reconnected");
    }
    return instance.mComposerService;
}

createScopedConnection函數,將建立和SurfaceFlinger的連接。

void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != 0 && mStatus == NO_INIT) {
        auto rootProducer = mParent.promote();
        sp<ISurfaceComposerClient> conn;
        conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
                sf->createConnection();
        if (conn != 0) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

對于我們這里的使用來說,rootProducer是nullptr,所以直接走的sf->createConnection()。Bn端SurfaceFlinger的實現為:

* frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
    return initClient(new Client(this));
}

static sp<ISurfaceComposerClient> initClient(const sp<Client>& client) {
    status_t err = client->initCheck();
    if (err == NO_ERROR) {
        return client;
    }
    return nullptr;
}

Client繼承BnSurfaceComposerClient,是ISurfaceComposerClient的Bn端。

我們來看一下,顯示系統中,Client和SurfaceFlinger的關系:


Client和SurfaceFlinger間的關系

應用端SurfaceComposerClient通過接口ISurfaceComposerClient和SurfaceFlinger的Client建立聯系。應用端通過的ComposerService通過ISurfaceComposer和SurfaceFlinger建立聯系。

SurfaceFlinger的啟動

SurfaceFlinger是一個系統級的服務,Android系統啟動的過程中就會啟動SurfaceFlinger,在初始化init時。

* frameworks/native/services/surfaceflinger/surfaceflinger.rc

service surfaceflinger /system/bin/surfaceflinger
    class core animation
    user system
    group graphics drmrpc readproc
    onrestart restart zygote
    writepid /dev/stune/foreground/tasks
    socket pdx/system/vr/display/client     stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
    socket pdx/system/vr/display/manager    stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
    socket pdx/system/vr/display/vsync      stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0

既然是獨立的進程,系統級的服務,那就有自己的main函數:

* frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp

int main(int, char**) {
    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();

    // 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);

    // initialize before clients can connect
    flinger->init();

    // publish surface flinger
    sp<IServiceManager> sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
                   IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);

    // 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, &param) != 0) {
        ALOGE("Couldn't set SCHED_FIFO");
    }

    // run surface flinger in this thread
    flinger->run();

    return 0;
}

SurfacFlinger進程中主要4個服務:

  • startHidlServices主要是啟動allocator
  • DisplayService,主要負責DisplayEvent的處理
  • SurfaceFlinger,主要顯示相關的,最重要的服務
  • GpuService,GPU相關的服務,為訪問GPU

SurfaceFlinger類定義如下:

* frameworks/native/services/surfaceflinger/SurfaceFlinger.h

class SurfaceFlinger : public BnSurfaceComposer,
                       public PriorityDumper,
                       private IBinder::DeathRecipient,
                       private HWC2::ComposerCallback

SurfaceComposer是ISurfaceComposer的Bn端。實現了HWC2的ComposerCallback回調。死亡回收DeathRecipient,以及Dump信息PriorityDumper。

構造函數如下:

* frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

SurfaceFlinger::SurfaceFlinger()
    :   BnSurfaceComposer(),
        mTransactionFlags(0),
        mTransactionPending(false),
        mAnimTransactionPending(false),
        mLayersRemoved(false),
        mLayersAdded(false),
        mRepaintEverything(0),
        mBootTime(systemTime()),
        mBuiltinDisplays(),
        mVisibleRegionsDirty(false),
        mGeometryInvalid(false),
        mAnimCompositionPending(false),
        mDebugRegion(0),
        mDebugDDMS(0),
        mDebugDisableHWC(0),
        mDebugDisableTransformHint(0),
        mDebugInSwapBuffers(0),
        mLastSwapBufferTime(0),
        mDebugInTransaction(0),
        mLastTransactionTime(0),
        mBootFinished(false),
        mForceFullDamage(false),
        mInterceptor(this),
        mPrimaryDispSync("PrimaryDispSync"),
        mPrimaryHWVsyncEnabled(false),
        mHWVsyncAvailable(false),
        mHasColorMatrix(false),
        mHasPoweredOff(false),
        mNumLayers(0),
        mVrFlingerRequestsDisplay(false),
        mMainThreadId(std::this_thread::get_id())
{
    ALOGI("SurfaceFlinger is starting");

    vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
            &ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);

    ... ...

    mPrimaryDispSync.init(SurfaceFlinger::hasSyncFramework, SurfaceFlinger::dispSyncPresentTimeOffset);

    // debugging stuff...
    char value[PROPERTY_VALUE_MAX];

    ... ...

    property_get("ro.sf.disable_triple_buffer", value, "1");
    mLayerTripleBufferingDisabled = atoi(value);
    ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering");

    ... ...
}

在構造函數中,主要是做初始化。從Android O開始,vendor的一些配置,都采用configstore的方式提供,就是這里的ISurfaceFlingerConfigs,這是一個系統服務。對應的接口在 hardware/interfaces/configstore/ 。當然,采用屬性進行設置,但是屬性設置的是debug的參數居多。

SurfaceFlinger真正的初始化,是在init函數中:

void SurfaceFlinger::init() {
    ... ...

    Mutex::Autolock _l(mStateLock);

    // start the EventThread
    sp<VSyncSource> vsyncSrc =
            new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
    mEventThread = new EventThread(vsyncSrc, *this, false);
    sp<VSyncSource> sfVsyncSrc =
            new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::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");
    }

    // Get a RenderEngine for the given display / config (can't fail)
    getBE().mRenderEngine = RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,
            hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
    LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine");

    LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
            "Starting with vr flinger active is not currently supported.");
    getBE().mHwc.reset(new HWComposer(getBE().mHwcServiceName));
    getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId);

    if (useVrFlinger) {
        auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
            // This callback is called from the vr flinger dispatch thread. We
            // need to call signalTransaction(), which requires holding
            // mStateLock when we're not on the main thread. Acquiring
            // mStateLock from the vr flinger dispatch thread might trigger a
            // deadlock in surface flinger (see b/66916578), so post a message
            // to be handled on the main thread instead.
            sp<LambdaMessage> message = new LambdaMessage([=]() {
                ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
                mVrFlingerRequestsDisplay = requestDisplay;
                signalTransaction();
            });
            postMessageAsync(message);
        };
        mVrFlinger = dvr::VrFlinger::Create(getBE().mHwc->getComposer(),
                getBE().mHwc->getHwcDisplayId(HWC_DISPLAY_PRIMARY).value_or(0),
                vrFlingerRequestDisplayCallback);
        if (!mVrFlinger) {
            ALOGE("Failed to start vrflinger");
        }
    }

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

    // initialize our drawing state
    mDrawingState = mCurrentState;

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

    getBE().mRenderEngine->primeCache();

    // Inform native graphics APIs whether the present timestamp is supported:
    if (getHwComposer().hasCapability(
            HWC2::Capability::PresentFenceIsNotReliable)) {
        mStartPropertySetThread = new StartPropertySetThread(false);
    } else {
        mStartPropertySetThread = new StartPropertySetThread(true);
    }

    if (mStartPropertySetThread->Start() != NO_ERROR) {
        ALOGE("Run StartPropertySetThread failed!");
    }

    ALOGV("Done initializing");
}

在init函數中,主要做了一下幾件事:

  • 創建兩個EventThread及其DispSyncSource,主要是用以處理和分發如Vsync;App和SurfaceFlinger的如Vsync是分開的,不是同一個。
  • 創建了自己的消息隊列mEventQueue,SurfaceFlinger的消息隊列
  • 初始化了Client合成模式(GPU)合成時,需要用到的RenderEngine
  • 初始化HWComposer,注冊回調接口registerCallback,HAL會回調一些方法。
  • 如果是VR模式,創建mVrFlinger
  • 創建mEventControlThread,處理Event事件,如Vsync事件和hotplug事件。
  • 初始化顯示設備initializeDisplays

SurfaceFlinger第一次引用時,啟動mEventQueue消息隊列

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

SurfaceFlinger這邊后續再繼續,先回到Native應用的創建

獲取Display信息

Android支持多給屏幕,多個屏幕可以顯示一樣的內容,也可以顯示不一樣的內容。我們通常的把他們稱為主顯,外顯和虛顯。主顯就是內置的,默認的手機屏幕;外顯就是HDMI,MHL等連接的屏幕;虛顯,就是虛擬顯示器,通過WFD連接的屏幕,或者是類似屏幕一樣的Buffer消費者。
屏幕都是通過ID來標記的:

* frameworks/native/services/surfaceflinger/DisplayDevice.h

    enum DisplayType {
        DISPLAY_ID_INVALID = -1,
        DISPLAY_PRIMARY     = HWC_DISPLAY_PRIMARY, //主顯
        DISPLAY_EXTERNAL    = HWC_DISPLAY_EXTERNAL, //外顯
        DISPLAY_VIRTUAL     = HWC_DISPLAY_VIRTUAL, //虛顯4
        NUM_BUILTIN_DISPLAY_TYPES = HWC_NUM_PHYSICAL_DISPLAY_TYPES,
    };

通過getBuiltInDisplay,去獲取指定ID的屏幕。

sp<IBinder> SurfaceComposerClient::getBuiltInDisplay(int32_t id) {
    return ComposerService::getComposerService()->getBuiltInDisplay(id);
}

getBuiltInDisplay是一個Binder調用,中間的Binder就省掉了,直接看實現:

sp<IBinder> SurfaceFlinger::getBuiltInDisplay(int32_t id) {
    if (uint32_t(id) >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
        ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id);
        return NULL;
    }
    return mBuiltinDisplays[id];
}

前面初始化的時候,屏幕都是采用熱插拔的形式上報。內置屏幕也是這樣。這個后續再介紹。

獲取屏幕后,通過getDisplayInfo函數,就能獲取屏幕的信息。

    DisplayInfo mainDisplayInfo;
    err = SurfaceComposerClient::getDisplayInfo(mainDisplay, &mainDisplayInfo);
    if (err != NO_ERROR) {
        fprintf(stderr, "ERROR: unable to get display characteristics\n");
        return;
    }

一個屏幕可以有多個config信息,當前再用的是activeconfig。在SurfaceComposerClient中,獲取config信息時,先獲取多有的config信息,再獲取active的config的ID,根據ID去取Display信息。

status_t SurfaceComposerClient::getDisplayInfo(const sp<IBinder>& display,
        DisplayInfo* info) {
    Vector<DisplayInfo> configs;
    status_t result = getDisplayConfigs(display, &configs);
    if (result != NO_ERROR) {
        return result;
    }

    int activeId = getActiveConfig(display);
    if (activeId < 0) {
        ALOGE("No active configuration found");
        return NAME_NOT_FOUND;
    }

    *info = configs[static_cast<size_t>(activeId)];
    return NO_ERROR;
}

getDisplayConfigs還是通過ComposerService去獲取的,走的ISurfaceComposer的接口。

status_t SurfaceComposerClient::getDisplayConfigs(
        const sp<IBinder>& display, Vector<DisplayInfo>* configs)
{
    return ComposerService::getComposerService()->getDisplayConfigs(display, configs);
}

在看SurfaceFlinger中getDisplayConfigs的實現之前。我們先來看DisplayInfo的定義,看看Display信息都包含哪些。看看怎么來描述一個顯示屏幕。

struct DisplayInfo {
    uint32_t w{0}; // 屏幕的寬
    uint32_t h{0}; // 屏幕的高
    float xdpi{0}; // 屏幕的x方向每英寸的像素點
    float ydpi{0}; // 屏幕y方向每英寸的像素點
    float fps{0}; // FPS屏幕的刷新率
    float density{0}; // 屏幕的密度
    uint8_t orientation{0}; // 屏幕的旋轉方式
    bool secure{false}; // 屏幕是否是安全的
    nsecs_t appVsyncOffset{0}; // App的Vsync的偏移
    nsecs_t presentationDeadline{0}; // 顯示的最后時間
};

我們結合SurfaceFlinger中getDisplayConfigs的實現,來說說Display的信息。

  • 首先,根據Display的IBinder,找到Display的類型type。
* frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
        Vector<DisplayInfo>* configs) {
    ... ...

    int32_t type = NAME_NOT_FOUND;
    for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
        if (display == mBuiltinDisplays[i]) {
            type = i;
            break;
        }
    }
  • 在根據type去獲取驅動中配置的信息getConfigs,getHwComposer().getConfigs(type);
    ConditionalLock _l(mStateLock,
            std::this_thread::get_id() != mMainThreadId);
    for (const auto& hwConfig : getHwComposer().getConfigs(type)) {
  • 最后,根據驅動給的配置,和一些設置,構建完整的顯示屏信息,下面是關鍵信息,刪掉了一些log和注解。
    for (const auto& hwConfig : getHwComposer().getConfigs(type)) {
        DisplayInfo info = DisplayInfo();

        float xdpi = hwConfig->getDpiX();
        float ydpi = hwConfig->getDpiY();

        if (type == DisplayDevice::DISPLAY_PRIMARY) {
            float density = Density::getBuildDensity() / 160.0f;
            if (density == 0) {
                density = xdpi / 160.0f;
            }
            if (Density::getEmuDensity()) {
                xdpi = ydpi = density = Density::getEmuDensity();
                density /= 160.0f;
            }
            info.density = density;

            sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
            info.orientation = hw->getOrientation();
        } else {
            static const int TV_DENSITY = 213;
            info.density = TV_DENSITY / 160.0f;
            info.orientation = 0;
        }

        info.w = hwConfig->getWidth();
        info.h = hwConfig->getHeight();
        info.xdpi = xdpi;
        info.ydpi = ydpi;
        info.fps = 1e9 / hwConfig->getVsyncPeriod();
        info.appVsyncOffset = vsyncPhaseOffsetNs;

        ... ...
        info.presentationDeadline = hwConfig->getVsyncPeriod() -
                sfVsyncPhaseOffsetNs + 1000000;

        // All non-virtual displays are currently considered secure.
        info.secure = true;

        configs->push_back(info);
    }

    return NO_ERROR;
}

屏幕信息:

  • 屏幕寬高(W*H)
    屏幕的寬高是用分辨率來描述的,也就是像素點的多少。像素是指在由一個數字序列表示的圖像中的一個最小單位,稱為像素。屏幕多寬,就是指,屏幕橫向可以顯示多少個像素點。屏幕多高就是指,屏幕縱向可以顯示多少給像素點。平常所說的720P屏幕,就是1080x720,橫向可以顯示1080個像素點,縱向可以顯示720個像素點。
    此圖是,平常什么所說的一些分辨率:


    常用的分辨率
  • 每英寸的點數xdpi,ydpi
    顯示屏幕的物理大小,用英寸來描述,描述屏幕對角線的長度。比如iPhoneX 5.8英寸,指的是對角線的長度5.8英寸。而dpi,即Dots Per Inch,表示每英寸有多少給點。百度百科的解釋為,dpi是一個量度單位,用于點陣數碼影像,指每一英寸長度中,取樣、可顯示或輸出點的數目。
    PPI(pixels per inch)和DPI是措辭的差別,很多時候,都是混用的。如iPhoneX是458 ppi;榮耀V9的DPI為488左右。

  • density密度
    這里的desity是一個縮放因子,是 DPI / (160像素/英寸) 后得到的值,是一個比例值。
    這可以看DisplayMetrics中關于density的定義:

frameworks/base/core/java/android/util/DisplayMetrics.java

    /**
     * The logical density of the display.  This is a scaling factor for the
     * Density Independent Pixel unit, where one DIP is one pixel on an
     * approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen), 
     * providing the baseline of the system's display. Thus on a 160dpi screen 
     * this density value will be 1; on a 120 dpi screen it would be .75; etc.
     *
     * <p>This value does not exactly follow the real screen size (as given by 
     * {@link #xdpi} and {@link #ydpi}, but rather is used to scale the size of
     * the overall UI in steps based on gross changes in the display dpi.  For 
     * example, a 240x320 screen will have a density of 1 even if its width is 
     * 1.8", 1.3", etc. However, if the screen resolution is increased to 
     * 320x480 but the screen size remained 1.5"x2" then the density would be 
     * increased (probably to 1.5).
     *
     * @see #DENSITY_DEFAULT
     */
    public float density;

以設備無關像素DIP(device independent pixels)在160dpi屏幕上顯示為基礎。160dip在160dpi的屏幕上,density就是1,在120dpi的屏幕上,density就為0.75。

  • 屏幕刷新率FPS
    FPS(Frame per second),幀每秒。表示屏幕一描述,可以顯示多少幀圖像數據。目前多少的手機顯示屏還是60FPS,顯示一幀16.67ms左右。

  • orientation屏幕旋轉方向
    手機默認豎屏,0度豎屏。

/* Display orientations as defined in Surface.java and ISurfaceComposer.h. */
enum {
    DISPLAY_ORIENTATION_0 = 0,
    DISPLAY_ORIENTATION_90 = 1,
    DISPLAY_ORIENTATION_180 = 2,
    DISPLAY_ORIENTATION_270 = 3
};
  • 屏幕是否安全secure
    這主要是用于DRM(數字版權保護)時,確保顯示的設備是安全的,以防止DRM的內容被在顯示的過程中被截取。只有安全的設備才能顯示DRM的內容。
    Android默認,所有的非虛擬顯示都是安全的。
        // All non-virtual displays are currently considered secure.
        info.secure = true;
  • appVsyncOffset和presentationDeadline
    這兩個都和 Vsync有關,后續會再介紹。appVsyncOffset是一個偏移量,在系統(或硬件Vsync)的基礎上做一些偏移。presentationDeadline表示,一幀數據,多就內,必現要顯示出來。

Ok~到此,SurfaceComposerClient端就拿到了多個config信息了,在configs中。

Active config,就是當前被激活使用的:

int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) {
    if (display == NULL) {
        ALOGE("%s : display is NULL", __func__);
        return BAD_VALUE;
    }

    sp<const DisplayDevice> device(getDisplayDevice(display));
    if (device != NULL) {
        return device->getActiveConfig();
    }

    return BAD_VALUE;
}

SurfaceFlinger服務中,Display的描述,用的DisplayDevice。每添加一個顯示屏,都會創建一個DisplayDevice。

int DisplayDevice::getActiveConfig()  const {
    return mActiveConfig;
}

activeconfig,是一個索引值,對應驅動中,對應的config的索引。一般來說,active的config,都是默認的0。當然SurfaceFlinger或上層是可以去設置的。

void DisplayDevice::setActiveConfig(int mode) {
    mActiveConfig = mode;
}

回到應用~

Native創建圖層Layer

拿到顯示信息后,根據轉屏,這邊的尺寸需要做一下交換。因為不關屏幕怎么旋轉,我們需要顯示的內容大小是沒有變的。

    uint32_t width, height;
    if (mainDisplayInfo.orientation != DISPLAY_ORIENTATION_0 &&
            mainDisplayInfo.orientation != DISPLAY_ORIENTATION_180) {
        // rotated
        width = mainDisplayInfo.h;
        height = mainDisplayInfo.w;
    } else {
        width = mainDisplayInfo.w;
        height = mainDisplayInfo.h;
    }

接下里,就可以創建圖層了。

    sp<SurfaceControl> surfaceControl = surfaceComposerClient->createSurface(
            mName, width, height,
            PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque);
    if (surfaceControl == NULL || !surfaceControl->isValid()) {
        fprintf(stderr, "Failed to create SurfaceControl\n");
        return;
    }

createSurface函數如下:

sp<SurfaceControl> SurfaceComposerClient::createSurface(
        const String8& name,
        uint32_t w,
        uint32_t h,
        PixelFormat format,
        uint32_t flags,
        SurfaceControl* parent,
        uint32_t windowType,
        uint32_t ownerUid)
{
    sp<SurfaceControl> sur;
    if (mStatus == NO_ERROR) {
        sp<IBinder> handle;
        sp<IBinder> parentHandle;
        sp<IGraphicBufferProducer> gbp;

        if (parent != nullptr) {
            parentHandle = parent->getHandle();
        }
        status_t err = mClient->createSurface(name, w, h, format, flags, parentHandle,
                windowType, ownerUid, &handle, &gbp);
        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
        if (err == NO_ERROR) {
            sur = new SurfaceControl(this, handle, gbp);
        }
    }
    return sur;
}

先解釋一下,其中的參數:

  • name
    name就是圖層的名字,沒有實際意義,主要是便于debug,有有名字,就可以知道,我們創建的圖層是哪個了。

  • w,h
    這個是圖層的寬高,我們用只是從DisplayInfo中讀出來的,跟屏幕的大小一樣。

  • format
    圖層的格式,應用中,我們用的格式是PIXEL_FORMAT_RGBX_8888。

我們通過RGB,紅,綠,藍,三原色可以調配所有的顏色。在數字世界里面,也是用RGB來表示顏色,外加一個Alpha通道,就是RGBA。
RGBA_8888,表示R,G,B,A分別用8bit表示。也就是說,R的取值范圍為0255。R從0255,表示最不紅到最紅,值的大小,表示紅的程度不同。

同樣,Alpha A,也是表示透明的程度,RGBX中的X表示,X為255,不透明。

下面是Android中,常用的一些格式。

* frameworks/native/libs/ui/include/ui/PixelFormat.h

enum {
    //
    // these constants need to match those
    // in graphics/PixelFormat.java & pixelflinger/format.h
    //
    PIXEL_FORMAT_UNKNOWN    =   0,
    PIXEL_FORMAT_NONE       =   0,

    // logical pixel formats used by the SurfaceFlinger -----------------------
    PIXEL_FORMAT_CUSTOM         = -4,
        // Custom pixel-format described by a PixelFormatInfo structure

    PIXEL_FORMAT_TRANSLUCENT    = -3,
        // System chooses a format that supports translucency (many alpha bits)

    PIXEL_FORMAT_TRANSPARENT    = -2,
        // System chooses a format that supports transparency
        // (at least 1 alpha bit)

    PIXEL_FORMAT_OPAQUE         = -1,
        // System chooses an opaque format (no alpha bits required)

    // real pixel formats supported for rendering -----------------------------

    PIXEL_FORMAT_RGBA_8888    = HAL_PIXEL_FORMAT_RGBA_8888,    // 4x8-bit RGBA
    PIXEL_FORMAT_RGBX_8888    = HAL_PIXEL_FORMAT_RGBX_8888,    // 4x8-bit RGB0
    PIXEL_FORMAT_RGB_888      = HAL_PIXEL_FORMAT_RGB_888,      // 3x8-bit RGB
    PIXEL_FORMAT_RGB_565      = HAL_PIXEL_FORMAT_RGB_565,      // 16-bit RGB
    PIXEL_FORMAT_BGRA_8888    = HAL_PIXEL_FORMAT_BGRA_8888,    // 4x8-bit BGRA
    PIXEL_FORMAT_RGBA_5551    = 6,                             // 16-bit ARGB
    PIXEL_FORMAT_RGBA_4444    = 7,                             // 16-bit ARGB
    PIXEL_FORMAT_RGBA_FP16    = HAL_PIXEL_FORMAT_RGBA_FP16,    // 64-bit RGBA
    PIXEL_FORMAT_RGBA_1010102 = HAL_PIXEL_FORMAT_RGBA_1010102, // 32-bit RGBA
};
  • flags
    createSurface時,可用的flag如下:
* frameworks/native/libs/gui/include/gui/ISurfaceComposerClient.h

    // flags for createSurface()
    enum { // (keep in sync with Surface.java)
        eHidden = 0x00000004,
        eDestroyBackbuffer = 0x00000020,
        eSecure = 0x00000080,
        eNonPremultiplied = 0x00000100,
        eOpaque = 0x00000400,
        eProtectedByApp = 0x00000800,
        eProtectedByDRM = 0x00001000,
        eCursorWindow = 0x00002000,

        eFXSurfaceNormal = 0x00000000,
        eFXSurfaceColor = 0x00020000,
        eFXSurfaceMask = 0x000F0000,
    };
Flag 作用 說明
eHidden 隱藏 表示Layer是不可見的
eDestroyBackbuffer 銷毀Back Buffer 表示Layer不保存Back Buffer
eSecure 安全layer 表示安全的Layer,只能顯示在Secure屏幕上
eNonPremultiplied 非自左乘 針對Alpha通道的,如果沒有Alpha通道沒有實際意義
eOpaque 非透明的 表示Layer不是透明的
eProtectedByApp 應用保護 應用將請求一個安全的硬件通道傳輸到外顯
eProtectedByDRM DRM保護 應用請求一個安全的通道傳輸DRM
eCursorWindow Cursor Layer 其實這Layer就是鼠標一類的圖標
eFXSurfaceNormal 普通的Layer 系統中大多數layer都是此類
eFXSurfaceColor 顏色layer 在之前的版本中,這個被稱為Dim Layer
  • windowType
    窗口類型,可以參照WindowManager.java中的定義,如FIRST_SYSTEM_WINDOW,TYPE_STATUS_BAR等。默認值為0。
  • ownerUid
    可以指定這個是哪個UID的Layer。

繼續看createSurfface,Service端的實現如下:

status_t Client::createSurface(
        const String8& name,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        const sp<IBinder>& parentHandle, uint32_t windowType, uint32_t ownerUid,
        sp<IBinder>* handle,
        sp<IGraphicBufferProducer>* gbp)
{
    sp<Layer> parent = nullptr;
    ... ...

    /*
     * createSurface must be called from the GL thread so that it can
     * have access to the GL context.
     */
    class MessageCreateLayer : public MessageBase {
        ... ...
    public:
        MessageCreateLayer(SurfaceFlinger* flinger,
                const String8& name, Client* client,
                uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
                sp<IBinder>* handle, uint32_t windowType, uint32_t ownerUid,
                sp<IGraphicBufferProducer>* gbp,
                sp<Layer>* parent)
            : flinger(flinger), client(client),
              handle(handle), gbp(gbp), result(NO_ERROR),
              name(name), w(w), h(h), format(format), flags(flags),
              parent(parent), windowType(windowType), ownerUid(ownerUid) {
        }
        status_t getResult() const { return result; }
        virtual bool handler() {
            result = flinger->createLayer(name, client, w, h, format, flags,
                    windowType, ownerUid, handle, gbp, parent);
            return true;
        }
    };

    sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
            name, this, w, h, format, flags, handle,
            windowType, ownerUid, gbp, &parent);
    mFlinger->postMessageSync(msg);
    return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
}

Client類中,創建Layer時,先找到parent Layer,對于我們的應用來說,是沒有parent Layer的。然后再postMessageSync到SurfaceFlinger中,去創建,調用的SurfaceFlinger的createLayer方法。

SurfaceFlinger中,都是采用post Message的形式調到SurfaceFlinger的主線程中。

status_t SurfaceFlinger::createLayer(
        const String8& name,
        const sp<Client>& client,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        uint32_t windowType, uint32_t ownerUid, sp<IBinder>* handle,
        sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent)
{
    if (int32_t(w|h) < 0) {
        ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
                int(w), int(h));
        return BAD_VALUE;
    }

    status_t result = NO_ERROR;

    sp<Layer> layer;

    String8 uniqueName = getUniqueLayerName(name);

    switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
        case ISurfaceComposerClient::eFXSurfaceNormal:
            result = createBufferLayer(client,
                    uniqueName, w, h, flags, format,
                    handle, gbp, &layer);

            break;
        case ISurfaceComposerClient::eFXSurfaceColor:
            result = createColorLayer(client,
                    uniqueName, w, h, flags,
                    handle, &layer);
            break;
        default:
            result = BAD_VALUE;
            break;
    }

    if (result != NO_ERROR) {
        return result;
    }

    // window type is WINDOW_TYPE_DONT_SCREENSHOT from SurfaceControl.java
    // TODO b/64227542
    if (windowType == 441731) {
        windowType = 2024; // TYPE_NAVIGATION_BAR_PANEL
        layer->setPrimaryDisplayOnly();
    }

    layer->setInfo(windowType, ownerUid);

    result = addClientLayer(client, *handle, *gbp, layer, *parent);
    if (result != NO_ERROR) {
        return result;
    }
    mInterceptor.saveSurfaceCreation(layer);

    setTransactionFlags(eTransactionNeeded);
    return result;
}

getUniqueLayerName,確保Layer 的name沒有重名。

SurfaceFlinger中,主要處理兩中類似的Layer,eFXSurfaceNormal和eFXSurfaceColor。兩種類似分別有createBufferLayer和createColorLayer兩個接口實現。怎么創建的這里就不介紹了,后續再介紹。

addClientLayer做了什么:

status_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
        const sp<IBinder>& handle,
        const sp<IGraphicBufferProducer>& gbc,
        const sp<Layer>& lbc,
        const sp<Layer>& parent)
{
    // add this layer to the current state list
    {
        Mutex::Autolock _l(mStateLock);
        if (mNumLayers >= MAX_LAYERS) {
            ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers,
                  MAX_LAYERS);
            return NO_MEMORY;
        }
        if (parent == nullptr) {
            mCurrentState.layersSortedByZ.add(lbc);
        } else {
            if (parent->isPendingRemoval()) {
                ALOGE("addClientLayer called with a removed parent");
                return NAME_NOT_FOUND;
            }
            parent->addChild(lbc);
        }

        mGraphicBufferProducerList.add(IInterface::asBinder(gbc));
        mLayersAdded = true;
        mNumLayers++;
    }

    // attach this layer to the client
    client->attachLayer(handle, lbc);

    return NO_ERROR;
}

將新創建的Layer添加到當前的layer列表中,按照Z-order。如果有parent的,添加到parent中。mGraphicBufferProducerList保存了當前的所有Layer內容的生產者。最后,將Layer關聯的Client上。

Layer創建完成后,調用setTransactionFlags函數,告訴SurfaceFlinger,新增加了Layer,有新的顯示,有很多顯示數據需要去更新。SurfaceFlinger根據flag,決定是否需要換醒服務。

uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) {
    uint32_t old = android_atomic_or(flags, &mTransactionFlags);
    if ((old & flags)==0) { // wake the server up
        signalTransaction();
    }
    return old;
}

Layer創建完成,回到我們的應用~

處理狀態的傳送

應用的代碼如下:

    SurfaceComposerClient::Transaction{}
            .setLayer(surfaceControl, 0x7FFFFFFF)
            .show(surfaceControl)
            .apply();

C++的新特性,是不是有點類似Java了。

從Android P開始,google又重構了這一塊的代碼。之前的代碼中,是SurfaceComposerClient提供全局的狀態處理;從Android P開始,transactions 被區分為不同的對象,直接處理對象。這是Transaction一個類圖。


Transaction類圖

可見,將處理類型分為了兩類:

  • ComposerState 合成處理狀態
struct ComposerState {
    sp<ISurfaceComposerClient> client;
    layer_state_t state;
    status_t    write(Parcel& output) const;
    status_t    read(const Parcel& input);
};

ComposerState封裝了layer_state_t,Layer的狀態,再實現Binder通信時的write,read。

  • DisplayState 顯示屏狀態
struct DisplayState {

    enum {
        eOrientationDefault     = 0,
        eOrientation90          = 1,
        eOrientation180         = 2,
        eOrientation270         = 3,
        eOrientationUnchanged   = 4,
        eOrientationSwapMask    = 0x01
    };

    enum {
        eSurfaceChanged             = 0x01,
        eLayerStackChanged          = 0x02,
        eDisplayProjectionChanged   = 0x04,
        eDisplaySizeChanged         = 0x08
    };

    DisplayState();
    void merge(const DisplayState& other);

    uint32_t what;
    sp<IBinder> token;
    sp<IGraphicBufferProducer> surface;
    uint32_t layerStack;
    uint32_t orientation;
    Rect viewport;
    Rect frame;
    uint32_t width, height;
    status_t write(Parcel& output) const;
    status_t read(const Parcel& input);
};

Display的狀態目前就4個,也就是

    enum {
        eSurfaceChanged             = 0x01, // Surface改變了
        eLayerStackChanged          = 0x02, // layerStack改變了
        eDisplayProjectionChanged   = 0x04, // Display的Projection改變了
        eDisplaySizeChanged         = 0x08 // Size改變了
    };

這里的what,就是用以標記mark到底是哪個屬性改變了,有多個屬性改變的時候,加上對應的mark標記位即可。

ComposerState中的layer_state_t和這里的DisplayState類似。也是采用what來標記的。Layer的狀態處理,包括以下屬性。

    enum {
        ePositionChanged            = 0x00000001,
        eLayerChanged               = 0x00000002,
        eSizeChanged                = 0x00000004,
        eAlphaChanged               = 0x00000008,
        eMatrixChanged              = 0x00000010,
        eTransparentRegionChanged   = 0x00000020,
        eFlagsChanged               = 0x00000040,
        eLayerStackChanged          = 0x00000080,
        eCropChanged                = 0x00000100,
        eDeferTransaction           = 0x00000200,
        eFinalCropChanged           = 0x00000400,
        eOverrideScalingModeChanged = 0x00000800,
        eGeometryAppliesWithResize  = 0x00001000,
        eReparentChildren           = 0x00002000,
        eDetachChildren             = 0x00004000,
        eRelativeLayerChanged       = 0x00008000,
        eReparent                   = 0x00010000,
        eColorChanged               = 0x00020000
    };

好了,讓我們通過本實例中的示例,來看看狀態處理是怎么傳遞,生效的。

setLayer,實際上是設置Layer的z-order,

SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer(
        const sp<SurfaceControl>& sc, int32_t z) {
    layer_state_t* s = getLayerStateLocked(sc);
    if (!s) {
        mStatus = BAD_INDEX;
        return *this;
    }
    s->what |= layer_state_t::eLayerChanged;
    s->z = z;
    return *this;
}

getLayerStateLocked,就是根據SurfaceCotrol對象去找,對應的layer_state_t。

layer_state_t* SurfaceComposerClient::Transaction::getLayerStateLocked(const sp<SurfaceControl>& sc) {
    ComposerState s;
    s.client = sc->getClient()->mClient;
    s.state.surface = sc->getHandle();

    ssize_t index = mComposerStates.indexOf(s);
    if (index < 0) {
        // we don't have it, add an initialized layer_state to our list
        index = mComposerStates.add(s);
    }

    ComposerState* const out = mComposerStates.editArray();
    return &(out[index].state);
}

我們看,setLayer時,增加mask標識what是layer_state_t::eLayerChanged,而對應的值保存到layer_state_t z中。注意,這里的設置并沒有立即生效。

同樣,show時,也是將對應的mask表示加到what中,而是否顯示的標識存放在layer_state_t的flag中。

SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::show(
        const sp<SurfaceControl>& sc) {
    return setFlags(sc, 0, layer_state_t::eLayerHidden);
}

SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFlags(
        const sp<SurfaceControl>& sc, uint32_t flags,
        uint32_t mask) {
    layer_state_t* s = getLayerStateLocked(sc);
    if (!s) {
        mStatus = BAD_INDEX;
        return *this;
    }
    if ((mask & layer_state_t::eLayerOpaque) ||
            (mask & layer_state_t::eLayerHidden) ||
            (mask & layer_state_t::eLayerSecure)) {
        s->what |= layer_state_t::eFlagsChanged;
    }
    s->flags &= ~mask;
    s->flags |= (flags & mask);
    s->mask |= mask;
    return *this;
}

我們設置的處理狀態,在apply時,才生效。

status_t SurfaceComposerClient::Transaction::apply(bool synchronous) {
    if (mStatus != NO_ERROR) {
        return mStatus;
    }

    sp<ISurfaceComposer> sf(ComposerService::getComposerService());

    Vector<ComposerState> composerStates;
    Vector<DisplayState> displayStates;
    uint32_t flags = 0;

    mForceSynchronous |= synchronous;

    composerStates = mComposerStates;
    mComposerStates.clear();

    displayStates = mDisplayStates;
    mDisplayStates.clear();

    if (mForceSynchronous) {
        flags |= ISurfaceComposer::eSynchronous;
    }
    if (mAnimation) {
        flags |= ISurfaceComposer::eAnimation;
    }

    mForceSynchronous = false;
    mAnimation = false;

    sf->setTransactionState(composerStates, displayStates, flags);
    mStatus = NO_ERROR;
    return NO_ERROR;
}

apply時,最重要的就是調用setTransactionState,

void SurfaceFlinger::setTransactionState(
        const Vector<ComposerState>& state,
        const Vector<DisplayState>& displays,
        uint32_t flags)
{
    ATRACE_CALL();
    Mutex::Autolock _l(mStateLock);
    uint32_t transactionFlags = 0;

    if (flags & eAnimation) {
        ... ...
        // Animation flag的處理,在Androd P上很少用到,重要是用做模擬back-pressure
    }

    // 處理Display State
    size_t count = displays.size();
    for (size_t i=0 ; i<count ; i++) {
        const DisplayState& s(displays[i]);
        transactionFlags |= setDisplayStateLocked(s);
    }

    // 處理layer State
    count = state.size();
    for (size_t i=0 ; i<count ; i++) {
        const ComposerState& s(state[i]);
        ... ...
        if (s.client != NULL) {
            sp<IBinder> binder = IInterface::asBinder(s.client);
            if (binder != NULL) {
                if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) != NULL) {
                    sp<Client> client( static_cast<Client *>(s.client.get()) );
                    transactionFlags |= setClientStateLocked(client, s.state);
                }
            }
        }
    }

    // 處理假動畫和同步模式
    if (transactionFlags == 0 &&
            ((flags & eSynchronous) || (flags & eAnimation))) {
        transactionFlags = eTransactionNeeded;
    }

    if (transactionFlags) {
       ... ...
    }
}

SurfaceFlinger中,處理狀態是怎么工作的呢?

SurfaceF中,有兩個狀態: mCurrentStatemDrawingState

  • mCurrentState主要是用作接受Client的處理變更請求;需要狀態鎖mStateLock的保護
  • mDrawingState主要用作,控制合成;只能在SurfaceFlinger的主線程中使用,不需要鎖的保護。

其實這很好理解,每個狀態中都有顯示數據及其處理的描述。mCurrentState在做顯示數據的準備,mDrawingState狀態,就是將顯示數據合成送給Display。兩個處理同時進行,兩個都處理完后,再將mCurrentState處理狀態,給到mDrawingState。主線程根據mDrawingState中描述的顯示數據和處理,把數據進行合成。

狀態的處理,同樣分為Display和Layer。
Client端采用Mask標記的方式,標記處理狀態的改變。SurfaceFlinger這邊收到后,根據mask標記,再將參數還原出來。保存到mCurrentState中。Display狀態的處理如下:

uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s)
{
    ssize_t dpyIdx = mCurrentState.displays.indexOfKey(s.token);
    if (dpyIdx < 0)
        return 0;

    uint32_t flags = 0;
    DisplayDeviceState& disp(mCurrentState.displays.editValueAt(dpyIdx));
    if (disp.isValid()) {
        const uint32_t what = s.what;
        ... ...
        if (what & DisplayState::eDisplaySizeChanged) {
            if (disp.width != s.width) {
                disp.width = s.width;
                flags |= eDisplayTransactionNeeded;
            }
            if (disp.height != s.height) {
                disp.height = s.height;
                flags |= eDisplayTransactionNeeded;
            }
        }
    }
    return flags;
}

Layer狀態的處理也是類似的,我們來看一下z-order的處理。

uint32_t SurfaceFlinger::setClientStateLocked(
        const sp<Client>& client,
        const layer_state_t& s)
{
    ... ...
    if (what & layer_state_t::eLayerChanged) {
        // NOTE: index needs to be calculated before we update the state
        const auto& p = layer->getParent();
        if (p == nullptr) {
            ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
            if (layer->setLayer(s.z) && idx >= 0) {
                mCurrentState.layersSortedByZ.removeAt(idx);
                mCurrentState.layersSortedByZ.add(layer);
                // we need traversal (state changed)
                // AND transaction (list changed)
                flags |= eTransactionNeeded|eTraversalNeeded;
            }
        } else {
            if (p->setChildLayer(layer, s.z)) {
                flags |= eTransactionNeeded|eTraversalNeeded;
            }
        }
    }
    ... ...
}

SurfaceFlinger有兩個狀態,Layer也是有兩個狀態的。

bool Layer::setLayer(int32_t z) {
    if (mCurrentState.z == z) return false;
    mCurrentState.sequence++;
    mCurrentState.z = z;
    mCurrentState.modified = true;

    // Discard all relative layering.
    if (mCurrentState.zOrderRelativeOf != nullptr) {
        sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
        if (strongRelative != nullptr) {
            strongRelative->removeZOrderRelative(this);
        }
        mCurrentState.zOrderRelativeOf = nullptr;
    }
    setTransactionFlags(eTransactionNeeded);
    return true;
}

到此,我們的WindowSurfaceWrapper基本算構建完成。

小結

本章從Native應用的角度出發,講解了應用怎么和SurfaceFlinger建立聯系,同時介紹了SurfaceFlinger的啟動。我們做應用開發,坑需要根據實際的屏幕參數來做,所以介紹了怎么獲取顯示屏參數信息;SurfaceFlinger中顯示的數據都是通過Layer進行封裝,介紹了創建Layer的過程。最后,介紹了,顯示的數據參數,也就說處理的狀態,怎么從Client端傳到SurfaceFlinger的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容