Android P 圖形顯示系統(tǒng)(十) BufferQueue(一)

[TOC]

BufferQueue

前面結(jié)合應(yīng)用中WindowSurfaceWrapper的,講解了應(yīng)用怎么和SurfaceFlinger建立連接泌霍,進(jìn)行交互的。

BufferQueue 類是 Android 中所有圖形處理操作的核心述召。它的作用很簡單:將生成圖形數(shù)據(jù)緩沖區(qū)的一方(生產(chǎn)方)連接到接受數(shù)據(jù)以進(jìn)行顯示或進(jìn)一步處理的一方(消耗方)朱转。幾乎所有在系統(tǒng)中移動圖形數(shù)據(jù)緩沖區(qū)的內(nèi)容都依賴于 BufferQueue。

現(xiàn)在积暖,我們添加一個空的drawNativeWindow實現(xiàn)肋拔,先將我們的應(yīng)用跑起來吧。

int drawNativeWindow(sp<WindowSurfaceWrapper> /* windowSurface */) {
    return NO_ERROR;
}

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

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

    return EXIT_SUCCESS;
}

Android.bp如下:

cc_binary {
    name: "NativeApp",

    srcs: [
        "NativeApp.cpp",
        "WindowSurfaceWrapper.cpp",
    ],

    shared_libs: [
        "liblog",
        "libbinder",
        "libui",
        "libgui",
        "libutils",
    ],
    init_rc: ["NativeApp.rc"],
}

NativeApp.rc文件如下:

service NativeApp /system/bin/NativeApp
    class core
    oneshot

將應(yīng)用push到系統(tǒng)的bin目錄下就可以運行了:

adb push out/target/product/generic/system/bin/NativeApp /vendor/bin/

運行應(yīng)用:

adb shell NativeBin

很遺憾的是呀酸,我們在手機(jī)屏幕上是看不是任何東西的凉蜂。Why?因為沒有畫任何東西。但是窿吩,我們dump SurfaceFlinger的時候茎杂,還是能夠看到我們創(chuàng)建的應(yīng)用窗口的,只是沒有內(nèi)容纫雁,SurfaceFlinger不顯示煌往,即使去顯示,也看不到轧邪。

adb shell dumpsys SurfaceFlinger

我們創(chuàng)建應(yīng)用Layer時刽脖,名字為“NativeBinApp”,下面就是我們dump出來的Layer的信息:

+ Layer 0x7b3ba66000 (NativeBinApp#0)
  Region transparentRegion (this=0x7b3ba66380, count=1)
    [  0,   0,   0,   0]
  Region visibleRegion (this=0x7b3ba66010, count=1)
    [  0,   0,   0,   0]
  Region surfaceDamageRegion (this=0x7b3ba66088, count=1)
    [  0,   0,   0,   0]
      layerStack=   0, z=2147483647, pos=(0,0), size=( 720,1280), crop=(   0,   0,  -1,  -1), finalCrop=(   0,   0,  -1,  -1), isOpaque=0, invalidate=0, dataspace=Default (0), pixelformat=Unknown/None alpha=1.000, flags=0x00000002, tr=[1.00, 0.00][0.00, 1.00]
      client=0x7b4002d0c0
      format= 2, activeBuffer=[   0x   0:   0,  0], queued-frames=0, mRefreshPending=0
            mTexName=7 mCurrentTexture=-1
            mCurrentCrop=[0,0,0,0] mCurrentTransform=0
            mAbandoned=0
            - BufferQueue mMaxAcquiredBufferCount=1 mMaxDequeuedBufferCount=2
              mDequeueBufferCannotBlock=0 mAsyncMode=0
              default-size=[720x1280] default-format=2 transform-hint=00 frame-counter=0
            FIFO(0):
            Slots:
              [00:0x0] state=FREE    
              [01:0x0] state=FREE    
              [02:0x0] state=FREE    

我們已經(jīng)創(chuàng)建了窗口忌愚,但是界面沒有內(nèi)容顯示曲管,我們先完善我們的應(yīng)用,在窗口中顯示點內(nèi)容吧~

Native應(yīng)用繪制界面

下面是drawNativeWindow窗口的對應(yīng)的代碼硕糊,關(guān)鍵的步驟的用序號標(biāo)出來了~

int drawNativeWindow(sp<WindowSurfaceWrapper> windowSurface) {
    status_t err = NO_ERROR;
    ANativeWindowBuffer *aNativeBuffer = nullptr;
    sp<SurfaceControl> surfaceControl = windowSurface->getSurfaceControl();
    ANativeWindow* aNativeWindow = surfaceControl->getSurface().get();

    // 1. We need to reconnect to the ANativeWindow as a CPU client to ensure that no frames 
    //  get dropped by SurfaceFlinger assuming that these are other frames.
    err = native_window_api_disconnect(aNativeWindow, NATIVE_WINDOW_API_CPU);
    if (err != NO_ERROR) {
        ALOGE("ERROR: unable to native_window_api_disconnect ignore...\n");
    }

    // 2. connect the ANativeWindow as a CPU client
    err = native_window_api_connect(aNativeWindow, NATIVE_WINDOW_API_CPU);
    if (err != NO_ERROR) {
        ALOGE("ERROR: unable to native_window_api_connect\n");
        return EXIT_FAILURE;
    }

    // 3. set the ANativeWindow dimensions
    err = native_window_set_buffers_user_dimensions(aNativeWindow, windowSurface->width(), windowSurface->height());
    if (err != NO_ERROR) {
        ALOGE("ERROR: unable to native_window_set_buffers_user_dimensions\n");
        return EXIT_FAILURE;
    }

    // 4. set the ANativeWindow format
    int format = PIXEL_FORMAT_RGBX_8888;
    err = native_window_set_buffers_format(aNativeWindow,format );
    if (err != NO_ERROR) {
        ALOGE("ERROR: unable to native_window_set_buffers_format\n");
        return EXIT_FAILURE;
    }

    // 5. set the ANativeWindow transform
    int rotation = 0;
    int transform = 0;
    if ((rotation % 90) == 0) {
        switch ((rotation / 90) & 3) {
            case 1:  transform = HAL_TRANSFORM_ROT_90;  break;
            case 2:  transform = HAL_TRANSFORM_ROT_180; break;
            case 3:  transform = HAL_TRANSFORM_ROT_270; break;
            default: transform = 0;                     break;
        }
    }
    err = native_window_set_buffers_transform(aNativeWindow, transform);
    if (err != NO_ERROR) {
        ALOGE("native_window_set_buffers_transform failed: %s (%d)", strerror(-err), -err);
        return err;
    }

    // 6. handle the ANativeWindow usage
    int consumerUsage = 0;
    err = aNativeWindow->query(aNativeWindow, NATIVE_WINDOW_CONSUMER_USAGE_BITS, &consumerUsage);
    if (err != NO_ERROR) {
        ALOGE("failed to get consumer usage bits. ignoring");
        err = NO_ERROR;
    }

    // Make sure to check whether either  requested protected buffers.
    int usage = GRALLOC_USAGE_SW_WRITE_OFTEN;
    if (usage & GRALLOC_USAGE_PROTECTED) {
        // Check if the ANativeWindow sends images directly to SurfaceFlinger.
        int queuesToNativeWindow = 0;
        err = aNativeWindow->query(
                aNativeWindow, NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &queuesToNativeWindow);
        if (err != NO_ERROR) {
            ALOGE("error authenticating native window: %s (%d)", strerror(-err), -err);
            return err;
        }

        // Check if the consumer end of the ANativeWindow can handle protected content.
        int isConsumerProtected = 0;
        err = aNativeWindow->query(
                aNativeWindow, NATIVE_WINDOW_CONSUMER_IS_PROTECTED, &isConsumerProtected);
        if (err != NO_ERROR) {
            ALOGE("error query native window: %s (%d)", strerror(-err), -err);
            return err;
        }

        // Deny queuing into native window if neither condition is satisfied.
        if (queuesToNativeWindow != 1 && isConsumerProtected != 1) {
            ALOGE("native window cannot handle protected buffers: the consumer should either be "
                  "a hardware composer or support hardware protection");
            return PERMISSION_DENIED;
        }
    }

    // 7. set the ANativeWindow usage
    int finalUsage = usage | consumerUsage;
    ALOGE("gralloc usage: %#x(producer) + %#x(consumer) = %#x", usage, consumerUsage, finalUsage);
    err = native_window_set_usage(aNativeWindow, finalUsage);
    if (err != NO_ERROR) {
        ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
        return err;
    }

    // 8. set the ANativeWindow scale mode
    err = native_window_set_scaling_mode(
            aNativeWindow, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
    if (err != NO_ERROR) {
        ALOGE("native_window_set_scaling_mode failed: %s (%d)", strerror(-err), -err);
        return err;
    }

    ALOGE("set up nativeWindow %p for %dx%d, color %#x, rotation %d, usage %#x",
            aNativeWindow, windowSurface->width(), windowSurface->height(), format, rotation, finalUsage);

    // 9. set the ANativeWindow permission to allocte new buffer, default is true
    static_cast<Surface*>(aNativeWindow)->getIGraphicBufferProducer()->allowAllocation(true);

    // 10. set the ANativeWindow buffer count
    int numBufs = 0;
    int minUndequeuedBufs = 0;

    err = aNativeWindow->query(aNativeWindow,
            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
    if (err != NO_ERROR) {
        ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
                "failed: %s (%d)", strerror(-err), -err);
        goto handle_error;
    }

    numBufs = minUndequeuedBufs + 1;
    err = native_window_set_buffer_count(aNativeWindow, numBufs);
    if (err != NO_ERROR) {
        ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)", strerror(-err), -err);
        goto handle_error;
    }

    // 11. draw the ANativeWindow
    for (int i = 0; i < numBufs + 1; i++) {
        // 12. dequeue a buffer
        int hwcFD= -1;
        err = aNativeWindow->dequeueBuffer(aNativeWindow, &aNativeBuffer, &hwcFD);
        if (err != NO_ERROR) {
            ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
                    strerror(-err), -err);
            break;
        }

        // 13. make sure really control the dequeued buffer
        sp<Fence> hwcFence(new Fence(hwcFD));
        int waitResult = hwcFence->waitForever("dequeueBuffer_EmptyNative");
        if (waitResult != OK) {
            ALOGE("dequeueBuffer_EmptyNative: Fence::wait returned an error: %d", waitResult);
            break;
        }

        sp<GraphicBuffer> buf(GraphicBuffer::from(aNativeBuffer));

        // 14. Fill the buffer with black
        uint8_t *img = NULL;
        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
        if (err != NO_ERROR) {
            ALOGE("error pushing blank frames: lock failed: %s (%d)", strerror(-err), -err);
            break;
        }

        //15. Draw the window, here we fill the window with black.
        *img = 0;

        err = buf->unlock();
        if (err != NO_ERROR) {
            ALOGE("error pushing blank frames: unlock failed: %s (%d)", strerror(-err), -err);
            break;
        }

        // 16. queue the buffer to display
        int gpuFD = -1;
        err = aNativeWindow->queueBuffer(aNativeWindow, buf->getNativeBuffer(), gpuFD);
        if (err != NO_ERROR) {
            ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)", strerror(-err), -err);
            break;
        }

        aNativeBuffer = NULL;
    }

handle_error:
    // 17. cancel buffer
    if (aNativeBuffer != NULL) {
        aNativeWindow->cancelBuffer(aNativeWindow, aNativeBuffer, -1);
        aNativeBuffer = NULL;
    }

    // 18. Clean up after success or error.
    status_t err2 = native_window_api_disconnect(aNativeWindow, NATIVE_WINDOW_API_CPU);
    if (err2 != NO_ERROR) {
        ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", strerror(-err2), -err2);
        if (err == NO_ERROR) {
            err = err2;
        }
    }
    return err;
}

