Merge changes I66085c30,Ic9b3be9f,Icc6b23ab,I359a9511,I11a7394e,Ic8bcd03e,I40834d6f,I02a1548a,I638a36b0,I814befe2,Iaaef7d53,I349575e5,I0b5acc78,I6fad8803 into jb-mr2-dev

* changes:
  Subclass GLES30 from GLES20, @Deprecate GL_STENCIL_INDEX
  Special-case glGetActiveUniformBlockName
  Special-case glGetStringi
  Special-case glMapBufferRange
  Special-case glGetBufferPointerv
  Special-case glGetUniformIndices
  Special-case glGetTransformFeedbackVarying
  Special-case glTransformFeedbackVaryings
  Add buffer object versions of several functions
  Add *int64 and GLsync types and related functions
  Add ES3 functions and constants, difficult ones commented out
  Support "const GLChar*" and "const GLenum*" types
  Minor changes to ES3 functions inherited from ES2
  Generate GLES30 class, just a clone of GLES20 for now
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 76ba81f..06e9744 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -80,6 +80,7 @@
     { "video",      "Video",            ATRACE_TAG_VIDEO, { } },
     { "camera",     "Camera",           ATRACE_TAG_CAMERA, { } },
     { "hal",        "Hardware Modules", ATRACE_TAG_HAL, { } },
+    { "res",        "Resource Loading", ATRACE_TAG_RESOURCES, { } },
     { "sched",      "CPU Scheduling",   0, {
         { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
         { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 6a86db6..6c1b691 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -48,7 +48,7 @@
     // ConsumerListener is the interface through which the BufferQueue notifies
     // the consumer of events that the consumer may wish to react to.  Because
     // the consumer will generally have a mutex that is locked during calls from
-    // teh consumer to the BufferQueue, these calls from the BufferQueue to the
+    // the consumer to the BufferQueue, these calls from the BufferQueue to the
     // consumer *MUST* be called only when the BufferQueue mutex is NOT locked.
     struct ConsumerListener : public virtual RefBase {
         // onFrameAvailable is called from queueBuffer each time an additional
@@ -104,66 +104,127 @@
             const sp<IGraphicBufferAlloc>& allocator = NULL);
     virtual ~BufferQueue();
 
+    // Query native window attributes.  The "what" values are enumerated in
+    // window.h (e.g. NATIVE_WINDOW_FORMAT).
     virtual int query(int what, int* value);
 
-    // setBufferCount updates the number of available buffer slots.  After
-    // calling this all buffer slots are both unallocated and owned by the
-    // BufferQueue object (i.e. they are not owned by the client).
+    // setBufferCount updates the number of available buffer slots.  If this
+    // method succeeds, buffer slots will be both unallocated and owned by
+    // the BufferQueue object (i.e. they are not owned by the producer or
+    // consumer).
+    //
+    // This will fail if the producer has dequeued any buffers, or if
+    // bufferCount is invalid.  bufferCount must generally be a value
+    // between the minimum undequeued buffer count and NUM_BUFFER_SLOTS
+    // (inclusive).  It may also be set to zero (the default) to indicate
+    // that the producer does not wish to set a value.  The minimum value
+    // can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+    // ...).
+    //
+    // This may only be called by the producer.  The consumer will be told
+    // to discard buffers through the onBuffersReleased callback.
     virtual status_t setBufferCount(int bufferCount);
 
+    // requestBuffer returns the GraphicBuffer for slot N.
+    //
+    // In normal operation, this is called the first time slot N is returned
+    // by dequeueBuffer.  It must be called again if dequeueBuffer returns
+    // flags indicating that previously-returned buffers are no longer valid.
     virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
 
-    // dequeueBuffer gets the next buffer slot index for the client to use. If a
-    // buffer slot is available then that slot index is written to the location
-    // pointed to by the buf argument and a status of OK is returned.  If no
-    // slot is available then a status of -EBUSY is returned and buf is
+    // dequeueBuffer gets the next buffer slot index for the producer to use.
+    // If a buffer slot is available then that slot index is written to the
+    // location pointed to by the buf argument and a status of OK is returned.
+    // If no slot is available then a status of -EBUSY is returned and buf is
     // unmodified.
     //
     // The fence parameter will be updated to hold the fence associated with
     // the buffer. The contents of the buffer must not be overwritten until the
-    // fence signals. If the fence is NULL, the buffer may be written
-    // immediately.
+    // fence signals. If the fence is Fence::NO_FENCE, the buffer may be
+    // written immediately.
     //
     // The width and height parameters must be no greater than the minimum of
     // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
     // An error due to invalid dimensions might not be reported until
-    // updateTexImage() is called.
+    // updateTexImage() is called.  If width and height are both zero, the
+    // default values specified by setDefaultBufferSize() are used instead.
+    //
+    // The pixel formats are enumerated in graphics.h, e.g.
+    // HAL_PIXEL_FORMAT_RGBA_8888.  If the format is 0, the default format
+    // will be used.
+    //
+    // The usage argument specifies gralloc buffer usage flags.  The values
+    // are enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER.  These
+    // will be merged with the usage flags specified by setConsumerUsageBits.
+    //
+    // The return value may be a negative error value or a non-negative
+    // collection of flags.  If the flags are set, the return values are
+    // valid, but additional actions must be performed.
+    //
+    // If IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION is set, the
+    // producer must discard cached GraphicBuffer references for the slot
+    // returned in buf.
+    // If IGraphicBufferProducer::RELEASE_ALL_BUFFERS is set, the producer
+    // must discard cached GraphicBuffer references for all slots.
+    //
+    // In both cases, the producer will need to call requestBuffer to get a
+    // GraphicBuffer handle for the returned slot.
     virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence,
             uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
 
-    // queueBuffer returns a filled buffer to the BufferQueue. In addition, a
-    // timestamp must be provided for the buffer. The timestamp is in
+    // queueBuffer returns a filled buffer to the BufferQueue.
+    //
+    // Additional data is provided in the QueueBufferInput struct.  Notably,
+    // a timestamp must be provided for the buffer. The timestamp is in
     // nanoseconds, and must be monotonically increasing. Its other semantics
-    // (zero point, etc) are client-dependent and should be documented by the
-    // client.
+    // (zero point, etc) are producer-specific and should be documented by the
+    // producer.
+    //
+    // The caller may provide a fence that signals when all rendering
+    // operations have completed.  Alternatively, NO_FENCE may be used,
+    // indicating that the buffer is ready immediately.
+    //
+    // Some values are returned in the output struct: the current settings
+    // for default width and height, the current transform hint, and the
+    // number of queued buffers.
     virtual status_t queueBuffer(int buf,
             const QueueBufferInput& input, QueueBufferOutput* output);
 
+    // cancelBuffer returns a dequeued buffer to the BufferQueue, but doesn't
+    // queue it for use by the consumer.
+    //
+    // The buffer will not be overwritten until the fence signals.  The fence
+    // will usually be the one obtained from dequeueBuffer.
     virtual void cancelBuffer(int buf, const sp<Fence>& fence);
 
-    // setSynchronousMode set whether dequeueBuffer is synchronous or
+    // setSynchronousMode sets whether dequeueBuffer is synchronous or
     // asynchronous. In synchronous mode, dequeueBuffer blocks until
     // a buffer is available, the currently bound buffer can be dequeued and
-    // queued buffers will be retired in order.
+    // queued buffers will be acquired in order.  In asynchronous mode,
+    // a queued buffer may be replaced by a subsequently queued buffer.
+    //
     // The default mode is asynchronous.
     virtual status_t setSynchronousMode(bool enabled);
 
-    // connect attempts to connect a producer client API to the BufferQueue.
-    // This must be called before any other IGraphicBufferProducer methods are called
-    // except for getAllocator.
+    // connect attempts to connect a producer API to the BufferQueue.  This
+    // must be called before any other IGraphicBufferProducer methods are
+    // called except for getAllocator.  A consumer must already be connected.
     //
-    // This method will fail if the connect was previously called on the
-    // BufferQueue and no corresponding disconnect call was made.
+    // This method will fail if connect was previously called on the
+    // BufferQueue and no corresponding disconnect call was made (i.e. if
+    // it's still connected to a producer).
+    //
+    // APIs are enumerated in window.h (e.g. NATIVE_WINDOW_API_CPU).
     virtual status_t connect(int api, QueueBufferOutput* output);
 
-    // disconnect attempts to disconnect a producer client API from the
-    // BufferQueue. Calling this method will cause any subsequent calls to other
+    // disconnect attempts to disconnect a producer API from the BufferQueue.
+    // Calling this method will cause any subsequent calls to other
     // IGraphicBufferProducer methods to fail except for getAllocator and connect.
     // Successfully calling connect after this will allow the other methods to
     // succeed again.
     //
     // This method will fail if the the BufferQueue is not currently
-    // connected to the specified client API.
+    // connected to the specified producer API.
     virtual status_t disconnect(int api);
 
     // dump our state in a String
@@ -181,7 +242,7 @@
            mFrameNumber(0),
            mBuf(INVALID_BUFFER_SLOT) {
              mCrop.makeInvalid();
-         }
+        }
         // 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).
@@ -210,7 +271,7 @@
         sp<Fence> mFence;
     };
 
-    // The following public functions is the consumer facing interface
+    // The following public functions are the consumer-facing interface
 
     // acquireBuffer attempts to acquire ownership of the next pending buffer in
     // the BufferQueue.  If no buffer is pending then it returns -EINVAL.  If a
@@ -222,7 +283,9 @@
     status_t acquireBuffer(BufferItem *buffer);
 
     // releaseBuffer releases a buffer slot from the consumer back to the
-    // BufferQueue pending a fence sync.
+    // BufferQueue.  This may be done while the buffer's contents are still
+    // being accessed.  The fence will signal when the buffer is no longer
+    // in use.
     //
     // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free
     // any references to the just-released buffer that it might have, as if it
@@ -238,6 +301,8 @@
     // consumer may be connected, and when that consumer disconnects the
     // BufferQueue is placed into the "abandoned" state, causing most
     // interactions with the BufferQueue by the producer to fail.
+    //
+    // consumer may not be NULL.
     status_t consumerConnect(const sp<ConsumerListener>& consumer);
 
     // consumerDisconnect disconnects a consumer from the BufferQueue. All
@@ -247,22 +312,28 @@
     status_t consumerDisconnect();
 
     // getReleasedBuffers sets the value pointed to by slotMask to a bit mask
-    // indicating which buffer slots the have been released by the BufferQueue
+    // indicating which buffer slots have been released by the BufferQueue
     // but have not yet been released by the consumer.
+    //
+    // This should be called from the onBuffersReleased() callback.
     status_t getReleasedBuffers(uint32_t* slotMask);
 
     // setDefaultBufferSize is used to set the size of buffers returned by
-    // requestBuffers when a with and height of zero is requested.
+    // dequeueBuffer when a width and height of zero is requested.  Default
+    // is 1x1.
     status_t setDefaultBufferSize(uint32_t w, uint32_t h);
 
-    // setDefaultBufferCount set the buffer count. If the client has requested
-    // a buffer count using setBufferCount, the server-buffer count will
-    // take effect once the client sets the count back to zero.
+    // 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.
     status_t setDefaultMaxBufferCount(int bufferCount);
 
     // setMaxAcquiredBufferCount sets the maximum number of buffers that can
-    // be acquired by the consumer at one time.  This call will fail if a
-    // producer is connected to the BufferQueue.
+    // be acquired by the consumer at one time (default 1).  This call will
+    // fail if a producer is connected to the BufferQueue.
     status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
 
     // isSynchronousMode returns whether the BufferQueue is currently in
@@ -274,41 +345,48 @@
 
     // setDefaultBufferFormat allows the BufferQueue to create
     // GraphicBuffers of a defaultFormat if no format is specified
-    // in dequeueBuffer
+    // in dequeueBuffer.  Formats are enumerated in graphics.h; the
+    // initial default is HAL_PIXEL_FORMAT_RGBA_8888.
     status_t setDefaultBufferFormat(uint32_t defaultFormat);
 
-    // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer
+    // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer.
+    // These are merged with the bits passed to dequeueBuffer.  The values are
+    // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
     status_t setConsumerUsageBits(uint32_t usage);
 
-    // setTransformHint bakes in rotation to buffers so overlays can be used
+    // setTransformHint bakes in rotation to buffers so overlays can be used.
+    // The values are enumerated in window.h, e.g.
+    // NATIVE_WINDOW_TRANSFORM_ROT_90.  The default is 0 (no transform).
     status_t setTransformHint(uint32_t hint);
 
 private:
-    // freeBufferLocked frees the resources (both GraphicBuffer and EGLImage)
-    // for the given slot.
+    // freeBufferLocked frees the GraphicBuffer and sync resources for the
+    // given slot.
     void freeBufferLocked(int index);
 
-    // freeAllBuffersLocked frees the resources (both GraphicBuffer and
-    // EGLImage) for all slots.
+    // freeAllBuffersLocked frees the GraphicBuffer and sync resources for
+    // all slots.
     void freeAllBuffersLocked();
 
-    // freeAllBuffersExceptHeadLocked frees the resources (both GraphicBuffer
-    // and EGLImage) for all slots except the head of mQueue
+    // freeAllBuffersExceptHeadLocked frees the GraphicBuffer and sync
+    // resources for all slots except the head of mQueue.
     void freeAllBuffersExceptHeadLocked();
 
-    // drainQueueLocked drains the buffer queue if we're in synchronous mode
-    // returns immediately otherwise. It returns NO_INIT if the BufferQueue
-    // became abandoned or disconnected during this call.
+    // drainQueueLocked waits for the buffer queue to empty if we're in
+    // synchronous mode, or returns immediately otherwise. It returns NO_INIT
+    // if the BufferQueue is abandoned (consumer disconnected) or disconnected
+    // (producer disconnected) during the call.
     status_t drainQueueLocked();
 
     // drainQueueAndFreeBuffersLocked drains the buffer queue if we're in
     // synchronous mode and free all buffers. In asynchronous mode, all buffers
-    // are freed except the current buffer.
+    // are freed except the currently queued buffer (if it exists).
     status_t drainQueueAndFreeBuffersLocked();
 
     // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
     // that will be used if the producer does not override the buffer slot
-    // count.
+    // count.  The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
+    // The initial default is 2.
     status_t setDefaultMaxBufferCountLocked(int count);
 
     // getMinBufferCountLocked returns the minimum number of buffers allowed
@@ -352,51 +430,56 @@
         // if no buffer has been allocated.
         sp<GraphicBuffer> mGraphicBuffer;
 
-        // mEglDisplay is the EGLDisplay used to create mEglImage.
+        // mEglDisplay is the EGLDisplay used to create EGLSyncKHR objects.
         EGLDisplay mEglDisplay;
 
         // BufferState represents the different states in which a buffer slot
-        // can be.
+        // can be.  All slots are initially FREE.
         enum BufferState {
-            // FREE indicates that the buffer is not currently being used and
-            // will not be used in the future until it gets dequeued and
-            // subsequently queued by the client.
-            // aka "owned by BufferQueue, ready to be dequeued"
+            // FREE indicates that the buffer is available to be dequeued
+            // by the producer.  The buffer may be in use by the consumer for
+            // a finite time, so the buffer must not be modified until the
+            // associated fence is signaled.
+            //
+            // The slot is "owned" by BufferQueue.  It transitions to DEQUEUED
+            // when dequeueBuffer is called.
             FREE = 0,
 
             // DEQUEUED indicates that the buffer has been dequeued by the
-            // client, but has not yet been queued or canceled. The buffer is
-            // considered 'owned' by the client, and the server should not use
-            // it for anything.
+            // producer, but has not yet been queued or canceled.  The
+            // producer may modify the buffer's contents as soon as the
+            // associated ready fence is signaled.
             //
-            // Note that when in synchronous-mode (mSynchronousMode == true),
-            // the buffer that's currently attached to the texture may be
-            // dequeued by the client.  That means that the current buffer can
-            // be in either the DEQUEUED or QUEUED state.  In asynchronous mode,
-            // however, the current buffer is always in the QUEUED state.
-            // aka "owned by producer, ready to be queued"
+            // The slot is "owned" by the producer.  It can transition to
+            // QUEUED (via queueBuffer) or back to FREE (via cancelBuffer).
             DEQUEUED = 1,
 
-            // QUEUED indicates that the buffer has been queued by the client,
-            // and has not since been made available for the client to dequeue.
-            // Attaching the buffer to the texture does NOT transition the
-            // buffer away from the QUEUED state. However, in Synchronous mode
-            // the current buffer may be dequeued by the client under some
-            // circumstances. See the note about the current buffer in the
-            // documentation for DEQUEUED.
-            // aka "owned by BufferQueue, ready to be acquired"
+            // QUEUED indicates that the buffer has been filled by the
+            // producer and queued for use by the consumer.  The buffer
+            // contents may continue to be modified for a finite time, so
+            // the contents must not be accessed until the associated fence
+            // is signaled.
+            //
+            // The slot is "owned" by BufferQueue.  It can transition to
+            // ACQUIRED (via acquireBuffer) or to FREE (if another buffer is
+            // queued in asynchronous mode).
             QUEUED = 2,
 
-            // aka "owned by consumer, ready to be released"
+            // ACQUIRED indicates that the buffer has been acquired by the
+            // consumer.  As with QUEUED, the contents must not be accessed
+            // by the consumer until the fence is signaled.
+            //
+            // The slot is "owned" by the consumer.  It transitions to FREE
+            // when releaseBuffer is called.
             ACQUIRED = 3
         };
 
         // mBufferState is the current state of this buffer slot.
         BufferState mBufferState;
 
-        // mRequestBufferCalled is used for validating that the client did
+        // mRequestBufferCalled is used for validating that the producer did
         // call requestBuffer() when told to do so. Technically this is not
-        // needed but useful for debugging and catching client bugs.
+        // needed but useful for debugging and catching producer bugs.
         bool mRequestBufferCalled;
 
         // mCrop is the current crop rectangle for this buffer slot.
@@ -414,13 +497,16 @@
         // to set by queueBuffer each time this slot is queued.
         int64_t mTimestamp;
 
-        // mFrameNumber is the number of the queued frame for this slot.
+        // mFrameNumber is the number of the queued frame for this slot.  This
+        // is used to dequeue buffers in LRU order (useful because buffers
+        // may be released before their release fence is signaled).
         uint64_t mFrameNumber;
 
         // mEglFence is the EGL sync object that must signal before the buffer
         // associated with this buffer slot may be dequeued. It is initialized
-        // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
-        // on a compile-time option) set to a new sync object in updateTexImage.
+        // to EGL_NO_SYNC_KHR when the buffer is created and may be set to a
+        // new sync object in releaseBuffer.  (This is deprecated in favor of
+        // mFence, below.)
         EGLSyncKHR mEglFence;
 
         // mFence is a fence which will signal when work initiated by the
@@ -431,29 +517,32 @@
         // QUEUED, it indicates when the producer has finished filling the
         // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been
         // passed to the consumer or producer along with ownership of the
-        // buffer, and mFence is empty.
+        // buffer, and mFence is set to NO_FENCE.
         sp<Fence> mFence;
 
         // Indicates whether this buffer has been seen by a consumer yet
         bool mAcquireCalled;
 
-        // Indicates whether this buffer needs to be cleaned up by consumer
+        // Indicates whether this buffer needs to be cleaned up by the
+        // consumer.  This is set when a buffer in ACQUIRED state is freed.
+        // It causes releaseBuffer to return STALE_BUFFER_SLOT.
         bool mNeedsCleanupOnRelease;
     };
 
-    // mSlots is the array of buffer slots that must be mirrored on the client
-    // side. This allows buffer ownership to be transferred between the client
-    // and server without sending a GraphicBuffer over binder. The entire array
-    // is initialized to NULL at construction time, and buffers are allocated
-    // for a slot when requestBuffer is called with that slot's index.
+    // mSlots is the array of buffer slots that must be mirrored on the
+    // producer side. This allows buffer ownership to be transferred between
+    // the producer and consumer without sending a GraphicBuffer over binder.
+    // The entire array is initialized to NULL at construction time, and
+    // buffers are allocated for a slot when requestBuffer is called with
+    // that slot's index.
     BufferSlot mSlots[NUM_BUFFER_SLOTS];
 
     // mDefaultWidth holds the default width of allocated buffers. It is used
-    // in requestBuffers() if a width and height of zero is specified.
+    // in dequeueBuffer() if a width and height of zero is specified.
     uint32_t mDefaultWidth;
 
     // mDefaultHeight holds the default height of allocated buffers. It is used
-    // in requestBuffers() if a width and height of zero is specified.
+    // in dequeueBuffer() if a width and height of zero is specified.
     uint32_t mDefaultHeight;
 
     // mMaxAcquiredBufferCount is the number of buffers that the consumer may
@@ -490,12 +579,13 @@
     // mSynchronousMode whether we're in synchronous mode or not
     bool mSynchronousMode;
 
-    // mAllowSynchronousMode whether we allow synchronous mode or not
+    // mAllowSynchronousMode whether we allow synchronous mode or not.  Set
+    // when the BufferQueue is created (by the consumer).
     const bool mAllowSynchronousMode;
 
-    // mConnectedApi indicates the API that is currently connected to this
-    // BufferQueue.  It defaults to NO_CONNECTED_API (= 0), and gets updated
-    // by the connect and disconnect methods.
+    // mConnectedApi indicates the producer API that is currently connected
+    // to this BufferQueue.  It defaults to NO_CONNECTED_API (= 0), and gets
+    // updated by the connect and disconnect methods.
     int mConnectedApi;
 
     // mDequeueCondition condition used for dequeueBuffer in synchronous mode
@@ -506,14 +596,15 @@
     Fifo mQueue;
 
     // mAbandoned indicates that the BufferQueue will no longer be used to
-    // consume images buffers pushed to it using the IGraphicBufferProducer interface.
-    // It is initialized to false, and set to true in the abandon method.  A
-    // BufferQueue that has been abandoned will return the NO_INIT error from
-    // all IGraphicBufferProducer methods capable of returning an error.
+    // consume image buffers pushed to it using the IGraphicBufferProducer
+    // interface.  It is initialized to false, and set to true in the
+    // consumerDisconnect method.  A BufferQueue that has been abandoned will
+    // return the NO_INIT error from all IGraphicBufferProducer methods
+    // capable of returning an error.
     bool mAbandoned;
 
-    // mName is a string used to identify the BufferQueue in log messages.
-    // It is set by the setName method.
+    // mConsumerName is a string used to identify the BufferQueue in log
+    // messages.  It is set by the setConsumerName method.
     String8 mConsumerName;
 
     // mMutex is the mutex used to prevent concurrent access to the member
@@ -521,12 +612,13 @@
     // member variables are accessed.
     mutable Mutex mMutex;
 
-    // mFrameCounter is the free running counter, incremented for every buffer queued
-    // with the surface Texture.
+    // mFrameCounter is the free running counter, incremented on every
+    // successful queueBuffer call.
     uint64_t mFrameCounter;
 
-    // mBufferHasBeenQueued is true once a buffer has been queued.  It is reset
-    // by changing the buffer count.
+    // 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).
     bool mBufferHasBeenQueued;
 
     // mDefaultBufferFormat can be set so it will override
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 75a0296..b4c7231 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -106,7 +106,7 @@
     mDefaultMaxBufferCount = count;
     mDequeueCondition.broadcast();
 
-    return OK;
+    return NO_ERROR;
 }
 
 bool BufferQueue::isSynchronousMode() const {
@@ -122,20 +122,20 @@
 status_t BufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) {
     Mutex::Autolock lock(mMutex);
     mDefaultBufferFormat = defaultFormat;
-    return OK;
+    return NO_ERROR;
 }
 
 status_t BufferQueue::setConsumerUsageBits(uint32_t usage) {
     Mutex::Autolock lock(mMutex);
     mConsumerUsageBits = usage;
-    return OK;
+    return NO_ERROR;
 }
 
 status_t BufferQueue::setTransformHint(uint32_t hint) {
     ST_LOGV("setTransformHint: %02x", hint);
     Mutex::Autolock lock(mMutex);
     mTransformHint = hint;
-    return OK;
+    return NO_ERROR;
 }
 
 status_t BufferQueue::setBufferCount(int bufferCount) {
@@ -150,7 +150,8 @@
             return NO_INIT;
         }
         if (bufferCount > NUM_BUFFER_SLOTS) {
-            ST_LOGE("setBufferCount: bufferCount larger than slots available");
+            ST_LOGE("setBufferCount: bufferCount too large (max %d)",
+                    NUM_BUFFER_SLOTS);
             return BAD_VALUE;
         }
 
