am c6f93a43: Merge "Add missing include to fix libc++ build."

* commit 'c6f93a43d636b0ad16b75adf664c6a33d30b39dd':
  Add missing include to fix libc++ build.
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 9e5c910..f0a52d8 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -77,7 +77,7 @@
     { "webview",    "WebView",          ATRACE_TAG_WEBVIEW, { } },
     { "wm",         "Window Manager",   ATRACE_TAG_WINDOW_MANAGER, { } },
     { "am",         "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } },
-    { "sync",       "Sync Manager",     ATRACE_TAG_SYNC_MANAGER, { } },
+    { "sm",         "Sync Manager",     ATRACE_TAG_SYNC_MANAGER, { } },
     { "audio",      "Audio",            ATRACE_TAG_AUDIO, { } },
     { "video",      "Video",            ATRACE_TAG_VIDEO, { } },
     { "camera",     "Camera",           ATRACE_TAG_CAMERA, { } },
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 1fbcef6..f9942e9 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
@@ -75,6 +76,28 @@
     }
 }
 
+static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
+{
+    DIR *d;
+    struct dirent *de;
+    char path[PATH_MAX];
+
+    d = opendir(driverpath);
+    if (d == NULL) {
+        return;
+    }
+
+    while ((de = readdir(d))) {
+        if (de->d_type != DT_LNK) {
+            continue;
+        }
+        snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
+        dump_file(title, path);
+    }
+
+    closedir(d);
+}
+
 /* dumps the current system state to stdout */
 static void dumpstate() {
     time_t now = time(NULL);
@@ -107,7 +130,9 @@
     printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
     printf("\n");
 
+    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 0a307c9..f2d8bef 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;
@@ -1017,6 +1018,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/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 3fc5de2..c619a11 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -197,6 +197,12 @@
 
     uint32_t mStickyTransform;
 
+    // This saves the fence from the last queueBuffer, such that the
+    // next queueBuffer call can throttle buffer production. The prior
+    // queueBuffer's fence is not nessessarily available elsewhere,
+    // since the previous buffer might have already been acquired.
+    sp<Fence> mLastQueueBufferFence;
+
 }; // class BufferQueueProducer
 
 } // namespace android
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/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/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index d2fd3b0..03bd4fd 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -38,7 +38,8 @@
     mCore(core),
     mSlots(core->mSlots),
     mConsumerName(),
-    mStickyTransform(0) {}
+    mStickyTransform(0),
+    mLastQueueBufferFence(Fence::NO_FENCE) {}
 
 BufferQueueProducer::~BufferQueueProducer() {}
 
@@ -522,12 +523,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) {
@@ -649,6 +645,15 @@
         ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
     } // Autolock scope
 
+    // Wait without lock held
+    if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) {
+        // Waiting here allows for two full buffers to be queued but not a
+        // third. In the event that frames take varying time, this makes a
+        // small trade-off in favor of latency rather than throughput.
+        mLastQueueBufferFence->waitForever("Throttling EGL Production");
+        mLastQueueBufferFence = fence;
+    }
+
     // Call back without lock held
     if (listener != NULL) {
         listener->onFrameAvailable();
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 6ba2ef8..b886c5b 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;
         }
     }
@@ -1065,6 +1065,7 @@
         if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
            ALOGE("~EglImage: eglDestroyImageKHR failed");
         }
+        eglTerminate(mEglDisplay);
     }
 }
 
@@ -1079,6 +1080,7 @@
         if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
            ALOGE("createIfNeeded: eglDestroyImageKHR failed");
         }
+        eglTerminate(mEglDisplay);
         mEglImage = EGL_NO_IMAGE_KHR;
         mEglDisplay = EGL_NO_DISPLAY;
     }
@@ -1129,11 +1131,13 @@
         // removes this restriction if there is hardware that can support it.
         attrs[2] = EGL_NONE;
     }
