Merge "Add a timeout for releasing SensorService wake_lock." into lmp-mr1-dev
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 526374e..f9942e9 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -132,6 +132,7 @@
 
     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
     run_command("UPTIME", 10, "uptime", NULL);
+    dump_file("MMC PERF", "/sys/block/mmcblk0/stat");
     dump_file("MEMORY INFO", "/proc/meminfo");
     run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-t", NULL);
     run_command("PROCRANK", 20, "procrank", NULL);
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index fc3972e..1954d8d 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -20,6 +20,7 @@
 #include <cutils/sched_policy.h>
 #include <diskusage/dirsize.h>
 #include <selinux/android.h>
+#include <system/thread_defs.h>
 
 /* Directory records that are used in execution of commands. */
 dir_rec_t android_data_dir;
@@ -985,6 +986,10 @@
             ALOGE("set_sched_policy failed: %s\n", strerror(errno));
             exit(70);
         }
+        if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
+            ALOGE("setpriority failed: %s\n", strerror(errno));
+            exit(71);
+        }
         if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) {
             ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno));
             exit(67);
diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h
index 5effd10..01b6ff4 100644
--- a/include/gui/BufferItem.h
+++ b/include/gui/BufferItem.h
@@ -44,6 +44,7 @@
     // The default value of mBuf, used to indicate this doesn't correspond to a slot.
     enum { INVALID_BUFFER_SLOT = -1 };
     BufferItem();
+    ~BufferItem();
     operator IGraphicBufferConsumer::BufferItem() const;
 
     static const char* scalingModeName(uint32_t scalingMode);
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 3297b10..1188837 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -62,7 +62,7 @@
     public:
         ProxyConsumerListener(const wp<ConsumerListener>& consumerListener);
         virtual ~ProxyConsumerListener();
-        virtual void onFrameAvailable();
+        virtual void onFrameAvailable(const android::BufferItem& item);
         virtual void onBuffersReleased();
         virtual void onSidebandStreamChanged();
     private:
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index c619a11..ed1056a 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -203,6 +203,16 @@
     // since the previous buffer might have already been acquired.
     sp<Fence> mLastQueueBufferFence;
 
+    // Take-a-ticket system for ensuring that onFrame* callbacks are called in
+    // the order that frames are queued. While the BufferQueue lock
+    // (mCore->mMutex) is held, a ticket is retained by the producer. After
+    // dropping the BufferQueue lock, the producer must wait on the condition
+    // variable until the current callback ticket matches its retained ticket.
+    Mutex mCallbackMutex;
+    int mNextCallbackTicket; // Protected by mCore->mMutex
+    int mCurrentCallbackTicket; // Protected by mCallbackMutex
+    Condition mCallbackCondition;
+
 }; // class BufferQueueProducer
 
 } // namespace android
diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h
index 100bb26..f7ab5ac 100644
--- a/include/gui/ConsumerBase.h
+++ b/include/gui/ConsumerBase.h
@@ -46,7 +46,7 @@
         //
         // This is called without any lock held and can be called concurrently
         // by multiple threads.
-        virtual void onFrameAvailable() = 0;
+        virtual void onFrameAvailable(const BufferItem& item) = 0;
     };
 
     virtual ~ConsumerBase();
@@ -106,7 +106,7 @@
     // the ConsumerBase implementation must be called from the derived class.
     // The ConsumerBase version of onSidebandStreamChanged does nothing and can
     // be overriden by derived classes if they want the notification.
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
     virtual void onBuffersReleased();
     virtual void onSidebandStreamChanged();
 
diff --git a/include/gui/IConsumerListener.h b/include/gui/IConsumerListener.h
index 260099e..2ef7c4d 100644
--- a/include/gui/IConsumerListener.h
+++ b/include/gui/IConsumerListener.h
@@ -28,6 +28,8 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
+class BufferItem;
+
 // 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
@@ -43,11 +45,24 @@
     // frame becomes available for consumption. This means that frames that
     // are queued while in asynchronous mode only trigger the callback if no
     // previous frames are pending. Frames queued while in synchronous mode
-    // always trigger the callback.
+    // always trigger the callback. The item passed to the callback will contain
+    // all of the information about the queued frame except for its
+    // GraphicBuffer pointer, which will always be null.
     //
     // This is called without any lock held and can be called concurrently
     // by multiple threads.
-    virtual void onFrameAvailable() = 0; /* Asynchronous */
+    virtual void onFrameAvailable(const BufferItem& item) = 0; /* Asynchronous */
+
+    // onFrameReplaced is called from queueBuffer if the frame being queued is
+    // replacing an existing slot in the queue. Any call to queueBuffer that
+    // doesn't call onFrameAvailable will call this callback instead. The item
+    // passed to the callback will contain all of the information about the
+    // queued frame except for its GraphicBuffer pointer, which will always be
+    // null.
+    //
+    // This is called without any lock held and can be called concurrently
+    // by multiple threads.
+    virtual void onFrameReplaced(const BufferItem& item) {} /* Asynchronous */
 
     // onBuffersReleased is called to notify the buffer consumer that the
     // BufferQueue has released its references to one or more GraphicBuffers
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 3ffc67e..51717a4 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -38,7 +38,7 @@
 
 class ComposerState;
 class DisplayState;
-class DisplayInfo;
+struct DisplayInfo;
 class DisplayStatInfo;
 class IDisplayEventConnection;
 class IMemoryHeap;
diff --git a/include/gui/StreamSplitter.h b/include/gui/StreamSplitter.h
index f927953..8f47eb4 100644
--- a/include/gui/StreamSplitter.h
+++ b/include/gui/StreamSplitter.h
@@ -74,7 +74,7 @@
     // can block if there are too many outstanding buffers. If it blocks, it
     // will resume when onBufferReleasedByOutput releases a buffer back to the
     // input.
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
 
     // From IConsumerListener
     // We don't care about released buffers because we detach each buffer as
diff --git a/include/media/drm/DrmAPI.h b/include/media/drm/DrmAPI.h
index 4633b7e..49939fd 100644
--- a/include/media/drm/DrmAPI.h
+++ b/include/media/drm/DrmAPI.h
@@ -209,7 +209,9 @@
         // confirmed. The persisted record on the client is only removed after positive
         // confirmation that the server received the message using releaseSecureStops().
         virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) = 0;
+        virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) = 0;
         virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
+        virtual status_t releaseAllSecureStops() = 0;
 
         // Read a property value given the device property string.  There are a few forms
         // of property access methods, depending on the data type returned.
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index 6cf64eb..31e28d2 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -34,6 +34,7 @@
     // because we want the compiler generated versions
 
     inline Rect() {
+      left = right = top = bottom = 0;
     }
 
     inline Rect(int32_t w, int32_t h) {
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 1dbb06f..09238c2 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -26,7 +26,6 @@
 #include <binder/TextOutput.h>
 
 #include <errno.h>
-#include <utils/CallStack.h>
 #include <utils/Debug.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
@@ -37,7 +36,6 @@
 
 #include <private/binder/binder_module.h>
 
-#include <fcntl.h>
 #include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -768,29 +766,6 @@
 status_t Parcel::writeDupFileDescriptor(int fd)
 {
     int dupFd = dup(fd);
-
-    {   // Temporary extra debug validation for b/17477219: a Parcel recipient is
-        // getting a positive but invalid fd unexpectedly. Trying to track down
-        // where it's coming from.
-        int dupErrno = dupFd < 0 ? errno : 0;
-        int fdFlags = fcntl(fd, F_GETFD);
-        int fdFlagsErrno = fdFlags == -1 ? errno : 0;
-        int dupFlags = fcntl(dupFd, F_GETFD);
-        int dupFlagsErrno = dupFlags == -1 ? errno : 0;
-        if (dupFd < 0 || fdFlags == -1 || dupFlags == -1) {
-            ALOGE("Parcel::writeDupFileDescriptor failed:\n"
-                    "  fd=%d flags=%d err=%d(%s)\n"
-                    "  dupFd=%d dupErr=%d(%s) flags=%d err=%d(%s)",
-                    fd, fdFlags, fdFlagsErrno, strerror(fdFlagsErrno),
-                    dupFd, dupErrno, strerror(dupErrno),
-                    dupFlags, dupFlagsErrno, strerror(dupFlagsErrno));
-            if (fd < 0 || fdFlags == -1) {
-                CallStack(LOG_TAG);
-            }
-            return -errno;
-        }
-    }
-
     if (dupFd < 0) {
         return -errno;
     }
@@ -1305,23 +1280,11 @@
 
     status_t err = NO_ERROR;
     for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {
-        int oldfd = this->readFileDescriptor();
-        fds[i] = dup(oldfd);
+        fds[i] = dup(this->readFileDescriptor());
         if (fds[i] < 0) {
-            int dupErrno = errno;
             err = BAD_VALUE;
-            int flags = fcntl(oldfd, F_GETFD);
-            int fcntlErrno = errno;
-            const flat_binder_object* flat = readObject(true);
-            ALOGE("dup failed in Parcel::read, fd %zu of %zu\n"
-                "  dup(%d) = %d [errno: %d (%s)]\n"
-                "  fcntl(%d, F_GETFD) = %d [errno: %d (%s)]\n"
-                "  flat %p type %d",
-                i, fd_count,
-                oldfd, fds[i], dupErrno, strerror(dupErrno),
-                oldfd, flags, fcntlErrno, strerror(fcntlErrno),
-                flat, flat ? flat->type : 0);
-            CallStack(LOG_TAG);
+            ALOGE("dup() failed in Parcel::read, i is %zu, fds[i] is %d, fd_count is %zu, error: %s",
+                i, fds[i], fd_count, strerror(errno));
         }
     }
 
diff --git a/libs/binder/TextOutput.cpp b/libs/binder/TextOutput.cpp
index db3e858..2ed5188 100644
--- a/libs/binder/TextOutput.cpp
+++ b/libs/binder/TextOutput.cpp
@@ -116,8 +116,8 @@
 
 TextOutput& operator<<(TextOutput& to, const void* val)
 {
-    char buf[16];
-    sprintf(buf, "%p", val);
+    char buf[32];
+    snprintf(buf, sizeof(buf), "%p", val);
     to.print(buf, strlen(buf));
     return to;
 }
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index d3fa43e..e6fc791 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -36,6 +36,8 @@
     mCrop.makeInvalid();
 }
 
+BufferItem::~BufferItem() {}
+
 BufferItem::operator IGraphicBufferConsumer::BufferItem() const {
     IGraphicBufferConsumer::BufferItem bufferItem;
     bufferItem.mGraphicBuffer = mGraphicBuffer;
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index c49a886..61fd8c4 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -31,10 +31,11 @@
 
 BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
 
-void BufferQueue::ProxyConsumerListener::onFrameAvailable() {
+void BufferQueue::ProxyConsumerListener::onFrameAvailable(
+        const android::BufferItem& item) {
     sp<ConsumerListener> listener(mConsumerListener.promote());
     if (listener != NULL) {
-        listener->onFrameAvailable();
+        listener->onFrameAvailable(item);
     }
 }
 
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 284ddb2..16b9747 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -39,7 +39,11 @@
     mSlots(core->mSlots),
     mConsumerName(),
     mStickyTransform(0),
-    mLastQueueBufferFence(Fence::NO_FENCE) {}
+    mLastQueueBufferFence(Fence::NO_FENCE),
+    mCallbackMutex(),
+    mNextCallbackTicket(0),
+    mCurrentCallbackTicket(0),
+    mCallbackCondition() {}
 
 BufferQueueProducer::~BufferQueueProducer() {}
 
@@ -523,12 +527,7 @@
 
     if (fence == NULL) {
         BQ_LOGE("queueBuffer: fence is NULL");
-        // Temporary workaround for b/17946343: soldier-on instead of returning an error. This
-        // prevents the client from dying, at the risk of visible corruption due to hwcomposer
-        // reading the buffer before the producer is done rendering it. Unless the buffer is the
-        // last frame of an animation, the corruption will be transient.
-        fence = Fence::NO_FENCE;
-        // return BAD_VALUE;
+        return BAD_VALUE;
     }
 
     switch (scalingMode) {
@@ -542,7 +541,10 @@
             return BAD_VALUE;
     }
 
-    sp<IConsumerListener> listener;
+    sp<IConsumerListener> frameAvailableListener;
+    sp<IConsumerListener> frameReplacedListener;
+    int callbackTicket = 0;
+    BufferItem item;
     { // Autolock scope
         Mutex::Autolock lock(mCore->mMutex);
 
@@ -598,7 +600,6 @@
         ++mCore->mFrameCounter;
         mSlots[slot].mFrameNumber = mCore->mFrameCounter;
 
-        BufferItem item;
         item.mAcquireCalled = mSlots[slot].mAcquireCalled;
         item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
         item.mCrop = crop;
@@ -619,7 +620,7 @@
             // When the queue is empty, we can ignore mDequeueBufferCannotBlock
             // and simply queue this buffer
             mCore->mQueue.push_back(item);
-            listener = mCore->mConsumerListener;
+            frameAvailableListener = mCore->mConsumerListener;
         } else {
             // When the queue is not empty, we need to look at the front buffer
             // state to see if we need to replace it
@@ -635,9 +636,10 @@
                 }
                 // Overwrite the droppable buffer with the incoming one
                 *front = item;
+                frameReplacedListener = mCore->mConsumerListener;
             } else {
                 mCore->mQueue.push_back(item);
-                listener = mCore->mConsumerListener;
+                frameAvailableListener = mCore->mConsumerListener;
             }
         }
 
@@ -648,6 +650,9 @@
                 mCore->mTransformHint, mCore->mQueue.size());
 
         ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
+
+        // Take a ticket for the callback functions
+        callbackTicket = mNextCallbackTicket++;
     } // Autolock scope
 
     // Wait without lock held
@@ -659,9 +664,27 @@
         mLastQueueBufferFence = fence;
     }
 
-    // Call back without lock held
-    if (listener != NULL) {
-        listener->onFrameAvailable();
+    // Don't send the GraphicBuffer through the callback, and don't send
+    // the slot number, since the consumer shouldn't need it
+    item.mGraphicBuffer.clear();
+    item.mSlot = BufferItem::INVALID_BUFFER_SLOT;
+
+    // Call back without the main BufferQueue lock held, but with the callback
+    // lock held so we can ensure that callbacks occur in order
+    {
+        Mutex::Autolock lock(mCallbackMutex);
+        while (callbackTicket != mCurrentCallbackTicket) {
+            mCallbackCondition.wait(mCallbackMutex);
+        }
+
+        if (frameAvailableListener != NULL) {
+            frameAvailableListener->onFrameAvailable(item);
+        } else if (frameReplacedListener != NULL) {
+            frameReplacedListener->onFrameReplaced(item);
+        }
+
+        ++mCurrentCallbackTicket;
+        mCallbackCondition.broadcast();
     }
 
     return NO_ERROR;
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index f19b6c7..210e98e 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -98,7 +98,7 @@
     mSlots[slotIndex].mFrameNumber = 0;
 }
 
