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

Commit bbb85c8e authored by Jamie Gennis's avatar Jamie Gennis Committed by Android (Google) Code Review
Browse files

Merge changes Ibd261f7b,Ifdd234ef,I0e2f0bc3

* changes:
  SurfaceTexture: add the abandon method.
  SurfaceTexture: add a deadlock scenario test
  SurfaceMediaSource: remove getAllocator method
parents 5bae58df 5ef59bc7
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -51,7 +51,7 @@ protected:
    // the given slot index, and the client is expected to mirror the
    // the given slot index, and the client is expected to mirror the
    // slot->buffer mapping so that it's not necessary to transfer a
    // slot->buffer mapping so that it's not necessary to transfer a
    // GraphicBuffer for every dequeue operation.
    // GraphicBuffer for every dequeue operation.
    virtual sp<GraphicBuffer> requestBuffer(int slot) = 0;
    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0;


    // setBufferCount sets the number of buffer slots available. Calling this
    // setBufferCount sets the number of buffer slots available. Calling this
    // will also cause all buffer slots to be emptied. The caller should empty
    // will also cause all buffer slots to be emptied. The caller should empty
+19 −1
Original line number Original line Diff line number Diff line
@@ -69,7 +69,7 @@ public:
    // SurfaceTexture object (i.e. they are not owned by the client).
    // SurfaceTexture object (i.e. they are not owned by the client).
    virtual status_t setBufferCount(int bufferCount);
    virtual status_t setBufferCount(int bufferCount);


    virtual sp<GraphicBuffer> requestBuffer(int buf);
    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);


    // dequeueBuffer gets the next buffer slot index for the client to use. If a
    // dequeueBuffer gets the next buffer slot index for the client to use. If a
    // buffer slot is available then that slot index is written to the location
    // buffer slot is available then that slot index is written to the location
@@ -190,6 +190,17 @@ public:
    // getCurrentScalingMode returns the scaling mode of the current buffer
    // getCurrentScalingMode returns the scaling mode of the current buffer
    uint32_t getCurrentScalingMode() const;
    uint32_t getCurrentScalingMode() const;


    // abandon frees all the buffers and puts the SurfaceTexture into the
    // 'abandoned' state.  Once put in this state the SurfaceTexture can never
    // leave it.  When in the 'abandoned' state, all methods of the
    // ISurfaceTexture interface will fail with the NO_INIT error.
    //
    // Note that while calling this method causes all the buffers to be freed
    // from the perspective of the the SurfaceTexture, if there are additional
    // references on the buffers (e.g. if a buffer is referenced by a client or
    // by OpenGL ES as a texture) then those buffer will remain allocated.
    void abandon();

    // dump our state in a String
    // dump our state in a String
    void dump(String8& result) const;
    void dump(String8& result) const;
    void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
    void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
@@ -411,6 +422,13 @@ private:
    typedef Vector<int> Fifo;
    typedef Vector<int> Fifo;
    Fifo mQueue;
    Fifo mQueue;


    // mAbandoned indicates that the SurfaceTexture will no longer be used to
    // consume images buffers pushed to it using the ISurfaceTexture interface.
    // It is initialized to false, and set to true in the abandon method.  A
    // SurfaceTexture that has been abandoned will return the NO_INIT error from
    // all ISurfaceTexture methods capable of returning an error.
    bool mAbandoned;

    // mMutex is the mutex used to prevent concurrent access to the member
    // mMutex is the mutex used to prevent concurrent access to the member
    // variables of SurfaceTexture objects. It must be locked whenever the
    // variables of SurfaceTexture objects. It must be locked whenever the
    // member variables are accessed.
    // member variables are accessed.
+1 −8
Original line number Original line Diff line number Diff line
@@ -81,7 +81,7 @@ public:
    // SurfaceMediaSource object (i.e. they are not owned by the client).
    // SurfaceMediaSource object (i.e. they are not owned by the client).
    virtual status_t setBufferCount(int bufferCount);
    virtual status_t setBufferCount(int bufferCount);


    virtual sp<GraphicBuffer> requestBuffer(int buf);
    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);


    // dequeueBuffer gets the next buffer slot index for the client to use. If a
    // dequeueBuffer gets the next buffer slot index for the client to use. If a
    // buffer slot is available then that slot index is written to the location
    // buffer slot is available then that slot index is written to the location