@@ -167,7 +168,7 @@
         if (bufferCount == 0) {
             mOverrideMaxBufferCount = 0;
             mDequeueCondition.broadcast();
-            return OK;
+            return NO_ERROR;
         }
 
         if (bufferCount < minBufferSlots) {
@@ -191,7 +192,7 @@
         listener->onBuffersReleased();
     }
 
-    return OK;
+    return NO_ERROR;
 }
 
 int BufferQueue::query(int what, int* outValue)
@@ -587,7 +588,7 @@
     if (listener != 0) {
         listener->onFrameAvailable();
     }
-    return OK;
+    return NO_ERROR;
 }
 
 void BufferQueue::cancelBuffer(int buf, const sp<Fence>& fence) {
@@ -858,7 +859,7 @@
         return NO_BUFFER_AVAILABLE;
     }
 
-    return OK;
+    return NO_ERROR;
 }
 
 status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,
@@ -889,7 +890,7 @@
     }
 
     mDequeueCondition.broadcast();
-    return OK;
+    return NO_ERROR;
 }
 
 status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) {
@@ -900,10 +901,14 @@
         ST_LOGE("consumerConnect: BufferQueue has been abandoned!");
         return NO_INIT;
     }
+    if (consumerListener == NULL) {
+        ST_LOGE("consumerConnect: consumerListener may not be NULL");
+        return BAD_VALUE;
+    }
 
     mConsumerListener = consumerListener;
 