-void ConsumerBase::onFrameAvailable() {
+void ConsumerBase::onFrameAvailable(const BufferItem& item) {
     CB_LOGV("onFrameAvailable");
 
     sp<FrameAvailableListener> listener;
@@ -109,7 +109,7 @@
 
     if (listener != NULL) {
         CB_LOGV("actually calling onFrameAvailable");
-        listener->onFrameAvailable();
+        listener->onFrameAvailable(item);
     }
 }
 
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index cc96a92..318c087 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -505,7 +505,7 @@
         if (mEglDisplay == EGL_NO_DISPLAY) {
             mEglDisplay = dpy;
         }
-        if (mEglContext == EGL_NO_DISPLAY) {
+        if (mEglContext == EGL_NO_CONTEXT) {
             mEglContext = ctx;
         }
     }
diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp
index 4ccf0ac..409dfe4 100644
--- a/libs/gui/IConsumerListener.cpp
+++ b/libs/gui/IConsumerListener.cpp
@@ -21,6 +21,7 @@
 #include <binder/Parcel.h>
 
 #include <gui/IConsumerListener.h>
+#include <gui/BufferItem.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -39,9 +40,10 @@
         : BpInterface<IConsumerListener>(impl) {
     }
 
-    virtual void onFrameAvailable() {
+    virtual void onFrameAvailable(const BufferItem& item) {
         Parcel data, reply;
         data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
+        data.write(item);
         remote()->transact(ON_FRAME_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY);
     }
 
@@ -66,18 +68,20 @@
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     switch(code) {
-        case ON_FRAME_AVAILABLE:
+        case ON_FRAME_AVAILABLE: {
             CHECK_INTERFACE(IConsumerListener, data, reply);
-            onFrameAvailable();
-            return NO_ERROR;
-        case ON_BUFFER_RELEASED:
+            BufferItem item;
+            data.read(item);
+            onFrameAvailable(item);
+            return NO_ERROR; }
+        case ON_BUFFER_RELEASED: {
             CHECK_INTERFACE(IConsumerListener, data, reply);
             onBuffersReleased();
-            return NO_ERROR;
-        case ON_SIDEBAND_STREAM_CHANGED:
+            return NO_ERROR; }
+        case ON_SIDEBAND_STREAM_CHANGED: {
             CHECK_INTERFACE(IConsumerListener, data, reply);
             onSidebandStreamChanged();
-            return NO_ERROR;
+            return NO_ERROR; }
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 81e8336..ebb687a 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -312,19 +312,29 @@
         case SET_TRANSACTION_STATE: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             size_t count = data.readInt32();
+            if (count > data.dataSize()) {
+                return BAD_VALUE;
+            }
             ComposerState s;
             Vector<ComposerState> state;
             state.setCapacity(count);
             for (size_t i=0 ; i<count ; i++) {
-                s.read(data);
+                if (s.read(data) == BAD_VALUE) {
+                    return BAD_VALUE;
+                }
                 state.add(s);
             }
             count = data.readInt32();
+            if (count > data.dataSize()) {
+                return BAD_VALUE;
+            }
             DisplayState d;
             Vector<DisplayState> displays;
             displays.setCapacity(count);
             for (size_t i=0 ; i<count ; i++) {
-                d.read(data);
+                if (d.read(data) == BAD_VALUE) {
+                    return BAD_VALUE;
+                }
                 displays.add(d);
             }
             uint32_t flags = data.readInt32();
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index e95d8b6..1183d59 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -55,8 +55,12 @@
     alpha = input.readFloat();
     flags = input.readInt32();
     mask = input.readInt32();
-    matrix = *reinterpret_cast<layer_state_t::matrix22_t const *>(
-            input.readInplace(sizeof(layer_state_t::matrix22_t)));
+    const void* matrix_data = input.readInplace(sizeof(layer_state_t::matrix22_t));
+    if (matrix_data) {
+        matrix = *reinterpret_cast<layer_state_t::matrix22_t const *>(matrix_data);
+    } else {
+        return BAD_VALUE;
+    }
     input.read(crop);
     input.read(transparentRegion);
     return NO_ERROR;
diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp
index 771b263..5f39905 100644
--- a/libs/gui/StreamSplitter.cpp
+++ b/libs/gui/StreamSplitter.cpp
@@ -98,7 +98,7 @@
     mInput->setConsumerName(name);
 }
 
-void StreamSplitter::onFrameAvailable() {
+void StreamSplitter::onFrameAvailable(const BufferItem& /* item */) {
     ATRACE_CALL();
     Mutex::Autolock lock(mMutex);
 
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index c781366..96de11f 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -67,7 +67,7 @@
 };
 
 struct DummyConsumer : public BnConsumerListener {
-    virtual void onFrameAvailable() {}
+    virtual void onFrameAvailable(const BufferItem& /* item */) {}
     virtual void onBuffersReleased() {}
     virtual void onSidebandStreamChanged() {}
 };
diff --git a/libs/gui/tests/DisconnectWaiter.h b/libs/gui/tests/DisconnectWaiter.h
index 56e96c2..6e6915b 100644
--- a/libs/gui/tests/DisconnectWaiter.h
+++ b/libs/gui/tests/DisconnectWaiter.h
@@ -44,7 +44,7 @@
         mPendingFrames--;
     }
 
-    virtual void onFrameAvailable() {
+    virtual void onFrameAvailable(const BufferItem& /* item */) {
         Mutex::Autolock lock(mMutex);
         mPendingFrames++;
         mFrameCondition.signal();
diff --git a/libs/gui/tests/FrameWaiter.h b/libs/gui/tests/FrameWaiter.h
index bdedba6..f78fa00 100644
--- a/libs/gui/tests/FrameWaiter.h
+++ b/libs/gui/tests/FrameWaiter.h
@@ -35,7 +35,7 @@
         mPendingFrames--;
     }
 
-    virtual void onFrameAvailable() {
+    virtual void onFrameAvailable(const BufferItem& /* item */) {
         Mutex::Autolock lock(mMutex);
         mPendingFrames++;
         mCondition.signal();
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index aadfe61..8d5fd8f 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -65,7 +65,7 @@
 }; // namespace anonymous
 
 struct DummyConsumer : public BnConsumerListener {
-    virtual void onFrameAvailable() {}
+    virtual void onFrameAvailable(const BufferItem& /* item */) {}
     virtual void onBuffersReleased() {}
     virtual void onSidebandStreamChanged() {}
 };
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index 32ec90d..4e63a6f 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -46,7 +46,7 @@
 };
 
 struct DummyListener : public BnConsumerListener {
-    virtual void onFrameAvailable() {}
+    virtual void onFrameAvailable(const BufferItem& /* item */) {}
     virtual void onBuffersReleased() {}
     virtual void onSidebandStreamChanged() {}
 };
diff --git a/libs/gui/tests/SurfaceTextureGLThreadToGL.h b/libs/gui/tests/SurfaceTextureGLThreadToGL.h
index 6410516..14e42ac 100644
--- a/libs/gui/tests/SurfaceTextureGLThreadToGL.h
+++ b/libs/gui/tests/SurfaceTextureGLThreadToGL.h
@@ -130,7 +130,7 @@
         }
 
         // This should be called by GLConsumer on the producer thread.
-        virtual void onFrameAvailable() {
+        virtual void onFrameAvailable(const BufferItem& /* item */) {
             Mutex::Autolock lock(mMutex);
             ALOGV("+onFrameAvailable");
             mFrameAvailable = true;
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 9b0bd60..e768f13 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -310,10 +310,19 @@
     const size_t numFds  = buf[8];
     const size_t numInts = buf[9];
 
+    const size_t maxNumber = UINT_MAX / sizeof(int);
+    if (numFds >= maxNumber || numInts >= (maxNumber - 10)) {
+        width = height = stride = format = usage = 0;
+        handle = NULL;
+        ALOGE("unflatten: numFds or numInts is too large: %d, %d",
+                numFds, numInts);
+        return BAD_VALUE;
+    }
+
     const size_t sizeNeeded = (10 + numInts) * sizeof(int);
     if (size < sizeNeeded) return NO_MEMORY;
 
-    size_t fdCountNeeded = 0;
+    size_t fdCountNeeded = numFds;
     if (count < fdCountNeeded) return NO_MEMORY;
 
     if (handle) {
@@ -328,6 +337,12 @@
         format = buf[4];
         usage  = buf[5];
         native_handle* h = native_handle_create(numFds, numInts);
+        if (!h) {
+            width = height = stride = format = usage = 0;
+            handle = NULL;
+            ALOGE("unflatten: native_handle_create failed");
+            return NO_MEMORY;
+        }
         memcpy(h->data,          fds,     numFds*sizeof(int));
         memcpy(h->data + numFds, &buf[10], numInts*sizeof(int));
         handle = h;
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index a4364c6..d69a275 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -101,7 +101,7 @@
     EXPECT_TRUE(eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs));
 
     struct DummyConsumer : public BnConsumerListener {
-        virtual void onFrameAvailable() {}
+        virtual void onFrameAvailable(const BufferItem& /* item */) {}
         virtual void onBuffersReleased() {}
         virtual void onSidebandStreamChanged() {}
     };
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 57e94ef..76545f3 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -83,6 +83,12 @@
     LOCAL_CFLAGS += -DPRESENT_TIME_OFFSET_FROM_VSYNC_NS=0
 endif
 
+ifneq ($(MAX_VIRTUAL_DISPLAY_DIMENSION),)
+    LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=$(MAX_VIRTUAL_DISPLAY_DIMENSION)
+else
+    LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=0
+endif
+
 LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
 LOCAL_CFLAGS += -std=c++11
 
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index d3f784a..8695a44 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -37,7 +37,7 @@
 
 namespace android {
 
-class DisplayInfo;
+struct DisplayInfo;
 class DisplaySurface;
 class IGraphicBufferProducer;
 class Layer;
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 086ccf8..22d3cec 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -68,7 +68,7 @@
     mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
 }
 
-status_t FramebufferSurface::beginFrame(bool mustRecompose) {
+status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
     return NO_ERROR;
 }
 
@@ -122,7 +122,7 @@
 }
 
 // Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
-void FramebufferSurface::onFrameAvailable() {
+void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
     sp<GraphicBuffer> buf;
     sp<Fence> acquireFence;
     status_t err = nextBuffer(buf, acquireFence);
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index d0bf22b..8605862 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -56,7 +56,7 @@
 private:
     virtual ~FramebufferSurface() { }; // this class cannot be overloaded
 
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
     virtual void freeBufferLocked(int slotIndex);
 
     virtual void dumpLocked(String8& result, const char* prefix) const;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 5cb56a0..a62ac5c 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -196,7 +196,7 @@
      * This behaves more or less like a forward iterator.
      */
     class LayerListIterator {
-        friend struct HWComposer;
+        friend class HWComposer;
         HWCLayer* const mLayerList;
         size_t mIndex;
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f6ad503..acc2775 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -159,7 +159,7 @@
     }
 }
 
-void Layer::onFrameAvailable() {
+void Layer::onFrameAvailable(const BufferItem& /* item */) {
     android_atomic_inc(&mQueuedFrames);
     mFlinger->signalLayerUpdate();
 }
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 1f8eff0..e2100fc 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -330,7 +330,7 @@
 
 private:
     // Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
     virtual void onSidebandStreamChanged();
 
     void commitTransaction();
diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
index 4de0ddc..a0cfca9 100644
--- a/services/surfaceflinger/LayerDim.h
+++ b/services/surfaceflinger/LayerDim.h
@@ -28,7 +28,7 @@
 
 class LayerDim : public Layer
 {
-public:    
+public:
                 LayerDim(SurfaceFlinger* flinger, const sp<Client>& client,
                         const String8& name, uint32_t w, uint32_t h, uint32_t flags);
         virtual ~LayerDim();
@@ -36,7 +36,7 @@
     virtual const char* getTypeId() const { return "LayerDim"; }
     virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
             bool useIdentityTransform) const;
-    virtual bool isOpaque() const         { return false; }
+    virtual bool isOpaque(const Layer::State&) const { return false; }
     virtual bool isSecure() const         { return false; }
     virtual bool isFixedSize() const      { return true; }
     virtual bool isVisible() const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 50968e7..c469627 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -507,6 +507,9 @@
         return BAD_VALUE;
     }
 
+    if (!display.get())
+        return NAME_NOT_FOUND;
+
     int32_t type = NAME_NOT_FOUND;
     for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
         if (display == mBuiltinDisplays[i]) {
@@ -653,7 +656,7 @@
         virtual bool handler() {
             Vector<DisplayInfo> configs;
             mFlinger.getDisplayConfigs(mDisplay, &configs);
-            if(mMode < 0 || mMode >= configs.size()) {
+            if (mMode < 0 || mMode >= static_cast<int>(configs.size())) {
                 ALOGE("Attempt to set active config = %d for display with %zu configs",
                         mMode, configs.size());
             }
@@ -1328,7 +1331,22 @@
                         // etc.) but no internal state (i.e. a DisplayDevice).
                         if (state.surface != NULL) {
 
-                            hwcDisplayId = allocateHwcDisplayId(state.type);
+                            int width = 0;
+                            int status = state.surface->query(
+                                    NATIVE_WINDOW_WIDTH, &width);
+                            ALOGE_IF(status != NO_ERROR,
+                                    "Unable to query width (%d)", status);
+                            int height = 0;
+                            status = state.surface->query(
+                                    NATIVE_WINDOW_HEIGHT, &height);
+                            ALOGE_IF(status != NO_ERROR,
+                                    "Unable to query height (%d)", status);
+                            if (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
+                                    (width <= MAX_VIRTUAL_DISPLAY_DIMENSION &&
+                                     height <= MAX_VIRTUAL_DISPLAY_DIMENSION)) {
+                                hwcDisplayId = allocateHwcDisplayId(state.type);
+                            }
+
                             sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(
                                     *mHwc, hwcDisplayId, state.surface,
                                     bqProducer, bqConsumer, state.displayName);
@@ -3089,13 +3107,13 @@
     if (sourceCrop.left < 0) {
         ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left);
     }
-    if (sourceCrop.right > hw_w) {
+    if (static_cast<uint32_t>(sourceCrop.right) > hw_w) {
         ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, hw_w);
     }
     if (sourceCrop.top < 0) {
         ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top);
     }
-    if (sourceCrop.bottom > hw_h) {
+    if (static_cast<uint32_t>(sourceCrop.bottom) > hw_h) {
         ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h);
     }