Merge "Report key request message type for unprefixed EME"
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 0cad9d8..8922d54 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -438,7 +438,7 @@
 
     /* set as high priority, and protect from OOM killer */
     setpriority(PRIO_PROCESS, 0, -20);
-    FILE *oom_adj = fopen("/proc/self/oom_adj", "w");
+    FILE *oom_adj = fopen("/proc/self/oom_adj", "we");
     if (oom_adj) {
         fputs("-17", oom_adj);
         fclose(oom_adj);
@@ -471,15 +471,14 @@
     /* open the vibrator before dropping root */
     FILE *vibrator = 0;
     if (do_vibrate) {
-        vibrator = fopen("/sys/class/timed_output/vibrator/enable", "w");
+        vibrator = fopen("/sys/class/timed_output/vibrator/enable", "we");
         if (vibrator) {
-            fcntl(fileno(vibrator), F_SETFD, FD_CLOEXEC);
             vibrate(vibrator, 150);
         }
     }
 
     /* read /proc/cmdline before dropping root */
-    FILE *cmdline = fopen("/proc/cmdline", "r");
+    FILE *cmdline = fopen("/proc/cmdline", "re");
     if (cmdline != NULL) {
         fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
         fclose(cmdline);
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c
index 48f59e1..3d9a2b5 100644
--- a/cmds/dumpstate/utils.c
+++ b/cmds/dumpstate/utils.c
@@ -104,7 +104,7 @@
 
         sprintf(cmdpath,"/proc/%d/cmdline", pid);
         memset(cmdline, 0, sizeof(cmdline));
-        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY))) < 0) {
+        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) < 0) {
             strcpy(cmdline, "N/A");
         } else {
             read(fd, cmdline, sizeof(cmdline) - 1);
@@ -155,7 +155,7 @@
 
         sprintf(commpath,"/proc/%d/comm", tid);
         memset(comm, 0, sizeof(comm));
-        if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY))) < 0) {
+        if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
             strcpy(comm, "N/A");
         } else {
             char *c;
@@ -186,7 +186,7 @@
     memset(buffer, 0, sizeof(buffer));
 
     sprintf(path, "/proc/%d/wchan", tid);
-    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY))) < 0) {
+    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
         printf("Failed to open '%s' (%s)\n", path, strerror(errno));
         return;
     }
@@ -483,6 +483,7 @@
         fprintf(stderr, "android_get_control_socket(%s): %s\n", service, strerror(errno));
         exit(1);
     }
+    fcntl(s, F_SETFD, FD_CLOEXEC);
     if (listen(s, 4) < 0) {
         fprintf(stderr, "listen(control socket): %s\n", strerror(errno));
         exit(1);
@@ -519,7 +520,7 @@
         }
     }
 
-    int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC,
+    int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
                                      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
     if (fd < 0) {
         fprintf(stderr, "%s: %s\n", path, strerror(errno));
@@ -575,7 +576,7 @@
     }
 
     /* create a new, empty traces.txt file to receive stack dumps */