-    return OK;
+    return NO_ERROR;
 }
 
 status_t BufferQueue::consumerDisconnect() {
@@ -920,7 +925,7 @@
     mQueue.clear();
     freeAllBuffersLocked();
     mDequeueCondition.broadcast();
-    return OK;
+    return NO_ERROR;
 }
 
 status_t BufferQueue::getReleasedBuffers(uint32_t* slotMask) {
@@ -956,7 +961,7 @@
     Mutex::Autolock lock(mMutex);
     mDefaultWidth = w;
     mDefaultHeight = h;
-    return OK;
+    return NO_ERROR;
 }
 
 status_t BufferQueue::setDefaultMaxBufferCount(int bufferCount) {
@@ -977,7 +982,7 @@
         return INVALID_OPERATION;
     }
     mMaxAcquiredBufferCount = maxAcquiredBuffers;
-    return OK;
+    return NO_ERROR;
 }
 
 void BufferQueue::freeAllBuffersExceptHeadLocked() {
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index a1de3c5..dd698c5 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -20,6 +20,7 @@
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 	libhardware \
+	libhardware_legacy \
 	libutils \
 	liblog \
 	libbinder \
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index a9e3ef4..b256cce 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -181,6 +181,12 @@
     return mSensorDevice->setDelay(mSensorDevice, handle, ns);
 }
 
