Merge "Avoid closing invalid FD in Surface and GraphicBufferMapper"
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index de6fd96..6aa2bb4 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -684,6 +684,15 @@
ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno));
}
+static bool check_boolean_property(const char* property_name, bool default_value = false) {
+ char tmp_property_value[PROPERTY_VALUE_MAX];
+ bool have_property = property_get(property_name, tmp_property_value, nullptr) > 0;
+ if (!have_property) {
+ return default_value;
+ }
+ return strcmp(tmp_property_value, "true") == 0;
+}
+
static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
const char* output_file_name, int swap_fd, const char *pkgname, const char *instruction_set,
bool vm_safe_mode, bool debuggable)
@@ -744,9 +753,8 @@
(strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
(strcmp(vold_decrypt, "1") == 0)));
- char use_jit_property[PROPERTY_VALUE_MAX];
- bool have_jit_property = property_get("debug.usejit", use_jit_property, NULL) > 0;
- bool use_jit = have_jit_property && strcmp(use_jit_property, "true") == 0;
+ bool use_jit = check_boolean_property("debug.usejit");
+ bool gen_cfi = check_boolean_property("debug.gencfi");
static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
@@ -839,6 +847,7 @@
+ (have_dex2oat_threads_flag ? 1 : 0)
+ (have_dex2oat_swap_fd ? 1 : 0)
+ (have_dex2oat_relocation_skip_flag ? 2 : 0)
+ + (gen_cfi ? 1 : 0)
+ (debuggable ? 1 : 0)
+ dex2oat_flags_count];
int i = 0;
@@ -877,6 +886,9 @@
if (have_dex2oat_swap_fd) {
argv[i++] = dex2oat_swap_fd;
}
+ if (gen_cfi) {
+ argv[i++] = "--include-cfi";
+ }
if (debuggable) {
argv[i++] = "--debuggable";
}
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index 40026bd..e3624b7 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -30,6 +30,9 @@
#include <utils/Trace.h>
#include <utils/Vector.h>
+#include <list>
+#include <set>
+
#define BQ_LOGV(x, ...) ALOGV("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
#define BQ_LOGD(x, ...) ALOGD("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
#define BQ_LOGI(x, ...) ALOGI("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
@@ -123,6 +126,10 @@
// waitWhileAllocatingLocked blocks until mIsAllocating is false.
void waitWhileAllocatingLocked() const;
+ // validateConsistencyLocked ensures that the free lists are in sync with
+ // the information stored in mSlots
+ void validateConsistencyLocked() const;
+
// mAllocator is the connection to SurfaceFlinger that is used to allocate
// new GraphicBuffer objects.
sp<IGraphicBufferAlloc> mAllocator;
@@ -177,6 +184,14 @@
// mQueue is a FIFO of queued buffers used in synchronous mode.
Fifo mQueue;
+ // mFreeSlots contains all of the slots which are FREE and do not currently
+ // have a buffer attached
+ std::set<int> mFreeSlots;
+
+ // mFreeBuffers contains all of the slots which are FREE and currently have
+ // a buffer attached
+ std::list<int> mFreeBuffers;
+
// mOverrideMaxBufferCount is the limit on the number of buffers that will
// be allocated at one time. This value is set by the producer by calling
// setBufferCount. The default is 0, which means that the producer doesn't
@@ -251,6 +266,14 @@
// mIsAllocatingCondition is a condition variable used by producers to wait until mIsAllocating
// becomes false.
mutable Condition mIsAllocatingCondition;
+
+ // mAllowAllocation determines whether dequeueBuffer is allowed to allocate
+ // new buffers
+ bool mAllowAllocation;
+
+ // mBufferAge tracks the age of the contents of the most recently dequeued
+ // buffer as the number of frames that have elapsed since it was last queued
+ uint64_t mBufferAge;
}; // class BufferQueueCore
} // namespace android
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index f794ea3..ed660fb 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -172,6 +172,9 @@
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
PixelFormat format, uint32_t usage);
+ // See IGraphicBufferProducer::allowAllocation
+ virtual status_t allowAllocation(bool allow);
+
private:
// This is required by the IBinder::DeathRecipient interface
virtual void binderDied(const wp<IBinder>& who);
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 2d99f24..5c50b2b 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -458,6 +458,18 @@
// allocated, this function has no effect.
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
PixelFormat format, uint32_t usage) = 0;
+
+ // Sets whether dequeueBuffer is allowed to allocate new buffers.
+ //
+ // Normally dequeueBuffer does not discriminate between free slots which
+ // already have an allocated buffer and those which do not, and will
+ // allocate a new buffer if the slot doesn't have a buffer or if the slot's
+ // buffer doesn't match the requested size, format, or usage. This method
+ // allows the producer to restrict the eligible slots to those which already
+ // have an allocated buffer of the correct size, format, and usage. If no
+ // eligible slot is available, dequeueBuffer will block or return an error
+ // as usual.
+ virtual status_t allowAllocation(bool allow) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index a9f78cf..fd6d48c 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -179,7 +179,7 @@
virtual int unlockAndPost();
virtual int connect(int api, const sp<IProducerListener>& listener);
- virtual int detachNextBuffer(ANativeWindowBuffer** outBuffer,
+ virtual int detachNextBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence);
virtual int attachBuffer(ANativeWindowBuffer*);
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index cea94fc..f91d192 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -97,6 +97,9 @@
status_t reallocate(uint32_t inWidth, uint32_t inHeight,
PixelFormat inFormat, uint32_t inUsage);
+ bool needsReallocation(uint32_t inWidth, uint32_t inHeight,
+ PixelFormat inFormat, uint32_t inUsage);
+
status_t lock(uint32_t inUsage, void** vaddr);
status_t lock(uint32_t inUsage, const Rect& rect, void** vaddr);
// For HAL_PIXEL_FORMAT_YCbCr_420_888
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 2c566f9..0921186 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1626,7 +1626,7 @@
binder_size_t* objects = NULL;
if (objectsSize) {
- objects = (binder_size_t*)malloc(objectsSize*sizeof(binder_size_t));
+ objects = (binder_size_t*)calloc(objectsSize, sizeof(binder_size_t));
if (!objects) {
free(data);
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index 239da20..5793d40 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -39,52 +39,66 @@
BufferItem::~BufferItem() {}
+template <typename T>
+static void addAligned(size_t& size, T /* value */) {
+ size = FlattenableUtils::align<sizeof(T)>(size);
+ size += sizeof(T);
+}
+
size_t BufferItem::getPodSize() const {
- size_t c = sizeof(mCrop) +
- sizeof(mTransform) +
- sizeof(mScalingMode) +
- sizeof(mTimestamp) +
- sizeof(mIsAutoTimestamp) +
- sizeof(mDataSpace) +
- sizeof(mFrameNumber) +
- sizeof(mSlot) +
- sizeof(mIsDroppable) +
- sizeof(mAcquireCalled) +
- sizeof(mTransformToDisplayInverse);
- return c;
+ // Must align<8> before writing these fields for this to be correct
+ size_t size = 0;
+ addAligned(size, mCrop);
+ addAligned(size, mTransform);
+ addAligned(size, mScalingMode);
+ addAligned(size, mTimestamp);
+ addAligned(size, mIsAutoTimestamp);
+ addAligned(size, mDataSpace);
+ addAligned(size, mFrameNumber);
+ addAligned(size, mSlot);
+ addAligned(size, mIsDroppable);
+ addAligned(size, mAcquireCalled);
+ addAligned(size, mTransformToDisplayInverse);
+ return size;
}
size_t BufferItem::getFlattenedSize() const {
- size_t c = 0;
+ size_t size = sizeof(uint32_t); // Flags
if (mGraphicBuffer != 0) {
- c += mGraphicBuffer->getFlattenedSize();
- FlattenableUtils::align<4>(c);
+ size += mGraphicBuffer->getFlattenedSize();
+ FlattenableUtils::align<4>(size);
}
if (mFence != 0) {
- c += mFence->getFlattenedSize();
- FlattenableUtils::align<4>(c);
+ size += mFence->getFlattenedSize();
+ FlattenableUtils::align<4>(size);
}
- c += mSurfaceDamage.getFlattenedSize();
- FlattenableUtils::align<4>(c);
- return sizeof(int32_t) + c + getPodSize();
+ size += mSurfaceDamage.getFlattenedSize();
+ size = FlattenableUtils::align<8>(size);
+ return size + getPodSize();
}
size_t BufferItem::getFdCount() const {
- size_t c = 0;
+ size_t count = 0;
if (mGraphicBuffer != 0) {
- c += mGraphicBuffer->getFdCount();
+ count += mGraphicBuffer->getFdCount();
}
if (mFence != 0) {
- c += mFence->getFdCount();
+ count += mFence->getFdCount();
}
- return c;
+ return count;
+}
+
+template <typename T>
+static void writeAligned(void*& buffer, size_t& size, T value) {
+ size -= FlattenableUtils::align<alignof(T)>(buffer);
+ FlattenableUtils::write(buffer, size, value);
}
status_t BufferItem::flatten(
void*& buffer, size_t& size, int*& fds, size_t& count) const {
// make sure we have enough space
- if (count < BufferItem::getFlattenedSize()) {
+ if (size < BufferItem::getFlattenedSize()) {
return NO_MEMORY;
}
@@ -107,35 +121,46 @@
size -= FlattenableUtils::align<4>(buffer);
flags |= 2;
}
+
status_t err = mSurfaceDamage.flatten(buffer, size);
if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
+ FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
- // check we have enough space (in case flattening the fence/graphicbuffer lied to us)
+ // Must align<8> so that getPodSize returns the correct value
+ size -= FlattenableUtils::align<8>(buffer);
+
+ // Check we still have enough space
if (size < getPodSize()) {
return NO_MEMORY;
}
- FlattenableUtils::write(buffer, size, mCrop);
- FlattenableUtils::write(buffer, size, mTransform);
- FlattenableUtils::write(buffer, size, mScalingMode);
- FlattenableUtils::write(buffer, size, mTimestamp);
- FlattenableUtils::write(buffer, size, mIsAutoTimestamp);
- FlattenableUtils::write(buffer, size, mDataSpace);
- FlattenableUtils::write(buffer, size, mFrameNumber);
- FlattenableUtils::write(buffer, size, mSlot);
- FlattenableUtils::write(buffer, size, mIsDroppable);
- FlattenableUtils::write(buffer, size, mAcquireCalled);
- FlattenableUtils::write(buffer, size, mTransformToDisplayInverse);
+ writeAligned(buffer, size, mCrop);
+ writeAligned(buffer, size, mTransform);
+ writeAligned(buffer, size, mScalingMode);
+ writeAligned(buffer, size, mTimestamp);
+ writeAligned(buffer, size, mIsAutoTimestamp);
+ writeAligned(buffer, size, mDataSpace);
+ writeAligned(buffer, size, mFrameNumber);
+ writeAligned(buffer, size, mSlot);
+ writeAligned(buffer, size, mIsDroppable);
+ writeAligned(buffer, size, mAcquireCalled);
+ writeAligned(buffer, size, mTransformToDisplayInverse);
return NO_ERROR;
}
+template <typename T>
+static void readAligned(const void*& buffer, size_t& size, T& value) {
+ size -= FlattenableUtils::align<alignof(T)>(buffer);
+ FlattenableUtils::read(buffer, size, value);
+}
+
status_t BufferItem::unflatten(
void const*& buffer, size_t& size, int const*& fds, size_t& count) {
- if (size < sizeof(uint32_t))
+ if (size < sizeof(uint32_t)) {
return NO_MEMORY;
+ }
uint32_t flags = 0;
FlattenableUtils::read(buffer, size, flags);
@@ -153,26 +178,30 @@
if (err) return err;
size -= FlattenableUtils::align<4>(buffer);
}
+
status_t err = mSurfaceDamage.unflatten(buffer, size);
if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
+ FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
- // check we have enough space
+ // Must align<8> so that getPodSize returns the correct value
+ size -= FlattenableUtils::align<8>(buffer);
+
+ // Check we still have enough space
if (size < getPodSize()) {
return NO_MEMORY;
}
- FlattenableUtils::read(buffer, size, mCrop);
- FlattenableUtils::read(buffer, size, mTransform);
- FlattenableUtils::read(buffer, size, mScalingMode);
- FlattenableUtils::read(buffer, size, mTimestamp);
- FlattenableUtils::read(buffer, size, mIsAutoTimestamp);
- FlattenableUtils::read(buffer, size, mDataSpace);
- FlattenableUtils::read(buffer, size, mFrameNumber);
- FlattenableUtils::read(buffer, size, mSlot);
- FlattenableUtils::read(buffer, size, mIsDroppable);
- FlattenableUtils::read(buffer, size, mAcquireCalled);
- FlattenableUtils::read(buffer, size, mTransformToDisplayInverse);
+ readAligned(buffer, size, mCrop);
+ readAligned(buffer, size, mTransform);
+ readAligned(buffer, size, mScalingMode);
+ readAligned(buffer, size, mTimestamp);
+ readAligned(buffer, size, mIsAutoTimestamp);
+ readAligned(buffer, size, mDataSpace);
+ readAligned(buffer, size, mFrameNumber);
+ readAligned(buffer, size, mSlot);
+ readAligned(buffer, size, mIsDroppable);
+ readAligned(buffer, size, mAcquireCalled);
+ readAligned(buffer, size, mTransformToDisplayInverse);
return NO_ERROR;
}
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 526c3b7..c7d5e00 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -120,6 +120,7 @@
if (mCore->stillTracking(front)) {
// Front buffer is still in mSlots, so mark the slot as free
mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
+ mCore->mFreeBuffers.push_back(front->mSlot);
}
mCore->mQueue.erase(front);
front = mCore->mQueue.begin();
@@ -173,6 +174,8 @@
ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
+ mCore->validateConsistencyLocked();
+
return NO_ERROR;
}
@@ -199,6 +202,7 @@
mCore->freeBufferLocked(slot);
mCore->mDequeueCondition.broadcast();
+ mCore->validateConsistencyLocked();
return NO_ERROR;
}
@@ -217,18 +221,11 @@
Mutex::Autolock lock(mCore->mMutex);
- // Make sure we don't have too many acquired buffers and find a free slot
- // to put the buffer into (the oldest if there are multiple).
+ // Make sure we don't have too many acquired buffers
int numAcquiredBuffers = 0;
- int found = BufferQueueCore::INVALID_BUFFER_SLOT;
for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) {
++numAcquiredBuffers;
- } else if (mSlots[s].mBufferState == BufferSlot::FREE) {
- if (found == BufferQueueCore::INVALID_BUFFER_SLOT ||
- mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
- found = s;
- }
}
}
@@ -238,6 +235,17 @@
mCore->mMaxAcquiredBufferCount);
return INVALID_OPERATION;
}
+
+ // Find a free slot to put the buffer into
+ int found = BufferQueueCore::INVALID_BUFFER_SLOT;
+ if (!mCore->mFreeSlots.empty()) {
+ auto slot = mCore->mFreeSlots.begin();
+ found = *slot;
+ mCore->mFreeSlots.erase(slot);
+ } else if (!mCore->mFreeBuffers.empty()) {
+ found = mCore->mFreeBuffers.front();
+ mCore->mFreeBuffers.remove(found);
+ }
if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
BQ_LOGE("attachBuffer(P): could not find free buffer slot");
return NO_MEMORY;
@@ -271,6 +279,8 @@
// for attached buffers.
mSlots[*outSlot].mAcquireCalled = false;
+ mCore->validateConsistencyLocked();
+
return NO_ERROR;
}
@@ -311,6 +321,7 @@
mSlots[slot].mEglFence = eglFence;
mSlots[slot].mFence = releaseFence;
mSlots[slot].mBufferState = BufferSlot::FREE;
+ mCore->mFreeBuffers.push_back(slot);
listener = mCore->mConnectedProducerListener;
BQ_LOGV("releaseBuffer: releasing slot %d", slot);
} else if (mSlots[slot].mNeedsCleanupOnRelease) {
@@ -325,6 +336,7 @@
}
mCore->mDequeueCondition.broadcast();
+ mCore->validateConsistencyLocked();
} // Autolock scope
// Call back without lock held
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index edebc45..887f2cb 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -53,6 +53,8 @@
mConnectedProducerListener(),
mSlots(),
mQueue(),
+ mFreeSlots(),
+ mFreeBuffers(),
mOverrideMaxBufferCount(0),
mDequeueCondition(),
mUseAsyncBuffer(true),
@@ -67,7 +69,9 @@
mFrameCounter(0),
mTransformHint(0),
mIsAllocating(false),
- mIsAllocatingCondition()
+ mIsAllocatingCondition(),
+ mAllowAllocation(true),
+ mBufferAge(0)
{
if (allocator == NULL) {
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
@@ -76,6 +80,9 @@
BQ_LOGE("createGraphicBufferAlloc failed");
}
}
+ for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
+ mFreeSlots.insert(slot);
+ }
}
BufferQueueCore::~BufferQueueCore() {}
@@ -190,12 +197,20 @@
void BufferQueueCore::freeBufferLocked(int slot) {
BQ_LOGV("freeBufferLocked: slot %d", slot);
+ bool hadBuffer = mSlots[slot].mGraphicBuffer != NULL;
mSlots[slot].mGraphicBuffer.clear();
if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) {
mSlots[slot].mNeedsCleanupOnRelease = true;
}
+ if (mSlots[slot].mBufferState != BufferSlot::FREE) {
+ mFreeSlots.insert(slot);
+ } else if (hadBuffer) {
+ // If the slot was FREE, but we had a buffer, we need to move this slot
+ // from the free buffers list to the the free slots list
+ mFreeBuffers.remove(slot);
+ mFreeSlots.insert(slot);
+ }
mSlots[slot].mBufferState = BufferSlot::FREE;
- mSlots[slot].mFrameNumber = UINT32_MAX;
mSlots[slot].mAcquireCalled = false;
// Destroy fence as BufferQueue now takes ownership
@@ -204,6 +219,7 @@
mSlots[slot].mEglFence = EGL_NO_SYNC_KHR;
}
mSlots[slot].mFence = Fence::NO_FENCE;
+ validateConsistencyLocked();
}
void BufferQueueCore::freeAllBuffersLocked() {
@@ -236,4 +252,48 @@
}
}
+void BufferQueueCore::validateConsistencyLocked() const {
+ static const useconds_t PAUSE_TIME = 0;
+ for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
+ bool isInFreeSlots = mFreeSlots.count(slot) != 0;
+ bool isInFreeBuffers =
+ std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) !=
+ mFreeBuffers.cend();
+ if (mSlots[slot].mBufferState == BufferSlot::FREE) {
+ if (mSlots[slot].mGraphicBuffer == NULL) {
+ if (!isInFreeSlots) {
+ BQ_LOGE("Slot %d is FREE but is not in mFreeSlots", slot);
+ usleep(PAUSE_TIME);
+ }
+ if (isInFreeBuffers) {
+ BQ_LOGE("Slot %d is in mFreeSlots "
+ "but is also in mFreeBuffers", slot);
+ usleep(PAUSE_TIME);
+ }
+ } else {
+ if (!isInFreeBuffers) {
+ BQ_LOGE("Slot %d is FREE but is not in mFreeBuffers", slot);
+ usleep(PAUSE_TIME);
+ }
+ if (isInFreeSlots) {
+ BQ_LOGE("Slot %d is in mFreeBuffers "
+ "but is also in mFreeSlots", slot);
+ usleep(PAUSE_TIME);
+ }
+ }
+ } else {
+ if (isInFreeSlots) {
+ BQ_LOGE("Slot %d is in mFreeSlots but is not FREE (%d)",
+ slot, mSlots[slot].mBufferState);
+ usleep(PAUSE_TIME);
+ }
+ if (isInFreeBuffers) {
+ BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE (%d)",
+ slot, mSlots[slot].mBufferState);
+ usleep(PAUSE_TIME);
+ }
+ }
+ }
+}
+
} // namespace android
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 6452cdd..7251d36 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -161,8 +161,6 @@
}
}
- // Look for a free buffer to give to the client
- *found = BufferQueueCore::INVALID_BUFFER_SLOT;
int dequeuedCount = 0;
int acquiredCount = 0;
for (int s = 0; s < maxBufferCount; ++s) {
@@ -173,15 +171,6 @@
case BufferSlot::ACQUIRED:
++acquiredCount;
break;
- case BufferSlot::FREE:
- // We return the oldest of the free buffers to avoid
- // stalling the producer if possible, since the consumer
- // may still have pending reads of in-flight buffers
- if (*found == BufferQueueCore::INVALID_BUFFER_SLOT ||
- mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) {
- *found = s;
- }
- break;
default:
break;
}
@@ -214,6 +203,8 @@
}
}
+ *found = BufferQueueCore::INVALID_BUFFER_SLOT;
+
// If we disconnect and reconnect quickly, we can be in a state where
// our slots are empty but we have many buffers in the queue. This can
// cause us to run out of memory if we outrun the consumer. Wait here if
@@ -223,6 +214,19 @@
if (tooManyBuffers) {
BQ_LOGV("%s: queue size is %zu, waiting", caller,
mCore->mQueue.size());
+ } else {
+ if (!mCore->mFreeBuffers.empty()) {
+ auto slot = mCore->mFreeBuffers.begin();
+ *found = *slot;
+ mCore->mFreeBuffers.erase(slot);
+ } else if (mCore->mAllowAllocation && !mCore->mFreeSlots.empty()) {
+ auto slot = mCore->mFreeSlots.begin();
+ // Only return free slots up to the max buffer count
+ if (*slot < maxBufferCount) {
+ *found = *slot;
+ mCore->mFreeSlots.erase(slot);
+ }
+ }
}
// If no buffer is found, or if the queue has too many buffers
@@ -281,17 +285,39 @@
// Enable the usage bits the consumer requested
usage |= mCore->mConsumerUsageBits;
- int found;
- status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
- &found, &returnFlags);
- if (status != NO_ERROR) {
- return status;
+ const bool useDefaultSize = !width && !height;
+ if (useDefaultSize) {
+ width = mCore->mDefaultWidth;
+ height = mCore->mDefaultHeight;
}
- // This should not happen
- if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
- BQ_LOGE("dequeueBuffer: no available buffer slots");
- return -EBUSY;
+ int found = BufferItem::INVALID_BUFFER_SLOT;
+ while (found == BufferItem::INVALID_BUFFER_SLOT) {
+ status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
+ &found, &returnFlags);
+ if (status != NO_ERROR) {
+ return status;
+ }
+
+ // This should not happen
+ if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
+ BQ_LOGE("dequeueBuffer: no available buffer slots");
+ return -EBUSY;
+ }
+
+ const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
+
+ // If we are not allowed to allocate new buffers,
+ // waitForFreeSlotThenRelock must have returned a slot containing a
+ // buffer. If this buffer would require reallocation to meet the
+ // requested attributes, we free it and attempt to get another one.
+ if (!mCore->mAllowAllocation) {
+ if (buffer->needsReallocation(width, height, format, usage)) {
+ mCore->freeBufferLocked(found);
+ found = BufferItem::INVALID_BUFFER_SLOT;
+ continue;
+ }
+ }
}
*outSlot = found;
@@ -299,20 +325,11 @@
attachedByConsumer = mSlots[found].mAttachedByConsumer;
- const bool useDefaultSize = !width && !height;
- if (useDefaultSize) {
- width = mCore->mDefaultWidth;
- height = mCore->mDefaultHeight;
- }
-
mSlots[found].mBufferState = BufferSlot::DEQUEUED;
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
if ((buffer == NULL) ||
- (static_cast<uint32_t>(buffer->width) != width) ||
- (static_cast<uint32_t>(buffer->height) != height) ||
- (buffer->format != format) ||
- ((static_cast<uint32_t>(buffer->usage) & usage) != usage))
+ buffer->needsReallocation(width, height, format, usage))
{
mSlots[found].mAcquireCalled = false;
mSlots[found].mGraphicBuffer = NULL;
@@ -320,10 +337,19 @@
mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
mSlots[found].mFence = Fence::NO_FENCE;
+ mCore->mBufferAge = 0;
returnFlags |= BUFFER_NEEDS_REALLOCATION;
+ } else {
+ // We add 1 because that will be the frame number when this buffer
+ // is queued
+ mCore->mBufferAge =
+ mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
}
+ BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
+ mCore->mBufferAge);
+
if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
"slot=%d w=%d h=%d format=%u",
@@ -335,6 +361,8 @@
*outFence = mSlots[found].mFence;
mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
mSlots[found].mFence = Fence::NO_FENCE;
+
+ mCore->validateConsistencyLocked();
} // Autolock scope
if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
@@ -355,7 +383,6 @@
return NO_INIT;
}
- mSlots[*outSlot].mFrameNumber = UINT32_MAX;
mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
} // Autolock scope
}
@@ -414,6 +441,7 @@
mCore->freeBufferLocked(slot);
mCore->mDequeueCondition.broadcast();
+ mCore->validateConsistencyLocked();
return NO_ERROR;
}
@@ -438,27 +466,19 @@
return NO_INIT;
}
- // Find the oldest valid slot
- int found = BufferQueueCore::INVALID_BUFFER_SLOT;
- for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
- if (mSlots[s].mBufferState == BufferSlot::FREE &&
- mSlots[s].mGraphicBuffer != NULL) {
- if (found == BufferQueueCore::INVALID_BUFFER_SLOT ||
- mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
- found = s;
- }
- }
- }
-
- if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
+ if (mCore->mFreeBuffers.empty()) {
return NO_MEMORY;
}
+ int found = mCore->mFreeBuffers.front();
+ mCore->mFreeBuffers.remove(found);
+
BQ_LOGV("detachNextBuffer detached slot %d", found);
*outBuffer = mSlots[found].mGraphicBuffer;
*outFence = mSlots[found].mFence;
mCore->freeBufferLocked(found);
+ mCore->validateConsistencyLocked();
return NO_ERROR;
}
@@ -506,6 +526,8 @@
mSlots[*outSlot].mFence = Fence::NO_FENCE;
mSlots[*outSlot].mRequestBufferCalled = true;
+ mCore->validateConsistencyLocked();
+
return returnFlags;
}
@@ -640,9 +662,7 @@
// mark it as freed
if (mCore->stillTracking(front)) {
mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
- // Reset the frame number of the freed buffer so that it is
- // the first in line to be dequeued again
- mSlots[front->mSlot].mFrameNumber = 0;
+ mCore->mFreeBuffers.push_front(front->mSlot);
}
// Overwrite the droppable buffer with the incoming one
*front = item;
@@ -664,6 +684,8 @@
// Take a ticket for the callback functions
callbackTicket = mNextCallbackTicket++;
+
+ mCore->validateConsistencyLocked();
} // Autolock scope
// Wait without lock held
@@ -724,10 +746,11 @@
return;
}
+ mCore->mFreeBuffers.push_front(slot);
mSlots[slot].mBufferState = BufferSlot::FREE;
- mSlots[slot].mFrameNumber = 0;
mSlots[slot].mFence = fence;
mCore->mDequeueCondition.broadcast();
+ mCore->validateConsistencyLocked();
}
int BufferQueueProducer::query(int what, int *outValue) {
@@ -770,6 +793,13 @@
case NATIVE_WINDOW_DEFAULT_DATASPACE:
value = static_cast<int32_t>(mCore->mDefaultBufferDataSpace);
break;
+ case NATIVE_WINDOW_BUFFER_AGE:
+ if (mCore->mBufferAge > INT32_MAX) {
+ value = 0;
+ } else {
+ value = static_cast<int32_t>(mCore->mBufferAge);
+ }
+ break;
default:
return BAD_VALUE;
}
@@ -932,6 +962,12 @@
Mutex::Autolock lock(mCore->mMutex);
mCore->waitWhileAllocatingLocked();
+ if (!mCore->mAllowAllocation) {
+ BQ_LOGE("allocateBuffers: allocation is not allowed for this "
+ "BufferQueue");
+ return;
+ }
+
int currentBufferCount = 0;
for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
if (mSlots[slot].mGraphicBuffer != NULL) {
@@ -1009,17 +1045,32 @@
}
mCore->freeBufferLocked(slot); // Clean up the slot first
mSlots[slot].mGraphicBuffer = buffers[i];
- mSlots[slot].mFrameNumber = 0;
mSlots[slot].mFence = Fence::NO_FENCE;
+
+ // freeBufferLocked puts this slot on the free slots list. Since
+ // we then attached a buffer, move the slot to free buffer list.
+ mCore->mFreeSlots.erase(slot);
+ mCore->mFreeBuffers.push_front(slot);
+
BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
}
mCore->mIsAllocating = false;
mCore->mIsAllocatingCondition.broadcast();
+ mCore->validateConsistencyLocked();
} // Autolock scope
}
}
+status_t BufferQueueProducer::allowAllocation(bool allow) {
+ ATRACE_CALL();
+ BQ_LOGV("allowAllocation: %s", allow ? "true" : "false");
+
+ Mutex::Autolock lock(mCore->mMutex);
+ mCore->mAllowAllocation = allow;
+ return NO_ERROR;
+}
+
void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
// 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
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index 3f23c2f..6658ab1 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -414,6 +414,15 @@
reply->writeInt32(result);
return NO_ERROR;
}
+ case GET_SIDEBAND_STREAM: {
+ CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
+ sp<NativeHandle> stream = getSidebandStream();
+ reply->writeInt32(static_cast<int32_t>(stream != NULL));
+ if (stream != NULL) {
+ reply->writeNativeHandle(stream->handle());
+ }
+ return NO_ERROR;
+ }
case DUMP: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
String8 result = data.readString8();
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index b7982a9..7093ffa 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -46,6 +46,7 @@
DISCONNECT,
SET_SIDEBAND_STREAM,
ALLOCATE_BUFFERS,
+ ALLOW_ALLOCATION,
};
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -271,6 +272,18 @@
ALOGE("allocateBuffers failed to transact: %d", result);
}
}
+
+ virtual status_t allowAllocation(bool allow) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+ data.writeInt32(static_cast<int32_t>(allow));
+ status_t result = remote()->transact(ALLOW_ALLOCATION, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt32();
+ return result;
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -418,7 +431,7 @@
reply->writeInt32(result);
return NO_ERROR;
}
- case ALLOCATE_BUFFERS:
+ case ALLOCATE_BUFFERS: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
bool async = static_cast<bool>(data.readInt32());
uint32_t width = data.readUint32();
@@ -427,6 +440,14 @@
uint32_t usage = data.readUint32();
allocateBuffers(async, width, height, format, usage);
return NO_ERROR;
+ }
+ case ALLOW_ALLOCATION: {
+ CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+ bool allow = static_cast<bool>(data.readInt32());
+ status_t result = allowAllocation(allow);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index b8acad2..5d81f10 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -651,7 +651,7 @@
return err;
}
-int Surface::detachNextBuffer(ANativeWindowBuffer** outBuffer,
+int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence) {
ATRACE_CALL();
ALOGV("Surface::detachNextBuffer");
@@ -670,7 +670,7 @@
return result;
}
- *outBuffer = buffer.get();
+ *outBuffer = buffer;
if (fence != NULL && fence->isValid()) {
*outFence = fence;
} else {
diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk
index 128a32a..6ad9986 100644
--- a/libs/gui/tests/Android.mk
+++ b/libs/gui/tests/Android.mk
@@ -3,6 +3,8 @@
include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_CLANG := true
+
LOCAL_MODULE := libgui_test
LOCAL_MODULE_TAGS := tests
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index c38c797..1584fef 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -73,6 +73,8 @@
virtual void onSidebandStreamChanged() {}
};
+static const uint32_t TEST_DATA = 0x12345678u;
+
// XXX: Tests that fork a process to hold the BufferQueue must run before tests
// that use a local BufferQueue, or else Binder will get unhappy
TEST_F(BufferQueueTest, BufferQueueInAnotherProcess) {
@@ -122,7 +124,7 @@
uint32_t* dataIn;
ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
reinterpret_cast<void**>(&dataIn)));
- *dataIn = 0x12345678;
+ *dataIn = TEST_DATA;
ASSERT_EQ(OK, buffer->unlock());
IGraphicBufferProducer::QueueBufferInput input(0, false,
@@ -136,7 +138,7 @@
uint32_t* dataOut;
ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
reinterpret_cast<void**>(&dataOut)));
- ASSERT_EQ(*dataOut, 0x12345678);
+ ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
}
@@ -239,7 +241,7 @@
uint32_t* dataIn;
ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
reinterpret_cast<void**>(&dataIn)));
- *dataIn = 0x12345678;
+ *dataIn = TEST_DATA;
ASSERT_EQ(OK, buffer->unlock());
int newSlot;
@@ -258,7 +260,7 @@
uint32_t* dataOut;
ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
reinterpret_cast<void**>(&dataOut)));
- ASSERT_EQ(*dataOut, 0x12345678);
+ ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
}
@@ -297,7 +299,7 @@
ASSERT_EQ(OK, item.mGraphicBuffer->lock(
GraphicBuffer::USAGE_SW_WRITE_OFTEN,
reinterpret_cast<void**>(&dataIn)));
- *dataIn = 0x12345678;
+ *dataIn = TEST_DATA;
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
int newSlot;
@@ -317,7 +319,7 @@
uint32_t* dataOut;
ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
reinterpret_cast<void**>(&dataOut)));
- ASSERT_EQ(*dataOut, 0x12345678);
+ ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, buffer->unlock());
}
@@ -340,7 +342,7 @@
uint32_t* dataIn;
ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
reinterpret_cast<void**>(&dataIn)));
- *dataIn = 0x12345678;
+ *dataIn = TEST_DATA;
ASSERT_EQ(OK, buffer->unlock());
IGraphicBufferProducer::QueueBufferInput input(0, false,
@@ -360,8 +362,44 @@
uint32_t* dataOut;
ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
reinterpret_cast<void**>(&dataOut)));
- ASSERT_EQ(*dataOut, 0x12345678);
+ ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
}
+TEST_F(BufferQueueTest, TestDisallowingAllocation) {
+ 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));
+
+ static const uint32_t WIDTH = 320;
+ static const uint32_t HEIGHT = 240;
+
+ ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT));
+
+ int slot;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buffer;
+ // This should return an error since it would require an allocation
+ ASSERT_EQ(OK, mProducer->allowAllocation(false));
+ ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false, 0, 0,
+ 0, GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+ // This should succeed, now that we've lifted the prohibition
+ ASSERT_EQ(OK, mProducer->allowAllocation(true));
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+ GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+ // Release the previous buffer back to the BufferQueue
+ mProducer->cancelBuffer(slot, fence);
+
+ // This should fail since we're requesting a different size
+ ASSERT_EQ(OK, mProducer->allowAllocation(false));
+ ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false,
+ WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN));
+}
+
} // namespace android
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index 0beca92..2dc9ccc 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -94,7 +94,7 @@
mPendingFrames--;
}
- virtual void onFrameAvailable() {
+ virtual void onFrameAvailable(const BufferItem&) {
Mutex::Autolock lock(mMutex);
mPendingFrames++;
mCondition.signal();
@@ -125,7 +125,7 @@
mPendingFrames--;
}
- virtual void onFrameAvailable() {
+ virtual void onFrameAvailable(const BufferItem&) {
Mutex::Autolock lock(mMutex);
mPendingFrames++;
mFrameCondition.signal();
@@ -457,9 +457,12 @@
const CpuConsumerTestParams& params,
int maxBufferSlack) {
status_t err;
- err = native_window_set_buffers_geometry(anw.get(),
- params.width, params.height, params.format);
- ASSERT_NO_ERROR(err, "set_buffers_geometry error: ");
+ err = native_window_set_buffers_dimensions(anw.get(),
+ params.width, params.height);
+ ASSERT_NO_ERROR(err, "set_buffers_dimensions error: ");
+
+ err = native_window_set_buffers_format(anw.get(), params.format);
+ ASSERT_NO_ERROR(err, "set_buffers_format error: ");
err = native_window_set_usage(anw.get(),
GRALLOC_USAGE_SW_WRITE_OFTEN);
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index c904a6b..ff58420 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -38,31 +38,31 @@
#define TEST_CONTROLLED_BY_APP false
#define TEST_PRODUCER_USAGE_BITS (0)
-// TODO: Make these public constants in a header
-enum {
- // Default dimensions before setDefaultBufferSize is called
- DEFAULT_WIDTH = 1,
- DEFAULT_HEIGHT = 1,
-
- // Default format before setDefaultBufferFormat is called
- DEFAULT_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888,
-
- // Default transform hint before setTransformHint is called
- DEFAULT_TRANSFORM_HINT = 0,
-};
-
namespace android {
namespace {
-// Parameters for a generic "valid" input for queueBuffer.
-const int64_t QUEUE_BUFFER_INPUT_TIMESTAMP = 1384888611;
-const bool QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP = false;
-const android_dataspace QUEUE_BUFFER_INPUT_DATASPACE = HAL_DATASPACE_UNKNOWN;
-const Rect QUEUE_BUFFER_INPUT_RECT = Rect(DEFAULT_WIDTH, DEFAULT_HEIGHT);
-const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0;
-const int QUEUE_BUFFER_INPUT_TRANSFORM = 0;
-const bool QUEUE_BUFFER_INPUT_ASYNC = false;
-const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
+ // Default dimensions before setDefaultBufferSize is called
+ const uint32_t DEFAULT_WIDTH = 1;
+ const uint32_t DEFAULT_HEIGHT = 1;
+
+ // Default format before setDefaultBufferFormat is called
+ const PixelFormat DEFAULT_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888;
+
+ // Default transform hint before setTransformHint is called
+ const uint32_t DEFAULT_TRANSFORM_HINT = 0;
+
+ // TODO: Make these constants in header
+ const int DEFAULT_CONSUMER_USAGE_BITS = 0;
+
+ // Parameters for a generic "valid" input for queueBuffer.
+ const int64_t QUEUE_BUFFER_INPUT_TIMESTAMP = 1384888611;
+ const bool QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP = false;
+ const android_dataspace QUEUE_BUFFER_INPUT_DATASPACE = HAL_DATASPACE_UNKNOWN;
+ const Rect QUEUE_BUFFER_INPUT_RECT = Rect(DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0;
+ const int QUEUE_BUFFER_INPUT_TRANSFORM = 0;
+ const bool QUEUE_BUFFER_INPUT_ASYNC = false;
+ const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
}; // namespace anonymous
struct DummyConsumer : public BnConsumerListener {
@@ -273,15 +273,12 @@
TEST_F(IGraphicBufferProducerTest, Query_Succeeds) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
- // TODO: Make these constants in header
- const int DEFAULT_CONSUMER_USAGE_BITS = 0;
-
- int value = -1;
+ int32_t value = -1;
EXPECT_OK(mProducer->query(NATIVE_WINDOW_WIDTH, &value));
- EXPECT_EQ(DEFAULT_WIDTH, value);
+ EXPECT_EQ(DEFAULT_WIDTH, static_cast<uint32_t>(value));
EXPECT_OK(mProducer->query(NATIVE_WINDOW_HEIGHT, &value));
- EXPECT_EQ(DEFAULT_HEIGHT, value);
+ EXPECT_EQ(DEFAULT_HEIGHT, static_cast<uint32_t>(value));
EXPECT_OK(mProducer->query(NATIVE_WINDOW_FORMAT, &value));
EXPECT_EQ(DEFAULT_FORMAT, value);
@@ -302,7 +299,7 @@
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
// One past the end of the last 'query' enum value. Update this if we add more enums.
- const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_CONSUMER_USAGE_BITS + 1;
+ const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_DEFAULT_DATASPACE + 1;
int value;
// What was out of range
@@ -369,7 +366,7 @@
EXPECT_EQ(DEFAULT_WIDTH, width);
EXPECT_EQ(DEFAULT_HEIGHT, height);
EXPECT_EQ(DEFAULT_TRANSFORM_HINT, transformHint);
- EXPECT_EQ(1, numPendingBuffers); // since queueBuffer was called exactly once
+ EXPECT_EQ(1u, numPendingBuffers); // since queueBuffer was called exactly once
}
// Buffer was not in the dequeued state
diff --git a/libs/gui/tests/SRGB_test.cpp b/libs/gui/tests/SRGB_test.cpp
index e5907e7..3b11b97 100644
--- a/libs/gui/tests/SRGB_test.cpp
+++ b/libs/gui/tests/SRGB_test.cpp
@@ -17,6 +17,10 @@
#define LOG_TAG "SRGB_test"
//#define LOG_NDEBUG 0
+// Ignore for this file because it flags every instance of
+// ASSERT_EQ(GL_NO_ERROR, glGetError());
+#pragma clang diagnostic ignored "-Wsign-compare"
+
#include "GLTest.h"
#include <math.h>
@@ -329,9 +333,9 @@
ANativeWindow_Buffer outBuffer;
ARect outBufferBounds;
mOutputSurface->lock(&outBuffer, &outBufferBounds);
- ASSERT_EQ(mLockedBuffer.width, outBuffer.width);
- ASSERT_EQ(mLockedBuffer.height, outBuffer.height);
- ASSERT_EQ(mLockedBuffer.stride, outBuffer.stride);
+ ASSERT_EQ(mLockedBuffer.width, static_cast<uint32_t>(outBuffer.width));
+ ASSERT_EQ(mLockedBuffer.height, static_cast<uint32_t>(outBuffer.height));
+ ASSERT_EQ(mLockedBuffer.stride, static_cast<uint32_t>(outBuffer.stride));
if (mLockedBuffer.format == outBuffer.format) {
memcpy(outBuffer.bits, mLockedBuffer.data, bufferSize);
@@ -401,7 +405,8 @@
// the debug surface if necessary
}
-TEST_F(SRGBTest, RenderToSRGBSurface) {
+// XXX: Disabled since we don't currently expect this to work
+TEST_F(SRGBTest, DISABLED_RenderToSRGBSurface) {
ASSERT_NO_FATAL_FAILURE(initShaders());
// By default, the first buffer we write into will be RGB
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index 767c7c6..00cc39d 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -76,6 +76,8 @@
int mAllocCount;
};
+static const uint32_t TEST_DATA = 0x12345678u;
+
TEST_F(StreamSplitterTest, OneInputOneOutput) {
sp<CountedAllocator> allocator(new CountedAllocator);
@@ -108,7 +110,7 @@
uint32_t* dataIn;
ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
reinterpret_cast<void**>(&dataIn)));
- *dataIn = 0x12345678;
+ *dataIn = TEST_DATA;
ASSERT_EQ(OK, buffer->unlock());
IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
@@ -123,7 +125,7 @@
uint32_t* dataOut;
ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
reinterpret_cast<void**>(&dataOut)));
- ASSERT_EQ(*dataOut, 0x12345678);
+ ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
ASSERT_EQ(OK, outputConsumer->releaseBuffer(item.mBuf, item.mFrameNumber,
@@ -175,7 +177,7 @@
uint32_t* dataIn;
ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
reinterpret_cast<void**>(&dataIn)));
- *dataIn = 0x12345678;
+ *dataIn = TEST_DATA;
ASSERT_EQ(OK, buffer->unlock());
IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
@@ -191,7 +193,7 @@
uint32_t* dataOut;
ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
reinterpret_cast<void**>(&dataOut)));
- ASSERT_EQ(*dataOut, 0x12345678);
+ ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
ASSERT_EQ(OK, outputConsumers[output]->releaseBuffer(item.mBuf,
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 8cdf3bc..d750cd0 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -207,12 +207,8 @@
}
TEST_F(SurfaceTextureClientTest, BufferGeometryInvalidSizesFail) {
- EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), -1, 0, 0));
- EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, -1, 0));
- EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, -1));
- EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), -1, -1, 0));
- EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, 8, 0));
- EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 8, 0, 0));
+ EXPECT_GT(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 8));
+ EXPECT_GT(OK, native_window_set_buffers_dimensions(mANW.get(), 8, 0));
}
TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) {
@@ -226,7 +222,8 @@
TEST_F(SurfaceTextureClientTest, BufferGeometryCanBeSet) {
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, PIXEL_FORMAT_RGB_565));
+ EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
+ EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
EXPECT_EQ(16, buf->width);
EXPECT_EQ(8, buf->height);
@@ -236,7 +233,8 @@
TEST_F(SurfaceTextureClientTest, BufferGeometryDefaultSizeSetFormat) {
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, PIXEL_FORMAT_RGB_565));
+ EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
+ EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
EXPECT_EQ(1, buf->width);
EXPECT_EQ(1, buf->height);
@@ -246,7 +244,8 @@
TEST_F(SurfaceTextureClientTest, BufferGeometrySetSizeDefaultFormat) {
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0));
+ EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
+ EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
EXPECT_EQ(16, buf->width);
EXPECT_EQ(8, buf->height);
@@ -256,13 +255,15 @@
TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeUnset) {
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0));
+ EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
+ EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
EXPECT_EQ(16, buf->width);
EXPECT_EQ(8, buf->height);
EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
- EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, 0));
+ EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
+ EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
EXPECT_EQ(1, buf->width);
EXPECT_EQ(1, buf->height);
@@ -272,7 +273,8 @@
TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeChangedWithoutFormat) {
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, PIXEL_FORMAT_RGB_565));
+ EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
+ EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
EXPECT_EQ(1, buf->width);
EXPECT_EQ(1, buf->height);
@@ -330,7 +332,8 @@
EXPECT_EQ(8, buf[1]->height);
ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1));
ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1));
- EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 12, 24, 0));
+ EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 12, 24));
+ EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
EXPECT_NE(buf[0], buf[1]);
@@ -468,7 +471,8 @@
// Once we've queued a buffer, however we should not be able to dequeue more
// than (buffer-count - MIN_UNDEQUEUED_BUFFERS), which is 2 in this case.
- EXPECT_EQ(-EBUSY, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
+ EXPECT_EQ(INVALID_OPERATION,
+ native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1));
ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2], -1));
@@ -620,7 +624,8 @@
crop.bottom = 5;
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
- ASSERT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 8, 8, 0));
+ ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 8, 8));
+ ASSERT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &crop));
ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
@@ -668,7 +673,8 @@
const int numFmts = (sizeof(fmts) / sizeof(fmts[0]));
for (int i = 0; i < numFmts; i++) {
int fmt = -1;
- ASSERT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, fmts[i]));
+ ASSERT_EQ(OK, native_window_set_buffers_dimensions(anw.get(), 0, 0));
+ ASSERT_EQ(OK, native_window_set_buffers_format(anw.get(), fmts[i]));
ASSERT_EQ(OK, anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt));
EXPECT_EQ(fmts[i], fmt);
}
diff --git a/libs/gui/tests/SurfaceTextureFBO_test.cpp b/libs/gui/tests/SurfaceTextureFBO_test.cpp
index b165ae6..c243fc0 100644
--- a/libs/gui/tests/SurfaceTextureFBO_test.cpp
+++ b/libs/gui/tests/SurfaceTextureFBO_test.cpp
@@ -27,8 +27,10 @@
const int texWidth = 64;
const int texHeight = 64;
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ texWidth, texHeight));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_RGBA_8888));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp
index fa1e1b7..fad133f 100644
--- a/libs/gui/tests/SurfaceTextureGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGL_test.cpp
@@ -28,8 +28,10 @@
const int texWidth = 64;
const int texHeight = 66;
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ texWidth, texHeight));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -74,8 +76,10 @@
const int texWidth = 64;
const int texHeight = 64;
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ texWidth, texHeight));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -120,8 +124,10 @@
const int texWidth = 64;
const int texHeight = 66;
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ texWidth, texHeight));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -185,8 +191,10 @@
enum { numFrames = 1024 };
ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ texWidth, texHeight));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -326,8 +334,10 @@
const int texWidth = 64;
const int texHeight = 66;
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ texWidth, texHeight));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_RGBA_8888));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -368,8 +378,10 @@
const int texWidth = 64;
const int texHeight = 64;
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ texWidth, texHeight));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_RGBA_8888));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 638ac62..6a42a22 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -152,6 +152,16 @@
return initSize(inWidth, inHeight, inFormat, inUsage);
}
+bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
+ PixelFormat inFormat, uint32_t inUsage)
+{
+ if (static_cast<int>(inWidth) != width) return true;
+ if (static_cast<int>(inHeight) != height) return true;
+ if (inFormat != format) return true;
+ if ((static_cast<uint32_t>(usage) & inUsage) != inUsage) return true;
+ return false;
+}
+
status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight,
PixelFormat inFormat, uint32_t inUsage)
{
@@ -303,7 +313,7 @@
static_cast<size_t>(handle->numInts) * sizeof(int));
}
- buffer = reinterpret_cast<void*>(static_cast<int*>(buffer) + sizeNeeded);
+ buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded);
size -= sizeNeeded;
if (handle) {
fds += handle->numFds;
@@ -385,7 +395,7 @@
}
}
- buffer = reinterpret_cast<void const*>(static_cast<int const*>(buffer) + sizeNeeded);
+ buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded);
size -= sizeNeeded;
fds += numFds;
count -= numFds;
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 8634e42..318c85f 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -4315,7 +4315,7 @@
bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
orientation -= M_PI_2;
- if (orientation < mOrientedRanges.orientation.min) {
+ if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
}
break;
@@ -4327,7 +4327,7 @@
bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
orientation -= M_PI;
- if (orientation < mOrientedRanges.orientation.min) {
+ if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
}
break;
@@ -4339,7 +4339,7 @@
bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
orientation += M_PI_2;
- if (orientation > mOrientedRanges.orientation.max) {
+ if (mOrientedRanges.haveOrientation && orientation > mOrientedRanges.orientation.max) {
orientation -= (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
}
break;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 0e94f0d..11cbdc6 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -526,6 +526,10 @@
// TODO: Should we actually allocate buffers for a virtual display?
}
+status_t VirtualDisplaySurface::allowAllocation(bool /* allow */) {
+ return INVALID_OPERATION;
+}
+
void VirtualDisplaySurface::updateQueueBufferOutput(
const QueueBufferOutput& qbo) {
uint32_t w, h, transformHint, numPendingBuffers;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 0a3f4a1..97af980 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -115,6 +115,7 @@
virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
PixelFormat format, uint32_t usage);
+ virtual status_t allowAllocation(bool allow);
//
// Utility methods
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index e4e7d42..9fb555b 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -110,6 +110,10 @@
mProducer->allocateBuffers(async, width, height, format, usage);
}
+status_t MonitoredProducer::allowAllocation(bool allow) {
+ return mProducer->allowAllocation(allow);
+}
+
IBinder* MonitoredProducer::onAsBinder() {
return IInterface::asBinder(mProducer).get();
}
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index aec3e85..b2f8293 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -53,6 +53,7 @@
virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
PixelFormat format, uint32_t usage);
+ virtual status_t allowAllocation(bool allow);
virtual IBinder* onAsBinder();
private: