libgui: Add generation numbers to BufferQueue
This change allows producers to set a generation number on a BufferQueue. This number will be embedded in any new GraphicBuffers created in that BufferQueue, and attempts to attach buffers which have a different generation number will fail. It also plumbs the setGenerationNumber method through Surface, with the additional effect that any buffers attached to the Surface after setting a new generation number will automatically be updated with the new number (as opposed to failing, as would happen on through IGBP). Bug: 20923096 Change-Id: I32bf726b035f99c3e5834beaf76afb9f01adcbc2
This commit is contained in:
parent
a8c2454d52
commit
812ed0644f
@ -275,6 +275,11 @@ private:
|
|||||||
// buffer as the number of frames that have elapsed since it was last queued
|
// buffer as the number of frames that have elapsed since it was last queued
|
||||||
uint64_t mBufferAge;
|
uint64_t mBufferAge;
|
||||||
|
|
||||||
|
// mGenerationNumber stores the current generation number of the attached
|
||||||
|
// producer. Any attempt to attach a buffer with a different generation
|
||||||
|
// number will fail.
|
||||||
|
uint32_t mGenerationNumber;
|
||||||
|
|
||||||
}; // class BufferQueueCore
|
}; // class BufferQueueCore
|
||||||
|
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
@ -175,6 +175,9 @@ public:
|
|||||||
// See IGraphicBufferProducer::allowAllocation
|
// See IGraphicBufferProducer::allowAllocation
|
||||||
virtual status_t allowAllocation(bool allow);
|
virtual status_t allowAllocation(bool allow);
|
||||||
|
|
||||||
|
// See IGraphicBufferProducer::setGenerationNumber
|
||||||
|
virtual status_t setGenerationNumber(uint32_t generationNumber);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This is required by the IBinder::DeathRecipient interface
|
// This is required by the IBinder::DeathRecipient interface
|
||||||
virtual void binderDied(const wp<IBinder>& who);
|
virtual void binderDied(const wp<IBinder>& who);
|
||||||
|
@ -110,7 +110,8 @@ public:
|
|||||||
// will be deallocated as stale.
|
// will be deallocated as stale.
|
||||||
//
|
//
|
||||||
// Return of a value other than NO_ERROR means an error has occurred:
|
// Return of a value other than NO_ERROR means an error has occurred:
|
||||||
// * BAD_VALUE - outSlot or buffer were NULL
|
// * BAD_VALUE - outSlot or buffer were NULL, or the generation number of
|
||||||
|
// the buffer did not match the buffer queue.
|
||||||
// * INVALID_OPERATION - cannot attach the buffer because it would cause too
|
// * INVALID_OPERATION - cannot attach the buffer because it would cause too
|
||||||
// many buffers to be acquired.
|
// many buffers to be acquired.
|
||||||
// * NO_MEMORY - no free slots available
|
// * NO_MEMORY - no free slots available
|
||||||
|
@ -218,8 +218,9 @@ public:
|
|||||||
//
|
//
|
||||||
// Return of a negative value means an error has occurred:
|
// Return of a negative value means an error has occurred:
|
||||||
// * NO_INIT - the buffer queue has been abandoned.
|
// * NO_INIT - the buffer queue has been abandoned.
|
||||||
// * BAD_VALUE - outSlot or buffer were NULL or invalid combination of
|
// * BAD_VALUE - outSlot or buffer were NULL, invalid combination of
|
||||||
// async mode and buffer count override.
|
// async mode and buffer count override, or the generation
|
||||||
|
// number of the buffer did not match the buffer queue.
|
||||||
// * INVALID_OPERATION - cannot attach the buffer because it would cause
|
// * INVALID_OPERATION - cannot attach the buffer because it would cause
|
||||||
// too many buffers to be dequeued, either because
|
// too many buffers to be dequeued, either because
|
||||||
// the producer already has a single buffer dequeued
|
// the producer already has a single buffer dequeued
|
||||||
@ -470,6 +471,15 @@ public:
|
|||||||
// eligible slot is available, dequeueBuffer will block or return an error
|
// eligible slot is available, dequeueBuffer will block or return an error
|
||||||
// as usual.
|
// as usual.
|
||||||
virtual status_t allowAllocation(bool allow) = 0;
|
virtual status_t allowAllocation(bool allow) = 0;
|
||||||
|
|
||||||
|
// Sets the current generation number of the BufferQueue.
|
||||||
|
//
|
||||||
|
// This generation number will be inserted into any buffers allocated by the
|
||||||
|
// BufferQueue, and any attempts to attach a buffer with a different
|
||||||
|
// generation number will fail. Buffers already in the queue are not
|
||||||
|
// affected and will retain their current generation number. The generation
|
||||||
|
// number defaults to 0.
|
||||||
|
virtual status_t setGenerationNumber(uint32_t generationNumber) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -101,6 +101,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void allocateBuffers();
|
void allocateBuffers();
|
||||||
|
|
||||||
|
/* Sets the generation number on the IGraphicBufferProducer and updates the
|
||||||
|
* generation number on any buffers attached to the Surface after this call.
|
||||||
|
* See IGBP::setGenerationNumber for more information. */
|
||||||
|
status_t setGenerationNumber(uint32_t generationNumber);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~Surface();
|
virtual ~Surface();
|
||||||
|
|
||||||
@ -305,6 +310,10 @@ private:
|
|||||||
// When a non-CPU producer is attached, this reflects the surface damage
|
// When a non-CPU producer is attached, this reflects the surface damage
|
||||||
// (the change since the previous frame) passed in by the producer.
|
// (the change since the previous frame) passed in by the producer.
|
||||||
Region mDirtyRegion;
|
Region mDirtyRegion;
|
||||||
|
|
||||||
|
// Stores the current generation number. See setGenerationNumber and
|
||||||
|
// IGraphicBufferProducer::setGenerationNumber for more information.
|
||||||
|
uint32_t mGenerationNumber;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
@ -94,6 +94,11 @@ public:
|
|||||||
Rect getBounds() const { return Rect(width, height); }
|
Rect getBounds() const { return Rect(width, height); }
|
||||||
uint64_t getId() const { return mId; }
|
uint64_t getId() const { return mId; }
|
||||||
|
|
||||||
|
uint32_t getGenerationNumber() const { return mGenerationNumber; }
|
||||||
|
void setGenerationNumber(uint32_t generation) {
|
||||||
|
mGenerationNumber = generation;
|
||||||
|
}
|
||||||
|
|
||||||
status_t reallocate(uint32_t inWidth, uint32_t inHeight,
|
status_t reallocate(uint32_t inWidth, uint32_t inHeight,
|
||||||
PixelFormat inFormat, uint32_t inUsage);
|
PixelFormat inFormat, uint32_t inUsage);
|
||||||
|
|
||||||
@ -166,6 +171,11 @@ private:
|
|||||||
sp<ANativeWindowBuffer> mWrappedBuffer;
|
sp<ANativeWindowBuffer> mWrappedBuffer;
|
||||||
|
|
||||||
uint64_t mId;
|
uint64_t mId;
|
||||||
|
|
||||||
|
// Stores the generation number of this buffer. If this number does not
|
||||||
|
// match the BufferQueue's internal generation number (set through
|
||||||
|
// IGBP::setGenerationNumber), attempts to attach the buffer will fail.
|
||||||
|
uint32_t mGenerationNumber;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
@ -248,6 +248,13 @@ status_t BufferQueueConsumer::attachBuffer(int* outSlot,
|
|||||||
return INVALID_OPERATION;
|
return INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
|
||||||
|
BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
|
||||||
|
"[queue %u]", buffer->getGenerationNumber(),
|
||||||
|
mCore->mGenerationNumber);
|
||||||
|
return BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
// Find a free slot to put the buffer into
|
// Find a free slot to put the buffer into
|
||||||
int found = BufferQueueCore::INVALID_BUFFER_SLOT;
|
int found = BufferQueueCore::INVALID_BUFFER_SLOT;
|
||||||
if (!mCore->mFreeSlots.empty()) {
|
if (!mCore->mFreeSlots.empty()) {
|
||||||
|
@ -71,7 +71,8 @@ BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
|
|||||||
mIsAllocating(false),
|
mIsAllocating(false),
|
||||||
mIsAllocatingCondition(),
|
mIsAllocatingCondition(),
|
||||||
mAllowAllocation(true),
|
mAllowAllocation(true),
|
||||||
mBufferAge(0)
|
mBufferAge(0),
|
||||||
|
mGenerationNumber(0)
|
||||||
{
|
{
|
||||||
if (allocator == NULL) {
|
if (allocator == NULL) {
|
||||||
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
|
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
|
||||||
|
@ -383,6 +383,7 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
|
|||||||
return NO_INIT;
|
return NO_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
|
||||||
mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
|
mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
|
||||||
} // Autolock scope
|
} // Autolock scope
|
||||||
}
|
}
|
||||||
@ -498,6 +499,13 @@ status_t BufferQueueProducer::attachBuffer(int* outSlot,
|
|||||||
Mutex::Autolock lock(mCore->mMutex);
|
Mutex::Autolock lock(mCore->mMutex);
|
||||||
mCore->waitWhileAllocatingLocked();
|
mCore->waitWhileAllocatingLocked();
|
||||||
|
|
||||||
|
if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
|
||||||
|
BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
|
||||||
|
"[queue %u]", buffer->getGenerationNumber(),
|
||||||
|
mCore->mGenerationNumber);
|
||||||
|
return BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
status_t returnFlags = NO_ERROR;
|
status_t returnFlags = NO_ERROR;
|
||||||
int found;
|
int found;
|
||||||
// TODO: Should we provide an async flag to attachBuffer? It seems
|
// TODO: Should we provide an async flag to attachBuffer? It seems
|
||||||
@ -1072,6 +1080,15 @@ status_t BufferQueueProducer::allowAllocation(bool allow) {
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t BufferQueueProducer::setGenerationNumber(uint32_t generationNumber) {
|
||||||
|
ATRACE_CALL();
|
||||||
|
BQ_LOGV("setGenerationNumber: %u", generationNumber);
|
||||||
|
|
||||||
|
Mutex::Autolock lock(mCore->mMutex);
|
||||||
|
mCore->mGenerationNumber = generationNumber;
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
|
void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
|
||||||
// If we're here, it means that a producer we were connected to died.
|
// If we're here, it means that a producer we were connected to died.
|
||||||
// We're guaranteed that we are still connected to it because we remove
|
// We're guaranteed that we are still connected to it because we remove
|
||||||
|
@ -47,6 +47,7 @@ enum {
|
|||||||
SET_SIDEBAND_STREAM,
|
SET_SIDEBAND_STREAM,
|
||||||
ALLOCATE_BUFFERS,
|
ALLOCATE_BUFFERS,
|
||||||
ALLOW_ALLOCATION,
|
ALLOW_ALLOCATION,
|
||||||
|
SET_GENERATION_NUMBER,
|
||||||
};
|
};
|
||||||
|
|
||||||
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
|
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
|
||||||
@ -284,6 +285,17 @@ public:
|
|||||||
result = reply.readInt32();
|
result = reply.readInt32();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual status_t setGenerationNumber(uint32_t generationNumber) {
|
||||||
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
|
||||||
|
data.writeUint32(generationNumber);
|
||||||
|
status_t result = remote()->transact(SET_GENERATION_NUMBER, data, &reply);
|
||||||
|
if (result == NO_ERROR) {
|
||||||
|
result = reply.readInt32();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Out-of-line virtual method definition to trigger vtable emission in this
|
// Out-of-line virtual method definition to trigger vtable emission in this
|
||||||
@ -448,6 +460,13 @@ status_t BnGraphicBufferProducer::onTransact(
|
|||||||
reply->writeInt32(result);
|
reply->writeInt32(result);
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
case SET_GENERATION_NUMBER: {
|
||||||
|
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
|
||||||
|
uint32_t generationNumber = data.readUint32();
|
||||||
|
status_t result = setGenerationNumber(generationNumber);
|
||||||
|
reply->writeInt32(result);
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return BBinder::onTransact(code, data, reply, flags);
|
return BBinder::onTransact(code, data, reply, flags);
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,8 @@ namespace android {
|
|||||||
Surface::Surface(
|
Surface::Surface(
|
||||||
const sp<IGraphicBufferProducer>& bufferProducer,
|
const sp<IGraphicBufferProducer>& bufferProducer,
|
||||||
bool controlledByApp)
|
bool controlledByApp)
|
||||||
: mGraphicBufferProducer(bufferProducer)
|
: mGraphicBufferProducer(bufferProducer),
|
||||||
|
mGenerationNumber(0)
|
||||||
{
|
{
|
||||||
// Initialize the ANativeWindow function pointers.
|
// Initialize the ANativeWindow function pointers.
|
||||||
ANativeWindow::setSwapInterval = hook_setSwapInterval;
|
ANativeWindow::setSwapInterval = hook_setSwapInterval;
|
||||||
@ -102,6 +103,14 @@ void Surface::allocateBuffers() {
|
|||||||
reqHeight, mReqFormat, mReqUsage);
|
reqHeight, mReqFormat, mReqUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t Surface::setGenerationNumber(uint32_t generation) {
|
||||||
|
status_t result = mGraphicBufferProducer->setGenerationNumber(generation);
|
||||||
|
if (result == NO_ERROR) {
|
||||||
|
mGenerationNumber = generation;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
|
int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
|
||||||
Surface* c = getSelf(window);
|
Surface* c = getSelf(window);
|
||||||
return c->setSwapInterval(interval);
|
return c->setSwapInterval(interval);
|
||||||
@ -698,11 +707,14 @@ int Surface::attachBuffer(ANativeWindowBuffer* buffer)
|
|||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
|
|
||||||
sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));
|
sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));
|
||||||
|
uint32_t priorGeneration = graphicBuffer->mGenerationNumber;
|
||||||
|
graphicBuffer->mGenerationNumber = mGenerationNumber;
|
||||||
int32_t attachedSlot = -1;
|
int32_t attachedSlot = -1;
|
||||||
status_t result = mGraphicBufferProducer->attachBuffer(
|
status_t result = mGraphicBufferProducer->attachBuffer(
|
||||||
&attachedSlot, graphicBuffer);
|
&attachedSlot, graphicBuffer);
|
||||||
if (result != NO_ERROR) {
|
if (result != NO_ERROR) {
|
||||||
ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result);
|
ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result);
|
||||||
|
graphicBuffer->mGenerationNumber = priorGeneration;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
mSlots[attachedSlot].buffer = graphicBuffer;
|
mSlots[attachedSlot].buffer = graphicBuffer;
|
||||||
|
@ -402,4 +402,46 @@ TEST_F(BufferQueueTest, TestDisallowingAllocation) {
|
|||||||
WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN));
|
WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(BufferQueueTest, TestGenerationNumbers) {
|
||||||
|
createBufferQueue();
|
||||||
|
sp<DummyConsumer> dc(new DummyConsumer);
|
||||||
|
ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
|
||||||
|
IGraphicBufferProducer::QueueBufferOutput output;
|
||||||
|
ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
|
||||||
|
NATIVE_WINDOW_API_CPU, true, &output));
|
||||||
|
|
||||||
|
ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
|
||||||
|
|
||||||
|
// Get one buffer to play with
|
||||||
|
int slot;
|
||||||
|
sp<Fence> fence;
|
||||||
|
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
|
||||||
|
mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, 0));
|
||||||
|
|
||||||
|
sp<GraphicBuffer> buffer;
|
||||||
|
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
|
||||||
|
|
||||||
|
// Ensure that the generation number we set propagates to allocated buffers
|
||||||
|
ASSERT_EQ(1U, buffer->getGenerationNumber());
|
||||||
|
|
||||||
|
ASSERT_EQ(OK, mProducer->detachBuffer(slot));
|
||||||
|
|
||||||
|
ASSERT_EQ(OK, mProducer->setGenerationNumber(2));
|
||||||
|
|
||||||
|
// These should fail, since we've changed the generation number on the queue
|
||||||
|
int outSlot;
|
||||||
|
ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer));
|
||||||
|
ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer));
|
||||||
|
|
||||||
|
buffer->setGenerationNumber(2);
|
||||||
|
|
||||||
|
// This should succeed now that we've changed the buffer's generation number
|
||||||
|
ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer));
|
||||||
|
|
||||||
|
ASSERT_EQ(OK, mProducer->detachBuffer(outSlot));
|
||||||
|
|
||||||
|
// This should also succeed with the new generation number
|
||||||
|
ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
@ -177,4 +177,37 @@ TEST_F(SurfaceTest, QueryDefaultBuffersDataSpace) {
|
|||||||
ASSERT_EQ(TEST_DATASPACE, dataSpace);
|
ASSERT_EQ(TEST_DATASPACE, dataSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SurfaceTest, SettingGenerationNumber) {
|
||||||
|
sp<IGraphicBufferProducer> producer;
|
||||||
|
sp<IGraphicBufferConsumer> consumer;
|
||||||
|
BufferQueue::createBufferQueue(&producer, &consumer);
|
||||||
|
sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
|
||||||
|
sp<Surface> surface = new Surface(producer);
|
||||||
|
sp<ANativeWindow> window(surface);
|
||||||
|
|
||||||
|
// Allocate a buffer with a generation number of 0
|
||||||
|
ANativeWindowBuffer* buffer;
|
||||||
|
int fenceFd;
|
||||||
|
ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fenceFd));
|
||||||
|
ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fenceFd));
|
||||||
|
|
||||||
|
// Detach the buffer and check its generation number
|
||||||
|
sp<GraphicBuffer> graphicBuffer;
|
||||||
|
sp<Fence> fence;
|
||||||
|
ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&graphicBuffer, &fence));
|
||||||
|
ASSERT_EQ(0U, graphicBuffer->getGenerationNumber());
|
||||||
|
|
||||||
|
ASSERT_EQ(NO_ERROR, surface->setGenerationNumber(1));
|
||||||
|
buffer = static_cast<ANativeWindowBuffer*>(graphicBuffer.get());
|
||||||
|
|
||||||
|
// This should change the generation number of the GraphicBuffer
|
||||||
|
ASSERT_EQ(NO_ERROR, surface->attachBuffer(buffer));
|
||||||
|
|
||||||
|
// Check that the new generation number sticks with the buffer
|
||||||
|
ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, -1));
|
||||||
|
ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fenceFd));
|
||||||
|
graphicBuffer = static_cast<GraphicBuffer*>(buffer);
|
||||||
|
ASSERT_EQ(1U, graphicBuffer->getGenerationNumber());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -278,7 +278,7 @@ status_t GraphicBuffer::unlockAsync(int *fenceFd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t GraphicBuffer::getFlattenedSize() const {
|
size_t GraphicBuffer::getFlattenedSize() const {
|
||||||
return static_cast<size_t>(10 + (handle ? handle->numInts : 0)) * sizeof(int);
|
return static_cast<size_t>(11 + (handle ? handle->numInts : 0)) * sizeof(int);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GraphicBuffer::getFdCount() const {
|
size_t GraphicBuffer::getFdCount() const {
|
||||||
@ -301,15 +301,16 @@ status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t&
|
|||||||
buf[5] = usage;
|
buf[5] = usage;
|
||||||
buf[6] = static_cast<int32_t>(mId >> 32);
|
buf[6] = static_cast<int32_t>(mId >> 32);
|
||||||
buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
|
buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
|
||||||
buf[8] = 0;
|
buf[8] = static_cast<int32_t>(mGenerationNumber);
|
||||||
buf[9] = 0;
|
buf[9] = 0;
|
||||||
|
buf[10] = 0;
|
||||||
|
|
||||||
if (handle) {
|
if (handle) {
|
||||||
buf[8] = handle->numFds;
|
buf[9] = handle->numFds;
|
||||||
buf[9] = handle->numInts;
|
buf[10] = handle->numInts;
|
||||||
memcpy(fds, handle->data,
|
memcpy(fds, handle->data,
|
||||||
static_cast<size_t>(handle->numFds) * sizeof(int));
|
static_cast<size_t>(handle->numFds) * sizeof(int));
|
||||||
memcpy(&buf[10], handle->data + handle->numFds,
|
memcpy(&buf[11], handle->data + handle->numFds,
|
||||||
static_cast<size_t>(handle->numInts) * sizeof(int));
|
static_cast<size_t>(handle->numInts) * sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,20 +326,20 @@ status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t&
|
|||||||
|
|
||||||
status_t GraphicBuffer::unflatten(
|
status_t GraphicBuffer::unflatten(
|
||||||
void const*& buffer, size_t& size, int const*& fds, size_t& count) {
|
void const*& buffer, size_t& size, int const*& fds, size_t& count) {
|
||||||
if (size < 8*sizeof(int)) return NO_MEMORY;
|
if (size < 11 * sizeof(int)) return NO_MEMORY;
|
||||||
|
|
||||||
int const* buf = static_cast<int const*>(buffer);
|
int const* buf = static_cast<int const*>(buffer);
|
||||||
if (buf[0] != 'GBFR') return BAD_TYPE;
|
if (buf[0] != 'GBFR') return BAD_TYPE;
|
||||||
|
|
||||||
const size_t numFds = static_cast<size_t>(buf[8]);
|
const size_t numFds = static_cast<size_t>(buf[9]);
|
||||||
const size_t numInts = static_cast<size_t>(buf[9]);
|
const size_t numInts = static_cast<size_t>(buf[10]);
|
||||||
|
|
||||||
// Limit the maxNumber to be relatively small. The number of fds or ints
|
// Limit the maxNumber to be relatively small. The number of fds or ints
|
||||||
// should not come close to this number, and the number itself was simply
|
// should not come close to this number, and the number itself was simply
|
||||||
// chosen to be high enough to not cause issues and low enough to prevent
|
// chosen to be high enough to not cause issues and low enough to prevent
|
||||||
// overflow problems.
|
// overflow problems.
|
||||||
const size_t maxNumber = 4096;
|
const size_t maxNumber = 4096;
|
||||||
if (numFds >= maxNumber || numInts >= (maxNumber - 10)) {
|
if (numFds >= maxNumber || numInts >= (maxNumber - 11)) {
|
||||||
width = height = stride = format = usage = 0;
|
width = height = stride = format = usage = 0;
|
||||||
handle = NULL;
|
handle = NULL;
|
||||||
ALOGE("unflatten: numFds or numInts is too large: %zd, %zd",
|
ALOGE("unflatten: numFds or numInts is too large: %zd, %zd",
|
||||||
@ -346,7 +347,7 @@ status_t GraphicBuffer::unflatten(
|
|||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t sizeNeeded = (10 + numInts) * sizeof(int);
|
const size_t sizeNeeded = (11 + numInts) * sizeof(int);
|
||||||
if (size < sizeNeeded) return NO_MEMORY;
|
if (size < sizeNeeded) return NO_MEMORY;
|
||||||
|
|
||||||
size_t fdCountNeeded = numFds;
|
size_t fdCountNeeded = numFds;
|
||||||
@ -372,7 +373,7 @@ status_t GraphicBuffer::unflatten(
|
|||||||
return NO_MEMORY;
|
return NO_MEMORY;
|
||||||
}
|
}
|
||||||
memcpy(h->data, fds, numFds * sizeof(int));
|
memcpy(h->data, fds, numFds * sizeof(int));
|
||||||
memcpy(h->data + numFds, &buf[10], numInts * sizeof(int));
|
memcpy(h->data + numFds, &buf[11], numInts * sizeof(int));
|
||||||
handle = h;
|
handle = h;
|
||||||
} else {
|
} else {
|
||||||
width = height = stride = format = usage = 0;
|
width = height = stride = format = usage = 0;
|
||||||
@ -382,6 +383,8 @@ status_t GraphicBuffer::unflatten(
|
|||||||
mId = static_cast<uint64_t>(buf[6]) << 32;
|
mId = static_cast<uint64_t>(buf[6]) << 32;
|
||||||
mId |= static_cast<uint32_t>(buf[7]);
|
mId |= static_cast<uint32_t>(buf[7]);
|
||||||
|
|
||||||
|
mGenerationNumber = static_cast<uint32_t>(buf[8]);
|
||||||
|
|
||||||
mOwner = ownHandle;
|
mOwner = ownHandle;
|
||||||
|
|
||||||
if (handle != 0) {
|
if (handle != 0) {
|
||||||
|
@ -530,6 +530,11 @@ status_t VirtualDisplaySurface::allowAllocation(bool /* allow */) {
|
|||||||
return INVALID_OPERATION;
|
return INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t VirtualDisplaySurface::setGenerationNumber(uint32_t /* generation */) {
|
||||||
|
ALOGE("setGenerationNumber not supported on VirtualDisplaySurface");
|
||||||
|
return INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
|
||||||
void VirtualDisplaySurface::updateQueueBufferOutput(
|
void VirtualDisplaySurface::updateQueueBufferOutput(
|
||||||
const QueueBufferOutput& qbo) {
|
const QueueBufferOutput& qbo) {
|
||||||
uint32_t w, h, transformHint, numPendingBuffers;
|
uint32_t w, h, transformHint, numPendingBuffers;
|
||||||
|
@ -116,6 +116,7 @@ private:
|
|||||||
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
|
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
|
||||||
PixelFormat format, uint32_t usage);
|
PixelFormat format, uint32_t usage);
|
||||||
virtual status_t allowAllocation(bool allow);
|
virtual status_t allowAllocation(bool allow);
|
||||||
|
virtual status_t setGenerationNumber(uint32_t generationNumber);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Utility methods
|
// Utility methods
|
||||||
|
@ -114,6 +114,10 @@ status_t MonitoredProducer::allowAllocation(bool allow) {
|
|||||||
return mProducer->allowAllocation(allow);
|
return mProducer->allowAllocation(allow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t MonitoredProducer::setGenerationNumber(uint32_t generationNumber) {
|
||||||
|
return mProducer->setGenerationNumber(generationNumber);
|
||||||
|
}
|
||||||
|
|
||||||
IBinder* MonitoredProducer::onAsBinder() {
|
IBinder* MonitoredProducer::onAsBinder() {
|
||||||
return IInterface::asBinder(mProducer).get();
|
return IInterface::asBinder(mProducer).get();
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ public:
|
|||||||
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
|
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
|
||||||
PixelFormat format, uint32_t usage);
|
PixelFormat format, uint32_t usage);
|
||||||
virtual status_t allowAllocation(bool allow);
|
virtual status_t allowAllocation(bool allow);
|
||||||
|
virtual status_t setGenerationNumber(uint32_t generationNumber);
|
||||||
virtual IBinder* onAsBinder();
|
virtual IBinder* onAsBinder();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user