關(guān)鍵步驟如下:

  1. 獲取我們已經(jīng)創(chuàng)建的Layer的窗口ANativeWindow
  2. 斷掉之前的BufferQueue連接native_window_api_disconnect院水,這一步是可選的
  3. 連接Window到BufferQueue native_window_api_connect
  4. 設(shè)置Buffer的大小尺寸native_window_set_buffers_user_dimensions,可選
  5. 設(shè)置Buffer格式简十,可選檬某,之前創(chuàng)建Layer的時候已經(jīng)設(shè)置了。
  6. 設(shè)置Buffer的transform
  7. 處理Buffer的usage螟蝙,主要的DRM內(nèi)容的處理
  8. 設(shè)置Buffer的usage恢恼,usage由producer的usage和Consumer的usage組成
  9. 設(shè)置scale模式,如果上層給的數(shù)據(jù)胰默,比如Video厅瞎,超出Buffer的大小后,怎么處理初坠,是截取一部分還是,縮小彭雾。
  10. 設(shè)置permission碟刺,設(shè)置Buffer,默認(rèn)true薯酝,可選半沽。
  11. 設(shè)置Buffer數(shù)量,就是吴菠,BufferQueue中有多少個buffer可以用者填,可選
  12. 繪制窗口,窗口有一個buffer隊列做葵,對每一個buffer都需要繪制占哟。
  13. dequeueBuffer先拿到一塊可用的Buffer,也就是FREE的Buffer。
  14. Buffer雖然是Free的榨乎,但是在異步模式下怎燥,Buffer不可能還在使用中,需要等到Fence才能確保buffer沒有在被使用
  15. 往Free的Buffer里面繪制東西蜜暑,
  16. 我們這里直接顯示全黑,*img = 0
  17. 將繪制好的Buffer铐姚,queue到Buffer隊列中,queueBuffer肛捍。
  18. 錯誤處理隐绵,取消掉Buffer,cancelBuffer
  19. 斷開BufferQueue和窗口的連接拙毫,native_window_api_disconnect

OK~再編譯執(zhí)行一下依许,屏幕是不是黑了?
Dumps一下SurfaceFlinger恬偷,我們的應(yīng)用窗口信息如下:

+ Layer 0x7b3ba61000 (NativeBinApp#0)
  Region transparentRegion (this=0x7b3ba61380, count=1)
    [  0,   0,   0,   0]
  Region visibleRegion (this=0x7b3ba61010, count=1)
    [  0,   0, 720, 1280]
  Region surfaceDamageRegion (this=0x7b3ba61088, count=1)
    [  0,   0,  -1,  -1]
      layerStack=   0, z=2147483647, pos=(0,0), size=( 720,1280), crop=(   0,   0,  -1,  -1), finalCrop=(   0,   0,  -1,  -1), isOpaque=1, invalidate=0, dataspace=Default (0), pixelformat=RGBx_8888 alpha=1.000, flags=0x00000002, tr=[1.00, 0.00][0.00, 1.00]
      client=0x7b4002d6c0
      format= 2, activeBuffer=[ 720x1280: 720,  2], queued-frames=0, mRefreshPending=0
            mTexName=2 mCurrentTexture=1
            mCurrentCrop=[0,0,0,0] mCurrentTransform=0
            mAbandoned=0
            - BufferQueue mMaxAcquiredBufferCount=1 mMaxDequeuedBufferCount=1
              mDequeueBufferCannotBlock=0 mAsyncMode=0
              default-size=[720x1280] default-format=2 transform-hint=00 frame-counter=3
            FIFO(0):
            Slots:
              [01:0x0] state=FREE    
              [02:0x0] state=FREE 

對比看一下悍手,和前面的dump信息有什么不一樣?

另外袍患,如果我們將原來的*img = 0替換掉坦康,可以繪制其他一些東西。fillWithCheckerboard可以將屏幕填充為小方塊诡延。


fillWithCheckerboard(img, windowSurface->width(), windowSurface->height(), buf->getStride());

void fillWithCheckerboard(uint8_t* img, int width, int height, int stride) {
    bool change = false;
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            uint8_t* pixel = img + (4 * (y*stride + x));
            if ( x % 10 == 0) {
                change = !change;
            }

            if(change) {
                pixel[0] = 255;
                pixel[1] = 255;
                pixel[2] = 255;
            } else {
                pixel[0] = 0;
                pixel[1] = 0;
                pixel[2] = 0;
            }
            pixel[3] = 0;
        }
        if ( y % 10 == 0) {
            change = !change;
        }
    }
}

繪制應(yīng)用滞欠,我們這里直接用的API,這些API是怎么工作的肆良,數(shù)據(jù)怎么送給顯示的筛璧?接下里,我們將具體分析惹恃。

SurfaceFlinger創(chuàng)建Layer

上一章講到夭谤,應(yīng)用創(chuàng)建Layer時,流程只跟到SurfaceFlinger巫糙,SurfaceFlinger是怎么窗口Layer的朗儒,和 Layer和BufferQueue又是怎么關(guān)聯(lián)的,我們接著就來看看参淹。
Layer分兩種類型:

  • bNormal Layer醉锄,普通Layer,由createBufferLayer創(chuàng)建浙值,由BufferLayer類描述恳不。
  • Coler Layer,由createColorLayer創(chuàng)建开呐,由ColorLayer類描述烟勋。

Layer相關(guān)類的關(guān)系如下:


Layer相關(guān)的類
  • BufferLayer和ColorLayer繼承Layer類
  • Layer類规求,有LayerBE的一個實例
  • BufferLayer實現(xiàn)ContentsChangedListener和FrameAvailableListener兩個接口類,主要是監(jiān)聽顯示內(nèi)容的改變神妹。

ColorLayer比較 簡單颓哮,我們先來看BufferLayer。reateBufferLayer實現(xiàn)如下:

status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client,
        const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
{
    ... ...
    sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags);
    status_t err = layer->setBuffers(w, h, format, flags);
    if (err == NO_ERROR) {
        *handle = layer->getHandle();
        *gbp = layer->getProducer();
        *outLayer = layer;
    }

    ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err));
    return err;
}

createBufferLayer時鸵荠,創(chuàng)建一個BufferLayer冕茅。

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

BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
                         uint32_t w, uint32_t h, uint32_t flags)
      : Layer(flinger, client, name, w, h, flags),
        mConsumer(nullptr),
        mTextureName(UINT32_MAX),
        mFormat(PIXEL_FORMAT_NONE),
        mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
        mBufferLatched(false),
        mPreviousFrameNumber(0),
        mUpdateTexImageFailed(false),
        mRefreshPending(false) {
    ALOGV("Creating Layer %s", name.string());

    mFlinger->getRenderEngine().genTextures(1, &mTextureName);
    mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);

    if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false;

    mCurrentState.requested = mCurrentState.active;

    // drawing state & current state are identical
    mDrawingState = mCurrentState;
}

在LayerBuffer的構(gòu)造函數(shù)中,主要是初始化了一個mTextureName蛹找,已經(jīng)一些狀態(tài)的初始化姨伤;以及調(diào)用Layer的構(gòu)造函數(shù)。

Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
             uint32_t h, uint32_t flags)
      : contentDirty(false),
        sequence(uint32_t(android_atomic_inc(&sSequence))),
        mFlinger(flinger),
        mPremultipliedAlpha(true),
        mName(name),
        mTransactionFlags(0),
        mPendingStateMutex(),
        mPendingStates(),
        mQueuedFrames(0),
        mSidebandStreamChanged(false),
        mActiveBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
        mCurrentTransform(0),
        mOverrideScalingMode(-1),
        mCurrentOpacity(true),
        mCurrentFrameNumber(0),
        mFrameLatencyNeeded(false),
        mFiltering(false),
        mNeedsFiltering(false),
        mProtectedByApp(false),
        mClientRef(client),
        mPotentialCursor(false),
        mQueueItemLock(),
        mQueueItemCondition(),
        mQueueItems(),
        mLastFrameNumberReceived(0),
        mAutoRefresh(false),
        mFreezeGeometryUpdates(false) {

    mCurrentCrop.makeInvalid();

    uint32_t layerFlags = 0;
    if (flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden;
    if (flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque;
    if (flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure;

    mName = name;
    mTransactionName = String8("TX - ") + mName;

    mCurrentState.active.w = w;
    ... ... init mCurrentState
    mCurrentState.type = 0;

    // drawing state & current state are identical
    mDrawingState = mCurrentState;

    const auto& hwc = flinger->getHwComposer();
    const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY);
    nsecs_t displayPeriod = activeConfig->getVsyncPeriod();
    mFrameTracker.setDisplayRefreshPeriod(displayPeriod);

    CompositorTiming compositorTiming;
    flinger->getCompositorTiming(&compositorTiming);
    mFrameEventHistory.initializeCompositorTiming(compositorTiming);

}

Layerd的構(gòu)造函數(shù)中庸疾,主要做一些變量的初始化乍楚,以及mCurrentState的初始化。

BufferLayer和Layer都是繼承RefBase的届慈,還要一個地方做初始化徒溪,那就是onFirstRef。

Layer的onFirstRef是空的:

void Layer::onFirstRef() {}

BufferLayer的onFirstRef則做了很多操作金顿。在這里我們就看到Producer和Consumer出場了臊泌。

void BufferLayer::onFirstRef() {
    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    BufferQueue::createBufferQueue(&producer, &consumer, true);
    mProducer = new MonitoredProducer(producer, mFlinger, this);
    mConsumer = new BufferLayerConsumer(consumer,
            mFlinger->getRenderEngine(), mTextureName, this);
    mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
    mConsumer->setContentsChangedListener(this);
    mConsumer->setName(mName);

    if (mFlinger->isLayerTripleBufferingDisabled()) {
        mProducer->setMaxDequeuedBufferCount(2);
    }

    const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
    updateTransformHint(hw);
}

BufferLayer,通過BufferQueue的createBufferQueue揍拆,創(chuàng)建了一個buffer隊列渠概,一個buffer隊列,有一個生產(chǎn)者producer嫂拴,和一個消費者consumer播揪。

createBufferQueue實現(xiàn)如下:
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger) {
... ...

sp<BufferQueueCore> core(new BufferQueueCore());
LOG_ALWAYS_FATAL_IF(core == NULL,
        "BufferQueue: failed to create BufferQueueCore");

sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
LOG_ALWAYS_FATAL_IF(producer == NULL,
        "BufferQueue: failed to create BufferQueueProducer");

sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
LOG_ALWAYS_FATAL_IF(consumer == NULL,
        "BufferQueue: failed to create BufferQueueConsumer");

*outProducer = producer;
*outConsumer = consumer;

}

  • 首先創(chuàng)建了一個BufferQueueCore,這個是BufferQueue的核心筒狠。
  • 然后創(chuàng)建了一個BufferQueueProducer和一個BufferQueueConsumer猪狈,注意Producer和Consumer都持有BufferQueueCore的引用。

BufferQueue創(chuàng)建完后辩恼,BufferLayer雇庙,又對BufferQueueCore中的Producer和Consume進(jìn)行封裝。分別創(chuàng)建了MonitoredProducer和BufferLayerConsumer运挫。

最后,再對創(chuàng)建的mConsumer和mProducer進(jìn)行初始化套耕。

mConsumer這邊主要有:

  • setConsumerUsageBits谁帕,設(shè)置Consumer的usage
  • setContentsChangedListener,這種內(nèi)容改變的監(jiān)聽冯袍,注意這里傳的是this指針匈挖,因為BufferLayer實現(xiàn)了兩個接口碾牌,還記得不?
  • setName儡循,設(shè)置Consumer 名

mProducer這邊主要有

  • setMaxDequeuedBufferCount
    根據(jù)系統(tǒng)的屬性舶吗,設(shè)置Producer最多可以申請多少個Buffer,默認(rèn)是3個择膝;如果配置了屬性ro.sf.disable_triple_buffer為true誓琼,那就只能用2個。

這個是在SurfaceFlinger初始化時肴捉,在SurfaceFlinger的構(gòu)造函數(shù)中決定的腹侣。

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

我們來看看Layer和BufferQueue之間的關(guān)系~


BUfferQueue架構(gòu)

解釋一下:

  • 一個Layer對應(yīng)一個BufferQueue,一個BufferQueue中有多個Buffer齿穗,一般是2個或者3個傲隶。
  • 一個Layer有一個Producer,一個Consumer
  • 結(jié)合前面的分析窃页,一個Surface和一個Layer也是一一對應(yīng)的跺株,和窗口也是一一對應(yīng)的。

可見脖卖,BufferQueue就是兩個連接紐帶就轧,連接著Producer和Consumer柜蜈。接下來,我們就來分別看一下Producer和Consumer。

MonitoredProducer是對BufferQueueProducer的封裝蜕乡,其目的,就是Producer銷毀時屋摇,能通知SurfaceFlinger偶洋。這就是取名Monitored的愿意。余下的妓雾,MonitoredProducer的很多接口都是直接調(diào)娶吞,對應(yīng)的BufferQueueProducer的實現(xiàn)。

銷毀監(jiān)聽械姻,就是在MonitoredProducer析構(gòu)函數(shù)中妒蛇,post一個消息到SurfaceFlinger的主線程中。通知SurFaceFlinger Producer已經(jīng)銷毀楷拳,SurfaceFlinger 會將銷毀的Producer從mGraphicBufferProducerList中刪掉绣夺。代碼如下:

MonitoredProducer::~MonitoredProducer() {
    // Remove ourselves from SurfaceFlinger's list. We do this asynchronously
    // because we don't know where this destructor is called from. It could be
    // called with the mStateLock held, leading to a dead-lock (it actually
    // happens).
    class MessageCleanUpList : public MessageBase {
    public:
        MessageCleanUpList(const sp<SurfaceFlinger>& flinger,
                const wp<IBinder>& producer)
            : mFlinger(flinger), mProducer(producer) {}

        virtual ~MessageCleanUpList() {}

        virtual bool handler() {
            Mutex::Autolock _l(mFlinger->mStateLock);
            mFlinger->mGraphicBufferProducerList.remove(mProducer);
            return true;
        }

    private:
        sp<SurfaceFlinger> mFlinger;
        wp<IBinder> mProducer;
    };

    mFlinger->postMessageAsync(new MessageCleanUpList(mFlinger, asBinder(mProducer)));
}

BufferQueueProducer就是Producer真是實現(xiàn)的地方了。前面我們的應(yīng)用代碼中欢揖,要繪制一個窗口陶耍,有很多個步驟,而每一步的實現(xiàn)她混,基本都在BufferQueueProducer中烈钞。

BufferQueueProducer的類圖如下:


BufferQueueProducer類圖

其中泊碑,dequeueBuffer和queueBuffer是兩個非常重要的函數(shù)。我們的應(yīng)用中毯欣,是不是通過ANativeWindow的dequeueBuffer函數(shù)馒过,獲取到一個Buffer,再通過ANativeWindow的queueBuffer酗钞,送到顯示這邊的腹忽。具體過程我們稍后我講解。

再來看Consumer算吩,BufferLayerConsumer繼承ConsumerBase留凭。BufferLayerConsumer的構(gòu)造函數(shù)中,主要是一些變量的初始化偎巢,主要是ConsumerBase的構(gòu)造函數(shù):

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

ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
        mAbandoned(false),
        mConsumer(bufferQueue),
        mPrevFinalReleaseFence(Fence::NO_FENCE) {
    // Choose a name using the PID and a process-unique ID.
    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());

    // Note that we can't create an sp<...>(this) in a ctor that will not keep a
    // reference once the ctor ends, as that would cause the refcount of 'this'
    // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
    // that's what we create.
    wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
    sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);

    status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
    if (err != NO_ERROR) {
        CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
                strerror(-err), err);
    } else {
        mConsumer->setConsumerName(mName);
    }
}