-    int fd = TEMP_FAILURE_RETRY(open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW,
+    int fd = TEMP_FAILURE_RETRY(open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC,
                                      0666));  /* -rw-rw-rw- */
     if (fd < 0) {
         fprintf(stderr, "%s: %s\n", traces_path, strerror(errno));
@@ -626,7 +627,7 @@
         if (!strncmp(data, "/system/bin/app_process", strlen("/system/bin/app_process"))) {
             /* skip zygote -- it won't dump its stack anyway */
             snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
-            int cfd = TEMP_FAILURE_RETRY(open(path, O_RDONLY));
+            int cfd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC));
             len = read(cfd, data, sizeof(data) - 1);
             close(cfd);
             if (len <= 0) {
@@ -711,7 +712,7 @@
 void dump_route_tables() {
     const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
     dump_file("RT_TABLES", RT_TABLES_PATH);
-    FILE* fp = fopen(RT_TABLES_PATH, "r");
+    FILE* fp = fopen(RT_TABLES_PATH, "re");
     if (!fp) {
         printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
         return;
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index d9376e1..9133a34 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -749,6 +749,10 @@
                              (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;
+
     static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
 
     static const char* RUNTIME_ARG = "--runtime-arg";
@@ -813,6 +817,9 @@
     } else if (vm_safe_mode) {
         strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only");
         have_dex2oat_compiler_filter_flag = true;
+    } else if (use_jit) {
+        strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-at-runtime");
+        have_dex2oat_compiler_filter_flag = true;
     } else if (have_dex2oat_compiler_filter_flag) {
         sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", dex2oat_compiler_filter_flag);
     }
diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h
index 112c482..cc41bae 100644
--- a/include/gui/BufferItem.h
+++ b/include/gui/BufferItem.h
@@ -20,10 +20,10 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
-#include <gui/IGraphicBufferConsumer.h>
-
 #include <ui/Rect.h>
 
+#include <system/graphics.h>
+
 #include <utils/Flattenable.h>
 #include <utils/StrongPointer.h>
 
@@ -44,9 +44,7 @@
     // The default value of mBuf, used to indicate this doesn't correspond to a slot.
     enum { INVALID_BUFFER_SLOT = -1 };
     BufferItem();
-    BufferItem(const IGraphicBufferConsumer::BufferItem& item);
     ~BufferItem();
-    operator IGraphicBufferConsumer::BufferItem() const;
 
     static const char* scalingModeName(uint32_t scalingMode);
 
diff --git a/include/gui/BufferItemConsumer.h b/include/gui/BufferItemConsumer.h
index 57e121e..930fabf 100644
--- a/include/gui/BufferItemConsumer.h
+++ b/include/gui/BufferItemConsumer.h
@@ -42,8 +42,6 @@
   public:
     typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
 
-    typedef BufferQueue::BufferItem BufferItem;
-
     enum { DEFAULT_MAX_BUFFERS = -1 };
     enum { INVALID_BUFFER_SLOT = BufferQueue::INVALID_BUFFER_SLOT };
     enum { NO_BUFFER_AVAILABLE = BufferQueue::NO_BUFFER_AVAILABLE };
@@ -76,9 +74,7 @@
     //
     // If waitForFence is true, and the acquired BufferItem has a valid fence object,
     // acquireBuffer will wait on the fence with no timeout before returning.
-    status_t acquireBuffer(BufferQueue::BufferItem *item, nsecs_t presentWhen,
-            bool waitForFence = true);
-    status_t acquireBuffer(android::BufferItem* item, nsecs_t presentWhen,
+    status_t acquireBuffer(BufferItem* item, nsecs_t presentWhen,
             bool waitForFence = true);
 
     // Returns an acquired buffer to the queue, allowing it to be reused. Since
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 1188837..721b218 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_GUI_BUFFERQUEUE_H
 #define ANDROID_GUI_BUFFERQUEUE_H
 
+#include <gui/BufferItem.h>
 #include <gui/BufferQueueDefs.h>
 #include <gui/IGraphicBufferConsumer.h>
 #include <gui/IGraphicBufferProducer.h>
@@ -34,7 +35,7 @@
     // Attempts at runtime to increase the number of buffers past this will fail.
     enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };
     // Used as a placeholder slot# when the value isn't pointing to an existing buffer.
-    enum { INVALID_BUFFER_SLOT = IGraphicBufferConsumer::BufferItem::INVALID_BUFFER_SLOT };
+    enum { INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT };
     // Alias to <IGraphicBufferConsumer.h> -- please scope from there in future code!
     enum {
         NO_BUFFER_AVAILABLE = IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
@@ -47,7 +48,6 @@
 
     // for backward source compatibility
     typedef ::android::ConsumerListener ConsumerListener;
-    typedef IGraphicBufferConsumer::BufferItem BufferItem;
 
     // ProxyConsumerListener is a ConsumerListener implementation that keeps a weak
     // reference to the actual consumer object.  It forwards all calls to that
@@ -62,7 +62,7 @@
     public:
         ProxyConsumerListener(const wp<ConsumerListener>& consumerListener);
         virtual ~ProxyConsumerListener();
-        virtual void onFrameAvailable(const android::BufferItem& item);
+        virtual void onFrameAvailable(const BufferItem& item);
         virtual void onBuffersReleased();
         virtual void onSidebandStreamChanged();
     private:
diff --git a/include/gui/BufferQueueConsumer.h b/include/gui/BufferQueueConsumer.h
index 92127c1..9c91fc7 100644
--- a/include/gui/BufferQueueConsumer.h
+++ b/include/gui/BufferQueueConsumer.h
@@ -48,8 +48,6 @@
     // is CLOCK_MONOTONIC.
     virtual status_t acquireBuffer(BufferItem* outBuffer,
             nsecs_t expectedPresent);
-    virtual status_t acquireBuffer(android::BufferItem* outBuffer,
-            nsecs_t expectedPresent);
 
     // See IGraphicBufferConsumer::detachBuffer
     virtual status_t detachBuffer(int slot);
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index 797a108..40026bd 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_GUI_BUFFERQUEUECORE_H
 #define ANDROID_GUI_BUFFERQUEUECORE_H
 
+#include <gui/BufferItem.h>
 #include <gui/BufferQueueDefs.h>
 #include <gui/BufferSlot.h>
 
@@ -45,7 +46,6 @@
 
 namespace android {
 
-class BufferItem;
 class IConsumerListener;
 class IGraphicBufferAlloc;
 class IProducerListener;
@@ -58,7 +58,7 @@
 public:
     // Used as a placeholder slot number when the value isn't pointing to an
     // existing buffer.
-    enum { INVALID_BUFFER_SLOT = -1 }; // TODO: Extract from IGBC::BufferItem
+    enum { INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT };
 
     // We reserve two slots in order to guarantee that the producer and
     // consumer can run asynchronously.
diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h
index 46ad20e..ef0feab 100644
--- a/include/gui/ConsumerBase.h
+++ b/include/gui/ConsumerBase.h
@@ -154,7 +154,6 @@
     // to a slot.  If it is overridden the derived class's implementation must
     // call ConsumerBase::acquireBufferLocked.
     virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen);
-    virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item, nsecs_t presentWhen);
 
     // releaseBufferLocked relinquishes control over a buffer, returning that
     // control to the BufferQueue.
diff --git a/include/gui/CpuConsumer.h b/include/gui/CpuConsumer.h
index c99ab29..0e3e1ec 100644
--- a/include/gui/CpuConsumer.h
+++ b/include/gui/CpuConsumer.h
@@ -114,6 +114,20 @@
     // lockNextBuffer.
     status_t unlockBuffer(const LockedBuffer &nativeBuffer);
 
+    // Gets the next buffer from the producer (if any), and transfers ownership
+    // of it from the queue to the caller.
+    //
+    // See IGraphicBufferConsumer::{acquireBuffer,detachBuffer} for possible
+    // error codes.
+    status_t detachNextBuffer(BufferItem* outItem);
+
+    // Transfers ownership of the buffer from the caller to the queue, and
+    // releases the buffer for use by the producer.
+    //
+    // See IGraphicBufferConsumer::{attachBuffer,releaseBuffer} for possible
+    // error codes.
+    status_t attachAndReleaseBuffer(const sp<GraphicBuffer>& buffer);
+
   private:
     // Maximum number of buffers that can be locked at a time
     size_t mMaxLockedBuffers;
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index 167ef20..4912580 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -242,7 +242,6 @@
     // acquireBufferLocked overrides the ConsumerBase method to update the
     // mEglSlots array in addition to the ConsumerBase behavior.
     virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen);
-    virtual status_t acquireBufferLocked(IGraphicBufferConsumer::BufferItem *item, nsecs_t presentWhen);
 
     // releaseBufferLocked overrides the ConsumerBase method to update the
     // mEglSlots array in addition to the ConsumerBase.
@@ -260,7 +259,7 @@
     // This releases the buffer in the slot referenced by mCurrentTexture,
     // then updates state to refer to the BufferItem, which must be a
     // newly-acquired buffer.
-    status_t updateAndReleaseLocked(const BufferQueue::BufferItem& item);
+    status_t updateAndReleaseLocked(const BufferItem& item);
 
     // Binds mTexName and the current buffer to mTexTarget.  Uses
     // mCurrentTexture if it's set, mCurrentTextureImage if not.  If the
diff --git a/include/gui/IGraphicBufferConsumer.h b/include/gui/IGraphicBufferConsumer.h
index ae85bd5..8f31b55 100644
--- a/include/gui/IGraphicBufferConsumer.h
+++ b/include/gui/IGraphicBufferConsumer.h
@@ -43,75 +43,6 @@
 class IGraphicBufferConsumer : public IInterface {
 
 public:
-
-    // public facing structure for BufferSlot
-    class BufferItem : public Flattenable<BufferItem> {
-        friend class Flattenable<BufferItem>;
-        size_t getPodSize() const;
-        size_t getFlattenedSize() const;
-        size_t getFdCount() const;
-        status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
-        status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
-
-    public:
-        // The default value of mBuf, used to indicate this doesn't correspond to a slot.
-        enum { INVALID_BUFFER_SLOT = -1 };
-        BufferItem();
-
-        // mGraphicBuffer points to the buffer allocated for this slot, or is NULL
-        // if the buffer in this slot has been acquired in the past (see
-        // BufferSlot.mAcquireCalled).
-        sp<GraphicBuffer> mGraphicBuffer;
-
-        // mFence is a fence that will signal when the buffer is idle.
-        sp<Fence> mFence;
-
-        // mCrop is the current crop rectangle for this buffer slot.
-        Rect mCrop;
-
-        // mTransform is the current transform flags for this buffer slot.
-        // refer to NATIVE_WINDOW_TRANSFORM_* in <window.h>
-        uint32_t mTransform;
-
-        // mScalingMode is the current scaling mode for this buffer slot.
-        // refer to NATIVE_WINDOW_SCALING_* in <window.h>
-        uint32_t mScalingMode;
-
-        // mTimestamp is the current timestamp for this buffer slot. This gets
-        // to set by queueBuffer each time this slot is queued. This value
-        // is guaranteed to be monotonically increasing for each newly
-        // acquired buffer.
-        int64_t mTimestamp;
-
-        // mIsAutoTimestamp indicates whether mTimestamp was generated
-        // automatically when the buffer was queued.
-        bool mIsAutoTimestamp;
-
-        // mDataSpace is the current dataSpace for this buffer slot. This gets
-        // set by queueBuffer each time this slot is queued.
-        android_dataspace mDataSpace;
-
-        // mFrameNumber is the number of the queued frame for this slot.
-        uint64_t mFrameNumber;
-
-        // mBuf is the slot index of this buffer (default INVALID_BUFFER_SLOT).
-        int mBuf;
-
-        // mIsDroppable whether this buffer was queued with the
-        // property that it can be replaced by a new buffer for the purpose of
-        // making sure dequeueBuffer() won't block.
-        // i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer
-        // was queued.
-        bool mIsDroppable;
-
-        // Indicates whether this buffer has been seen by a consumer yet
-        bool mAcquireCalled;
-
-        // Indicates this buffer must be transformed by the inverse transform of the screen
-        // it is displayed onto. This is applied after mTransform.
-        bool mTransformToDisplayInverse;
-    };
-
     enum {
         // Returned by releaseBuffer, after which the consumer must
         // free any references to the just-released buffer that it might have.
@@ -148,7 +79,6 @@
     // Return of a negative value means an error has occurred:
     // * INVALID_OPERATION - too many buffers have been acquired
     virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen) = 0;
-    virtual status_t acquireBuffer(android::BufferItem* buffer, nsecs_t presentWhen) = 0;
 
     // detachBuffer attempts to remove all ownership of the buffer in the given
     // slot from the buffer queue. If this call succeeds, the slot will be
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 40e2fc1..e973483 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -158,7 +158,6 @@
 
     virtual int lockBuffer_DEPRECATED(ANativeWindowBuffer* buffer);
 
-    virtual int connect(int api, const sp<IProducerListener>& listener);
     virtual int connect(int api);
     virtual int disconnect(int api);
     virtual int setBufferCount(int bufferCount);
@@ -177,6 +176,11 @@
     virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
     virtual int unlockAndPost();
 
+    virtual int connect(int api, const sp<IProducerListener>& listener);
+    virtual int detachNextBuffer(ANativeWindowBuffer** outBuffer,
+            sp<Fence>* outFence);
+    virtual int attachBuffer(ANativeWindowBuffer*);
+
 protected:
     enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS };
     enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index 389d867..312fb3b 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -37,41 +37,8 @@
     mCrop.makeInvalid();
 }
 
-BufferItem::BufferItem(const IGraphicBufferConsumer::BufferItem& item) :
-    mGraphicBuffer(item.mGraphicBuffer),
-    mFence(item.mFence),
-    mCrop(item.mCrop),
-    mTransform(item.mTransform),
-    mScalingMode(item.mScalingMode),
-    mTimestamp(item.mTimestamp),
-    mIsAutoTimestamp(item.mIsAutoTimestamp),
-    mDataSpace(item.mDataSpace),
-    mFrameNumber(item.mFrameNumber),
-    mSlot(item.mBuf),
-    mIsDroppable(item.mIsDroppable),
-    mAcquireCalled(item.mAcquireCalled),
-    mTransformToDisplayInverse(item.mTransformToDisplayInverse) {}
-
 BufferItem::~BufferItem() {}
 
-BufferItem::operator IGraphicBufferConsumer::BufferItem() const {
-    IGraphicBufferConsumer::BufferItem bufferItem;
-    bufferItem.mGraphicBuffer = mGraphicBuffer;
-    bufferItem.mFence = mFence;
-    bufferItem.mCrop = mCrop;
-    bufferItem.mTransform = mTransform;
-    bufferItem.mScalingMode = mScalingMode;
-    bufferItem.mTimestamp = mTimestamp;
-    bufferItem.mIsAutoTimestamp = mIsAutoTimestamp;
-    bufferItem.mDataSpace = mDataSpace;
-    bufferItem.mFrameNumber = mFrameNumber;
-    bufferItem.mBuf = mSlot;
-    bufferItem.mIsDroppable = mIsDroppable;
-    bufferItem.mAcquireCalled = mAcquireCalled;
-    bufferItem.mTransformToDisplayInverse = mTransformToDisplayInverse;
-    return bufferItem;
-}
-
 size_t BufferItem::getPodSize() const {
     size_t c =  sizeof(mCrop) +
             sizeof(mTransform) +
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index fb978dd..194121f 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -53,7 +53,7 @@
     mConsumer->setConsumerName(name);
 }
 
-status_t BufferItemConsumer::acquireBuffer(BufferQueue::BufferItem *item,
+status_t BufferItemConsumer::acquireBuffer(BufferItem *item,
         nsecs_t presentWhen, bool waitForFence) {
     status_t err;
 
@@ -83,17 +83,6 @@
     return OK;
 }
 
-status_t BufferItemConsumer::acquireBuffer(android::BufferItem* outItem,
-        nsecs_t presentWhen, bool waitForFence) {
-    BufferQueue::BufferItem item;
-    status_t result = acquireBuffer(&item, presentWhen, waitForFence);
-    if (result != NO_ERROR) {
-        return result;
-    }
-    *outItem = item;
-    return NO_ERROR;
-}
-
 status_t BufferItemConsumer::releaseBuffer(const BufferItem &item,
         const sp<Fence>& releaseFence) {
     status_t err;
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 61fd8c4..2fcbaf2 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -32,7 +32,7 @@
 BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
 
 void BufferQueue::ProxyConsumerListener::onFrameAvailable(
-        const android::BufferItem& item) {
+        const BufferItem& item) {
     sp<ConsumerListener> listener(mConsumerListener.promote());
     if (listener != NULL) {
         listener->onFrameAvailable(item);
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 821a744..c7faeeb 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -176,22 +176,6 @@
     return NO_ERROR;
 }
 
-status_t BufferQueueConsumer::acquireBuffer(android::BufferItem* outBuffer,
-        nsecs_t expectedPresent) {
-    if (outBuffer == nullptr) {
-        return BAD_VALUE;
-    }
-
-    BufferItem item;
-    status_t result = acquireBuffer(&item, expectedPresent);
-    if (result != NO_ERROR) {
-        return result;
-    }
-
-    *outBuffer = item;
-    return NO_ERROR;
-}
-
 status_t BufferQueueConsumer::detachBuffer(int slot) {
     ATRACE_CALL();
     ATRACE_BUFFER_INDEX(slot);
@@ -263,12 +247,16 @@
     ATRACE_BUFFER_INDEX(*outSlot);
     BQ_LOGV("attachBuffer(C): returning slot %d", *outSlot);
 
+    // If these are modified, they also need to be modified in
+    // CpuConsumer::attachAndReleaseBuffer
     mSlots[*outSlot].mGraphicBuffer = buffer;
+    mSlots[*outSlot].mFence = Fence::NO_FENCE;
+    mSlots[*outSlot].mFrameNumber = 0;
+
+    // Changes to these do not need to be propagated to CpuConsumer
     mSlots[*outSlot].mBufferState = BufferSlot::ACQUIRED;
     mSlots[*outSlot].mAttachedByConsumer = true;
     mSlots[*outSlot].mNeedsCleanupOnRelease = false;
-    mSlots[*outSlot].mFence = Fence::NO_FENCE;
-    mSlots[*outSlot].mFrameNumber = 0;
 
     // mAcquireCalled tells BufferQueue that it doesn't need to send a valid
     // GraphicBuffer pointer on the next acquireBuffer call, which decreases
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index c8b5d0c..b874e3a 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -200,17 +200,6 @@
     return OK;
 }
 
-status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *outItem,
-        nsecs_t presentWhen) {
-    BufferItem item;
-    status_t result = acquireBufferLocked(&item, presentWhen);
-    if (result != NO_ERROR) {
-        return result;
-    }
-    *outItem = item;
-    return NO_ERROR;
-}
-
 status_t ConsumerBase::addReleaseFence(int slot,
         const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
     Mutex::Autolock lock(mMutex);
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index eb39469..1f9c657 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -277,4 +277,59 @@
     ConsumerBase::freeBufferLocked(slotIndex);
 }
 
+status_t CpuConsumer::detachNextBuffer(BufferItem* outItem) {
+    if (outItem == NULL) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mMutex);
+
+    BufferItem item;
+    status_t result = acquireBufferLocked(&item, 0);
+    if (result != NO_ERROR) {
+        CC_LOGE("%s: Failed to acquire buffer (%d)", __FUNCTION__, result);
+        return result;
+    }
+
+    result = mConsumer->detachBuffer(item.mSlot);
+    if (result != NO_ERROR) {
+        CC_LOGE("%s: Failed to detach buffer (%d)", __FUNCTION__, result);
+        return result;
+    }
+
+    freeBufferLocked(item.mSlot);
+
+    *outItem = item;
+    return NO_ERROR;
+}
+
+status_t CpuConsumer::attachAndReleaseBuffer(const sp<GraphicBuffer>& buffer) {
+    if (buffer == NULL) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mMutex);
+
+    int slot = -1;
+    status_t result = mConsumer->attachBuffer(&slot, buffer);
+    if (result != NO_ERROR) {
+        CC_LOGE("%s: Failed to attach buffer (%d)", __FUNCTION__, result);
+        return result;
+    }
+
+    // These behaviors must be kept in sync with
+    // BufferQueueConsumer::attachBuffer
+    mSlots[slot].mGraphicBuffer = buffer;
+    mSlots[slot].mFence = Fence::NO_FENCE;
+    mSlots[slot].mFrameNumber = 0;
+
+    result = releaseBufferLocked(slot, buffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
+    if (result != NO_ERROR) {
+        CC_LOGE("%s: Failed to release buffer (%d)", __FUNCTION__, result);
+        return result;
+    }
+
+    return NO_ERROR;
+}
+
 } // namespace android
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index d256ae5..96c0841 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -361,17 +361,6 @@
     return NO_ERROR;
 }
 