@@ -163,13 +163,6 @@ public:
    // when a new frame becomes available.
    // when a new frame becomes available.
    void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
    void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);


    // getAllocator retrieves the binder object that must be referenced as long
    // as the GraphicBuffers dequeued from this SurfaceMediaSource are referenced.
    // Holding this binder reference prevents SurfaceFlinger from freeing the
    // buffers before the client is done with them.
    sp<IBinder> getAllocator();


    // getCurrentBuffer returns the buffer associated with the current image.
    // getCurrentBuffer returns the buffer associated with the current image.
    sp<GraphicBuffer> getCurrentBuffer() const;
    sp<GraphicBuffer> getCurrentBuffer() const;


+8 −6
Original line number Original line Diff line number Diff line
@@ -54,18 +54,18 @@ public:
    {
    {
    }
    }


    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx) {
    virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
        Parcel data, reply;
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
        data.writeInt32(bufferIdx);
        data.writeInt32(bufferIdx);
        remote()->transact(REQUEST_BUFFER, data, &reply);
        remote()->transact(REQUEST_BUFFER, data, &reply);
        sp<GraphicBuffer> buffer;
        bool nonNull = reply.readInt32();
        bool nonNull = reply.readInt32();
        if (nonNull) {
        if (nonNull) {
            buffer = new GraphicBuffer();
            *buf = new GraphicBuffer();
            reply.read(*buffer);
            reply.read(**buf);
        }
        }
        return buffer;
        status_t result = reply.readInt32();
        return result;
    }
    }


    virtual status_t setBufferCount(int bufferCount)
    virtual status_t setBufferCount(int bufferCount)