在ConsumerBase的構(gòu)造函數(shù)中蔼夜,給BufferQueue設(shè)置了監(jiān)聽,這樣Consumer和BufferQueue压昼,就算是連上了求冷。

注意這里的Listener。BufferLayer是實現(xiàn)了BufferLayerConsumer的ContentsChangedListener窍霞,在BufferLayer的onFirstRef中匠题,這個Listener被設(shè)置給了BufferLayerConsumer。

mConsumer->setContentsChangedListener(this);

BufferLayerConsumer的setContentsChangedListener函數(shù)如下:

void BufferLayerConsumer::setContentsChangedListener(const wp<ContentsChangedListener>& listener) {
    setFrameAvailableListener(listener);
    Mutex::Autolock lock(mMutex);
    mContentsChangedListener = listener;
}

可見但金,在setFrameAvailableListener函數(shù)中韭山,BufferLayer的Listener實現(xiàn)被賦值給了mFrameAvailableListener。同時調(diào)用setFrameAvailableListener

setFrameAvailableListener的實現(xiàn)在父類ConsumerBase中冷溃。

void ConsumerBase::setFrameAvailableListener(
        const wp<FrameAvailableListener>& listener) {
    CB_LOGV("setFrameAvailableListener");
    Mutex::Autolock lock(mFrameAvailableMutex);
    mFrameAvailableListener = listener;
}

此時钱磅,又被賦值給了mFrameAvailableListener,注意似枕,這里的mFrameAvailableListener是BufferLayer中實現(xiàn)的Listener盖淡。

ConsumerBase自身實現(xiàn)ConsumerListener,中構(gòu)造的Listener凿歼,通過代理ProxyConsumerListener褪迟,在connect時傳給了BufferQueueConsumer。

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

status_t BufferQueueConsumer::connect(
        const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
    ATRACE_CALL();

    if (consumerListener == NULL) {
        BQ_LOGE("connect: consumerListener may not be NULL");
        return BAD_VALUE;
    }

    BQ_LOGV("connect: controlledByApp=%s",
            controlledByApp ? "true" : "false");

    Mutex::Autolock lock(mCore->mMutex);

    if (mCore->mIsAbandoned) {
        BQ_LOGE("connect: BufferQueue has been abandoned");
        return NO_INIT;
    }

    mCore->mConsumerListener = consumerListener;
    mCore->mConsumerControlledByApp = controlledByApp;

    return NO_ERROR;
}