-status_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *outItem,
-        nsecs_t presentWhen) {
-    BufferItem item;
-    status_t result = acquireBufferLocked(&item, presentWhen);
-    if (result != NO_ERROR) {
-        return result;
-    }
-    *outItem = item;
-    return NO_ERROR;
-}
-
 status_t GLConsumer::releaseBufferLocked(int buf,
         sp<GraphicBuffer> graphicBuffer,
         EGLDisplay display, EGLSyncKHR eglFence) {
@@ -385,7 +374,7 @@
     return err;
 }
 
-status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item)
+status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item)
 {
     status_t err = NO_ERROR;
 
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index edf4408..3f23c2f 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -33,163 +33,6 @@
 #include <system/window.h>
 
 namespace android {
-// ---------------------------------------------------------------------------
-
-IGraphicBufferConsumer::BufferItem::BufferItem() :
-    mTransform(0),
-    mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
-    mTimestamp(0),
-    mIsAutoTimestamp(false),
-    mDataSpace(HAL_DATASPACE_UNKNOWN),
-    mFrameNumber(0),
-    mBuf(INVALID_BUFFER_SLOT),
-    mIsDroppable(false),
-    mAcquireCalled(false),
-    mTransformToDisplayInverse(false) {
-    mCrop.makeInvalid();
-}
-
-size_t IGraphicBufferConsumer::BufferItem::getPodSize() const {
-    size_t c =  sizeof(mCrop) +
-            sizeof(mTransform) +
-            sizeof(mScalingMode) +
-            sizeof(mTimestamp) +
-            sizeof(mIsAutoTimestamp) +
-            sizeof(mDataSpace) +
-            sizeof(mFrameNumber) +
-            sizeof(mBuf) +
-            sizeof(mIsDroppable) +
-            sizeof(mAcquireCalled) +
-            sizeof(mTransformToDisplayInverse);
-    return c;
-}
-
-size_t IGraphicBufferConsumer::BufferItem::getFlattenedSize() const {
-    size_t c = 0;
-    if (mGraphicBuffer != 0) {
-        c += mGraphicBuffer->getFlattenedSize();
-        c = FlattenableUtils::align<4>(c);
-    }
-    if (mFence != 0) {
-        c += mFence->getFlattenedSize();
-        c = FlattenableUtils::align<4>(c);
-    }
-    return sizeof(int32_t) + c + getPodSize();
-}
-
-size_t IGraphicBufferConsumer::BufferItem::getFdCount() const {
-    size_t c = 0;
-    if (mGraphicBuffer != 0) {
-        c += mGraphicBuffer->getFdCount();
-    }
-    if (mFence != 0) {
-        c += mFence->getFdCount();
-    }
-    return c;
-}
-
-static void writeBoolAsInt(void*& buffer, size_t& size, bool b) {
-    FlattenableUtils::write(buffer, size, static_cast<int32_t>(b));
-}
-
-static bool readBoolFromInt(void const*& buffer, size_t& size) {
-    int32_t i;
-    FlattenableUtils::read(buffer, size, i);
-    return static_cast<bool>(i);
-}
-
-status_t IGraphicBufferConsumer::BufferItem::flatten(
-        void*& buffer, size_t& size, int*& fds, size_t& count) const {
-
-    // make sure we have enough space
-    if (size < BufferItem::getFlattenedSize()) {
-        return NO_MEMORY;
-    }
-
-    // content flags are stored first
-    uint32_t& flags = *static_cast<uint32_t*>(buffer);
-
-    // advance the pointer
-    FlattenableUtils::advance(buffer, size, sizeof(uint32_t));
-
-    flags = 0;
-    if (mGraphicBuffer != 0) {
-        status_t err = mGraphicBuffer->flatten(buffer, size, fds, count);
-        if (err) return err;
-        size -= FlattenableUtils::align<4>(buffer);
-        flags |= 1;
-    }
-    if (mFence != 0) {
-        status_t err = mFence->flatten(buffer, size, fds, count);
-        if (err) return err;
-        size -= FlattenableUtils::align<4>(buffer);
-        flags |= 2;
-    }
-
-    // check we have enough space (in case flattening the fence/graphicbuffer lied to us)
-    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);
-    writeBoolAsInt(buffer, size, mIsAutoTimestamp);
-    FlattenableUtils::write(buffer, size, mDataSpace);
-    FlattenableUtils::write(buffer, size, mFrameNumber);
-    FlattenableUtils::write(buffer, size, mBuf);
-    writeBoolAsInt(buffer, size, mIsDroppable);
-    writeBoolAsInt(buffer, size, mAcquireCalled);
-    writeBoolAsInt(buffer, size, mTransformToDisplayInverse);
-
-    return NO_ERROR;
-}
-
-status_t IGraphicBufferConsumer::BufferItem::unflatten(
-        void const*& buffer, size_t& size, int const*& fds, size_t& count) {
-
-    if (size < sizeof(uint32_t))
-        return NO_MEMORY;
-
-    uint32_t flags = 0;
-    FlattenableUtils::read(buffer, size, flags);
-
-    if (flags & 1) {
-        mGraphicBuffer = new GraphicBuffer();
-        status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count);
-        if (err) return err;
-        size -= FlattenableUtils::align<4>(buffer);
-    }
-
-    if (flags & 2) {
-        mFence = new Fence();
-        status_t err = mFence->unflatten(buffer, size, fds, count);
-        if (err) return err;
-        size -= FlattenableUtils::align<4>(buffer);
-    }
-
-    // check we 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);
-    mIsAutoTimestamp = readBoolFromInt(buffer, size);
-    FlattenableUtils::read(buffer, size, mDataSpace);
-    FlattenableUtils::read(buffer, size, mFrameNumber);
-    FlattenableUtils::read(buffer, size, mBuf);
-    mIsDroppable = readBoolFromInt(buffer, size);
-    mAcquireCalled = readBoolFromInt(buffer, size);
-    mTransformToDisplayInverse = readBoolFromInt(buffer, size);
-
-    return NO_ERROR;
-}
-
-// ---------------------------------------------------------------------------
 
 enum {
     ACQUIRE_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
@@ -238,21 +81,6 @@
         return reply.readInt32();
     }
 