+    eglInitialize(dpy, 0, 0);
     EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
             EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
     if (image == EGL_NO_IMAGE_KHR) {
         EGLint error = eglGetError();
         ALOGE("error creating EGLImage: %#x", error);
+        eglTerminate(dpy);
     }
     return image;
 }
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 9d3f116..39f8f92 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/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/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index a273c96..eade2e2 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/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 086ccf8..b767983 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;
 }
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index fa07656..f6ad503 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -278,12 +278,17 @@
 
 Rect Layer::computeBounds() const {
     const Layer::State& s(getDrawingState());
+    return computeBounds(s.activeTransparentRegion);
+}
+
+Rect Layer::computeBounds(const Region& activeTransparentRegion) const {
+    const Layer::State& s(getDrawingState());
     Rect win(s.active.w, s.active.h);
     if (!s.active.crop.isEmpty()) {
         win.intersect(s.active.crop, &win);
     }
     // subtract the transparent region and snap to the bounds
-    return reduce(win, s.activeTransparentRegion);
+    return reduce(win, activeTransparentRegion);
 }
 
 FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
@@ -405,7 +410,22 @@
 
     // apply the layer's transform, followed by the display's global transform
     // here we're guaranteed that the layer's transform preserves rects
-    Rect frame(s.transform.transform(computeBounds()));
+    Region activeTransparentRegion(s.activeTransparentRegion);
+    if (!s.active.crop.isEmpty()) {
+        Rect activeCrop(s.active.crop);
+        activeCrop = s.transform.transform(activeCrop);
+        activeCrop.intersect(hw->getViewport(), &activeCrop);
+        activeCrop = s.transform.inverse().transform(activeCrop);
+        // mark regions outside the crop as transparent
+        activeTransparentRegion.orSelf(Rect(0, 0, s.active.w, activeCrop.top));
+        activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom,
+                s.active.w, s.active.h));
+        activeTransparentRegion.orSelf(Rect(0, activeCrop.top,
+                activeCrop.left, activeCrop.bottom));
+        activeTransparentRegion.orSelf(Rect(activeCrop.right, activeCrop.top,
+                s.active.w, activeCrop.bottom));
+    }
+    Rect frame(s.transform.transform(computeBounds(activeTransparentRegion)));
     frame.intersect(hw->getViewport(), &frame);
     const Transform& tr(hw->getTransform());
     layer.setFrame(tr.transform(frame));
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index f0fe58a..1f8eff0 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -142,6 +142,7 @@
 
     void computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
             bool useIdentityTransform) const;
+    Rect computeBounds(const Region& activeTransparentRegion) const;
     Rect computeBounds() const;
 
     sp<IBinder> getHandle();
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/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index d5d5da8..a77e0e9 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -219,6 +219,10 @@
     drawMesh(mesh);
 }
 
+void RenderEngine::flush() {
+    glFlush();
+}
+
 void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
     glClearColor(red, green, blue, alpha);
     glClear(GL_COLOR_BUFFER_BIT);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index acbff9b..8d7529c 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -67,6 +67,7 @@
     virtual void dump(String8& result);
 
     // helpers
+    void flush();
     void clearWithColor(float red, float green, float blue, float alpha);
     void fillRegionWithColor(const Region& region, uint32_t height,
             float red, float green, float blue, float alpha);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index c6a4c7a..77fc347 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());
             }
@@ -1332,7 +1335,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);
@@ -3093,13 +3111,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);
     }
 
@@ -3205,6 +3223,8 @@
                         EGLSyncKHR sync;
                         if (!DEBUG_SCREENSHOTS) {
                            sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+                           // native fence fd will not be populated until flush() is done.
+                           getRenderEngine().flush();
                         } else {
                             sync = EGL_NO_SYNC_KHR;
                         }
@@ -3251,10 +3271,8 @@
                 } else {
                     result = BAD_VALUE;
                 }
+                // queueBuffer takes ownership of syncFd
                 window->queueBuffer(window, buffer, syncFd);
-                if (syncFd != -1) {
-                    close(syncFd);
-                }
             }
         } else {
             result = BAD_VALUE;