看明白了吧答憔?BufferLayer實現(xiàn)的ContentsChangedListener被保存在ConsumerBase中mFrameAvailableListener味赃。而ConsumerBase實現(xiàn)的ConsumerListener,被傳到BufferQueueConsumer虐拓,保存在BufferQueueCore的mConsumerListener中心俗。

所以,Listener的通知路線應(yīng)該是這樣的~

  1. Producer生產(chǎn)完后侯嘀,會通過BufferQueueCore中的mConsumerListener通知ConsumerBase
  2. ConsumerBase另凌,接受到BufferQueueConsumer的通知,再通過BufferLayer傳下來的信使mFrameAvailableListener戒幔,通知BufferLayer吠谢。
  3. BufferLayer接受到通知后,就可以去消費生產(chǎn)完的Buffer了诗茎。

到此工坊,Consumer這邊準(zhǔn)備就緒了,就等著Producer去生產(chǎn)了敢订。注意一點王污,在分析應(yīng)用創(chuàng)建Layer時,會得到一個IGraphicBufferProducer楚午,這個就是對應(yīng)BufferLayer

sp<SurfaceControl> SurfaceComposerClient::createSurface(
        ... ...
        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;
}

讓我們回到我們的應(yīng)用代碼~

Native窗口

在應(yīng)用代碼中昭齐,我們已經(jīng)用到幾個關(guān)鍵的類,Surface和SurfaceControl矾柜,ANativeWindow和ANativeWindowBuffer阱驾;他們又是什么的關(guān)系呢,怎么和BufferQueue產(chǎn)生聯(lián)系的呢怪蔑?

ANativeWindow

ANativeWindow是Native對一個窗口的描述里覆,和Surface是對等的,Why缆瓣?可以通過接口ANativeWindow_fromSurface()將Surface轉(zhuǎn)換為ANativeWindow喧枷。而事實也ANativeWindow是對BufferQueue的Producer端進(jìn)行一個封裝。

ANativeWindow的定義如下弓坞,英文的注釋很詳細(xì)

* frameworks/native/libs/nativewindow/include/system/window.h

struct ANativeWindow
{
#ifdef __cplusplus
    ANativeWindow()
        : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
    {
        common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
        common.version = sizeof(ANativeWindow);
        memset(common.reserved, 0, sizeof(common.reserved));
    }

    /* Implement the methods that sp<ANativeWindow> expects so that it
       can be used to automatically refcount ANativeWindow's. */
    void incStrong(const void* /*id*/) const {
        common.incRef(const_cast<android_native_base_t*>(&common));
    }
    void decStrong(const void* /*id*/) const {
        common.decRef(const_cast<android_native_base_t*>(&common));
    }
#endif

    // 相當(dāng)于從android_native_base_t繼承
    struct android_native_base_t common;

    /* flags describing some attributes of this surface or its updater */
    const uint32_t flags;

    /* min swap interval supported by this updated */
    const int   minSwapInterval;

    /* max swap interval supported by this updated */
    const int   maxSwapInterval;

    /* horizontal and vertical resolution in DPI */
    const float xdpi;
    const float ydpi;

    /* Some storage reserved for the OEM's driver. */
    intptr_t    oem[4];

     // 設(shè)置swap的間隔隧甚,也就是設(shè)置Producer是同步還是異步
    int     (*setSwapInterval)(struct ANativeWindow* window,
                int interval);

    // dequeue一塊buffer,執(zhí)行后昼丑,buffer就不是locked狀態(tài)呻逆,內(nèi)容不能修改
    // 這里會造成block,引起ANR等如果沒有空閑Buffer
    // 這個方法現(xiàn)象不建議使用菩帝,現(xiàn)在直接使用下面的dequeueBuffer方法
    int     (*dequeueBuffer_DEPRECATED)(struct ANativeWindow* window,
                struct ANativeWindowBuffer** buffer);

    // 在修改Buffer的內(nèi)容前咖城,先鎖住這個Buffer
    int     (*lockBuffer_DEPRECATED)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer);

    // 修改完后,通過此方法將buffer送輸出呼奢,這個Buffer也沒有在用了宜雀。
    int     (*queueBuffer_DEPRECATED)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer);

    // 獲取我們需要的值
    int     (*query)(const struct ANativeWindow* window,
                int what, int* value);

    // 執(zhí)行對應(yīng)的操縱
    int     (*perform)(struct ANativeWindow* window,
                int operation, ... );

    // 取消掉一個已經(jīng)被deueue出來的值
    int     (*cancelBuffer_DEPRECATED)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer);

    // dequeueBuffer_DEPRECATED的新版本,使用者自己處理Fence
    int     (*dequeueBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer** buffer, int* fenceFd);

    // queueBuffer_DEPRECATED的新版本
    int     (*queueBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer, int fenceFd);

    // cancelBuffer_DEPRECATED的新版本握础,必須要和dequeue在同一個線程中
    int     (*cancelBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer, int fenceFd);
};

此外辐董,window.h頭文件中還提供了很多類型native_window_**的API,這些API就是通過ANativeWindow的perform函數(shù)調(diào)下去的禀综。API很多简烘,這里就不一一介紹了苔严,前面我們的應(yīng)用代碼中已經(jīng)使用了不少。

為什么說ANativeWindow和Surface是對等的孤澎?我們來看看Surface

Surface

Surface也是BufferQueue在Producer端的封裝届氢,每個窗口都有且只有一個自己的Surface(同一時刻)。為什么說ANativeWindow和Surface是對等的覆旭,實際上Surface繼承ANativeWindow退子。

* frameworks/native/libs/gui/include/gui/Surface.h

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

ANativeWindow是一個模板類,主要是將類似ANativeWindow這樣的類型型将,轉(zhuǎn)換為引用計數(shù)控制的類型寂祥,實現(xiàn)對象的自動釋放。

template <typename NATIVE_TYPE, typename TYPE, typename REF,
        typename NATIVE_BASE = android_native_base_t>
class ANativeObjectBase : public NATIVE_TYPE, public REF
{

Surface的代碼比較多七兜,這里就不貼代碼了丸凭。但是整體而言,主要如下:

  • ANativeWindow的hooks函數(shù)腕铸,命名為hook_***贮乳,總共10個hook函數(shù),如hook_perform恬惯,hook_dequeueBuffer等
  • window.h頭文件中定義的API的分發(fā)向拆,命名為dispatch***,總共29個酪耳,如dispatchConnect浓恳,dispatchSetCrop等
  • Surface對hook函數(shù)和dispatch函數(shù)的具體實現(xiàn),這些給函數(shù)就和BufferQueue交互碗暗。
  • 窗口颈将,Buffer的很多描述的屬性定義在Surface中。

Surface的實現(xiàn)在:

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

在構(gòu)造函數(shù)中言疗,主要是變量的初始化晴圾,和ANativeWindow的函數(shù)的初始化,將hook函數(shù)直接賦值給ANativeWindow對應(yīng)的函數(shù)噪奄。

根據(jù)我們應(yīng)用的代碼死姚,我們來看看具有代表行的一兩個流程,就看native_window_set_buffers_format勤篮。

* frameworks/native/libs/nativewindow/include/system/window.h

static inline int native_window_set_buffers_format(
        struct ANativeWindow* window,
        int format)
{
    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_FORMAT, format);
}

native_window_api_connect 調(diào)的是 ANativeWindow 的 perform 函數(shù)都毒,而perform的類型為 NATIVE_WINDOW_SET_BUFFERS_FORMAT。

perform函數(shù)是Surface中實現(xiàn)的:

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

int Surface::perform(int operation, va_list args)
{
    int res = NO_ERROR;
    switch (operation) {
    ... ...
    case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
        res = dispatchSetBuffersFormat(args);
        break;
     ... ...
}

dispatch函數(shù)為dispatchSetBuffersFormat

int Surface::dispatchSetBuffersFormat(va_list args) {
    PixelFormat format = va_arg(args, PixelFormat);
    return setBuffersFormat(format);
}

Surface的實現(xiàn)為:

int Surface::setBuffersFormat(PixelFormat format)
{
    ALOGV("Surface::setBuffersFormat");

    Mutex::Autolock lock(mMutex);
    if (format != mReqFormat) {
        mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
    }
    mReqFormat = format;
    return NO_ERROR;
}

設(shè)置的Buffer格式被賦值給了mReqFormat碰缔。

以此類推账劲,window.h 頭文件中的API,都會設(shè)置一個類型,然后通過perform函數(shù)瀑焦,調(diào)到Surface中的具體實現(xiàn)腌且。

hook的函數(shù)也是類似的,我們以ANativeWindow的dequeueBuffer為例榛瓮,ANativeWindow的dequeueBuffer函數(shù)切蟋,直接被賦值為Surface的dequeueBuffer。

int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
    ... ...
    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, reqWidth, reqHeight,
                                                            reqFormat, reqUsage, &mBufferAge,
                                                            enableFrameTimestamps ? &frameTimestamps
                                                                                  : nullptr);
    ... ...
    sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
    ... ...
    *buffer = gbuf.get();
    ... ...
    return OK;
}

dequeueBuffer的時候榆芦,通過mGraphicBufferProducer的dequeueBuffer,去找到可用Buffer的id喘鸟,然后根據(jù)id去隊列里面取Buffer匆绣。

這下明白,為什么說 ANativeWindow和Surface是對等的了吧什黑。但是... ..

但是崎淳,對不對等,取決于是否真是的用到Surface愕把。比如拣凹,我不想用 Surface的這個流程,我自己寫一個MySurface恨豁,繼承與ANativeWindow嚣镜,然后我用自己的MySurface。此時橘蜜,元芳菊匿,你怎么看?

那么ANativeWindow和Surface怎么對等的呢计福?我們且來看SurfaceControl跌捆。

SurfaceControl

SurfaceControl,簡單理解就是控制Surface的。怎么控制象颖?我們先來看佩厚,什么時候創(chuàng)建的SurfaceControl。

創(chuàng)建Layer的時候说订,通過createSurface創(chuàng)建了Layer抄瓦,

sp<SurfaceControl> SurfaceComposerClient::createSurface(
        ... ...
        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;
}

創(chuàng)建了Layer后,獲取到Layer的handle和BufferQueue的Producer陶冷,SurfaceControl中就有了Layer的handle和Producer了闺鲸。

SurfaceControl的類圖:


SurfaceControl類圖

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

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

SurfaceControl::SurfaceControl(
        const sp<SurfaceComposerClient>& client,
        const sp<IBinder>& handle,
        const sp<IGraphicBufferProducer>& gbp)
    : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp)
{
}

這里SurfaceControl就和Layer,BufferQueue建立聯(lián)系了埃叭。

再回到我們的代碼:

ANativeWindow* aNativeWindow = surfaceControl->getSurface().get();

這里SurfaceControl的getSurface是一個sp<Surface>摸恍,這里是多態(tài)的用法,這就是為什么說ANativeWindow和Surface對等了。

getSurface函數(shù)如下:

sp<Surface> SurfaceControl::getSurface() const
{
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == 0) {
        return generateSurfaceLocked();
    }
    return mSurfaceData;
}

generateSurfaceLocked函數(shù)中立镶,創(chuàng)建一個Surface

sp<Surface> SurfaceControl::generateSurfaceLocked() const
{
    // This surface is always consumed by SurfaceFlinger, so the
    // producerControlledByApp value doesn't matter; using false.
    mSurfaceData = new Surface(mGraphicBufferProducer, false);

    return mSurfaceData;
}

看到了吧壁袄,Surface中的mGraphicBufferProducer是從哪兒來的了吧。在Layer端為MonitoredProducer媚媒,Surface這邊是Binder的Bp端嗜逻。

我們先來看Surface相關(guān)類的關(guān)系吧


Surface相關(guān)類直接關(guān)系

看了Surface相關(guān)的關(guān)系類圖,再和SurfaceFlinger缭召,Layer相關(guān)的關(guān)系類似結(jié)合栈顷,應(yīng)用和SurfaceFlinger服務(wù)的關(guān)系是不是就很清楚了。

到此嵌巷,應(yīng)用該做的準(zhǔn)備工作都準(zhǔn)備完了萄凤,應(yīng)用端主要通過IGraphicBufferProducer和ISurfaceComposerClient兩個接口SurfaceFlinger進(jìn)行交互。