-    virtual status_t acquireBuffer(android::BufferItem* buffer,
-            nsecs_t presentWhen) {
-        if (buffer == nullptr) {
-            return BAD_VALUE;
-        }
-
-        BufferItem item;
-        status_t result = acquireBuffer(&item, presentWhen);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        *buffer = item;
-        return NO_ERROR;
-    }
-
     virtual status_t detachBuffer(int slot) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index aa6f97e..b80890f 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -610,6 +610,55 @@
     return err;
 }
 
+int Surface::detachNextBuffer(ANativeWindowBuffer** outBuffer,
+        sp<Fence>* outFence) {
+    ATRACE_CALL();
+    ALOGV("Surface::detachNextBuffer");
+
+    if (outBuffer == NULL || outFence == NULL) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mMutex);
+
+    sp<GraphicBuffer> buffer(NULL);
+    sp<Fence> fence(NULL);
+    status_t result = mGraphicBufferProducer->detachNextBuffer(
+            &buffer, &fence);
+    if (result != NO_ERROR) {
+        return result;
+    }
+
+    *outBuffer = buffer.get();
+    if (fence != NULL && fence->isValid()) {
+        *outFence = fence;
+    } else {
+        *outFence = Fence::NO_FENCE;
+    }
+
+    return NO_ERROR;
+}
+
+int Surface::attachBuffer(ANativeWindowBuffer* buffer)
+{
+    ATRACE_CALL();
+    ALOGV("Surface::attachBuffer");
+
+    Mutex::Autolock lock(mMutex);
+
+    sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));
+    int32_t attachedSlot = -1;
+    status_t result = mGraphicBufferProducer->attachBuffer(
+            &attachedSlot, graphicBuffer);
+    if (result != NO_ERROR) {
+        ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result);
+        return result;
+    }
+    mSlots[attachedSlot].buffer = graphicBuffer;
+
+    return NO_ERROR;
+}
+
 int Surface::setUsage(uint32_t reqUsage)
 {
     ALOGV("Surface::setUsage");