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

[TOC]

上層Client和SurfaceFlinger的交互

為了很好的切入主題滞谢,我們這里基于Native的Framework進行應(yīng)用的開發(fā)呢运吓,不是指的NDK應(yīng)用淀歇。我們直接用系統(tǒng)接口逼纸,進行開發(fā)歌亲。Native應(yīng)用直接拋棄掉Android的Java上層,AMS疾就,WMS澜术,View等,直接在Native開發(fā)猬腰,這樣便于我們理解顯示系統(tǒng)鸟废。

Native應(yīng)用建立

在顯示子系統(tǒng)中,Surface是一個很重要的類漆诽,通過Surface我們就能獲取到Buffer侮攀,我們就能夠和Android Native窗口系統(tǒng)建立連接锣枝。我們就基于Surface來寫一個Native的應(yīng)用厢拭。

首先,我們先定義一個封裝類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對應(yīng)的實現(xiàn)如下:

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的窗口系統(tǒng)建立聯(lián)系陨闹,我們直接往這個窗口里面繪制我們需要的界面就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;
}

解釋一下代碼中的關(guān)鍵點:

  • 創(chuàng)建一個SurfaceComposerClient,這是應(yīng)用端趋厉,是SurfaceFlinger的Client端寨闹,它將建立和SurfaceFlinger服務(wù)的通信
  • getDisplayInfo,獲取手機屏幕的信息
  • createSurface君账,創(chuàng)建SurfaceControl繁堡,在SurfaceFlinger創(chuàng)建對應(yīng)的Layer等~
  • setLayer,設(shè)置窗口的z-Oder乡数,SurfaceFlinger根據(jù)z-Oder決定窗口的可見性及可見大小
  • show椭蹄,讓當前窗口可見
  • apply,這時净赴,上面的設(shè)置的屬性才真正生效绳矩,傳給SurfaceFlinger

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

應(yīng)用和SurfaceFlinger的鏈接建立

應(yīng)用和SurfaceFlinger是兩個不同的進程写妥,他們采用Binder通信拳球,應(yīng)用是Client端,SurfaceFlinger是服務(wù)端珍特。在Android中ProcessState是客戶端和服務(wù)端公共的部分祝峻,作為Binder通信的基礎(chǔ),ProcessState是一個singleton類扎筒,每個進程只有一個對象莱找,這個對象負責(zé)打開Binder驅(qū)動,建立線程池嗜桌,讓其進程里面的所有線程都能通過Binder通信奥溺。與之相關(guān)的是IPCThreadState,每個線程都有一個IPCThreadState實例登記在Linux線程的上下文附屬數(shù)據(jù)中骨宠,主要負責(zé)Binder的讀取浮定,寫入和請求處理框架。IPCThreadState在構(gòu)造的時候獲取進程的ProcessState并記錄在自己的成員變量mProcess中层亿,通過mProcess可以獲得Binder的句柄桦卒。

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

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

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

在SurfaceComposerClient的構(gòu)造函數(shù)中快压,只初始化了一個裝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在構(gòu)建時,創(chuàng)建鏈接:

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服務(wù)還沒有啟動,等待250000后再查詢沪曙,知道等到SurffaceFlinger進程啟動奕污。DeathObserver是監(jiān)聽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函數(shù),將建立和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的實現(xiàn)為:

* 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端。

我們來看一下顶燕,顯示系統(tǒng)中凑保,Client和SurfaceFlinger的關(guān)系:


Client和SurfaceFlinger間的關(guān)系

應(yīng)用端SurfaceComposerClient通過接口ISurfaceComposerClient和SurfaceFlinger的Client建立聯(lián)系。應(yīng)用端通過的ComposerService通過ISurfaceComposer和SurfaceFlinger建立聯(lián)系涌攻。

SurfaceFlinger的啟動

SurfaceFlinger是一個系統(tǒng)級的服務(wù)欧引,Android系統(tǒng)啟動的過程中就會啟動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