@@ -192,11 +192,13 @@ status_t BnSurfaceTexture::onTransact(
        case REQUEST_BUFFER: {
        case REQUEST_BUFFER: {
            CHECK_INTERFACE(ISurfaceTexture, data, reply);
            CHECK_INTERFACE(ISurfaceTexture, data, reply);
            int bufferIdx   = data.readInt32();
            int bufferIdx   = data.readInt32();
            sp<GraphicBuffer> buffer(requestBuffer(bufferIdx));
            sp<GraphicBuffer> buffer;
            int result = requestBuffer(bufferIdx, &buffer);
            reply->writeInt32(buffer != 0);
            reply->writeInt32(buffer != 0);
            if (buffer != 0) {
            if (buffer != 0) {
                reply->write(*buffer);
                reply->write(*buffer);
            }
            }
            reply->writeInt32(result);
            return NO_ERROR;
            return NO_ERROR;
        } break;
        } break;
        case SET_BUFFER_COUNT: {
        case SET_BUFFER_COUNT: {
+76 −7
Original line number Original line Diff line number Diff line
@@ -94,7 +94,8 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) :
    mTexName(tex),
    mTexName(tex),
    mSynchronousMode(false),
    mSynchronousMode(false),
    mAllowSynchronousMode(allowSynchronousMode),
    mAllowSynchronousMode(allowSynchronousMode),
    mConnectedApi(NO_CONNECTED_API) {
    mConnectedApi(NO_CONNECTED_API),
    mAbandoned(false) {
    LOGV("SurfaceTexture::SurfaceTexture");
    LOGV("SurfaceTexture::SurfaceTexture");
    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
@@ -150,6 +151,11 @@ status_t SurfaceTexture::setBufferCount(int bufferCount) {
    LOGV("SurfaceTexture::setBufferCount");
    LOGV("SurfaceTexture::setBufferCount");
    Mutex::Autolock lock(mMutex);
    Mutex::Autolock lock(mMutex);


    if (mAbandoned) {
        LOGE("setBufferCount: SurfaceTexture has been abandoned!");
        return NO_INIT;
    }

    if (bufferCount > NUM_BUFFER_SLOTS) {
    if (bufferCount > NUM_BUFFER_SLOTS) {
        LOGE("setBufferCount: bufferCount larger than slots available");
        LOGE("setBufferCount: bufferCount larger than slots available");
        return BAD_VALUE;
        return BAD_VALUE;
@@ -199,22 +205,32 @@ status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
    return OK;
    return OK;
}
}


sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf) {
status_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
    LOGV("SurfaceTexture::requestBuffer");
    LOGV("SurfaceTexture::requestBuffer");
    Mutex::Autolock lock(mMutex);
    Mutex::Autolock lock(mMutex);
    if (buf < 0 || mBufferCount <= buf) {
    if (mAbandoned) {
        LOGE("requestBuffer: SurfaceTexture has been abandoned!");
        return NO_INIT;
    }
    if (slot < 0 || mBufferCount <= slot) {
        LOGE("requestBuffer: slot index out of range [0, %d]: %d",
        LOGE("requestBuffer: slot index out of range [0, %d]: %d",
                mBufferCount, buf);
                mBufferCount, slot);
        return 0;
        return BAD_VALUE;
    }
    }
    mSlots[buf].mRequestBufferCalled = true;
    mSlots[slot].mRequestBufferCalled = true;
    return mSlots[buf].mGraphicBuffer;
    *buf = mSlots[slot].mGraphicBuffer;
    return NO_ERROR;
}
}


status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
        uint32_t format, uint32_t usage) {
        uint32_t format, uint32_t usage) {
    LOGV("SurfaceTexture::dequeueBuffer");
    LOGV("SurfaceTexture::dequeueBuffer");


    if (mAbandoned) {
        LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
        return NO_INIT;
    }

    if ((w && !h) || (!w && h)) {
    if ((w && !h) || (!w && h)) {
        LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
        LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
        return BAD_VALUE;
        return BAD_VALUE;
@@ -252,6 +268,11 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
            // wait for the FIFO to drain
            // wait for the FIFO to drain
            while (!mQueue.isEmpty()) {
            while (!mQueue.isEmpty()) {
                mDequeueCondition.wait(mMutex);
                mDequeueCondition.wait(mMutex);
                if (mAbandoned) {
                    LOGE("dequeueBuffer: SurfaceTexture was abandoned while "
                            "blocked!");
                    return NO_INIT;
                }
            }
            }
            minBufferCountNeeded = mSynchronousMode ?
            minBufferCountNeeded = mSynchronousMode ?
                    MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
                    MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
@@ -380,6 +401,11 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
status_t SurfaceTexture::setSynchronousMode(bool enabled) {
status_t SurfaceTexture::setSynchronousMode(bool enabled) {
    Mutex::Autolock lock(mMutex);
    Mutex::Autolock lock(mMutex);


    if (mAbandoned) {
        LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
        return NO_INIT;
    }

    status_t err = OK;
    status_t err = OK;
    if (!mAllowSynchronousMode && enabled)
    if (!mAllowSynchronousMode && enabled)
        return err;
        return err;
@@ -410,6 +436,10 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,


    { // scope for the lock
    { // scope for the lock
        Mutex::Autolock lock(mMutex);
        Mutex::Autolock lock(mMutex);
        if (mAbandoned) {
            LOGE("queueBuffer: SurfaceTexture has been abandoned!");
            return NO_INIT;
        }
        if (buf < 0 || buf >= mBufferCount) {
        if (buf < 0 || buf >= mBufferCount) {
            LOGE("queueBuffer: slot index out of range [0, %d]: %d",
            LOGE("queueBuffer: slot index out of range [0, %d]: %d",
                    mBufferCount, buf);
                    mBufferCount, buf);
@@ -475,6 +505,12 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,
void SurfaceTexture::cancelBuffer(int buf) {
void SurfaceTexture::cancelBuffer(int buf) {
    LOGV("SurfaceTexture::cancelBuffer");
    LOGV("SurfaceTexture::cancelBuffer");
    Mutex::Autolock lock(mMutex);
    Mutex::Autolock lock(mMutex);

    if (mAbandoned) {
        LOGW("cancelBuffer: SurfaceTexture has been abandoned!");
        return;
    }

    if (buf < 0 || buf >= mBufferCount) {
    if (buf < 0 || buf >= mBufferCount) {
        LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
        LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
                mBufferCount, buf);
                mBufferCount, buf);
@@ -491,6 +527,10 @@ void SurfaceTexture::cancelBuffer(int buf) {
status_t SurfaceTexture::setCrop(const Rect& crop) {
status_t SurfaceTexture::setCrop(const Rect& crop) {
    LOGV("SurfaceTexture::setCrop");
    LOGV("SurfaceTexture::setCrop");
    Mutex::Autolock lock(mMutex);
    Mutex::Autolock lock(mMutex);
    if (mAbandoned) {
        LOGE("setCrop: SurfaceTexture has been abandoned!");
        return NO_INIT;
    }
    mNextCrop = crop;
    mNextCrop = crop;
    return OK;
    return OK;
}
}
@@ -498,6 +538,10 @@ status_t SurfaceTexture::setCrop(const Rect& crop) {
status_t SurfaceTexture::setTransform(uint32_t transform) {
status_t SurfaceTexture::setTransform(uint32_t transform) {
    LOGV("SurfaceTexture::setTransform");
    LOGV("SurfaceTexture::setTransform");
    Mutex::Autolock lock(mMutex);
    Mutex::Autolock lock(mMutex);
    if (mAbandoned) {
        LOGE("setTransform: SurfaceTexture has been abandoned!");
        return NO_INIT;
    }
    mNextTransform = transform;
    mNextTransform = transform;
    return OK;
    return OK;
}
}
@@ -505,6 +549,12 @@ status_t SurfaceTexture::setTransform(uint32_t transform) {
status_t SurfaceTexture::connect(int api) {
status_t SurfaceTexture::connect(int api) {
    LOGV("SurfaceTexture::connect(this=%p, %d)", this, api);
    LOGV("SurfaceTexture::connect(this=%p, %d)", this, api);
    Mutex::Autolock lock(mMutex);
    Mutex::Autolock lock(mMutex);

    if (mAbandoned) {
        LOGE("connect: SurfaceTexture has been abandoned!");
        return NO_INIT;
    }

    int err = NO_ERROR;
    int err = NO_ERROR;
    switch (api) {
    switch (api) {
        case NATIVE_WINDOW_API_EGL:
        case NATIVE_WINDOW_API_EGL:
@@ -529,6 +579,12 @@ status_t SurfaceTexture::connect(int api) {
status_t SurfaceTexture::disconnect(int api) {
status_t SurfaceTexture::disconnect(int api) {
    LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api);
    LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api);
    Mutex::Autolock lock(mMutex);
    Mutex::Autolock lock(mMutex);

    if (mAbandoned) {
        LOGE("connect: SurfaceTexture has been abandoned!");
        return NO_INIT;
    }

    int err = NO_ERROR;
    int err = NO_ERROR;
    switch (api) {
    switch (api) {
        case NATIVE_WINDOW_API_EGL:
        case NATIVE_WINDOW_API_EGL:
@@ -837,6 +893,12 @@ uint32_t SurfaceTexture::getCurrentScalingMode() const {
int SurfaceTexture::query(int what, int* outValue)
int SurfaceTexture::query(int what, int* outValue)
{
{
    Mutex::Autolock lock(mMutex);
    Mutex::Autolock lock(mMutex);

    if (mAbandoned) {
        LOGE("query: SurfaceTexture has been abandoned!");
        return NO_INIT;
    }

    int value;
    int value;
    switch (what) {
    switch (what) {
    case NATIVE_WINDOW_WIDTH:
    case NATIVE_WINDOW_WIDTH:
@@ -863,6 +925,13 @@ int SurfaceTexture::query(int what, int* outValue)
    return NO_ERROR;
    return NO_ERROR;
}
}


void SurfaceTexture::abandon() {
    Mutex::Autolock lock(mMutex);
    freeAllBuffers();
    mAbandoned = true;
    mDequeueCondition.signal();
}

void SurfaceTexture::dump(String8& result) const
void SurfaceTexture::dump(String8& result) const
{
{
    char buffer[1024];
    char buffer[1024];
Loading