Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7670d3cb authored by Mathias Agopian's avatar Mathias Agopian Committed by Android (Google) Code Review
Browse files

Merge "get rid of purgatory and fix QueuesToWindowComposer query" into jb-mr2-dev

parents a493be58 67106042
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
void Layer::onFirstRef()
{
    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    sp<BufferQueue> bq = new SurfaceTextureLayer();
    sp<BufferQueue> bq = new SurfaceTextureLayer(mFlinger);
    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mTextureName, true,
            GL_TEXTURE_EXTERNAL_OES, false, bq);

@@ -153,8 +153,9 @@ void Layer::onFrameAvailable() {
    mFlinger->signalLayerUpdate();
}

// called with SurfaceFlinger::mStateLock as soon as the layer is entered
// in the purgatory list
// called with SurfaceFlinger::mStateLock from the drawing thread after
// the layer has been remove from the current state list (and just before
// it's removed from the drawing state list)
void Layer::onRemoved() {
    mSurfaceFlingerConsumer->abandon();
}
+16 −101
Original line number Diff line number Diff line
@@ -574,39 +574,7 @@ bool SurfaceFlinger::authenticateSurfaceTexture(
        const sp<IGraphicBufferProducer>& bufferProducer) const {
    Mutex::Autolock _l(mStateLock);
    sp<IBinder> surfaceTextureBinder(bufferProducer->asBinder());

    // We want to determine whether the IGraphicBufferProducer was created by
    // SurfaceFlinger.  Check to see if we can find it in the layer list.
    const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
    size_t count = currentLayers.size();
    for (size_t i=0 ; i<count ; i++) {
        const sp<Layer>& layer(currentLayers[i]);
        // Get the consumer interface of SurfaceFlingerConsumer's
        // BufferQueue.  If it's the same Binder object as the graphic
        // buffer producer interface, return success.
        sp<IBinder> lbcBinder = layer->getBufferQueue()->asBinder();
        if (lbcBinder == surfaceTextureBinder) {
            return true;
        }
    }

    // Check the layers in the purgatory.  This check is here so that if a
    // GLConsumer gets destroyed before all the clients are done using it,
    // the error will not be reported as "surface XYZ is not authenticated", but
    // will instead fail later on when the client tries to use the surface,
    // which should be reported as "surface XYZ returned an -ENODEV".  The
    // purgatorized layers are no less authentic than the visible ones, so this
    // should not cause any harm.
    size_t purgatorySize =  mLayerPurgatory.size();
    for (size_t i=0 ; i<purgatorySize ; i++) {
        const sp<Layer>& layer(mLayerPurgatory.itemAt(i));
        sp<IBinder> lbcBinder = layer->getBufferQueue()->asBinder();
        if (lbcBinder == surfaceTextureBinder) {
            return true;
        }
    }

    return false;
    return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
}

status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) {
@@ -1676,6 +1644,7 @@ void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& hw,

void SurfaceFlinger::addClientLayer(const sp<Client>& client,
        const sp<IBinder>& handle,
        const sp<IGraphicBufferProducer>& gbc,
        const sp<Layer>& lbc)
{
    // attach this layer to the client
@@ -1684,45 +1653,22 @@ void SurfaceFlinger::addClientLayer(const sp<Client>& client,
    // add this layer to the current state list
    Mutex::Autolock _l(mStateLock);
    mCurrentState.layersSortedByZ.add(lbc);
    mGraphicBufferProducerList.add(gbc->asBinder());
}

status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer)
{
    Mutex::Autolock _l(mStateLock);
    status_t err = purgatorizeLayer_l(layer);
    if (err == NO_ERROR)
        setTransactionFlags(eTransactionNeeded);
    return err;
}

status_t SurfaceFlinger::removeLayer_l(const sp<Layer>& layer)
{
    ssize_t index = mCurrentState.layersSortedByZ.remove(layer);
    if (index >= 0) {
        mLayersPendingRemoval.push(layer);
        mLayersRemoved = true;
        setTransactionFlags(eTransactionNeeded);
        return NO_ERROR;
    }
    return status_t(index);
}

status_t SurfaceFlinger::purgatorizeLayer_l(const sp<Layer>& layer)
{
    // First add the layer to the purgatory list, which makes sure it won't
    // go away, then remove it from the main list (through a transaction).
    ssize_t err = removeLayer_l(layer);
    if (err >= 0) {
        mLayerPurgatory.add(layer);
    }

    mLayersPendingRemoval.push(layer);

    // it's possible that we don't find a layer, because it might
    // have been destroyed already -- this is not technically an error
    // from the user because there is a race between Client::destroySurface(),
    // ~Client() and ~LayerCleaner().
    return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err;
}

uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t flags)
{
    return android_atomic_release_load(&mTransactionFlags);
@@ -1957,7 +1903,7 @@ status_t SurfaceFlinger::createLayer(
    }

    if (result == NO_ERROR) {
        addClientLayer(client, *handle, layer);
        addClientLayer(client, *handle, *gbp, layer);
        setTransactionFlags(eTransactionNeeded);
    }
    return result;
@@ -2010,44 +1956,25 @@ status_t SurfaceFlinger::createDimLayer(const sp<Client>& client,

status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
{
    /*
     * called by the window manager, when a surface should be marked for
     * destruction.
     *
     * The surface is removed from the current and drawing lists, but placed
     * in the purgatory queue, so it's not destroyed right-away (we need
     * to wait for all client's references to go away first).
     */

    status_t err = NAME_NOT_FOUND;
    Mutex::Autolock _l(mStateLock);
    sp<Layer> layer = client->getLayerUser(handle);

    if (layer != 0) {
        err = purgatorizeLayer_l(layer);
        if (err == NO_ERROR) {
            setTransactionFlags(eTransactionNeeded);
        }
    // called by the window manager when it wants to remove a Layer
    status_t err = NO_ERROR;
    sp<Layer> l(client->getLayerUser(handle));
    if (l != NULL) {
        err = removeLayer(l);
        ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
                "error removing layer=%p (%s)", l.get(), strerror(-err));
    }
    return err;
}

status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer)
{
    // called by ~LayerCleaner() when all references are gone
    // called by ~LayerCleaner() when all references to the IBinder (handle)
    // are gone
    status_t err = NO_ERROR;
    sp<Layer> l(layer.promote());
    if (l != NULL) {
        Mutex::Autolock _l(mStateLock);
        err = removeLayer_l(l);
        if (err == NAME_NOT_FOUND) {
            // The surface wasn't in the current list, which means it was
            // removed already, which means it is in the purgatory,
            // and need to be removed from there.
            ssize_t idx = mLayerPurgatory.remove(l);
            ALOGE_IF(idx < 0,
                    "layer=%p is not in the purgatory list", l.get());
        }
        err = removeLayer(l);
        ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
                "error removing layer=%p (%s)", l.get(), strerror(-err));
    }
@@ -2358,18 +2285,6 @@ void SurfaceFlinger::dumpAllLocked(
        layer->dump(result, buffer, SIZE);
    }

    /*
     * Dump the layers in the purgatory
     */

    const size_t purgatorySize = mLayerPurgatory.size();
    snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize);
    result.append(buffer);
    for (size_t i=0 ; i<purgatorySize ; i++) {
        const sp<Layer>& layer(mLayerPurgatory.itemAt(i));
        layer->shortDump(result, buffer, SIZE);
    }

    /*
     * Dump Display state
     */