既然是獨立的進程维咸,系統(tǒng)級的服務(wù)剂买,那就有自己的main函數(shù):

* 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個服務(wù):

  • startHidlServices主要是啟動allocator
  • DisplayService惠爽,主要負責(zé)DisplayEvent的處理
  • SurfaceFlinger,主要顯示相關(guān)的瞬哼,最重要的服務(wù)
  • GpuService婚肆,GPU相關(guān)的服務(wù),為訪問GPU

SurfaceFlinger類定義如下:

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

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

SurfaceComposer是ISurfaceComposer的Bn端坐慰。實現(xiàn)了HWC2的ComposerCallback回調(diào)较性。死亡回收DeathRecipient,以及Dump信息PriorityDumper结胀。

構(gòu)造函數(shù)如下:

* 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");

    ... ...
}

在構(gòu)造函數(shù)中赞咙,主要是做初始化。從Android O開始糟港,vendor的一些配置攀操,都采用configstore的方式提供,就是這里的ISurfaceFlingerConfigs秸抚,這是一個系統(tǒng)服務(wù)速和。對應(yīng)的接口在 hardware/interfaces/configstore/ 歹垫。當然,采用屬性進行設(shè)置颠放,但是屬性設(shè)置的是debug的參數(shù)居多排惨。

SurfaceFlinger真正的初始化,是在init函數(shù)中:

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函數(shù)中碰凶,主要做了一下幾件事:

  • 創(chuàng)建兩個EventThread及其DispSyncSource暮芭,主要是用以處理和分發(fā)如Vsync;App和SurfaceFlinger的如Vsync是分開的欲低,不是同一個谴麦。
  • 創(chuàng)建了自己的消息隊列mEventQueue,SurfaceFlinger的消息隊列
  • 初始化了Client合成模式(GPU)合成時伸头,需要用到的RenderEngine
  • 初始化HWComposer,注冊回調(diào)接口registerCallback恤磷,HAL會回調(diào)一些方法。
  • 如果是VR模式魔策,創(chuàng)建mVrFlinger
  • 創(chuàng)建mEventControlThread闯袒,處理Event事件,如Vsync事件和hotplug事件游岳。
  • 初始化顯示設(shè)備initializeDisplays

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

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

SurfaceFlinger這邊后續(xù)再繼續(xù),先回到Native應(yīng)用的創(chuàng)建

獲取Display信息

Android支持多給屏幕胚迫,多個屏幕可以顯示一樣的內(nèi)容喷户,也可以顯示不一樣的內(nèi)容。我們通常的把他們稱為主顯访锻,外顯和虛顯褪尝。主顯就是內(nèi)置的,默認的手機屏幕期犬;外顯就是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調(diào)用,中間的Binder就省掉了古涧,直接看實現(xiàn):

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];
}

前面初始化的時候算芯,屏幕都是采用熱插拔的形式上報职祷。內(nèi)置屏幕也是這樣。這個后續(xù)再介紹。

獲取屏幕后痰催,通過getDisplayInfo函數(shù),就能獲取屏幕的信息夹攒。

    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,根據(jù)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中g(shù)etDisplayConfigs的實現(xiàn)之前针史。我們先來看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}; // 屏幕的旋轉(zhuǎn)方式
    bool secure{false}; // 屏幕是否是安全的
    nsecs_t appVsyncOffset{0}; // App的Vsync的偏移
    nsecs_t presentationDeadline{0}; // 顯示的最后時間
};