+int SensorDevice::getHalDeviceVersion() const {
+    if (!mSensorDevice) return -1;
+
+    return mSensorDevice->common.version;
+}
+
 // ---------------------------------------------------------------------------
 
 status_t SensorDevice::Info::setDelayForIdent(void* ident, int64_t ns)
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 728b6cb..b423f40 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -52,6 +52,7 @@
 public:
     ssize_t getSensorList(sensor_t const** list);
     status_t initCheck() const;
+    int getHalDeviceVersion() const;
     ssize_t poll(sensors_event_t* buffer, size_t count);
     status_t activate(void* ident, int handle, int enabled);
     status_t setDelay(void* ident, int handle, int64_t ns);
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index e3dcd02..9ca6b45 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -38,6 +38,7 @@
 #include <gui/SensorEventQueue.h>
 
 #include <hardware/sensors.h>
+#include <hardware_legacy/power.h>
 
 #include "BatteryService.h"
 #include "CorrectedGyroSensor.h"
@@ -60,6 +61,8 @@
  *
  */
 
+const char* SensorService::WAKE_LOCK_NAME = "SensorService";
+
 SensorService::SensorService()
     : mInitCheck(NO_INIT)
 {
@@ -237,6 +240,18 @@
     return NO_ERROR;
 }
 
+void SensorService::cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection,
+        sensors_event_t const* buffer, const int count) {
+    for (int i=0 ; i<count ; i++) {
+        int handle = buffer[i].sensor;
+        if (getSensorType(handle) == SENSOR_TYPE_SIGNIFICANT_MOTION) {
+            if (connection->hasSensor(handle)) {
+                cleanupWithoutDisable(connection, handle);
+            }
+        }
+    }
+}
+
 bool SensorService::threadLoop()
 {
     ALOGD("nuSensorService thread starting...");
@@ -249,6 +264,8 @@
     const size_t vcount = mVirtualSensorList.size();
 
     ssize_t count;
+    bool wakeLockAcquired = false;
+    const int halVersion = device.getHalDeviceVersion();
     do {
         count = device.poll(buffer, numEventMax);
         if (count<0) {
@@ -256,6 +273,17 @@
             break;
         }
 
+        // Poll has returned. Hold a wakelock.
+        // Todo(): add a flag to the sensors definitions to indicate
+        // the sensors which can wake up the AP
+        for (int i = 0; i < count; i++) {
+            if (getSensorType(buffer[i].sensor) == SENSOR_TYPE_SIGNIFICANT_MOTION) {
+                 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
+                 wakeLockAcquired = true;
+                 break;
+            }
+        }
+
         recordLastValue(buffer, count);
 
         // handle virtual sensors
@@ -298,6 +326,17 @@
             }
         }
 
+        // handle backward compatibility for RotationVector sensor
+        if (halVersion < SENSORS_DEVICE_API_VERSION_1_0) {
+            for (int i = 0; i < count; i++) {
+                if (getSensorType(buffer[i].sensor) == SENSOR_TYPE_ROTATION_VECTOR) {
+                    // All the 4 components of the quaternion should be available
+                    // No heading accuracy. Set it to -1
+                    buffer[i].data[4] = -1;
+                }
+            }
+        }
+
         // send our events to clients...
         const SortedVector< wp<SensorEventConnection> > activeConnections(
                 getActiveConnections());
@@ -307,8 +346,14 @@
                     activeConnections[i].promote());
             if (connection != 0) {
                 connection->sendEvents(buffer, count, scratch);
+                // Some sensors need to be auto disabled after the trigger
+                cleanupAutoDisabledSensor(connection, buffer, count);
             }
         }
+
+        // We have read the data, upper layers should hold the wakelock.
+        if (wakeLockAcquired) release_wake_lock(WAKE_LOCK_NAME);
+
     } while (count >= 0 || Thread::exitPending());
 
     ALOGW("Exiting SensorService::threadLoop => aborting...");
@@ -372,6 +417,18 @@
     return result;
 }
 