在開始下面的知識之前搪哪,我們先來看看這個LayerCleaner

窗口銷毀的善后處理

應(yīng)用被銷毀后靡努,Client端就被清理了,SurfaceControl晓折,SurfaceComposerClient惑朦,被銷毀。但是服務(wù)端漓概,SurfaceFlinger是另外一個進(jìn)程漾月,為應(yīng)用進(jìn)程申請的相關(guān)資源什么很好釋放呢?

關(guān)鍵還是看上面類圖中的Handler胃珍。我們就來看一下流程:

SurfaceControl::~SurfaceControl()
{
    destroy();
}

在destroy函數(shù)中栅屏,銷毀應(yīng)用進(jìn)程中的資源:

void SurfaceControl::destroy()
{
    if (isValid()) {
        mClient->destroySurface(mHandle);
    }
    // clear all references and trigger an IPC now, to make sure things
    // happen without delay, since these resources are quite heavy.
    mClient.clear();
    mHandle.clear();
    mGraphicBufferProducer.clear();
    IPCThreadState::self()->flushCommands();
}

而服務(wù)端的,有兩種方式:

  • 直接通過 Client destroySurface:
* frameworks/native/services/surfaceflinger/Client.cpp

status_t Client::destroySurface(const sp<IBinder>& handle) {
    return mFlinger->onLayerRemoved(this, handle);
}
status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
{
    // called by a client when it wants to remove a Layer
    status_t err = NO_ERROR;
    sp<Layer> l(client->getLayerUser(handle));
    if (l != NULL) {
        mInterceptor.saveSurfaceDeletion(l);
        err = removeLayer(l);
        ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
                "error removing layer=%p (%s)", l.get(), strerror(-err));
    }
    return err;
}

但是堂鲜,注意這里的isValid()

如果isValid無效呢栈雳?
這個時候,我們就要通過mClient和mHandle缔莲。這個時候是引用計數(shù)控制的自動釋放哥纫。

  • 引用計數(shù)控制自動釋放
    mClient.clear();
    mHandle.clear();

clear函數(shù)會是否對象的應(yīng)用,最終調(diào)用析構(gòu)函數(shù):

Client::~Client()
{
    const size_t count = mLayers.size();
    for (size_t i=0 ; i<count ; i++) {
        sp<Layer> l = mLayers.valueAt(i).promote();
        if (l != nullptr) {
            mFlinger->removeLayer(l);
        }
    }
}

這里是不是和destroySurface函數(shù)是異曲同工之處痴奏。

再來看Handle:

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

    class Handle : public BBinder, public LayerCleaner {
    public:
        Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
              : LayerCleaner(flinger, layer), owner(layer) {}

        wp<Layer> owner;
    };

Handle析構(gòu)時蛀骇,會調(diào)父類的析構(gòu):

    protected:
        ~LayerCleaner() {
            // destroy client resources
            mFlinger->onLayerDestroyed(mLayer);
        }
    };

LayerCleaner的析構(gòu)中同樣調(diào)的SurfaceFlinger的onLayerRemoved函數(shù)。再調(diào)的removeLayer

status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer, bool topLevelOnly) {
    ... ...

    const auto& p = layer->getParent();
    ssize_t index;
    if (p != nullptr) {
        ... ...

        index = p->removeChild(layer);
    } else {
        index = mCurrentState.layersSortedByZ.remove(layer);
    }

    ... ...

    layer->onRemovedFromCurrentState();
    mLayersPendingRemoval.add(layer);
    mLayersRemoved = true;
    mNumLayers -= 1 + layer->getChildrenCount();
    setTransactionFlags(eTransactionNeeded);
    return NO_ERROR;
}

刪除Layer時读拆,主要做了以下幾件事:

  • 將Layer從父Layer中刪掉擅憔,或者從mCurrentState中刪掉,放到待刪除Layer列表中
  • onRemovedFromCurrentState檐晕,清理Layer暑诸,如果是父Layer蚌讼,子Layer也刪掉
  • setTransactionFlags,通知SurfaceFlinger更新个榕,更新后篡石,我們刪掉的Layer就沒有了,屏幕就不顯示了西采。

最后銷毀Layer

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

Layer::~Layer() {
    sp<Client> c(mClientRef.promote());
    if (c != 0) {
        c->detachLayer(this);
    }

    for (auto& point : mRemoteSyncPoints) {
        point->setTransactionApplied();
    }
    for (auto& point : mLocalSyncPoints) {
        point->setFrameAvailable();
    }
    mFrameTracker.logAndResetStats(mName);
}

善終... ...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末凰萨,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子械馆,更是在濱河造成了極大的恐慌胖眷,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件霹崎,死亡現(xiàn)場離奇詭異珊搀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)仿畸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來朗和,“玉大人错沽,你說我怎么就攤上這事】衾” “怎么了千埃?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長忆植。 經(jīng)常有香客問我放可,道長,這世上最難降的妖魔是什么朝刊? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任耀里,我火速辦了婚禮,結(jié)果婚禮上拾氓,老公的妹妹穿的比我還像新娘冯挎。我一直安慰自己,他們只是感情好咙鞍,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布房官。 她就那樣靜靜地躺著,像睡著了一般续滋。 火紅的嫁衣襯著肌膚如雪翰守。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天疲酌,我揣著相機(jī)與錄音蜡峰,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛事示,可吹牛的內(nèi)容都是我干的早像。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼肖爵,長吁一口氣:“原來是場噩夢啊……” “哼卢鹦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起劝堪,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤冀自,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后秒啦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體熬粗,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年余境,在試婚紗的時候發(fā)現(xiàn)自己被綠了驻呐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡芳来,死狀恐怖含末,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情即舌,我是刑警寧澤佣盒,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站顽聂,受9級特大地震影響肥惭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜紊搪,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一蜜葱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧耀石,春花似錦笼沥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至诗良,卻和暖如春汹桦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鉴裹。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工舞骆, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留钥弯,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓督禽,卻偏偏與公主長得像脆霎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子狈惫,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

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