我們結(jié)合SurfaceFlinger中g(shù)etDisplayConfigs的實現(xiàn)蝇庭,來說說Display的信息病曾。

  • 首先鲫竞,根據(jù)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;
        }
    }
  • 在根據(jù)type去獲取驅(qū)動中配置的信息getConfigs,getHwComposer().getConfigs(type);
    ConditionalLock _l(mStateLock,
            std::this_thread::get_id() != mMainThreadId);
    for (const auto& hwConfig : getHwComposer().getConfigs(type)) {
  • 最后合呐,根據(jù)驅(qū)動給的配置猖腕,和一些設(shè)置缘屹,構(gòu)建完整的顯示屏信息逻炊,下面是關(guān)鍵信息,刪掉了一些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)
    屏幕的寬高是用分辨率來描述的,也就是像素點的多少留美。像素是指在由一個數(shù)字序列表示的圖像中的一個最小單位捧颅,稱為像素症歇。屏幕多寬激捏,就是指闰蛔,屏幕橫向可以顯示多少個像素點蚤吹。屏幕多高就是指拱她,屏幕縱向可以顯示多少給像素點扔罪。平常所說的720P屏幕秉沼,就是1080x720,橫向可以顯示1080個像素點矿酵,縱向可以顯示720個像素點唬复。
    此圖是,平常什么所說的一些分辨率:


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

  • density密度
    這里的desity是一個縮放因子私痹,是 DPI / (160像素/英寸) 后得到的值,是一個比例值稠炬。
    這可以看DisplayMetrics中關(guān)于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;

以設(shè)備無關(guān)像素DIP(device independent pixels)在160dpi屏幕上顯示為基礎(chǔ)焕阿。160dip在160dpi的屏幕上,density就是1酸纲,在120dpi的屏幕上捣鲸,density就為0.75。

  • 屏幕刷新率FPS
    FPS(Frame per second)闽坡,幀每秒栽惶。表示屏幕一描述,可以顯示多少幀圖像數(shù)據(jù)疾嗅。目前多少的手機顯示屏還是60FPS外厂,顯示一幀16.67ms左右。

  • orientation屏幕旋轉(zhuǎn)方向
    手機默認豎屏代承,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(數(shù)字版權(quán)保護)時,確保顯示的設(shè)備是安全的,以防止DRM的內(nèi)容被在顯示的過程中被截取掖棉。只有安全的設(shè)備才能顯示DRM的內(nèi)容墓律。
    Android默認,所有的非虛擬顯示都是安全的幔亥。
        // All non-virtual displays are currently considered secure.
        info.secure = true;
  • appVsyncOffset和presentationDeadline
    這兩個都和 Vsync有關(guān)耻讽,后續(xù)會再介紹。appVsyncOffset是一個偏移量帕棉,在系統(tǒng)(或硬件Vsync)的基礎(chǔ)上做一些偏移针肥。presentationDeadline表示,一幀數(shù)據(jù)香伴,多就內(nèi)慰枕,必現(xiàn)要顯示出來。

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服務(wù)中匕坯,Display的描述,用的DisplayDevice拔稳。每添加一個顯示屏,都會創(chuàng)建一個DisplayDevice锹雏。

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

activeconfig巴比,是一個索引值,對應(yīng)驅(qū)動中礁遵,對應(yīng)的config的索引轻绞。一般來說,active的config佣耐,都是默認的0政勃。當然SurfaceFlinger或上層是可以去設(shè)置的。

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

回到應(yīng)用~

Native創(chuàng)建圖層Layer

拿到顯示信息后兼砖,根據(jù)轉(zhuǎn)屏奸远,這邊的尺寸需要做一下交換。因為不關(guān)屏幕怎么旋轉(zhuǎn)讽挟,我們需要顯示的內(nèi)容大小是沒有變的懒叛。

    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;
    }

接下里,就可以創(chuàng)建圖層了耽梅。

    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函數(shù)如下:

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;
}

先解釋一下薛窥,其中的參數(shù):

  • name
    name就是圖層的名字,沒有實際意義眼姐,主要是便于debug诅迷,有有名字佩番,就可以知道,我們創(chuàng)建的圖層是哪個了罢杉。

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

  • format
    圖層的格式拱镐,應(yīng)用中,我們用的格式是PIXEL_FORMAT_RGBX_8888持际。