+6 −8
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ private:
    friend class Client;
    friend class DisplayEventConnection;
    friend class Layer;
    friend class SurfaceTextureLayer;

    // We're reference counted, never destroy SurfaceFlinger directly
    virtual ~SurfaceFlinger();
@@ -272,8 +273,6 @@ private:

    // called in response to the window-manager calling
    // ISurfaceComposerClient::destroySurface()
    // The specified layer is first placed in a purgatory list
    // until all references from the client are released.
    status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle);

    // called when all clients have released all their references to
@@ -285,12 +284,11 @@ private:
    status_t removeLayer(const sp<Layer>& layer);

    // add a layer to SurfaceFlinger
    void addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
    void addClientLayer(const sp<Client>& client,
            const sp<IBinder>& handle,
            const sp<IGraphicBufferProducer>& gbc,
            const sp<Layer>& lbc);

    status_t removeLayer_l(const sp<Layer>& layer);
    status_t purgatorizeLayer_l(const sp<Layer>& layer);

    /* ------------------------------------------------------------------------
     * Boot animation, on/off animations and screen capture
     */
@@ -403,10 +401,10 @@ private:
    State mCurrentState;
    volatile int32_t mTransactionFlags;
    Condition mTransactionCV;
    SortedVector< sp<Layer> > mLayerPurgatory;
    bool mTransactionPending;
    bool mAnimTransactionPending;
    Vector< sp<Layer> > mLayersPendingRemoval;
    SortedVector< wp<IBinder> > mGraphicBufferProducerList;

    // protected by mStateLock (but we could use another lock)
    bool mLayersRemoved;
+20 −2
Original line number Diff line number Diff line
@@ -20,17 +20,35 @@

#include <utils/Errors.h>

#include "SurfaceFlinger.h"
#include "SurfaceTextureLayer.h"

namespace android {
// ---------------------------------------------------------------------------


SurfaceTextureLayer::SurfaceTextureLayer()
    : BufferQueue(true) {
SurfaceTextureLayer::SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger)
    : BufferQueue(true), flinger(flinger) {
}

SurfaceTextureLayer::~SurfaceTextureLayer() {
    // remove ourselves from SurfaceFlinger's list. We do this asynchronously
    // because we don't know where this dtor is called from, it could be
    // called with the mStateLock held, leading to a dead-lock (it actually
    // happens).
    class MessageCleanUpList : public MessageBase {
        sp<SurfaceFlinger> flinger;
        wp<IBinder> gbp;
    public:
        MessageCleanUpList(const sp<SurfaceFlinger>& flinger, const wp<IBinder>& gbp)
            : flinger(flinger), gbp(gbp) { }
        virtual bool handler() {
            Mutex::Autolock _l(flinger->mStateLock);
            flinger->mGraphicBufferProducerList.remove(gbp);
            return true;
        }
    };
    flinger->postMessageAsync( new MessageCleanUpList(flinger, this) );
}

status_t SurfaceTextureLayer::connect(int api, QueueBufferOutput* output) {
+5 −4
Original line number Diff line number Diff line
@@ -28,15 +28,16 @@ namespace android {
// ---------------------------------------------------------------------------

class Layer;
class SurfaceFlinger;

/*
 * This is a thin wrapper around BufferQueue, used by the Layer class.
 */
class SurfaceTextureLayer : public BufferQueue
{
class SurfaceTextureLayer : public BufferQueue {
    sp<SurfaceFlinger> flinger;
public:
    SurfaceTextureLayer();
    ~SurfaceTextureLayer();
    SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger);
    virtual ~SurfaceTextureLayer();

    // After calling the superclass connect(), set or clear synchronous
    // mode appropriately for the specified API.