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

Commit 0714d09e authored by Mathias Agopian's avatar Mathias Agopian Committed by Android Git Automerger
Browse files

am 7670d3cb: Merge "get rid of purgatory and fix QueuesToWindowComposer query" into jb-mr2-dev

* commit '7670d3cb':
  get rid of purgatory and fix QueuesToWindowComposer query
parents 28e89fed 7670d3cb
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.