我們通過RGB沃琅,紅,綠蜘欲,藍益眉,三原色可以調(diào)配所有的顏色。在數(shù)字世界里面姥份,也是用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 應(yīng)用保護 應(yīng)用將請求一個安全的硬件通道傳輸?shù)酵怙@
eProtectedByDRM DRM保護 應(yīng)用請求一個安全的通道傳輸DRM
eCursorWindow Cursor Layer 其實這Layer就是鼠標一類的圖標
eFXSurfaceNormal 普通的Layer 系統(tǒng)中大多數(shù)layer都是此類
eFXSurfaceColor 顏色layer 在之前的版本中中狂,這個被稱為Dim Layer
  • windowType
    窗口類型,可以參照WindowManager.java中的定義扑毡,如FIRST_SYSTEM_WINDOW胃榕,TYPE_STATUS_BAR等。默認值為0瞄摊。
  • ownerUid
    可以指定這個是哪個UID的Layer勋又。

繼續(xù)看createSurfface,Service端的實現(xiàn)如下:

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類中换帜,創(chuàng)建Layer時楔壤,先找到parent Layer,對于我們的應(yīng)用來說惯驼,是沒有parent Layer的蹲嚣。然后再postMessageSync到SurfaceFlinger中,去創(chuàng)建祟牲,調(diào)用的SurfaceFlinger的createLayer方法隙畜。

SurfaceFlinger中,都是采用post Message的形式調(diào)到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兩個接口實現(xiàn)几颜。怎么創(chuàng)建的這里就不介紹了,后續(xù)再介紹讯屈。

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;
}

將新創(chuàng)建的Layer添加到當前的layer列表中蛋哭,按照Z-order。如果有parent的涮母,添加到parent中谆趾。mGraphicBufferProducerList保存了當前的所有Layer內(nèi)容的生產(chǎn)者。最后叛本,將Layer關(guān)聯(lián)的Client上沪蓬。

Layer創(chuàng)建完成后,調(diào)用setTransactionFlags函數(shù)来候,告訴SurfaceFlinger跷叉,新增加了Layer,有新的顯示,有很多顯示數(shù)據(jù)需要去更新云挟。SurfaceFlinger根據(jù)flag梆砸,決定是否需要換醒服務(wù)。

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創(chuàng)建完成园欣,回到我們的應(yīng)用~

處理狀態(tài)的傳送

應(yīng)用的代碼如下:

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

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

從Android P開始沸枯,google又重構(gòu)了這一塊的代碼日矫。之前的代碼中,是SurfaceComposerClient提供全局的狀態(tài)處理绑榴;從Android P開始哪轿,transactions 被區(qū)分為不同的對象,直接處理對象彭沼。這是Transaction一個類圖缔逛。


Transaction類圖

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

  • ComposerState 合成處理狀態(tài)
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的狀態(tài)褐奴,再實現(xiàn)Binder通信時的write,read于毙。

  • DisplayState 顯示屏狀態(tài)
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的狀態(tài)目前就4個敦冬,也就是

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

這里的what,就是用以標記mark到底是哪個屬性改變了唯沮,有多個屬性改變的時候脖旱,加上對應(yīng)的mark標記位即可。

ComposerState中的layer_state_t和這里的DisplayState類似介蛉。也是采用what來標記的萌庆。Layer的狀態(tài)處理,包括以下屬性币旧。

    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
    };

好了践险,讓我們通過本實例中的示例,來看看狀態(tài)處理是怎么傳遞吹菱,生效的巍虫。

setLayer,實際上是設(shè)置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占遥,就是根據(jù)SurfaceCotrol對象去找,對應(yīng)的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,而對應(yīng)的值保存到layer_state_t z中凛捏。注意担忧,這里的設(shè)置并沒有立即生效。

同樣坯癣,show時瓶盛,也是將對應(yīng)的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;
}

我們設(shè)置的處理狀態(tài)惩猫,在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時轧房,最重要的就是調(diào)用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中奶镶,處理狀態(tài)是怎么工作的呢?

SurfaceF中陪拘,有兩個狀態(tài): mCurrentStatemDrawingState厂镇。

  • mCurrentState主要是用作接受Client的處理變更請求;需要狀態(tài)鎖mStateLock的保護
  • mDrawingState主要用作左刽,控制合成捺信;只能在SurfaceFlinger的主線程中使用,不需要鎖的保護欠痴。

其實這很好理解迄靠,每個狀態(tài)中都有顯示數(shù)據(jù)及其處理的描述。mCurrentState在做顯示數(shù)據(jù)的準備喇辽,mDrawingState狀態(tài)掌挚,就是將顯示數(shù)據(jù)合成送給Display。兩個處理同時進行菩咨,兩個都處理完后疫诽,再將mCurrentState處理狀態(tài),給到mDrawingState旦委。主線程根據(jù)mDrawingState中描述的顯示數(shù)據(jù)和處理,把數(shù)據(jù)進行合成雏亚。

狀態(tài)的處理缨硝,同樣分為Display和Layer。
Client端采用Mask標記的方式罢低,標記處理狀態(tài)的改變查辩。SurfaceFlinger這邊收到后胖笛,根據(jù)mask標記,再將參數(shù)還原出來宜岛。保存到mCurrentState中长踊。Display狀態(tài)的處理如下:

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狀態(tài)的處理也是類似的,我們來看一下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有兩個狀態(tài)身弊,Layer也是有兩個狀態(tài)的。

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基本算構(gòu)建完成阱佛。

小結(jié)

本章從Native應(yīng)用的角度出發(fā),講解了應(yīng)用怎么和SurfaceFlinger建立聯(lián)系戴而,同時介紹了SurfaceFlinger的啟動凑术。我們做應(yīng)用開發(fā),坑需要根據(jù)實際的屏幕參數(shù)來做所意,所以介紹了怎么獲取顯示屏參數(shù)信息淮逊;SurfaceFlinger中顯示的數(shù)據(jù)都是通過Layer進行封裝,介紹了創(chuàng)建Layer的過程扶踊。最后泄鹏,介紹了,顯示的數(shù)據(jù)參數(shù)姻檀,也就說處理的狀態(tài)命满,怎么從Client端傳到SurfaceFlinger的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绣版,一起剝皮案震驚了整個濱河市胶台,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌杂抽,老刑警劉巖诈唬,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異缩麸,居然都是意外死亡铸磅,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門杭朱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阅仔,“玉大人,你說我怎么就攤上這事弧械“司疲” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵刃唐,是天一觀的道長羞迷。 經(jīng)常有香客問我界轩,道長,這世上最難降的妖魔是什么衔瓮? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任浊猾,我火速辦了婚禮,結(jié)果婚禮上热鞍,老公的妹妹穿的比我還像新娘葫慎。我一直安慰自己,他們只是感情好碍现,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布幅疼。 她就那樣靜靜地躺著,像睡著了一般昼接。 火紅的嫁衣襯著肌膚如雪爽篷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天慢睡,我揣著相機與錄音逐工,去河邊找鬼。 笑死漂辐,一個胖子當著我的面吹牛泪喊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播髓涯,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼袒啼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了纬纪?” 一聲冷哼從身側(cè)響起蚓再,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎包各,沒想到半個月后摘仅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡问畅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年娃属,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片护姆。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡矾端,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出卵皂,到底是詐尸還是另有隱情须床,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布渐裂,位于F島的核電站豺旬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏柒凉。R本人自食惡果不足惜族阅,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望膝捞。 院中可真熱鬧坦刀,春花似錦、人聲如沸蔬咬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽林艘。三九已至盖奈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狐援,已是汗流浹背钢坦。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留啥酱,地道東北人爹凹。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像镶殷,于是被迫代替她去往敵國和親禾酱。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容