+int SensorService::getSensorType(int handle) const {
+    size_t count = mUserSensorList.size();
+    for (size_t i=0 ; i<count ; i++) {
+        const Sensor& sensor(mUserSensorList[i]);
+        if (sensor.getHandle() == handle) {
+            return sensor.getType();
+        }
+    }
+    return -1;
+}
+
+
 Vector<Sensor> SensorService::getSensorList()
 {
     char value[PROPERTY_VALUE_MAX];
@@ -433,44 +490,48 @@
 
     Mutex::Autolock _l(mLock);
     SensorInterface* sensor = mSensorMap.valueFor(handle);
+    SensorRecord* rec = mActiveSensors.valueFor(handle);
+    if (rec == 0) {
+        rec = new SensorRecord(connection);
+        mActiveSensors.add(handle, rec);
+        if (sensor->isVirtual()) {
+            mActiveVirtualSensors.add(handle, sensor);
+        }
+    } else {
+        if (rec->addConnection(connection)) {
+            // this sensor is already activated, but we are adding a
+            // connection that uses it. Immediately send down the last
+            // known value of the requested sensor if it's not a
+            // "continuous" sensor.
+            if (sensor->getSensor().getMinDelay() == 0) {
+                sensors_event_t scratch;
+                sensors_event_t& event(mLastEventSeen.editValueFor(handle));
+                if (event.version == sizeof(sensors_event_t)) {
+                    connection->sendEvents(&event, 1);
+                }
+            }
+        }
+    }
+
+    if (connection->addSensor(handle)) {
+        BatteryService::enableSensor(connection->getUid(), handle);
+        // the sensor was added (which means it wasn't already there)
+        // so, see if this connection becomes active
+        if (mActiveConnections.indexOf(connection) < 0) {
+            mActiveConnections.add(connection);
+        }
+    } else {
+        ALOGW("sensor %08x already enabled in connection %p (ignoring)",
+            handle, connection.get());
+    }
+
+
+    // we are setup, now enable the sensor.
     status_t err = sensor ? sensor->activate(connection.get(), true) : status_t(BAD_VALUE);
-    if (err == NO_ERROR) {
-        SensorRecord* rec = mActiveSensors.valueFor(handle);
-        if (rec == 0) {
-            rec = new SensorRecord(connection);
-            mActiveSensors.add(handle, rec);
-            if (sensor->isVirtual()) {
-                mActiveVirtualSensors.add(handle, sensor);
-            }
-        } else {
-            if (rec->addConnection(connection)) {
-                // this sensor is already activated, but we are adding a
-                // connection that uses it. Immediately send down the last
-                // known value of the requested sensor if it's not a
-                // "continuous" sensor.
-                if (sensor->getSensor().getMinDelay() == 0) {
-                    sensors_event_t scratch;
-                    sensors_event_t& event(mLastEventSeen.editValueFor(handle));
-                    if (event.version == sizeof(sensors_event_t)) {
-                        connection->sendEvents(&event, 1);
-                    }
-                }
-            }
-        }
-        if (err == NO_ERROR) {
-            // connection now active
-            if (connection->addSensor(handle)) {
-                BatteryService::enableSensor(connection->getUid(), handle);
-                // the sensor was added (which means it wasn't already there)
-                // so, see if this connection becomes active
-                if (mActiveConnections.indexOf(connection) < 0) {
-                    mActiveConnections.add(connection);
-                }
-            } else {
-                ALOGW("sensor %08x already enabled in connection %p (ignoring)",
-                        handle, connection.get());
-            }
-        }
+
+    if (err != NO_ERROR) {
+        // enable has failed, reset our state.
+        cleanupWithoutDisable(connection, handle);
     }
     return err;
 }
@@ -481,7 +542,16 @@
     if (mInitCheck != NO_ERROR)
         return mInitCheck;
 
-    status_t err = NO_ERROR;
+    status_t err = cleanupWithoutDisable(connection, handle);
+    if (err == NO_ERROR) {
+        SensorInterface* sensor = mSensorMap.valueFor(handle);
+        err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
+    }
+    return err;
+}
+
+status_t SensorService::cleanupWithoutDisable(const sp<SensorEventConnection>& connection,
+        int handle) {
     Mutex::Autolock _l(mLock);
     SensorRecord* rec = mActiveSensors.valueFor(handle);
     if (rec) {
@@ -498,10 +568,9 @@
             mActiveVirtualSensors.removeItem(handle);
             delete rec;
         }
-        SensorInterface* sensor = mSensorMap.valueFor(handle);
-        err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
+        return NO_ERROR;
     }
-    return err;
+    return BAD_VALUE;
 }
 
 status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection,
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 18591bf..25e5f76 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -53,6 +53,7 @@
    friend class BinderService<SensorService>;
 
    static const nsecs_t MINIMUM_EVENTS_PERIOD =   1000000; // 1000 Hz
+   static const char* WAKE_LOCK_NAME;
 
             SensorService();
     virtual ~SensorService();
@@ -109,10 +110,15 @@
     DefaultKeyedVector<int, SensorInterface*> getActiveVirtualSensors() const;
 
     String8 getSensorName(int handle) const;
+    int getSensorType(int handle) const;
     void recordLastValue(sensors_event_t const * buffer, size_t count);
     static void sortEventBuffer(sensors_event_t* buffer, size_t count);
     void registerSensor(SensorInterface* sensor);
     void registerVirtualSensor(SensorInterface* sensor);
+    status_t cleanupWithoutDisable(const sp<SensorEventConnection>& connection,
+        int handle);
+    void cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection,
+        sensors_event_t const* buffer, const int count);
 
     // constants
     Vector<Sensor> mSensorList;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2302367..4779804 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1067,6 +1067,16 @@
                 if (!front.activeTransparentRegion.isTriviallyEqual(
                         front.requestedTransparentRegion)) {
                     front.activeTransparentRegion = front.requestedTransparentRegion;
+
+                    // We also need to update the current state so that
+                    // we don't end-up overwriting the drawing state with
+                    // this stale current state during the next transaction
+                    //
+                    // NOTE: We don't need to hold the transaction lock here
+                    // because State::active is only accessed from this thread.
+                    current.activeTransparentRegion = front.activeTransparentRegion;
+
+                    // recompute visible region
                     recomputeVisibleRegions = true;
                 }
 
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index 3f77f74..c9c7b96 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -61,6 +61,12 @@
     }
 }
 
+void MessageQueue::Handler::dispatchTransaction() {
+    if ((android_atomic_or(eventMaskTransaction, &mEventMask) & eventMaskTransaction) == 0) {
+        mQueue.mLooper->sendMessage(this, Message(MessageQueue::TRANSACTION));
+    }
+}
+
 void MessageQueue::Handler::handleMessage(const Message& message) {
     switch (message.what) {
         case INVALIDATE:
@@ -71,6 +77,10 @@
             android_atomic_and(~eventMaskRefresh, &mEventMask);
             mQueue.mFlinger->onMessageReceived(message.what);
             break;
+        case TRANSACTION:
+            android_atomic_and(~eventMaskTransaction, &mEventMask);
+            mQueue.mFlinger->onMessageReceived(message.what);
+            break;
     }
 }
 
@@ -132,6 +142,7 @@
     return NO_ERROR;
 }
 
+
 /* when INVALIDATE_ON_VSYNC is set SF only processes
  * buffer updates on VSYNC and performs a refresh immediately
  * after.
@@ -143,6 +154,10 @@
  */
 #define INVALIDATE_ON_VSYNC 1
 
+void MessageQueue::invalidateTransactionNow() {
+    mHandler->dispatchTransaction();
+}
+
 void MessageQueue::invalidate() {
 #if INVALIDATE_ON_VSYNC
     mEvents->requestNextVsync();
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index 710b2c2..b77e08e 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -62,8 +62,9 @@
 class MessageQueue {
     class Handler : public MessageHandler {
         enum {
-            eventMaskInvalidate = 0x1,
-            eventMaskRefresh    = 0x2
+            eventMaskInvalidate     = 0x1,
+            eventMaskRefresh        = 0x2,
+            eventMaskTransaction    = 0x4
         };
         MessageQueue& mQueue;
         int32_t mEventMask;
@@ -72,6 +73,7 @@
         virtual void handleMessage(const Message& message);
         void dispatchRefresh();
         void dispatchInvalidate();
+        void dispatchTransaction();
     };
 
     friend class Handler;
@@ -89,8 +91,9 @@
 
 public:
     enum {
-        INVALIDATE = 0,
-        REFRESH    = 1,
+        INVALIDATE  = 0,
+        REFRESH     = 1,
+        TRANSACTION = 2
     };
 
     MessageQueue();
@@ -100,8 +103,13 @@
 
     void waitMessage();
     status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
+
+    // sends INVALIDATE message at next VSYNC
     void invalidate();
+    // sends REFRESH message at next VSYNC
     void refresh();
+    // sends TRANSACTION message immediately
+    void invalidateTransactionNow();
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a4426cd..dc29e48 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -744,6 +744,9 @@
 void SurfaceFlinger::onMessageReceived(int32_t what) {
     ATRACE_CALL();
     switch (what) {
+    case MessageQueue::TRANSACTION:
+        handleMessageTransaction();
+        break;
     case MessageQueue::INVALIDATE:
         handleMessageTransaction();
         handleMessageInvalidate();
@@ -1242,17 +1245,22 @@
                         if (disp == NULL) {
                             disp = hw;
                         } else {
-                            disp = getDefaultDisplayDevice();
+                            disp = NULL;
                             break;
                         }
                     }
                 }
             }
-            if (disp != NULL) {
-                // presumably this means this layer is using a layerStack
-                // that is not visible on any display
-                layer->updateTransformHint(disp);
+            if (disp == NULL) {
+                // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to
+                // redraw after transform hint changes. See bug 8508397.
+
+                // could be null when this layer is using a layerStack
+                // that is not visible on any display. Also can occur at
+                // screen off/on times.
+                disp = getDefaultDisplayDevice();
             }
+            layer->updateTransformHint(disp);
         }
     }
 
@@ -2626,6 +2634,13 @@
         }
     };
 
+    // make sure to process transactions before screenshots -- a transaction
+    // might already be pending but scheduled for VSYNC; this guarantees we
+    // will handle it before the screenshot. When VSYNC finally arrives
+    // the scheduled transaction will be a no-op. If no transactions are
+    // scheduled at this time, this will end-up being a no-op as well.
+    mEventQueue.invalidateTransactionNow();
+
     sp<MessageBase> msg = new MessageCaptureScreen(this,
             display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ,
             isCpuConsumer);
@@ -2636,6 +2651,61 @@
     return res;
 }
 
+
+void SurfaceFlinger::renderScreenImplLocked(
+        const sp<const DisplayDevice>& hw,
+        uint32_t reqWidth, uint32_t reqHeight,
+        uint32_t minLayerZ, uint32_t maxLayerZ,
+        bool yswap)
+{
+    ATRACE_CALL();
+
+    // get screen geometry
+    const uint32_t hw_w = hw->getWidth();
+    const uint32_t hw_h = hw->getHeight();
+
+    const bool filtering = reqWidth != hw_w || reqWidth != hw_h;
+
+    // make sure to clear all GL error flags
+    while ( glGetError() != GL_NO_ERROR ) ;
+
+    // set-up our viewport
+    glViewport(0, 0, reqWidth, reqHeight);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    if (yswap)  glOrthof(0, hw_w, hw_h, 0, 0, 1);
+    else        glOrthof(0, hw_w, 0, hw_h, 0, 1);
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+
+    // redraw the screen entirely...
+    glDisable(GL_SCISSOR_TEST);
+    glClearColor(0,0,0,1);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glDisable(GL_TEXTURE_EXTERNAL_OES);
+    glDisable(GL_TEXTURE_2D);
+
+    const LayerVector& layers( mDrawingState.layersSortedByZ );
+    const size_t count = layers.size();
+    for (size_t i=0 ; i<count ; ++i) {
+        const sp<Layer>& layer(layers[i]);
+        const Layer::State& state(layer->drawingState());
+        if (state.layerStack == hw->getLayerStack()) {
+            if (state.z >= minLayerZ && state.z <= maxLayerZ) {
+                if (layer->isVisible()) {
+                    if (filtering) layer->setFiltering(true);
+                    layer->draw(hw);
+                    if (filtering) layer->setFiltering(false);
+                }
+            }
+        }
+    }
+
+    // compositionComplete is needed for older driver
+    hw->compositionComplete();
+}
+
+
 status_t SurfaceFlinger::captureScreenImplLocked(
         const sp<const DisplayDevice>& hw,
         const sp<IGraphicBufferProducer>& producer,
@@ -2662,7 +2732,6 @@
 
     reqWidth = (!reqWidth) ? hw_w : reqWidth;
     reqHeight = (!reqHeight) ? hw_h : reqHeight;
-    const bool filtering = reqWidth != hw_w || reqWidth != hw_h;
 
     // Create a surface to render into
     sp<Surface> surface = new Surface(producer);
@@ -2687,41 +2756,7 @@
         return BAD_VALUE;
     }
 
-    // make sure to clear all GL error flags
-    while ( glGetError() != GL_NO_ERROR ) ;
-
-    // set-up our viewport
-    glViewport(0, 0, reqWidth, reqHeight);
-    glMatrixMode(GL_PROJECTION);
-    glLoadIdentity();
-    glOrthof(0, hw_w, 0, hw_h, 0, 1);
-    glMatrixMode(GL_MODELVIEW);
-    glLoadIdentity();
-
-    // redraw the screen entirely...
-    glDisable(GL_TEXTURE_EXTERNAL_OES);
-    glDisable(GL_TEXTURE_2D);
-    glClearColor(0,0,0,1);
-    glClear(GL_COLOR_BUFFER_BIT);
-
-    const LayerVector& layers( mDrawingState.layersSortedByZ );
-    const size_t count = layers.size();
-    for (size_t i=0 ; i<count ; ++i) {
-        const sp<Layer>& layer(layers[i]);
-        const Layer::State& state(layer->drawingState());
-        if (state.layerStack == hw->getLayerStack()) {
-            if (state.z >= minLayerZ && state.z <= maxLayerZ) {
-                if (layer->isVisible()) {
-                    if (filtering) layer->setFiltering(true);
-                    layer->draw(hw);
-                    if (filtering) layer->setFiltering(false);
-                }
-            }
-        }
-    }
-
-    // compositionComplete is needed for older driver
-    hw->compositionComplete();
+    renderScreenImplLocked(hw, reqWidth, reqHeight, minLayerZ, maxLayerZ, false);
 
     // and finishing things up...
     if (eglSwapBuffers(mEGLDisplay, eglSurface) != EGL_TRUE) {
@@ -2749,102 +2784,87 @@
         return INVALID_OPERATION;
     }
 
-    // create the texture that will receive the screenshot, later we'll
-    // attach a FBO to it so we can call glReadPixels().
-    GLuint tname;
-    glGenTextures(1, &tname);
-    glBindTexture(GL_TEXTURE_2D, tname);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    // get screen geometry
+    const uint32_t hw_w = hw->getWidth();
+    const uint32_t hw_h = hw->getHeight();
 
-    // the GLConsumer will provide the BufferQueue
-    sp<GLConsumer> consumer = new GLConsumer(tname, true, GL_TEXTURE_2D);
-    consumer->getBufferQueue()->setDefaultBufferFormat(HAL_PIXEL_FORMAT_RGBA_8888);
-
-    // call the new screenshot taking code, passing a BufferQueue to it
-    status_t result = captureScreenImplLocked(hw,
-            consumer->getBufferQueue(), reqWidth, reqHeight, minLayerZ, maxLayerZ);
-
-    if (result == NO_ERROR) {
-        result = consumer->updateTexImage();
-        if (result == NO_ERROR) {
-            // create a FBO
-            GLuint name;
-            glGenFramebuffersOES(1, &name);
-            glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
-            glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
-                    GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
-
-            reqWidth = consumer->getCurrentBuffer()->getWidth();
-            reqHeight = consumer->getCurrentBuffer()->getHeight();
-
-            {
-                // in this block we render the screenshot into the
-                // CpuConsumer using glReadPixels from our GLConsumer,
-                // Some older drivers don't support the GL->CPU path so
-                // have to wrap it with a CPU->CPU path, which is what
-                // glReadPixels essentially is
-
-                sp<Surface> sur = new Surface(producer);
-                ANativeWindow* window = sur.get();
-                ANativeWindowBuffer* buffer;
-                void* vaddr;
-
-                if (native_window_api_connect(window,
-                        NATIVE_WINDOW_API_CPU) == NO_ERROR) {
-                    int err = 0;
-                    err = native_window_set_buffers_dimensions(window,
-                            reqWidth, reqHeight);
-                    err |= native_window_set_buffers_format(window,
-                            HAL_PIXEL_FORMAT_RGBA_8888);
-                    err |= native_window_set_usage(window,
-                            GRALLOC_USAGE_SW_READ_OFTEN |
-                            GRALLOC_USAGE_SW_WRITE_OFTEN);
-
-                    if (err == NO_ERROR) {
-                        if (native_window_dequeue_buffer_and_wait(window,
-                                &buffer) == NO_ERROR) {
-                            sp<GraphicBuffer> buf =
-                                    static_cast<GraphicBuffer*>(buffer);
-                            if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN,
-                                    &vaddr) == NO_ERROR) {
-                                if (buffer->stride != int(reqWidth)) {
-                                    // we're unlucky here, glReadPixels is
-                                    // not able to deal with a stride not
-                                    // equal to the width.
-                                    uint32_t* tmp = new uint32_t[reqWidth*reqHeight];
-                                    if (tmp != NULL) {
-                                        glReadPixels(0, 0, reqWidth, reqHeight,
-                                                GL_RGBA, GL_UNSIGNED_BYTE, tmp);
-                                        for (size_t y=0 ; y<reqHeight ; y++) {
-                                            memcpy((uint32_t*)vaddr + y*buffer->stride,
-                                                    tmp + y*reqWidth, reqWidth*4);
-                                        }
-                                        delete [] tmp;
-                                    }
-                                } else {
-                                    glReadPixels(0, 0, reqWidth, reqHeight,
-                                            GL_RGBA, GL_UNSIGNED_BYTE, vaddr);
-                                }
-                                buf->unlock();
-                            }
-                            window->queueBuffer(window, buffer, -1);
-                        }
-                    }
-                    native_window_api_disconnect(window, NATIVE_WINDOW_API_CPU);
-                }
-            }
-
-            // back to main framebuffer
-            glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
-            glDeleteFramebuffersOES(1, &name);
-        }
+    // if we have secure windows on this display, never allow the screen capture
+    if (hw->getSecureLayerVisible()) {
+        ALOGW("FB is protected: PERMISSION_DENIED");
+        return PERMISSION_DENIED;
     }
 
-    glDeleteTextures(1, &tname);
+    if ((reqWidth > hw_w) || (reqHeight > hw_h)) {
+        ALOGE("size mismatch (%d, %d) > (%d, %d)",
+                reqWidth, reqHeight, hw_w, hw_h);
+        return BAD_VALUE;
+    }
 
-    DisplayDevice::makeCurrent(mEGLDisplay,
-            getDefaultDisplayDevice(), mEGLContext);
+    reqWidth  = (!reqWidth)  ? hw_w : reqWidth;
+    reqHeight = (!reqHeight) ? hw_h : reqHeight;
+
+    GLuint tname;
+    glGenRenderbuffersOES(1, &tname);
+    glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname);
+    glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, reqWidth, reqHeight);
+
+    // create a FBO
+    GLuint name;
+    glGenFramebuffersOES(1, &name);
+    glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
+    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
+            GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname);
+
+    GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+
+    status_t result = NO_ERROR;
+    if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
+
+        renderScreenImplLocked(hw, reqWidth, reqHeight, minLayerZ, maxLayerZ, true);
+
+        // Below we render the screenshot into the
+        // CpuConsumer using glReadPixels from our FBO.
+        // Some older drivers don't support the GL->CPU path so we
+        // have to wrap it with a CPU->CPU path, which is what
+        // glReadPixels essentially is.
+
+        sp<Surface> sur = new Surface(producer);
+        ANativeWindow* window = sur.get();
+
+        if (native_window_api_connect(window, NATIVE_WINDOW_API_CPU) == NO_ERROR) {
+            int err = 0;
+            err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight);
+            err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
+            err |= native_window_set_usage(window,
+                    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+
+            if (err == NO_ERROR) {
+                ANativeWindowBuffer* buffer;
+                if (native_window_dequeue_buffer_and_wait(window,  &buffer) == NO_ERROR) {
+                    sp<GraphicBuffer> buf = static_cast<GraphicBuffer*>(buffer);
+                    void* vaddr;
+                    if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &vaddr) == NO_ERROR) {
+                        glReadPixels(0, 0, buffer->stride, reqHeight,
+                                GL_RGBA, GL_UNSIGNED_BYTE, vaddr);
+                        buf->unlock();
+                    }
+                    window->queueBuffer(window, buffer, -1);
+                }
+            }
+            native_window_api_disconnect(window, NATIVE_WINDOW_API_CPU);
+        }
+
+    } else {
+        ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES while taking screenshot");
+        result = INVALID_OPERATION;
+    }
+
+    // back to main framebuffer
+    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
+    glDeleteRenderbuffersOES(1, &tname);
+    glDeleteFramebuffersOES(1, &name);
+
+    DisplayDevice::setViewportAndProjection(hw);
 
     return result;
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 57ee8b9..739099c 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -288,6 +288,12 @@
 
     void startBootAnim();
 
+    void renderScreenImplLocked(
+            const sp<const DisplayDevice>& hw,
+            uint32_t reqWidth, uint32_t reqHeight,
+            uint32_t minLayerZ, uint32_t maxLayerZ,
+            bool yswap);
+
     status_t captureScreenImplLocked(
             const sp<const DisplayDevice>& hw,
             const sp<IGraphicBufferProducer>& producer,