Merge "SF: Improve surface flinger unit tests"
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 0aa8fe9..713634c 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -437,8 +437,6 @@
run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
- run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "connectivity", "--diag", NULL);
-
run_command("IPTABLES", 10, SU_PATH, "root", "iptables", "-L", "-nvx", NULL);
run_command("IP6TABLES", 10, SU_PATH, "root", "ip6tables", "-L", "-nvx", NULL);
run_command("IPTABLE NAT", 10, SU_PATH, "root", "iptables", "-t", "nat", "-L", "-nvx", NULL);
@@ -450,25 +448,29 @@
SU_PATH, "root", "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
#ifdef FWDUMP_bcmdhd
- run_command("DUMP WIFI INTERNAL COUNTERS", 20,
+ run_command("ND OFFLOAD TABLE", 5,
+ SU_PATH, "root", "wlutil", "nd_hostip", NULL);
+
+ run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
SU_PATH, "root", "wlutil", "counters", NULL);
+
+ run_command("ND OFFLOAD STATUS (1)", 5,
+ SU_PATH, "root", "wlutil", "nd_status", NULL);
+
#endif
dump_file("INTERRUPTS (1)", "/proc/interrupts");
- property_get("dhcp.wlan0.gateway", network, "");
- if (network[0])
- run_command("PING GATEWAY", 10, "ping", "-c", "3", "-i", ".5", network, NULL);
- property_get("dhcp.wlan0.dns1", network, "");
- if (network[0])
- run_command("PING DNS1", 10, "ping", "-c", "3", "-i", ".5", network, NULL);
- property_get("dhcp.wlan0.dns2", network, "");
- if (network[0])
- run_command("PING DNS2", 10, "ping", "-c", "3", "-i", ".5", network, NULL);
+ run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "connectivity", "--diag", NULL);
+
#ifdef FWDUMP_bcmdhd
run_command("DUMP WIFI STATUS", 20,
SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
- run_command("DUMP WIFI INTERNAL COUNTERS", 20,
+
+ run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
SU_PATH, "root", "wlutil", "counters", NULL);
+
+ run_command("ND OFFLOAD STATUS (2)", 5,
+ SU_PATH, "root", "wlutil", "nd_status", NULL);
#endif
dump_file("INTERRUPTS (2)", "/proc/interrupts");
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index 3155766..ddf3aa8 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -207,7 +207,7 @@
sp<GLConsumer> glc = new GLConsumer(consumer, name,
GL_TEXTURE_EXTERNAL_OES, false, true);
glc->setDefaultBufferSize(w, h);
- glc->setDefaultMaxBufferCount(3);
+ producer->setMaxDequeuedBufferCount(2);
glc->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
sp<ANativeWindow> anw = new Surface(producer);
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 7090b36..769cd34 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -746,7 +746,7 @@
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)
+ bool vm_safe_mode, bool debuggable, bool post_bootcomplete)
{
static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
@@ -770,8 +770,24 @@
dex2oat_compiler_filter_flag, NULL) > 0;
char dex2oat_threads_buf[PROPERTY_VALUE_MAX];
- bool have_dex2oat_threads_flag = property_get("dalvik.vm.dex2oat-threads", dex2oat_threads_buf,
- NULL) > 0;
+ bool have_dex2oat_threads_flag = false;
+ if (!post_bootcomplete) {
+ have_dex2oat_threads_flag = property_get("dalvik.vm.boot-dex2oat-threads",
+ dex2oat_threads_buf,
+ NULL) > 0;
+ // If there's no boot property, fall back to the image property.
+ if (!have_dex2oat_threads_flag) {
+ have_dex2oat_threads_flag = property_get("dalvik.vm.image-dex2oat-threads",
+ dex2oat_threads_buf,
+ NULL) > 0;
+ }
+ // If there's neither, fall back to the default property.
+ }
+ if (!have_dex2oat_threads_flag) {
+ have_dex2oat_threads_flag = property_get("dalvik.vm.dex2oat-threads",
+ dex2oat_threads_buf,
+ NULL) > 0;
+ }
char dex2oat_threads_arg[PROPERTY_VALUE_MAX + 2];
if (have_dex2oat_threads_flag) {
sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf);
@@ -1065,6 +1081,27 @@
return true;
}
+static bool IsPostBootComplete() {
+ char dev_bootcomplete_prop_buf[PROPERTY_VALUE_MAX];
+ if (property_get("dev.bootcomplete", dev_bootcomplete_prop_buf, "0") > 0) {
+ return (strcmp(dev_bootcomplete_prop_buf, "1") == 0);
+ }
+ return false;
+}
+
+static void SetDex2OatAndPatchOatScheduling(bool set_to_bg) {
+ if (set_to_bg) {
+ if (set_sched_policy(0, SP_BACKGROUND) < 0) {
+ ALOGE("set_sched_policy failed: %s\n", strerror(errno));
+ exit(70);
+ }
+ if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
+ ALOGE("setpriority failed: %s\n", strerror(errno));
+ exit(71);
+ }
+ }
+}
+
int dexopt(const char *apk_path, uid_t uid, bool is_public,
const char *pkgname, const char *instruction_set, int dexopt_needed,
bool vm_safe_mode, bool debuggable, const char* oat_dir)
@@ -1076,6 +1113,7 @@
const char *input_file;
char in_odex_path[PKG_PATH_MAX];
int res, input_fd=-1, out_fd=-1, swap_fd=-1;
+ bool post_bootcomplete = IsPostBootComplete();
// Early best-effort check whether we can fit the the path into our buffers.
// Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
@@ -1198,14 +1236,7 @@
ALOGE("capset failed: %s\n", strerror(errno));
exit(66);
}
- if (set_sched_policy(0, SP_BACKGROUND) < 0) {
- ALOGE("set_sched_policy failed: %s\n", strerror(errno));
- exit(70);
- }
- if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
- ALOGE("setpriority failed: %s\n", strerror(errno));
- exit(71);
- }
+ SetDex2OatAndPatchOatScheduling(post_bootcomplete);
if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) {
ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno));
exit(67);
@@ -1222,7 +1253,7 @@
input_file_name++;
}
run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, pkgname,
- instruction_set, vm_safe_mode, debuggable);
+ instruction_set, vm_safe_mode, debuggable, post_bootcomplete);
} else {
ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
exit(73);
diff --git a/include/binder/IServiceManager.h b/include/binder/IServiceManager.h
index 2c297d6..7ccd9fe 100644
--- a/include/binder/IServiceManager.h
+++ b/include/binder/IServiceManager.h
@@ -81,20 +81,6 @@
int32_t* outPid, int32_t* outUid);
bool checkPermission(const String16& permission, pid_t pid, uid_t uid);
-
-// ----------------------------------------------------------------------
-
-class BnServiceManager : public BnInterface<IServiceManager>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------
-
}; // namespace android
#endif // ANDROID_ISERVICE_MANAGER_H
diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h
index 145efe6..504ac64 100644
--- a/include/gui/BufferItem.h
+++ b/include/gui/BufferItem.h
@@ -98,13 +98,8 @@
};
};
- union {
- // mSlot is the slot index of this buffer (default INVALID_BUFFER_SLOT).
- int mSlot;
-
- // mBuf is the former name for mSlot
- int mBuf;
- };
+ // mSlot is the slot index of this buffer (default INVALID_BUFFER_SLOT).
+ int mSlot;
// mIsDroppable whether this buffer was queued with the
// property that it can be replaced by a new buffer for the purpose of
diff --git a/include/gui/BufferQueueConsumer.h b/include/gui/BufferQueueConsumer.h
index cde302f..b2daae4 100644
--- a/include/gui/BufferQueueConsumer.h
+++ b/include/gui/BufferQueueConsumer.h
@@ -100,20 +100,8 @@
// is 1x1.
virtual status_t setDefaultBufferSize(uint32_t width, uint32_t height);
- // setDefaultMaxBufferCount sets the default value for the maximum buffer
- // count (the initial default is 2). If the producer has requested a
- // buffer count using setBufferCount, the default buffer count will only
- // take effect if the producer sets the count back to zero.
- //
- // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
- virtual status_t setDefaultMaxBufferCount(int bufferCount);
-
- // disableAsyncBuffer disables the extra buffer used in async mode
- // (when both producer and consumer have set their "isControlledByApp"
- // flag) and has dequeueBuffer() return WOULD_BLOCK instead.
- //
- // This can only be called before connect().
- virtual status_t disableAsyncBuffer();
+ // see IGraphicBufferConsumer::setMaxBufferCount
+ virtual status_t setMaxBufferCount(int bufferCount);
// setMaxAcquiredBufferCount sets the maximum number of buffers that can
// be acquired by the consumer at one time (default 1). This call will
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index c6643ea..e824124 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -105,12 +105,6 @@
// connected, mDequeueCondition must be broadcast.
int getMaxBufferCountLocked(bool async) const;
- // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
- // that will be used if the producer does not override the buffer slot
- // count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. The
- // initial default is 2.
- status_t setDefaultMaxBufferCountLocked(int count);
-
// freeBufferLocked frees the GraphicBuffer and sync resources for the
// given slot.
void freeBufferLocked(int slot);
@@ -196,10 +190,6 @@
// synchronous mode.
mutable Condition mDequeueCondition;
- // mUseAsyncBuffer indicates whether an extra buffer is used in async mode
- // to prevent dequeueBuffer from blocking.
- bool mUseAsyncBuffer;
-
// mDequeueBufferCannotBlock indicates whether dequeueBuffer is allowed to
// block. This flag is set during connect when both the producer and
// consumer are controlled by the application.
@@ -222,11 +212,9 @@
// is specified.
android_dataspace mDefaultBufferDataSpace;
- // mDefaultMaxBufferCount is the default limit on the number of buffers that
- // will be allocated at one time. This default limit is set by the consumer.
- // The limit (as opposed to the default limit) may be overriden by the
- // producer.
- int mDefaultMaxBufferCount;
+ // mMaxBufferCount is the limit on the number of buffers that will be
+ // allocated at one time. This limit can be set by the consumer.
+ int mMaxBufferCount;
// mMaxAcquiredBufferCount is the number of buffers that the consumer may
// acquire at one time. It defaults to 1, and can be changed by the consumer
@@ -240,13 +228,6 @@
// via setMaxDequeuedBufferCount.
int mMaxDequeuedBufferCount;
- // mOverrideMaxBufferCount defaults to false and is set to true once the
- // producer has called setMaxDequeuedBufferCount or setAsyncMode. Once it is
- // set mDefaultMaxBufferCount is ignored and the max buffer count is
- // calculated based on mMaxAcquiredBufferCount, mMaxDequeuedBufferCount, and
- // mAsyncMode.
- bool mOverrideMaxBufferCount;
-
// mBufferHasBeenQueued is true once a buffer has been queued. It is reset
// when something causes all buffers to be freed (e.g., changing the buffer
// count).
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index c35c7be..0e4acee 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -112,11 +112,6 @@
// union fence.
void setReleaseFence(const sp<Fence>& fence);
- // setDefaultMaxBufferCount sets the default limit on the maximum number
- // of buffers that will be allocated at one time. The image producer may
- // override the limit.
- status_t setDefaultMaxBufferCount(int bufferCount);
-
// getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
// associated with the texture image set by the most recent call to
// updateTexImage.
@@ -201,6 +196,7 @@
status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace);
status_t setConsumerUsageBits(uint32_t usage);
status_t setTransformHint(uint32_t hint);
+ status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
// detachFromContext detaches the GLConsumer from the calling thread's
// current OpenGL ES context. This context must be the same as the context
diff --git a/include/gui/IGraphicBufferConsumer.h b/include/gui/IGraphicBufferConsumer.h
index 60ec9cc..d4c9ee5 100644
--- a/include/gui/IGraphicBufferConsumer.h
+++ b/include/gui/IGraphicBufferConsumer.h
@@ -188,32 +188,28 @@
// * BAD_VALUE - either w or h was zero
virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) = 0;
- // setDefaultMaxBufferCount sets the default value for the maximum buffer
- // count (the initial default is 2). If the producer has requested a
- // buffer count using setBufferCount, the default buffer count will only
- // take effect if the producer sets the count back to zero.
+ // setMaxBufferCount sets the maximum value for the number of buffers used
+ // in the buffer queue (the initial default is NUM_BUFFER_SLOTS). If a call
+ // to setMaxAcquiredBufferCount (by the consumer), or a call to setAsyncMode
+ // or setMaxDequeuedBufferCount (by the producer), would cause this value to
+ // be exceeded then that call will fail. This call will fail if a producer
+ // is connected to the BufferQueue.
//
- // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
+ // The count must be between 1 and NUM_BUFFER_SLOTS, inclusive. The count
+ // cannot be less than maxAcquiredBufferCount.
//
// Return of a value other than NO_ERROR means an error has occurred:
// * BAD_VALUE - bufferCount was out of range (see above).
- virtual status_t setDefaultMaxBufferCount(int bufferCount) = 0;
-
- // disableAsyncBuffer disables the extra buffer used in async mode
- // (when both producer and consumer have set their "isControlledByApp"
- // flag) and has dequeueBuffer() return WOULD_BLOCK instead.
- //
- // This can only be called before consumerConnect().
- //
- // Return of a value other than NO_ERROR means an error has occurred:
- // * INVALID_OPERATION - attempting to call this after consumerConnect.
- virtual status_t disableAsyncBuffer() = 0;
+ // * INVALID_OPERATION - attempting to call this after a producer connected.
+ virtual status_t setMaxBufferCount(int bufferCount) = 0;
// setMaxAcquiredBufferCount sets the maximum number of buffers that can
// be acquired by the consumer at one time (default 1). This call will
// fail if a producer is connected to the BufferQueue.
//
- // maxAcquiredBuffers must be (inclusive) between 1 and MAX_MAX_ACQUIRED_BUFFERS.
+ // maxAcquiredBuffers must be (inclusive) between 1 and
+ // MAX_MAX_ACQUIRED_BUFFERS. It also cannot cause the maxBufferCount value
+ // to be exceeded.
//
// Return of a value other than NO_ERROR means an error has occurred:
// * BAD_VALUE - maxAcquiredBuffers was out of range (see above).
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 91502e2..5b84bdc 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -99,8 +99,9 @@
// Return of a value other than NO_ERROR means an error has occurred:
// * NO_INIT - the buffer queue has been abandoned.
// * BAD_VALUE - one of the below conditions occurred:
- // * bufferCount was out of range (see above)
- // * client has one or more buffers dequeued
+ // * bufferCount was out of range (see above)
+ // * client has one or more buffers dequeued
+ // * this call would cause the maxBufferCount value to be exceeded
virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) = 0;
// Set the async flag if the producer intends to asynchronously queue
@@ -116,7 +117,9 @@
//
// Return of a value other than NO_ERROR means an error has occurred:
// * NO_INIT - the buffer queue has been abandoned.
- // * BAD_VALUE - client has one or more buffers dequeued
+ // * BAD_VALUE - one of the below conditions occurred:
+ // * client has one or more buffers dequeued
+ // * this call would cause the maxBufferCount value to be exceeded
virtual status_t setAsyncMode(bool async) = 0;
// dequeueBuffer requests a new buffer slot for the client to use. Ownership
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 25b6719..ed2331b 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -170,8 +170,6 @@
virtual int connect(int api);
virtual int disconnect(int api);
virtual int setBufferCount(int bufferCount);
- virtual int setMaxDequeuedBufferCount(int maxDequeuedBuffers);
- virtual int setAsyncMode(bool async);
virtual int setBuffersDimensions(uint32_t width, uint32_t height);
virtual int setBuffersUserDimensions(uint32_t width, uint32_t height);
virtual int setBuffersFormat(PixelFormat format);
@@ -185,6 +183,8 @@
virtual void setSurfaceDamage(android_native_rect_t* rects, size_t numRects);
public:
+ virtual int setMaxDequeuedBufferCount(int maxDequeuedBuffers);
+ virtual int setAsyncMode(bool async);
virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
virtual int unlockAndPost();
diff --git a/include/powermanager/IPowerManager.h b/include/powermanager/IPowerManager.h
index 91ecc5a..49ff637 100644
--- a/include/powermanager/IPowerManager.h
+++ b/include/powermanager/IPowerManager.h
@@ -25,12 +25,23 @@
// ----------------------------------------------------------------------------
-// must be kept in sync with interface defined in IPowerManager.aidl
class IPowerManager : public IInterface
{
public:
+ // These transaction IDs must be kept in sync with the method order from
+ // IPowerManager.aidl.
+ enum {
+ ACQUIRE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION,
+ ACQUIRE_WAKE_LOCK_UID = IBinder::FIRST_CALL_TRANSACTION + 1,
+ RELEASE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION + 2,
+ UPDATE_WAKE_LOCK_UIDS = IBinder::FIRST_CALL_TRANSACTION + 3,
+ POWER_HINT = IBinder::FIRST_CALL_TRANSACTION + 4,
+ };
+
DECLARE_META_INTERFACE(PowerManager);
+ // The parcels created by these methods must be kept in sync with the
+ // corresponding methods from IPowerManager.aidl.
// FIXME remove the bool isOneWay parameters as they are not oneway in the .aidl
virtual status_t acquireWakeLock(int flags, const sp<IBinder>& lock, const String16& tag,
const String16& packageName, bool isOneWay = false) = 0;
diff --git a/include/ui/Region.h b/include/ui/Region.h
index 2a14918..e9b3a0b 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -130,11 +130,6 @@
// Region object.
Rect const* getArray(size_t* count) const;
- // returns a SharedBuffer as well as the number of rects.
- // ownership is transfered to the caller.
- // the caller must call SharedBuffer::release() to free the memory.
- SharedBuffer const* getSharedBuffer(size_t* count) const;
-
/* no user serviceable parts here... */
// add a rectangle to the internal list. This rectangle must
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index d5860ef..ce29ea6 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -43,6 +43,9 @@
include $(CLEAR_VARS)
LOCAL_MODULE := libbinder
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
+
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
LOCAL_SRC_FILES := $(sources)
ifneq ($(TARGET_USES_64_BIT_BINDER),true)
ifneq ($(TARGET_IS_64_BIT),true)
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 3c716df..134aadc 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -184,48 +184,4 @@
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
-// ----------------------------------------------------------------------
-
-status_t BnServiceManager::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- //printf("ServiceManager received: "); data.print();
- switch(code) {
- case GET_SERVICE_TRANSACTION: {
- CHECK_INTERFACE(IServiceManager, data, reply);
- String16 which = data.readString16();
- sp<IBinder> b = const_cast<BnServiceManager*>(this)->getService(which);
- reply->writeStrongBinder(b);
- return NO_ERROR;
- } break;
- case CHECK_SERVICE_TRANSACTION: {
- CHECK_INTERFACE(IServiceManager, data, reply);
- String16 which = data.readString16();
- sp<IBinder> b = const_cast<BnServiceManager*>(this)->checkService(which);
- reply->writeStrongBinder(b);
- return NO_ERROR;
- } break;
- case ADD_SERVICE_TRANSACTION: {
- CHECK_INTERFACE(IServiceManager, data, reply);
- String16 which = data.readString16();
- sp<IBinder> b = data.readStrongBinder();
- status_t err = addService(which, b);
- reply->writeInt32(err);
- return NO_ERROR;
- } break;
- case LIST_SERVICES_TRANSACTION: {
- CHECK_INTERFACE(IServiceManager, data, reply);
- Vector<String16> list = listServices();
- const size_t N = list.size();
- reply->writeInt32(N);
- for (size_t i=0; i<N; i++) {
- reply->writeString16(list[i]);
- }
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
}; // namespace android
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 7a4ddc4..8315c58 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -350,13 +350,11 @@
size_t Parcel::dataAvail() const
{
- // TODO: decide what to do about the possibility that this can
- // report an available-data size that exceeds a Java int's max
- // positive value, causing havoc. Fortunately this will only
- // happen if someone constructs a Parcel containing more than two
- // gigabytes of data, which on typical phone hardware is simply
- // not possible.
- return dataSize() - dataPosition();
+ size_t result = dataSize() - dataPosition();
+ if (result > INT32_MAX) {
+ abort();
+ }
+ return result;
}
size_t Parcel::dataPosition() const
@@ -1645,8 +1643,14 @@
if (mData) {
LOG_ALLOC("Parcel %p: freeing with %zu capacity", this, mDataCapacity);
pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
- gParcelGlobalAllocSize -= mDataCapacity;
- gParcelGlobalAllocCount--;
+ if (mDataCapacity <= gParcelGlobalAllocSize) {
+ gParcelGlobalAllocSize = gParcelGlobalAllocSize - mDataCapacity;
+ } else {
+ gParcelGlobalAllocSize = 0;
+ }
+ if (gParcelGlobalAllocCount > 0) {
+ gParcelGlobalAllocCount--;
+ }
pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
free(mData);
}
@@ -1825,6 +1829,7 @@
pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
gParcelGlobalAllocSize += desired;
gParcelGlobalAllocSize -= mDataCapacity;
+ gParcelGlobalAllocCount++;
pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
mData = data;
mDataCapacity = desired;
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index 578b8d9..6f4c89d 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -78,7 +78,7 @@
}
}
- item->mGraphicBuffer = mSlots[item->mBuf].mGraphicBuffer;
+ item->mGraphicBuffer = mSlots[item->mSlot].mGraphicBuffer;
return OK;
}
@@ -89,9 +89,9 @@
Mutex::Autolock _l(mMutex);
- err = addReleaseFenceLocked(item.mBuf, item.mGraphicBuffer, releaseFence);
+ err = addReleaseFenceLocked(item.mSlot, item.mGraphicBuffer, releaseFence);
- err = releaseBufferLocked(item.mBuf, item.mGraphicBuffer, EGL_NO_DISPLAY,
+ err = releaseBufferLocked(item.mSlot, item.mGraphicBuffer, EGL_NO_DISPLAY,
EGL_NO_SYNC_KHR);
if (err != OK) {
BI_LOGE("Failed to release buffer: %s (%d)",
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index bb3e1b0..950a074 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -482,24 +482,29 @@
return NO_ERROR;
}
-status_t BufferQueueConsumer::setDefaultMaxBufferCount(int bufferCount) {
+status_t BufferQueueConsumer::setMaxBufferCount(int bufferCount) {
ATRACE_CALL();
- Mutex::Autolock lock(mCore->mMutex);
- return mCore->setDefaultMaxBufferCountLocked(bufferCount);
-}
-status_t BufferQueueConsumer::disableAsyncBuffer() {
- ATRACE_CALL();
+ if (bufferCount < 1 || bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
+ BQ_LOGE("setMaxBufferCount: invalid count %d", bufferCount);
+ return BAD_VALUE;
+ }
Mutex::Autolock lock(mCore->mMutex);
- if (mCore->mConsumerListener != NULL) {
- BQ_LOGE("disableAsyncBuffer: consumer already connected");
+ if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("setMaxBufferCount: producer is already connected");
return INVALID_OPERATION;
}
- BQ_LOGV("disableAsyncBuffer");
- mCore->mUseAsyncBuffer = false;
+ if (bufferCount < mCore->mMaxAcquiredBufferCount) {
+ BQ_LOGE("setMaxBufferCount: invalid buffer count (%d) less than"
+ "mMaxAcquiredBufferCount (%d)", bufferCount,
+ mCore->mMaxAcquiredBufferCount);
+ return BAD_VALUE;
+ }
+
+ mCore->mMaxBufferCount = bufferCount;
return NO_ERROR;
}
@@ -521,6 +526,15 @@
return INVALID_OPERATION;
}
+ if ((maxAcquiredBuffers + mCore->mMaxDequeuedBufferCount +
+ (mCore->mAsyncMode ? 1 : 0)) > mCore->mMaxBufferCount) {
+ BQ_LOGE("setMaxAcquiredBufferCount: %d acquired buffers would exceed "
+ "the maxBufferCount (%d) (maxDequeued %d async %d)",
+ maxAcquiredBuffers, mCore->mMaxBufferCount,
+ mCore->mMaxDequeuedBufferCount, mCore->mAsyncMode);
+ return BAD_VALUE;
+ }
+
BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
return NO_ERROR;
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index d297112..8b97c2a 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -30,9 +30,6 @@
#include <gui/ISurfaceComposer.h>
#include <private/gui/ComposerService.h>
-template <typename T>
-static inline T max(T a, T b) { return a > b ? a : b; }
-
namespace android {
static String8 getUniqueName() {
@@ -56,16 +53,14 @@
mFreeSlots(),
mFreeBuffers(),
mDequeueCondition(),
- mUseAsyncBuffer(true),
mDequeueBufferCannotBlock(false),
mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
mDefaultWidth(1),
mDefaultHeight(1),
mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
- mDefaultMaxBufferCount(2),
+ mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS),
mMaxAcquiredBufferCount(1),
mMaxDequeuedBufferCount(1),
- mOverrideMaxBufferCount(false),
mBufferHasBeenQueued(false),
mFrameCounter(0),
mTransformHint(0),
@@ -145,10 +140,6 @@
int BufferQueueCore::getMinUndequeuedBufferCountLocked(bool async) const {
// If dequeueBuffer is allowed to error out, we don't have to add an
// extra buffer.
- if (!mUseAsyncBuffer) {
- return mMaxAcquiredBufferCount;
- }
-
if (mDequeueBufferCannotBlock || async) {
return mMaxAcquiredBufferCount + 1;
}
@@ -161,15 +152,11 @@
}
int BufferQueueCore::getMaxBufferCountLocked(bool async) const {
- int minMaxBufferCount = getMinMaxBufferCountLocked(async);
+ int maxBufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
+ (async ? 1 : 0);
- int maxBufferCount = max(mDefaultMaxBufferCount, minMaxBufferCount);
- if (mOverrideMaxBufferCount) {
- int bufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
- (async ? 1 : 0);
- assert(bufferCount >= minMaxBufferCount);
- maxBufferCount = bufferCount;
- }
+ // limit maxBufferCount by mMaxBufferCount always
+ maxBufferCount = std::min(mMaxBufferCount, maxBufferCount);
// Any buffers that are dequeued by the producer or sitting in the queue
// waiting to be consumed need to have their slots preserved. Such buffers
@@ -185,22 +172,6 @@
return maxBufferCount;
}
-status_t BufferQueueCore::setDefaultMaxBufferCountLocked(int count) {
- const int minBufferCount = mUseAsyncBuffer ? 2 : 1;
- if (count < minBufferCount || count > BufferQueueDefs::NUM_BUFFER_SLOTS) {
- BQ_LOGV("setDefaultMaxBufferCount: invalid count %d, should be in "
- "[%d, %d]",
- count, minBufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
- return BAD_VALUE;
- }
-
- BQ_LOGV("setDefaultMaxBufferCount: setting count to %d", count);
- mDefaultMaxBufferCount = count;
- mDequeueCondition.broadcast();
-
- return NO_ERROR;
-}
-
void BufferQueueCore::freeBufferLocked(int slot) {
BQ_LOGV("freeBufferLocked: slot %d", slot);
bool hadBuffer = mSlots[slot].mGraphicBuffer != NULL;
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 61878f6..8cc0cfa 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -115,13 +115,20 @@
return BAD_VALUE;
}
+ if (bufferCount > mCore->mMaxBufferCount) {
+ BQ_LOGE("setMaxDequeuedBufferCount: %d dequeued buffers would "
+ "exceed the maxBufferCount (%d) (maxAcquired %d async %d)",
+ maxDequeuedBuffers, mCore->mMaxBufferCount,
+ mCore->mMaxAcquiredBufferCount, mCore->mAsyncMode);
+ return BAD_VALUE;
+ }
+
// Here we are guaranteed that the producer doesn't have any dequeued
// buffers and will release all of its buffer references. We don't
// clear the queue, however, so that currently queued buffers still
// get displayed.
mCore->freeAllBuffersLocked();
mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
- mCore->mOverrideMaxBufferCount = true;
mCore->mDequeueCondition.broadcast();
listener = mCore->mConsumerListener;
} // Autolock scope
@@ -156,8 +163,17 @@
}
}
+ if ((mCore->mMaxAcquiredBufferCount + mCore->mMaxDequeuedBufferCount +
+ (async ? 1 : 0)) > mCore->mMaxBufferCount) {
+ BQ_LOGE("setAsyncMode(%d): this call would cause the "
+ "maxBufferCount (%d) to be exceeded (maxAcquired %d "
+ "maxDequeued %d)", async,mCore->mMaxBufferCount,
+ mCore->mMaxAcquiredBufferCount,
+ mCore->mMaxDequeuedBufferCount);
+ return BAD_VALUE;
+ }
+
mCore->mAsyncMode = async;
- mCore->mOverrideMaxBufferCount = true;
mCore->mDequeueCondition.broadcast();
listener = mCore->mConsumerListener;
} // Autolock scope
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 04ab06b..d01187f 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -239,14 +239,14 @@
}
if (item->mGraphicBuffer != NULL) {
- mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
+ mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
}
- mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;
- mSlots[item->mBuf].mFence = item->mFence;
+ mSlots[item->mSlot].mFrameNumber = item->mFrameNumber;
+ mSlots[item->mSlot].mFence = item->mFence;
CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
- item->mBuf, item->mFrameNumber);
+ item->mSlot, item->mFrameNumber);
return OK;
}
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index e29b740..7ed3d0f 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -106,22 +106,22 @@
}
}
- int buf = b.mBuf;
+ int slot = b.mSlot;
void *bufferPointer = NULL;
android_ycbcr ycbcr = android_ycbcr();
- PixelFormat format = mSlots[buf].mGraphicBuffer->getPixelFormat();
+ PixelFormat format = mSlots[slot].mGraphicBuffer->getPixelFormat();
PixelFormat flexFormat = format;
if (isPossiblyYUV(format)) {
if (b.mFence.get()) {
- err = mSlots[buf].mGraphicBuffer->lockAsyncYCbCr(
+ err = mSlots[slot].mGraphicBuffer->lockAsyncYCbCr(
GraphicBuffer::USAGE_SW_READ_OFTEN,
b.mCrop,
&ycbcr,
b.mFence->dup());
} else {
- err = mSlots[buf].mGraphicBuffer->lockYCbCr(
+ err = mSlots[slot].mGraphicBuffer->lockYCbCr(
GraphicBuffer::USAGE_SW_READ_OFTEN,
b.mCrop,
&ycbcr);
@@ -141,13 +141,13 @@
if (bufferPointer == NULL) { // not flexible YUV
if (b.mFence.get()) {
- err = mSlots[buf].mGraphicBuffer->lockAsync(
+ err = mSlots[slot].mGraphicBuffer->lockAsync(
GraphicBuffer::USAGE_SW_READ_OFTEN,
b.mCrop,
&bufferPointer,
b.mFence->dup());
} else {
- err = mSlots[buf].mGraphicBuffer->lock(
+ err = mSlots[slot].mGraphicBuffer->lock(
GraphicBuffer::USAGE_SW_READ_OFTEN,
b.mCrop,
&bufferPointer);
@@ -169,19 +169,19 @@
assert(lockedIdx < mMaxLockedBuffers);
AcquiredBuffer &ab = mAcquiredBuffers.editItemAt(lockedIdx);
- ab.mSlot = buf;
+ ab.mSlot = slot;
ab.mBufferPointer = bufferPointer;
- ab.mGraphicBuffer = mSlots[buf].mGraphicBuffer;
+ ab.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
nativeBuffer->data =
reinterpret_cast<uint8_t*>(bufferPointer);
- nativeBuffer->width = mSlots[buf].mGraphicBuffer->getWidth();
- nativeBuffer->height = mSlots[buf].mGraphicBuffer->getHeight();
+ nativeBuffer->width = mSlots[slot].mGraphicBuffer->getWidth();
+ nativeBuffer->height = mSlots[slot].mGraphicBuffer->getHeight();
nativeBuffer->format = format;
nativeBuffer->flexFormat = flexFormat;
nativeBuffer->stride = (ycbcr.y != NULL) ?
static_cast<uint32_t>(ycbcr.ystride) :
- mSlots[buf].mGraphicBuffer->getStride();
+ mSlots[slot].mGraphicBuffer->getStride();
nativeBuffer->crop = b.mCrop;
nativeBuffer->transform = b.mTransform;
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index be5075c..1572a89 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -183,12 +183,6 @@
mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
}
-status_t GLConsumer::setDefaultMaxBufferCount(int bufferCount) {
- Mutex::Autolock lock(mMutex);
- return mConsumer->setDefaultMaxBufferCount(bufferCount);
-}
-
-
status_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
{
Mutex::Autolock lock(mMutex);
@@ -357,7 +351,7 @@
// before, so any prior EglImage created is using a stale buffer. This
// replaces any old EglImage with a new one (using the new buffer).
if (item->mGraphicBuffer != NULL) {
- int slot = item->mBuf;
+ int slot = item->mSlot;
mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
}
@@ -381,12 +375,12 @@
{
status_t err = NO_ERROR;
- int buf = item.mBuf;
+ int slot = item.mSlot;
if (!mAttached) {
GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
"ES context");
- releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
+ releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
mEglDisplay, EGL_NO_SYNC_KHR);
return INVALID_OPERATION;
}
@@ -394,7 +388,7 @@
// Confirm state.
err = checkAndUpdateEglStateLocked();
if (err != NO_ERROR) {
- releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
+ releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
mEglDisplay, EGL_NO_SYNC_KHR);
return err;
}
@@ -404,11 +398,11 @@
// ConsumerBase.
// We may have to do this even when item.mGraphicBuffer == NULL (which
// means the buffer was previously acquired).
- err = mEglSlots[buf].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
+ err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
if (err != NO_ERROR) {
GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
- mEglDisplay, buf);
- releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
+ mEglDisplay, slot);
+ releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
mEglDisplay, EGL_NO_SYNC_KHR);
return UNKNOWN_ERROR;
}
@@ -420,7 +414,7 @@
// release the old buffer, so instead we just drop the new frame.
// As we are still under lock since acquireBuffer, it is safe to
// release by slot.
- releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
+ releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
mEglDisplay, EGL_NO_SYNC_KHR);
return err;
}
@@ -428,7 +422,7 @@
GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
mCurrentTexture, mCurrentTextureImage != NULL ?
mCurrentTextureImage->graphicBufferHandle() : 0,
- buf, mSlots[buf].mGraphicBuffer->handle);
+ slot, mSlots[slot].mGraphicBuffer->handle);
// release old buffer
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
@@ -444,8 +438,8 @@
}
// Update the GLConsumer state.
- mCurrentTexture = buf;
- mCurrentTextureImage = mEglSlots[buf].mEglImage;
+ mCurrentTexture = slot;
+ mCurrentTextureImage = mEglSlots[slot].mEglImage;
mCurrentCrop = item.mCrop;
mCurrentTransform = item.mTransform;
mCurrentScalingMode = item.mScalingMode;
@@ -1048,6 +1042,11 @@
return mConsumer->setTransformHint(hint);
}
+status_t GLConsumer::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
+ Mutex::Autolock lock(mMutex);
+ return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
+}
+
void GLConsumer::dumpLocked(String8& result, const char* prefix) const
{
result.appendFormat(
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index b86f4c5..d2f482e 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -43,8 +43,7 @@
CONSUMER_DISCONNECT,
GET_RELEASED_BUFFERS,
SET_DEFAULT_BUFFER_SIZE,
- SET_DEFAULT_MAX_BUFFER_COUNT,
- DISABLE_ASYNC_BUFFER,
+ SET_MAX_BUFFER_COUNT,
SET_MAX_ACQUIRED_BUFFER_COUNT,
SET_CONSUMER_NAME,
SET_DEFAULT_BUFFER_FORMAT,
@@ -172,21 +171,11 @@
return reply.readInt32();
}
- virtual status_t setDefaultMaxBufferCount(int bufferCount) {
+ virtual status_t setMaxBufferCount(int bufferCount) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
data.writeInt32(bufferCount);
- status_t result = remote()->transact(SET_DEFAULT_MAX_BUFFER_COUNT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t disableAsyncBuffer() {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- status_t result = remote()->transact(DISABLE_ASYNC_BUFFER, data, &reply);
+ status_t result = remote()->transact(SET_MAX_BUFFER_COUNT, data, &reply);
if (result != NO_ERROR) {
return result;
}
@@ -363,16 +352,10 @@
reply->writeInt32(result);
return NO_ERROR;
}
- case SET_DEFAULT_MAX_BUFFER_COUNT: {
+ case SET_MAX_BUFFER_COUNT: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
int bufferCount = data.readInt32();
- status_t result = setDefaultMaxBufferCount(bufferCount);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case DISABLE_ASYNC_BUFFER: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- status_t result = disableAsyncBuffer();
+ status_t result = setMaxBufferCount(bufferCount);
reply->writeInt32(result);
return NO_ERROR;
}
diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp
index 43f9214..dce0e87 100644
--- a/libs/gui/StreamSplitter.cpp
+++ b/libs/gui/StreamSplitter.cpp
@@ -132,7 +132,7 @@
ALOGV("acquired buffer %#" PRIx64 " from input",
bufferItem.mGraphicBuffer->getId());
- status = mInput->detachBuffer(bufferItem.mBuf);
+ status = mInput->detachBuffer(bufferItem.mSlot);
LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
"detaching buffer from input failed (%d)", status);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 27f7ed6..de5c275 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -184,7 +184,9 @@
va_list args;
va_start(args, operation);
Surface* c = getSelf(window);
- return c->perform(operation, args);
+ int result = c->perform(operation, args);
+ va_end(args);
+ return result;
}
int Surface::setSwapInterval(int interval) {
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 115e4db..8a3be3d 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -189,6 +189,9 @@
EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100));
+
+ EXPECT_EQ(OK, mConsumer->setMaxBufferCount(5));
+ EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(5));
}
TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
@@ -206,6 +209,28 @@
BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
}
+TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) {
+ createBufferQueue();
+ sp<DummyConsumer> dc(new DummyConsumer);
+ mConsumer->consumerConnect(dc, false);
+
+ // Test single buffer mode
+ EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
+}
+
+TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) {
+ createBufferQueue();
+ sp<DummyConsumer> dc(new DummyConsumer);
+ mConsumer->consumerConnect(dc, false);
+
+ EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0));
+ EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(
+ BufferQueue::NUM_BUFFER_SLOTS + 1));
+
+ EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(5));
+ EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(3));
+}
+
TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
createBufferQueue();
sp<DummyConsumer> dc(new DummyConsumer);
@@ -288,8 +313,8 @@
BufferItem item;
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
- ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf));
- ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mBuf)); // Not acquired
+ ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
+ ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mSlot)); // Not acquired
uint32_t* dataIn;
ASSERT_EQ(OK, item.mGraphicBuffer->lock(
@@ -348,7 +373,7 @@
BufferItem item;
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
- ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf));
+ ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
int newSlot;
ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index 00cc39d..afd149e 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -128,7 +128,7 @@
ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
- ASSERT_EQ(OK, outputConsumer->releaseBuffer(item.mBuf, item.mFrameNumber,
+ ASSERT_EQ(OK, outputConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
@@ -196,7 +196,7 @@
ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
- ASSERT_EQ(OK, outputConsumers[output]->releaseBuffer(item.mBuf,
+ ASSERT_EQ(OK, outputConsumers[output]->releaseBuffer(item.mSlot,
item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
Fence::NO_FENCE));
}
diff --git a/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp b/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp
index 9776733..b4e25f3 100644
--- a/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp
@@ -134,8 +134,6 @@
}
};
- ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
-
runProducerThread(new PT());
// Allow three frames to be rendered and queued before starting the
diff --git a/libs/gui/tests/SurfaceTextureGLToGL_test.cpp b/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
index 6edbfb8..b3f6066 100644
--- a/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
@@ -29,8 +29,9 @@
mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
// This test requires 3 buffers to avoid deadlock because we're
- // both producer and consumer, and only using one thread.
- mST->setDefaultMaxBufferCount(3);
+ // both producer and consumer, and only using one thread. Set max dequeued
+ // to 2, and max acquired already defaults to 1.
+ ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
// Do the producer side of things
EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
@@ -81,7 +82,8 @@
mST->setDefaultBufferSize(texWidth, texHeight);
// This test requires 3 buffers to complete run on a single thread.
- mST->setDefaultMaxBufferCount(3);
+ // Set max dequeued to 2, and max acquired already defaults to 1.
+ ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
// Do the producer side of things
EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
@@ -330,7 +332,8 @@
enum { texHeight = 64 };
// This test requires 3 buffers to complete run on a single thread.
- mST->setDefaultMaxBufferCount(3);
+ // Set max dequeued to 2, and max acquired already defaults to 1.
+ ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
// Set the user buffer size.
native_window_set_buffers_user_dimensions(mANW.get(), texWidth, texHeight);
@@ -387,7 +390,8 @@
enum { texHeight = 16 };
// This test requires 3 buffers to complete run on a single thread.
- mST->setDefaultMaxBufferCount(3);
+ // Set max dequeued to 2, and max acquired already defaults to 1.
+ ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
// Set the transform hint.
mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
@@ -448,7 +452,8 @@
enum { texHeight = 16 };
// This test requires 3 buffers to complete run on a single thread.
- mST->setDefaultMaxBufferCount(3);
+ // Set max dequeued to 2, and max acquired already defaults to 1.
+ ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
// Set the transform hint.
mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp
index fad133f..0e85b90 100644
--- a/libs/gui/tests/SurfaceTextureGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGL_test.cpp
@@ -190,7 +190,6 @@
enum { texHeight = 16 };
enum { numFrames = 1024 };
- ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
texWidth, texHeight));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -658,8 +657,6 @@
Mutex mMutex;
};
- ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
-
sp<Thread> pt(new ProducerThread(mANW));
pt->run();
diff --git a/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp b/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
index 1cd101e..f74ac3d 100644
--- a/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
@@ -361,7 +361,6 @@
TEST_F(SurfaceTextureMultiContextGLTest,
UpdateTexImageSucceedsForBufferConsumedBeforeDetach) {
- ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
// produce two frames and consume them both on the primary context
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
@@ -388,7 +387,6 @@
TEST_F(SurfaceTextureMultiContextGLTest,
AttachAfterDisplayTerminatedSucceeds) {
- ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
// produce two frames and consume them both on the primary context
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 1ce8626..54ff741 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -17,6 +17,7 @@
LOCAL_CLANG := true
LOCAL_CPPFLAGS := -std=c++1y -Weverything -Werror
+LOCAL_SANITIZE := integer
# The static constructors and destructors in this library have not been noted to
# introduce significant overheads
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 7792975..ac37990 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -835,18 +835,6 @@
return begin();
}
-SharedBuffer const* Region::getSharedBuffer(size_t* count) const {
- // We can get to the SharedBuffer of a Vector<Rect> because Rect has
- // a trivial destructor.
- SharedBuffer const* sb = SharedBuffer::bufferFromData(mStorage.array());
- if (count) {
- size_t numRects = isRect() ? 1 : mStorage.size() - 1;
- count[0] = numRects;
- }
- sb->acquire();
- return sb;
-}
-
// ----------------------------------------------------------------------------
void Region::dump(String8& out, const char* what, uint32_t /* flags */) const
diff --git a/services/powermanager/Android.mk b/services/powermanager/Android.mk
index 7b24c65..4deb115 100644
--- a/services/powermanager/Android.mk
+++ b/services/powermanager/Android.mk
@@ -14,4 +14,6 @@
LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/../../include
+
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/powermanager/IPowerManager.cpp b/services/powermanager/IPowerManager.cpp
index ec864ee..0a4244f 100644
--- a/services/powermanager/IPowerManager.cpp
+++ b/services/powermanager/IPowerManager.cpp
@@ -27,15 +27,6 @@
namespace android {
-// must be kept in sync with IPowerManager.aidl
-enum {
- ACQUIRE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION,
- ACQUIRE_WAKE_LOCK_UID = IBinder::FIRST_CALL_TRANSACTION + 1,
- RELEASE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION + 2,
- UPDATE_WAKE_LOCK_UIDS = IBinder::FIRST_CALL_TRANSACTION + 3,
- POWER_HINT = IBinder::FIRST_CALL_TRANSACTION + 4,
-};
-
class BpPowerManager : public BpInterface<IPowerManager>
{
public:
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 6ef3295..a6bc158 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -66,7 +66,7 @@
GRALLOC_USAGE_HW_COMPOSER);
mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));
mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));
- mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
+ mConsumer->setMaxAcquiredBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS - 1);
}
status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
@@ -106,7 +106,7 @@
// releaseBuffer call and we should be in the same state we'd be in if we
// had released the old buffer first.
if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
- item.mBuf != mCurrentBufferSlot) {
+ item.mSlot != mCurrentBufferSlot) {
// Release the previous buffer.
err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,
EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
@@ -115,7 +115,7 @@
return err;
}
}
- mCurrentBufferSlot = item.mBuf;
+ mCurrentBufferSlot = item.mSlot;
mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
outFence = item.mFence;
outBuffer = mCurrentBuffer;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 0859149..d37fcb2 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -1036,12 +1036,10 @@
}
}
virtual void setVisibleRegionScreen(const Region& reg) {
- // Region::getSharedBuffer creates a reference to the underlying
- // SharedBuffer of this Region, this reference is freed
- // in onDisplayed()
hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
- SharedBuffer const* sb = reg.getSharedBuffer(&visibleRegion.numRects);
- visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
+ mVisibleRegion = reg;
+ visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(
+ mVisibleRegion.getArray(&visibleRegion.numRects));
}
virtual void setSurfaceDamage(const Region& reg) {
if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
@@ -1055,8 +1053,9 @@
surfaceDamage.rects = NULL;
return;
}
- SharedBuffer const* sb = reg.getSharedBuffer(&surfaceDamage.numRects);
- surfaceDamage.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
+ mSurfaceDamage = reg;
+ surfaceDamage.rects = reinterpret_cast<hwc_rect_t const *>(
+ mSurfaceDamage.getArray(&surfaceDamage.numRects));
}
virtual void setSidebandStream(const sp<NativeHandle>& stream) {
ALOG_ASSERT(stream->handle() != NULL);
@@ -1078,29 +1077,15 @@
}
}
virtual void onDisplayed() {
- hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
- SharedBuffer const* sb = SharedBuffer::bufferFromData(visibleRegion.rects);
- if (sb) {
- sb->release();
- // not technically needed but safer
- visibleRegion.numRects = 0;
- visibleRegion.rects = NULL;
- }
-
getLayer()->acquireFenceFd = -1;
-
- if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
- return;
- }
-
- hwc_region_t& surfaceDamage = getLayer()->surfaceDamage;
- sb = SharedBuffer::bufferFromData(surfaceDamage.rects);
- if (sb) {
- sb->release();
- surfaceDamage.numRects = 0;
- surfaceDamage.rects = NULL;
- }
}
+
+protected:
+ // We need to hold "copies" of these for memory management purposes. The
+ // actual hwc_layer_1_t holds pointers to the memory within. Vector<>
+ // internally doesn't copy the memory unless one of the copies is modified.
+ Region mVisibleRegion;
+ Region mSurfaceDamage;
};
/*
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 3180d29..94f30d5 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -92,7 +92,6 @@
mConsumer->setConsumerName(ConsumerBase::mName);
mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight);
- mConsumer->setDefaultMaxBufferCount(2);
}
VirtualDisplaySurface::~VirtualDisplaySurface() {
@@ -447,11 +446,11 @@
result = acquireBufferLocked(&item, 0);
if (result != NO_ERROR)
return result;
- VDS_LOGW_IF(item.mBuf != sslot,
+ VDS_LOGW_IF(item.mSlot != sslot,
"queueBuffer: acquired sslot %d from SCRATCH after queueing sslot %d",
- item.mBuf, sslot);
- mFbProducerSlot = mapSource2ProducerSlot(SOURCE_SCRATCH, item.mBuf);
- mFbFence = mSlots[item.mBuf].mFence;
+ item.mSlot, sslot);
+ mFbProducerSlot = mapSource2ProducerSlot(SOURCE_SCRATCH, item.mSlot);
+ mFbFence = mSlots[item.mSlot].mFence;
} else {
LOG_FATAL_IF(mCompositionType != COMPOSITION_GLES,
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5ff79a9..33af4a5 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -135,9 +135,8 @@
#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
#warning "disabling triple buffering"
- mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
#else
- mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);
+ mProducer->setMaxDequeuedBufferCount(2);
#endif
const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index ed1f31b..930e7c7 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -72,9 +72,9 @@
// We call the rejecter here, in case the caller has a reason to
// not accept this buffer. This is used by SurfaceFlinger to
// reject buffers which have the wrong size
- int buf = item.mBuf;
- if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) {
- releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, EGL_NO_SYNC_KHR);
+ int slot = item.mSlot;
+ if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) {
+ releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer, EGL_NO_SYNC_KHR);
return BUFFER_REJECTED;
}