Merge "gralloc: Fix NV12_ENCODEABLE allocation"
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index 2a4b1c5..65c78f7 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -341,6 +341,13 @@
                             __FUNCTION__, value);
                 }
                 break;
+            case COPYBIT_FG_LAYER:
+                if(value == COPYBIT_ENABLE) {
+                     ctx->mFlags |= MDP_IS_FG;
+                } else if (value == COPYBIT_DISABLE) {
+                    ctx->mFlags &= ~MDP_IS_FG;
+                }
+                break ;
             default:
                 status = -EINVAL;
                 break;
diff --git a/libcopybit/copybit.h b/libcopybit/copybit.h
index 0f4332f..878eca4 100644
--- a/libcopybit/copybit.h
+++ b/libcopybit/copybit.h
@@ -77,6 +77,7 @@
     COPYBIT_FRAMEBUFFER_WIDTH = 7,
     /* FB height */
     COPYBIT_FRAMEBUFFER_HEIGHT = 8,
+    COPYBIT_FG_LAYER = 9,
 };
 
 /* values for copybit_set_parameter(COPYBIT_TRANSFORM) */
diff --git a/libexternal/Android.mk b/libexternal/Android.mk
index f723113..3df6984 100644
--- a/libexternal/Android.mk
+++ b/libexternal/Android.mk
@@ -6,7 +6,7 @@
 LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES        := $(common_libs) liboverlay
+LOCAL_SHARED_LIBRARIES        := $(common_libs) liboverlay libqdutils
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdexternal\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES               := external.cpp
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index b247dfb..89d63e9 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -34,6 +34,7 @@
 #include "external.h"
 #include "overlayUtils.h"
 #include "overlay.h"
+#include "mdp_version.h"
 
 using namespace android;
 
@@ -65,6 +66,11 @@
     return 0;
 }
 
+void ExternalDisplay::getAttributes(int& width, int& height) {
+    int fps = 0;
+    getAttrForMode(width, height, fps);
+}
+
 int ExternalDisplay::teardown() {
     closeFrameBuffer();
     resetInfo();
@@ -564,15 +570,38 @@
     return ret;
 }
 
+
 void ExternalDisplay::setAttributes() {
     int width = 0, height = 0, fps = 0;
     getAttrForMode(width, height, fps);
-
     ALOGD("ExtDisplay setting xres = %d, yres = %d", width, height);
-    mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = width;
-    mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = height;
-    mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].vsync_period =
-        1000000000l / fps;
+    if(mHwcContext) {
+        // Always set dpyAttr res to mVInfo res
+        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = width;
+        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = height;
+        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode = false;
+        if(!qdutils::MDPVersion::getInstance().is8x26()) {
+            int priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
+            int priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
+            // if primary resolution is more than the hdmi resolution
+            // configure dpy attr to primary resolution and set
+            // downscale mode
+            if((priW * priH) > (width * height)) {
+                mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = priW;
+                mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = priH;
+                // HDMI is always in landscape, so always assign the higher
+                // dimension to hdmi's xres
+                if(priH > priW) {
+                    mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = priH;
+                    mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = priW;
+                }
+                // Set External Display MDP Downscale mode indicator
+                mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode =true;
+            }
+        }
+        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].vsync_period =
+                1000000000l / fps;
+    }
 }
 
 void ExternalDisplay::getAttrForMode(int& width, int& height, int& fps) {
diff --git a/libexternal/external.h b/libexternal/external.h
index 2fbb027..1a3602d 100644
--- a/libexternal/external.h
+++ b/libexternal/external.h
@@ -45,6 +45,7 @@
     void setActionSafeDimension(int w, int h);
     bool isCEUnderscanSupported() { return mUnderscanSupported; }
     int configure();
+    void getAttributes(int& width, int& height);
     int teardown();
     bool isConnected() {
         return  mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].connected;
diff --git a/libgenlock/Android.mk b/libgenlock/Android.mk
deleted file mode 100644
index 96e8b4e..0000000
--- a/libgenlock/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(LOCAL_PATH)/../common.mk
-include $(CLEAR_VARS)
-
-LOCAL_MODULE                  := libgenlock
-LOCAL_MODULE_TAGS             := optional
-LOCAL_C_INCLUDES              := $(common_includes)
-LOCAL_SHARED_LIBRARIES        := liblog libcutils
-LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdgenlock\"
-LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
-LOCAL_SRC_FILES               := genlock.cpp
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/libgenlock/genlock.cpp b/libgenlock/genlock.cpp
deleted file mode 100644
index c606ecc..0000000
--- a/libgenlock/genlock.cpp
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *   * Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the following
- *     disclaimer in the documentation and/or other materials provided
- *     with the distribution.
- *   * Neither the name of The Linux Foundation nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <cutils/log.h>
-#include <cutils/native_handle.h>
-#include <gralloc_priv.h>
-#include <linux/genlock.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-#include "genlock.h"
-
-#define GENLOCK_DEVICE "/dev/genlock"
-
-namespace {
-/* Internal function to map the userspace locks to the kernel lock types */
-    int get_kernel_lock_type(genlock_lock_type lockType)
-    {
-        int kLockType = 0;
-#ifdef USE_GENLOCK
-        // If the user sets both a read and write lock, higher preference is
-        // given to the write lock.
-        if (lockType & GENLOCK_WRITE_LOCK) {
-            kLockType = GENLOCK_WRLOCK;
-        } else if (lockType & GENLOCK_READ_LOCK) {
-            kLockType = GENLOCK_RDLOCK;
-        } else {
-            ALOGE("%s: invalid lockType (lockType = %d)",
-                  __FUNCTION__, lockType);
-            return -1;
-        }
-#endif
-        return kLockType;
-    }
-
-    /* Internal function to perform the actual lock/unlock operations */
-    genlock_status_t perform_lock_unlock_operation(native_handle_t *buffer_handle,
-                                                   int lockType, int timeout,
-                                                   int flags)
-    {
-#ifdef USE_GENLOCK
-        if (private_handle_t::validate(buffer_handle)) {
-            ALOGE("%s: handle is invalid", __FUNCTION__);
-            return GENLOCK_FAILURE;
-        }
-
-        private_handle_t *hnd = reinterpret_cast<private_handle_t*>
-                                (buffer_handle);
-        if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) {
-            if (hnd->genlockPrivFd < 0) {
-                ALOGE("%s: the lock has not been created,"
-                      "or has not been attached", __FUNCTION__);
-                return GENLOCK_FAILURE;
-            }
-
-            genlock_lock lock;
-            lock.op = lockType;
-            lock.flags = flags;
-            lock.timeout = timeout;
-            lock.fd = hnd->genlockHandle;
-
-#ifdef GENLOCK_IOC_DREADLOCK
-            if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_DREADLOCK, &lock)) {
-                ALOGE("%s: GENLOCK_IOC_DREADLOCK failed (lockType0x%x,"
-                       "err=%s fd=%d)", __FUNCTION__,
-                      lockType, strerror(errno), hnd->fd);
-                if (ETIMEDOUT == errno)
-                    return GENLOCK_TIMEDOUT;
-
-                return GENLOCK_FAILURE;
-            }
-#else
-            // depreciated
-            if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_LOCK, &lock)) {
-                ALOGE("%s: GENLOCK_IOC_LOCK failed (lockType0x%x, err=%s fd=%d)"
-                      ,__FUNCTION__, lockType, strerror(errno), hnd->fd);
-                if (ETIMEDOUT == errno)
-                    return GENLOCK_TIMEDOUT;
-
-                return GENLOCK_FAILURE;
-            }
-#endif
-        }
-#endif
-        return GENLOCK_NO_ERROR;
-    }
-
-    /* Internal function to close the fd and release the handle */
-    void close_genlock_fd_and_handle(int& fd, int& handle)
-    {
-        if (fd >=0 ) {
-            close(fd);
-            fd = -1;
-        }
-
-        if (handle >= 0) {
-            close(handle);
-            handle = -1;
-        }
-    }
-}
-/*
- * Create a genlock lock. The genlock lock file descriptor and the lock
- * handle are stored in the buffer_handle.
- *
- * @param: handle of the buffer
- * @return error status.
- */
-genlock_status_t genlock_create_lock(native_handle_t *buffer_handle)
-{
-    genlock_status_t ret = GENLOCK_NO_ERROR;
-#ifdef USE_GENLOCK
-    if (private_handle_t::validate(buffer_handle)) {
-        ALOGE("%s: handle is invalid", __FUNCTION__);
-        return GENLOCK_FAILURE;
-    }
-
-    private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle);
-    if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) {
-        // Open the genlock device
-        int fd = open(GENLOCK_DEVICE, O_RDWR);
-        if (fd < 0) {
-            ALOGE("%s: open genlock device failed (err=%s)", __FUNCTION__,
-                  strerror(errno));
-            return GENLOCK_FAILURE;
-        }
-
-        // Create a new lock
-        genlock_lock lock;
-        if (ioctl(fd, GENLOCK_IOC_NEW, NULL)) {
-            ALOGE("%s: GENLOCK_IOC_NEW failed (error=%s)", __FUNCTION__,
-                  strerror(errno));
-            close_genlock_fd_and_handle(fd, lock.fd);
-            ret = GENLOCK_FAILURE;
-        }
-
-        // Export the lock for other processes to be able to use it.
-        if (GENLOCK_FAILURE != ret) {
-            if (ioctl(fd, GENLOCK_IOC_EXPORT, &lock)) {
-                ALOGE("%s: GENLOCK_IOC_EXPORT failed (error=%s)", __FUNCTION__,
-                      strerror(errno));
-                close_genlock_fd_and_handle(fd, lock.fd);
-                ret = GENLOCK_FAILURE;
-            }
-        }
-
-        // Store the lock params in the handle.
-        hnd->genlockPrivFd = fd;
-        hnd->genlockHandle = lock.fd;
-    } else {
-        hnd->genlockHandle = 0;
-    }
-#endif
-    return ret;
-}
-
-
-/*
- * Release a genlock lock associated with the handle.
- *
- * @param: handle of the buffer
- * @return error status.
- */
-genlock_status_t genlock_release_lock(native_handle_t *buffer_handle)
-{
-    genlock_status_t ret = GENLOCK_NO_ERROR;
-#ifdef USE_GENLOCK
-    if (private_handle_t::validate(buffer_handle)) {
-        ALOGE("%s: handle is invalid", __FUNCTION__);
-        return GENLOCK_FAILURE;
-    }
-
-    private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle);
-    if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) {
-        if (hnd->genlockPrivFd < 0) {
-            ALOGE("%s: the lock is invalid", __FUNCTION__);
-            return GENLOCK_FAILURE;
-        }
-
-        // Close the fd and reset the parameters.
-        close_genlock_fd_and_handle(hnd->genlockPrivFd, hnd->genlockHandle);
-    }
-#endif
-    return ret;
-}
-
-
-/*
- * Attach a lock to the buffer handle passed via an IPC.
- *
- * @param: handle of the buffer
- * @return error status.
- */
-genlock_status_t genlock_attach_lock(native_handle_t *buffer_handle)
-{
-    genlock_status_t ret = GENLOCK_NO_ERROR;
-#ifdef USE_GENLOCK
-    if (private_handle_t::validate(buffer_handle)) {
-        ALOGE("%s: handle is invalid", __FUNCTION__);
-        return GENLOCK_FAILURE;
-    }
-
-    private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle);
-    if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) {
-        // Open the genlock device
-        int fd = open(GENLOCK_DEVICE, O_RDWR);
-        if (fd < 0) {
-            ALOGE("%s: open genlock device failed (err=%s)", __FUNCTION__,
-                  strerror(errno));
-            return GENLOCK_FAILURE;
-        }
-
-        // Attach the local handle to an existing lock
-        genlock_lock lock;
-        lock.fd = hnd->genlockHandle;
-        if (ioctl(fd, GENLOCK_IOC_ATTACH, &lock)) {
-            ALOGE("%s: GENLOCK_IOC_ATTACH failed (err=%s)", __FUNCTION__,
-                  strerror(errno));
-            close_genlock_fd_and_handle(fd, lock.fd);
-            ret = GENLOCK_FAILURE;
-        }
-
-        // Store the relavant information in the handle
-        hnd->genlockPrivFd = fd;
-    }
-#endif
-    return ret;
-}
-
-/*
- * Lock the buffer specified by the buffer handle. The lock held by the buffer
- * is specified by the lockType. This function will block if a write lock is
- * requested on the buffer which has previously been locked for a read or write
- * operation. A buffer can be locked by multiple clients for read. An optional
- * timeout value can be specified. By default, there is no timeout.
- *
- * @param: handle of the buffer
- * @param: type of lock to be acquired by the buffer.
- * @param: timeout value in ms. GENLOCK_MAX_TIMEOUT is the maximum timeout value.
- * @return error status.
- */
-genlock_status_t genlock_lock_buffer(native_handle_t *buffer_handle,
-                                     genlock_lock_type_t lockType,
-                                     int timeout)
-{
-    genlock_status_t ret = GENLOCK_NO_ERROR;
-#ifdef USE_GENLOCK
-    // Translate the locktype
-    int kLockType = get_kernel_lock_type(lockType);
-    if (-1 == kLockType) {
-        ALOGE("%s: invalid lockType", __FUNCTION__);
-        return GENLOCK_FAILURE;
-    }
-
-    if (0 == timeout) {
-        ALOGW("%s: trying to lock a buffer with timeout = 0", __FUNCTION__);
-    }
-    // Call the private function to perform the lock operation specified.
-    ret = perform_lock_unlock_operation(buffer_handle, kLockType, timeout, 0);
-#endif
-    return ret;
-}
-
-
-/*
- * Unlocks a buffer that has previously been locked by the client.
- *
- * @param: handle of the buffer to be unlocked.
- * @return: error status.
- */
-genlock_status_t genlock_unlock_buffer(native_handle_t *buffer_handle)
-{
-    genlock_status_t ret = GENLOCK_NO_ERROR;
-#ifdef USE_GENLOCK
-    // Do the unlock operation by setting the unlock flag. Timeout is always
-    // 0 in this case.
-    ret = perform_lock_unlock_operation(buffer_handle, GENLOCK_UNLOCK, 0, 0);
-#endif
-    return ret;
-}
-
-/*
- * Blocks the calling process until the lock held on the handle is unlocked.
- *
- * @param: handle of the buffer
- * @param: timeout value for the wait.
- * return: error status.
- */
-genlock_status_t genlock_wait(native_handle_t *buffer_handle, int timeout) {
-#ifdef USE_GENLOCK
-    if (private_handle_t::validate(buffer_handle)) {
-        ALOGE("%s: handle is invalid", __FUNCTION__);
-        return GENLOCK_FAILURE;
-    }
-
-    private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle);
-    if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) {
-        if (hnd->genlockPrivFd < 0) {
-            ALOGE("%s: the lock is invalid", __FUNCTION__);
-            return GENLOCK_FAILURE;
-        }
-
-        if (0 == timeout)
-            ALOGW("%s: timeout = 0", __FUNCTION__);
-
-        genlock_lock lock;
-        lock.fd = hnd->genlockHandle;
-        lock.timeout = timeout;
-        if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_WAIT, &lock)) {
-            ALOGE("%s: GENLOCK_IOC_WAIT failed (err=%s)",  __FUNCTION__,
-                  strerror(errno));
-            return GENLOCK_FAILURE;
-        }
-    }
-#endif
-    return GENLOCK_NO_ERROR;
-}
-
-/*
- * Convert a write lock that we own to a read lock
- *
- * @param: handle of the buffer
- * @param: timeout value for the wait.
- * return: error status.
- */
-genlock_status_t genlock_write_to_read(native_handle_t *buffer_handle,
-                                       int timeout) {
-    genlock_status_t ret = GENLOCK_NO_ERROR;
-#ifdef USE_GENLOCK
-    if (0 == timeout) {
-        ALOGW("%s: trying to lock a buffer with timeout = 0", __FUNCTION__);
-    }
-    // Call the private function to perform the lock operation specified.
-#ifdef GENLOCK_IOC_DREADLOCK
-    ret = perform_lock_unlock_operation(buffer_handle, GENLOCK_RDLOCK, timeout,
-                                        GENLOCK_WRITE_TO_READ);
-#else
-    // depreciated
-    ret = perform_lock_unlock_operation(buffer_handle, GENLOCK_RDLOCK,
-                                        timeout, 0);
-#endif
-#endif
-    return ret;
-}
diff --git a/libgenlock/genlock.h b/libgenlock/genlock.h
deleted file mode 100644
index 222f2a7..0000000
--- a/libgenlock/genlock.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *   * Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the following
- *     disclaimer in the documentation and/or other materials provided
- *     with the distribution.
- *   * Neither the name of The Linux Foundation nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef INCLUDE_LIBGENLOCK
-#define INCLUDE_LIBGENLOCK
-
-#include <cutils/native_handle.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-    /* Genlock lock types */
-    typedef enum genlock_lock_type{
-        GENLOCK_READ_LOCK  = 1<<0,  // Read lock
-        GENLOCK_WRITE_LOCK = 1<<1,  // Write lock
-    }genlock_lock_type_t;
-
-    /* Genlock return values */
-    typedef enum genlock_status{
-        GENLOCK_NO_ERROR = 0,
-        GENLOCK_TIMEDOUT,
-        GENLOCK_FAILURE,
-    } genlock_status_t;
-
-    /* Genlock defines */
-#define GENLOCK_MAX_TIMEOUT 1000 // Max 1s timeout
-
-    /*
-     * Create a genlock lock. The genlock lock file descriptor and the lock
-     * handle are stored in the buffer_handle.
-     *
-     * @param: handle of the buffer
-     * @return error status.
-     */
-    genlock_status_t genlock_create_lock(native_handle_t *buffer_handle);
-
-
-    /*
-     * Release a genlock lock associated with the handle.
-     *
-     * @param: handle of the buffer
-     * @return error status.
-     */
-    genlock_status_t genlock_release_lock(native_handle_t *buffer_handle);
-
-    /*
-     * Attach a lock to the buffer handle passed via an IPC.
-     *
-     * @param: handle of the buffer
-     * @return error status.
-     */
-    genlock_status_t genlock_attach_lock(native_handle_t *buffer_handle);
-
-    /*
-     * Lock the buffer specified by the buffer handle. The lock held by the
-     * buffer is specified by the lockType. This function will block if a write
-     * lock is requested on the buffer which has previously been locked for a
-     * read or write operation. A buffer can be locked by multiple clients for
-     * read. An optional timeout value can be specified.
-     * By default, there is no timeout.
-     *
-     * @param: handle of the buffer
-     * @param: type of lock to be acquired by the buffer.
-     * @param: timeout value in ms. GENLOCK_MAX_TIMEOUT is the maximum timeout
-     *         value.
-     * @return error status.
-     */
-    genlock_status_t genlock_lock_buffer(native_handle_t *buffer_handle,
-                                         genlock_lock_type_t lockType,
-                                         int timeout);
-
-    /*
-     * Unlocks a buffer that has previously been locked by the client.
-     *
-     * @param: handle of the buffer to be unlocked.
-     * @return: error status.
-     */
-    genlock_status_t genlock_unlock_buffer(native_handle_t *buffer_handle);
-
-    /*
-     * Blocks the calling process until the lock held on the handle is unlocked.
-     *
-     * @param: handle of the buffer
-     * @param: timeout value for the wait.
-     * return: error status.
-     */
-    genlock_status_t genlock_wait(native_handle_t *buffer_handle, int timeout);
-
-    /*
-     * Convert a write lock that we own to a read lock
-     *
-     * @param: handle of the buffer
-     * @param: timeout value for the wait.
-     * return: error status.
-     */
-    genlock_status_t genlock_write_to_read(native_handle_t *buffer_handle,
-                                           int timeout);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 1f757bc..1b3e934 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -109,11 +109,17 @@
 #ifndef MDSS_TARGET
                 flags |= private_handle_t::PRIV_FLAGS_ITU_R_601_FR;
 #else
-                    if (usage & (GRALLOC_USAGE_HW_TEXTURE |
-                                 GRALLOC_USAGE_HW_VIDEO_ENCODER))
+                // Per the camera spec ITU 709 format should be set only for
+                // video encoding.
+                // It should be set to ITU 601 full range format for any other
+                // camera buffer
+                //
+                if (usage & GRALLOC_USAGE_HW_CAMERA_MASK) {
+                    if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
                         flags |= private_handle_t::PRIV_FLAGS_ITU_R_709;
-                    else if (usage & GRALLOC_USAGE_HW_CAMERA_ZSL)
+                    else
                         flags |= private_handle_t::PRIV_FLAGS_ITU_R_601_FR;
+                }
 #endif
             } else {
                 flags |= private_handle_t::PRIV_FLAGS_ITU_R_601;
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 558cc29..f90420f 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -118,6 +118,8 @@
             ctx->mFBUpdate[i]->reset();
         if(ctx->mCopyBit[i])
             ctx->mCopyBit[i]->reset();
+        if(ctx->mLayerRotMap[i])
+            ctx->mLayerRotMap[i]->reset();
     }
 
     ctx->mAD->reset();
@@ -258,6 +260,7 @@
     ctx->mBlankLock.lock();
     //Will be unlocked at the end of set
     ctx->mExtLock.lock();
+    ctx->mSecureLock.lock();
     reset(ctx, numDisplays, displays);
 
     ctx->mOverlay->configBegin();
@@ -612,6 +615,7 @@
     MDPComp::resetIdleFallBack();
     ctx->mVideoTransFlag = false;
     //Was locked at the beginning of prepare
+    ctx->mSecureLock.unlock();
     ctx->mExtLock.unlock();
     ctx->mBlankLock.unlock();
     return ret;
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index a701eb6..068e28a 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -291,7 +291,7 @@
             list->hwLayers[i].acquireFenceFd = -1;
         }
         retVal = drawLayerUsingCopybit(ctx, &(list->hwLayers[i]),
-                                                    renderBuffer, dpy);
+                                                    renderBuffer, dpy, !i);
         copybitLayerCount++;
         if(retVal < 0) {
             ALOGE("%s : drawLayerUsingCopybit failed", __FUNCTION__);
@@ -307,7 +307,7 @@
 }
 
 int  CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
-                                     private_handle_t *renderBuffer, int dpy)
+                          private_handle_t *renderBuffer, int dpy, bool isFG)
 {
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     int err = 0, acquireFd;
@@ -411,7 +411,7 @@
         dtdy < 1/copybitsMinScale){
         // The requested scale is out of the range the hardware
         // can support.
-       ALOGE("%s:%d::Need to scale twice dsdx=%f, dtdy=%f,copybitsMaxScale=%f,\
+       ALOGD("%s:%d::Need to scale twice dsdx=%f, dtdy=%f,copybitsMaxScale=%f,\
                                  copybitsMinScale=%f,screen_w=%d,screen_h=%d \
                   src_crop_width=%d src_crop_height=%d",__FUNCTION__,__LINE__,
               dsdx,dtdy,copybitsMaxScale,1/copybitsMinScale,screen_w,screen_h,
@@ -436,7 +436,7 @@
          tmp_w  = (tmp_w/2)*2;
          tmp_h = (tmp_h/2)*2;
        }
-       ALOGE("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
+       ALOGD("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
 
        int usage = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
        int format = fbHandle->format;
@@ -504,6 +504,9 @@
     copybit->set_parameter(copybit, COPYBIT_DITHER,
                              (dst.format == HAL_PIXEL_FORMAT_RGB_565)?
                                              COPYBIT_ENABLE : COPYBIT_DISABLE);
+    copybit->set_parameter(copybit, COPYBIT_FG_LAYER, isFG ?
+                                             COPYBIT_ENABLE : COPYBIT_DISABLE);
+
     copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
                                                 COPYBIT_ENABLE);
     copybit->set_sync(copybit, acquireFd);
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index 31de9ee..03fe950 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -49,7 +49,7 @@
     struct copybit_device_t *mEngine;
     // Helper functions for copybit composition
     int  drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
-                                       private_handle_t *renderBuffer, int dpy);
+                          private_handle_t *renderBuffer, int dpy, bool isFG);
     bool canUseCopybitForYUV (hwc_context_t *ctx);
     bool canUseCopybitForRGB (hwc_context_t *ctx,
                                      hwc_display_contents_1_t *list, int dpy);
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index ba3b5d2..a0f5faa 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -26,10 +26,12 @@
 #include "hwc_fbupdate.h"
 #include "mdp_version.h"
 #include "external.h"
+#include "virtual.h"
 
 using namespace qdutils;
 using namespace overlay;
 using overlay::Rotator;
+using namespace overlay::utils;
 
 namespace qhwc {
 
@@ -110,51 +112,46 @@
         hwc_rect_t sourceCrop = layer->sourceCrop;
         hwc_rect_t displayFrame = layer->displayFrame;
         int transform = layer->transform;
-        int fbWidth  = ctx->dpyAttr[mDpy].xres;
-        int fbHeight = ctx->dpyAttr[mDpy].yres;
         int rotFlags = ovutils::ROT_FLAGS_NONE;
 
         ovutils::eTransform orient =
                     static_cast<ovutils::eTransform>(transform);
-        if(mDpy && ctx->mExtOrientation) {
-            // If there is a external orientation set, use that
-            transform = ctx->mExtOrientation;
-            orient = static_cast<ovutils::eTransform >(ctx->mExtOrientation);
-        }
+        // use ext orientation if any
+        int extOrient = ctx->mExtOrientation;
+        if(ctx->mBufferMirrorMode)
+            extOrient = getMirrorModeOrientation(ctx);
 
         // Do not use getNonWormholeRegion() function to calculate the
         // sourceCrop during animation on external display and
         // Dont do wormhole calculation when extorientation is set on External
+        // Dont do wormhole calculation when extDownscale is enabled on External
         if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
             sourceCrop = layer->displayFrame;
             displayFrame = sourceCrop;
-        } else if((!mDpy || (mDpy && !ctx->mExtOrientation))
-                               && extOnlyLayerIndex == -1) {
+        } else if((!mDpy ||
+                   (mDpy && !extOrient
+                   && !ctx->dpyAttr[mDpy].mDownScaleMode))
+                   && (extOnlyLayerIndex == -1)) {
             if(!qdutils::MDPVersion::getInstance().is8x26()) {
                 getNonWormholeRegion(list, sourceCrop);
                 displayFrame = sourceCrop;
             }
         }
-        ovutils::Dim dpos(displayFrame.left,
-                          displayFrame.top,
-                          displayFrame.right - displayFrame.left,
-                          displayFrame.bottom - displayFrame.top);
-
         if(mDpy && !qdutils::MDPVersion::getInstance().is8x26()) {
-            // Get Aspect Ratio for external
-            getAspectRatioPosition(ctx, mDpy, ctx->mExtOrientation, dpos.x,
-                                    dpos.y, dpos.w, dpos.h);
+            if(extOrient || ctx->dpyAttr[mDpy].mDownScaleMode) {
+                calcExtDisplayPosition(ctx, mDpy, sourceCrop, displayFrame);
+                // If there is a external orientation set, use that
+                if(extOrient) {
+                    transform = extOrient;
+                    orient = static_cast<ovutils::eTransform >(extOrient);
+                }
+            }
             // Calculate the actionsafe dimensions for External(dpy = 1 or 2)
-            getActionSafePosition(ctx, mDpy, dpos.x, dpos.y, dpos.w, dpos.h);
-            // Convert dim to hwc_rect_t
-            displayFrame.left = dpos.x;
-            displayFrame.top = dpos.y;
-            displayFrame.right = dpos.w + displayFrame.left;
-            displayFrame.bottom = dpos.h + displayFrame.top;
+            getActionSafePosition(ctx, mDpy, displayFrame);
         }
         setMdpFlags(layer, mdpFlags, 0, transform);
         // For External use rotator if there is a rotation value set
-        if(mDpy && (ctx->mExtOrientation & HWC_TRANSFORM_ROT_90)) {
+        if(mDpy && (extOrient & HWC_TRANSFORM_ROT_90)) {
             mRot = ctx->mRotMgr->getNext();
             if(mRot == NULL) return -1;
             //Configure rotator for pre-rotation
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 5c0ad4d..e97d769 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -123,20 +123,24 @@
             sMaxPipesPerMixer = min(val, MAX_PIPES_PER_MIXER);
     }
 
-    long idle_timeout = DEFAULT_IDLE_TIME;
-    if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
-        if(atoi(property) != 0)
-            idle_timeout = atoi(property);
-    }
+    if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
+        // Idle invalidation is not necessary on command mode panels
+        long idle_timeout = DEFAULT_IDLE_TIME;
+        if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
+            if(atoi(property) != 0)
+                idle_timeout = atoi(property);
+        }
 
-    //create Idle Invalidator only when not disabled through property
-    if(idle_timeout != -1)
-        idleInvalidator = IdleInvalidator::getInstance();
+        //create Idle Invalidator only when not disabled through property
+        if(idle_timeout != -1)
+            idleInvalidator = IdleInvalidator::getInstance();
 
-    if(idleInvalidator == NULL) {
-        ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__);
-    } else {
-        idleInvalidator->init(timeout_handler, ctx, idle_timeout);
+        if(idleInvalidator == NULL) {
+            ALOGE("%s: failed to instantiate idleInvalidator object",
+                  __FUNCTION__);
+        } else {
+            idleInvalidator->init(timeout_handler, ctx, idle_timeout);
+        }
     }
     return true;
 }
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index b27a88c..5d7d4d3 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -64,6 +64,9 @@
         case IQService::EXTERNAL_ORIENTATION:
             setExtOrientation(value);
             break;
+        case IQService::BUFFER_MIRRORMODE:
+            setBufferMirrorMode(value);
+            break;
         default:
             return NO_ERROR;
     }
@@ -71,6 +74,7 @@
 }
 
 void QClient::securing(uint32_t startEnd) {
+    Locker::Autolock _sl(mHwcContext->mSecureLock);
     //The only way to make this class in this process subscribe to media
     //player's death.
     IMediaDeathNotifier::getMediaPlayerService();
@@ -84,6 +88,7 @@
 }
 
 void QClient::unsecuring(uint32_t startEnd) {
+    Locker::Autolock _sl(mHwcContext->mSecureLock);
     mHwcContext->mSecuring = startEnd;
     //We're done unsecuring
     if(startEnd == IQService::END)
@@ -93,6 +98,7 @@
 }
 
 void QClient::MPDeathNotifier::died() {
+    Locker::Autolock _sl(mHwcContext->mSecureLock);
     ALOGD_IF(QCLIENT_DEBUG, "Media Player died");
     mHwcContext->mSecuring = false;
     mHwcContext->mSecureMode = false;
@@ -115,4 +121,8 @@
     mHwcContext->mExtOrientation = orientation;
 }
 
+void QClient::setBufferMirrorMode(uint32_t enable) {
+    mHwcContext->mBufferMirrorMode = enable;
+}
+
 }
diff --git a/libhwcomposer/hwc_qclient.h b/libhwcomposer/hwc_qclient.h
index 4cbabef..848d8d2 100644
--- a/libhwcomposer/hwc_qclient.h
+++ b/libhwcomposer/hwc_qclient.h
@@ -61,6 +61,7 @@
     void unsecuring(uint32_t startEnd);
     android::status_t screenRefresh();
     void setExtOrientation(uint32_t orientation);
+    void setBufferMirrorMode(uint32_t enable);
 
     hwc_context_t *mHwcContext;
     const android::sp<android::IMediaDeathNotifier> mMPDeathNotifier;
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 0e2eb2e..fa3c15f 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -159,6 +159,9 @@
     ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected = false;
     ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = false;
     ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected = false;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].mDownScaleMode= false;
+    ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode = false;
+    ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = false;
 
     ctx->mMDPComp[HWC_DISPLAY_PRIMARY] =
          MDPComp::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
@@ -193,6 +196,8 @@
         ctx->mPrevDestVideo.right = ctx->mPrevDestVideo.bottom = 0;
     ctx->mPrevTransformVideo = 0;
 
+    ctx->mBufferMirrorMode = false;
+
     ALOGI("Initializing Qualcomm Hardware Composer");
     ALOGI("MDP version: %d", ctx->mMDP.version);
 }
@@ -262,8 +267,11 @@
 }
 
 /* Calculates the destination position based on the action safe rectangle */
-void getActionSafePosition(hwc_context_t *ctx, int dpy, uint32_t& x,
-                           uint32_t& y, uint32_t& w, uint32_t& h) {
+void getActionSafePosition(hwc_context_t *ctx, int dpy, hwc_rect_t& rect) {
+    // Position
+    int x = rect.left, y = rect.top;
+    int w = rect.right - rect.left;
+    int h = rect.bottom - rect.top;
 
     // if external supports underscan, do nothing
     // it will be taken care in the driver
@@ -291,7 +299,11 @@
     float fbHeight = ctx->dpyAttr[dpy].yres;
 
     // Since external is rotated 90, need to swap width/height
-    if(ctx->mExtOrientation & HWC_TRANSFORM_ROT_90)
+    int extOrient = ctx->mExtOrientation;
+    if(ctx->mBufferMirrorMode)
+        extOrient = getMirrorModeOrientation(ctx);
+
+    if(extOrient & HWC_TRANSFORM_ROT_90)
         swap(fbWidth, fbHeight);
 
     float asX = 0;
@@ -317,40 +329,245 @@
     w = (wRatio * asW);
     h = (hRatio * asH);
 
+    // Convert it back to hwc_rect_t
+    rect.left = x;
+    rect.top = y;
+    rect.right = w + rect.left;
+    rect.bottom = h + rect.top;
+
     return;
 }
 
-/* Calculates the aspect ratio for external based on the primary */
-void getAspectRatioPosition(hwc_context_t *ctx, int dpy, int orientation,
-                        uint32_t& x, uint32_t& y, uint32_t& w, uint32_t& h) {
-    int fbWidth  = ctx->dpyAttr[dpy].xres;
-    int fbHeight = ctx->dpyAttr[dpy].yres;
+/* Calculates the aspect ratio for based on src & dest */
+void getAspectRatioPosition(int destWidth, int destHeight, int srcWidth,
+                                int srcHeight, hwc_rect_t& rect) {
+   int x =0, y =0;
 
-    switch(orientation) {
-        case HAL_TRANSFORM_ROT_90:
-        case HAL_TRANSFORM_ROT_270:
-            y = 0;
-            h = fbHeight;
-            if (ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres <
-                ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres) {
-                // Portrait primary panel
-                w = (ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres *
-                     fbHeight/ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres);
-            } else {
-                //Landscape primary panel
-                w = (ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres *
-                     fbHeight/ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres);
-            }
-            x = (fbWidth - w)/2;
-            break;
-        default:
-            //Do nothing
-            break;
-     }
-    ALOGD_IF(HWC_UTILS_DEBUG, "%s: Position: x = %d, y = %d w = %d h = %d",
-                    __FUNCTION__, x, y, w ,h);
+   if (srcWidth * destHeight > destWidth * srcHeight) {
+        srcHeight = destWidth * srcHeight / srcWidth;
+        srcWidth = destWidth;
+    } else if (srcWidth * destHeight < destWidth * srcHeight) {
+        srcWidth = destHeight * srcWidth / srcHeight;
+        srcHeight = destHeight;
+    } else {
+        srcWidth = destWidth;
+        srcHeight = destHeight;
+    }
+    if (srcWidth > destWidth) srcWidth = destWidth;
+    if (srcHeight > destHeight) srcHeight = destHeight;
+    x = (destWidth - srcWidth) / 2;
+    y = (destHeight - srcHeight) / 2;
+    ALOGD_IF(HWC_UTILS_DEBUG, "%s: AS Position: x = %d, y = %d w = %d h = %d",
+             __FUNCTION__, x, y, srcWidth , srcHeight);
+    // Convert it back to hwc_rect_t
+    rect.left = x;
+    rect.top = y;
+    rect.right = srcWidth + rect.left;
+    rect.bottom = srcHeight + rect.top;
 }
 
+// This function gets the destination position for Seconday display
+// based on the position and aspect ratio with orientation
+void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
+                            hwc_rect_t& inRect, hwc_rect_t& outRect) {
+    // Physical display resolution
+    float fbWidth  = ctx->dpyAttr[dpy].xres;
+    float fbHeight = ctx->dpyAttr[dpy].yres;
+    //display position(x,y,w,h) in correct aspectratio after rotation
+    int xPos = 0;
+    int yPos = 0;
+    float width = fbWidth;
+    float height = fbHeight;
+    // Width/Height used for calculation, after rotation
+    float actualWidth = fbWidth;
+    float actualHeight = fbHeight;
+
+    float wRatio = 1.0;
+    float hRatio = 1.0;
+    float xRatio = 1.0;
+    float yRatio = 1.0;
+    hwc_rect_t rect = {0, 0, (int)fbWidth, (int)fbHeight};
+
+    Dim inPos(inRect.left, inRect.top, inRect.right - inRect.left,
+                inRect.bottom - inRect.top);
+    Dim outPos(outRect.left, outRect.top, outRect.right - outRect.left,
+                outRect.bottom - outRect.top);
+
+    Whf whf(fbWidth, fbHeight, 0);
+    eTransform extorient = static_cast<eTransform>(extOrientation);
+    // To calculate the destination co-ordinates in the new orientation
+    preRotateSource(extorient, whf, inPos);
+
+    if(extOrientation & HAL_TRANSFORM_ROT_90) {
+        // Swap width/height for input position
+        swapWidthHeight(actualWidth, actualHeight);
+        getAspectRatioPosition(fbWidth, fbHeight, (int)actualWidth,
+                               (int)actualHeight, rect);
+        xPos = rect.left;
+        yPos = rect.top;
+        width = rect.right - rect.left;
+        height = rect.bottom - rect.top;
+    }
+
+    //Calculate the position...
+    xRatio = inPos.x/actualWidth;
+    yRatio = inPos.y/actualHeight;
+    wRatio = inPos.w/actualWidth;
+    hRatio = inPos.h/actualHeight;
+
+    outPos.x = (xRatio * width) + xPos;
+    outPos.y = (yRatio * height) + yPos;
+    outPos.w = wRatio * width;
+    outPos.h = hRatio * height;
+    ALOGD_IF(HWC_UTILS_DEBUG, "%s: Calculated AspectRatio Position: x = %d,"
+                 "y = %d w = %d h = %d", __FUNCTION__, outPos.x, outPos.y,
+                 outPos.w, outPos.h);
+
+    // For sidesync, the dest fb will be in portrait orientation, and the crop
+    // will be updated to avoid the black side bands, and it will be upscaled
+    // to fit the dest RB, so recalculate
+    // the position based on the new width and height
+    if ((extOrientation & HWC_TRANSFORM_ROT_90) &&
+                        isOrientationPortrait(ctx)) {
+        hwc_rect_t r;
+        //Calculate the position
+        xRatio = (outPos.x - xPos)/width;
+        // GetaspectRatio -- tricky to get the correct aspect ratio
+        // But we need to do this.
+        getAspectRatioPosition(width, height, width, height, r);
+        xPos = r.left;
+        yPos = r.top;
+        float tempWidth = r.right - r.left;
+        float tempHeight = r.bottom - r.top;
+        yRatio = yPos/height;
+        wRatio = outPos.w/width;
+        hRatio = tempHeight/height;
+
+        //Map the coordinates back to Framebuffer domain
+        outPos.x = (xRatio * fbWidth);
+        outPos.y = (yRatio * fbHeight);
+        outPos.w = wRatio * fbWidth;
+        outPos.h = hRatio * fbHeight;
+
+        ALOGD_IF(HWC_UTILS_DEBUG, "%s: Calculated AspectRatio for device in"
+                 "portrait: x = %d,y = %d w = %d h = %d", __FUNCTION__,
+                 outPos.x, outPos.y,
+                 outPos.w, outPos.h);
+    }
+    if(ctx->dpyAttr[dpy].mDownScaleMode) {
+        int extW, extH;
+        if(dpy == HWC_DISPLAY_EXTERNAL)
+            ctx->mExtDisplay->getAttributes(extW, extH);
+        else
+            ctx->mVirtualDisplay->getAttributes(extW, extH);
+        fbWidth  = ctx->dpyAttr[dpy].xres;
+        fbHeight = ctx->dpyAttr[dpy].yres;
+        //Calculate the position...
+        xRatio = outPos.x/fbWidth;
+        yRatio = outPos.y/fbHeight;
+        wRatio = outPos.w/fbWidth;
+        hRatio = outPos.h/fbHeight;
+
+        outPos.x = xRatio * extW;
+        outPos.y = yRatio * extH;
+        outPos.w = wRatio * extW;
+        outPos.h = hRatio * extH;
+    }
+    // Convert Dim to hwc_rect_t
+    outRect.left = outPos.x;
+    outRect.top = outPos.y;
+    outRect.right = outPos.x + outPos.w;
+    outRect.bottom = outPos.y + outPos.h;
+
+    return;
+}
+
+bool isPrimaryPortrait(hwc_context_t *ctx) {
+    int fbWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
+    int fbHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
+    if(fbWidth < fbHeight) {
+        return true;
+    }
+    return false;
+}
+
+bool isOrientationPortrait(hwc_context_t *ctx) {
+    if(isPrimaryPortrait(ctx)) {
+        return !(ctx->deviceOrientation & 0x1);
+    }
+    return (ctx->deviceOrientation & 0x1);
+}
+
+void calcExtDisplayPosition(hwc_context_t *ctx, int dpy,
+                               hwc_rect_t& sourceCrop,
+                               hwc_rect_t& displayFrame) {
+    // Swap width and height when there is a 90deg transform
+    int extOrient = ctx->mExtOrientation;
+    if(ctx->mBufferMirrorMode)
+        extOrient = getMirrorModeOrientation(ctx);
+    if(extOrient & HWC_TRANSFORM_ROT_90) {
+        int dstWidth = ctx->dpyAttr[dpy].xres;
+        int dstHeight = ctx->dpyAttr[dpy].yres;;
+        int srcWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
+        int srcHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
+        if(!isPrimaryPortrait(ctx)) {
+            swap(srcWidth, srcHeight);
+        }                    // Get Aspect Ratio for external
+        getAspectRatioPosition(dstWidth, dstHeight, srcWidth,
+                            srcHeight, displayFrame);
+        // Crop - this is needed, because for sidesync, the dest fb will
+        // be in portrait orientation, so update the crop to not show the
+        // black side bands.
+        if (isOrientationPortrait(ctx)) {
+            sourceCrop = displayFrame;
+            displayFrame.left = 0;
+            displayFrame.top = 0;
+            displayFrame.right = dstWidth;
+            displayFrame.bottom = dstHeight;
+        }
+    }
+    if(ctx->dpyAttr[dpy].mDownScaleMode) {
+        int extW, extH;
+        // if downscale is enabled, map the co-ordinates to new
+        // domain(downscaled)
+        float fbWidth  = ctx->dpyAttr[dpy].xres;
+        float fbHeight = ctx->dpyAttr[dpy].yres;
+        // query MDP configured attributes
+        if(dpy == HWC_DISPLAY_EXTERNAL)
+            ctx->mExtDisplay->getAttributes(extW, extH);
+        else
+            ctx->mVirtualDisplay->getAttributes(extW, extH);
+        //Calculate the ratio...
+        float wRatio = ((float)extW)/fbWidth;
+        float hRatio = ((float)extH)/fbHeight;
+
+        //convert Dim to hwc_rect_t
+        displayFrame.left *= wRatio;
+        displayFrame.top *= hRatio;
+        displayFrame.right *= wRatio;
+        displayFrame.bottom *= hRatio;
+    }
+}
+
+/* Returns the orientation which needs to be set on External for
+ *  SideSync/Buffer Mirrormode
+ */
+int getMirrorModeOrientation(hwc_context_t *ctx) {
+    int extOrientation = 0;
+    int deviceOrientation = ctx->deviceOrientation;
+    if(!isPrimaryPortrait(ctx))
+        deviceOrientation = (deviceOrientation + 1) % 4;
+     if (deviceOrientation == 0)
+         extOrientation = HWC_TRANSFORM_ROT_270;
+     else if (deviceOrientation == 1)//90
+         extOrientation = 0;
+     else if (deviceOrientation == 2)//180
+         extOrientation = HWC_TRANSFORM_ROT_90;
+     else if (deviceOrientation == 3)//270
+         extOrientation = HWC_TRANSFORM_FLIP_V | HWC_TRANSFORM_FLIP_H;
+
+    return extOrientation;
+}
 
 bool needsScaling(hwc_context_t* ctx, hwc_layer_1_t const* layer,
         const int& dpy) {
@@ -474,9 +691,10 @@
         ctx->mExtOrientation = atoi(value); */
         // Assuming the orientation value is in terms of HAL_TRANSFORM,
         // This needs mapping to HAL, if its in different convention
-        if(ctx->mExtOrientation) {
-            ALOGD_IF(HWC_UTILS_DEBUG, "%s: ext orientation = %d",
-                     __FUNCTION__, ctx->mExtOrientation);
+        if(ctx->mExtOrientation || ctx->mBufferMirrorMode) {
+            ALOGD_IF(HWC_UTILS_DEBUG, "%s: ext orientation = %d"
+                     "BufferMirrorMode = %d", __FUNCTION__,
+                     ctx->mExtOrientation, ctx->mBufferMirrorMode);
             if(ctx->mOverlay->isPipeTypeAttached(OV_MDP_PIPE_DMA)) {
                 ctx->isPaddingRound = true;
             }
@@ -975,22 +1193,21 @@
             }
         }
     }
-
-    uint32_t x = dst.left, y  = dst.top;
-    uint32_t w = dst.right - dst.left;
-    uint32_t h = dst.bottom - dst.top;
-
     if(dpy) {
+        int extOrient = ctx->mExtOrientation;
+        if(ctx->mBufferMirrorMode)
+            extOrient = getMirrorModeOrientation(ctx);
         // Just need to set the position to portrait as the transformation
         // will already be set to required orientation on TV
-        getAspectRatioPosition(ctx, dpy, ctx->mExtOrientation, x, y, w, h);
+        if(extOrient || ctx->dpyAttr[dpy].mDownScaleMode) {
+            getAspectRatioPosition(ctx, dpy, extOrient, dst, dst);
+            if(extOrient) {
+                transform = extOrient;
+                orient = static_cast<eTransform>(transform);
+            }
+        }
         // Calculate the actionsafe dimensions for External(dpy = 1 or 2)
-        getActionSafePosition(ctx, dpy, x, y, w, h);
-        // Convert position to hwc_rect_t
-        dst.left = x;
-        dst.top = y;
-        dst.right = w + dst.left;
-        dst.bottom = h + dst.top;
+        getActionSafePosition(ctx, dpy, dst);
     }
 
     if(isYuvBuffer(hnd) && ctx->mMDP.version >= qdutils::MDP_V4_2 &&
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 9a7ef0d..71b51ab 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -83,6 +83,8 @@
     // To trigger padding round to clean up mdp
     // pipes
     bool isConfiguring;
+    // External Display is in MDP Downscale mode indicator
+    bool mDownScaleMode;
 };
 
 struct ListStats {
@@ -175,12 +177,25 @@
 void dumpsys_log(android::String8& buf, const char* fmt, ...);
 
 /* Calculates the destination position based on the action safe rectangle */
-void getActionSafePosition(hwc_context_t *ctx, int dpy, uint32_t& x,
-                                        uint32_t& y, uint32_t& w, uint32_t& h);
+void getActionSafePosition(hwc_context_t *ctx, int dpy, hwc_rect_t& dst);
 
+void getAspectRatioPosition(int destWidth, int destHeight, int srcWidth,
+                                int srcHeight, hwc_rect_t& rect);
 
-void getAspectRatioPosition(hwc_context_t *ctx, int dpy, int orientation,
-                        uint32_t& x, uint32_t& y, uint32_t& w, uint32_t& h);
+void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
+                                hwc_rect_t& inRect, hwc_rect_t& outRect);
+
+bool isPrimaryPortrait(hwc_context_t *ctx);
+
+bool isOrientationPortrait(hwc_context_t *ctx);
+
+void calcExtDisplayPosition(hwc_context_t *ctx,
+                               int dpy,
+                               hwc_rect_t& sourceCrop,
+                               hwc_rect_t& displayFrame);
+// Returns the orientation that needs to be set on external for
+// BufferMirrirMode(Sidesync)
+int getMirrorModeOrientation(hwc_context_t *ctx);
 
 //Close acquireFenceFds of all layers of incoming list
 void closeAcquireFds(hwc_display_contents_1_t* list);
@@ -346,12 +361,24 @@
     mutable Locker mBlankLock;
     //Lock to protect prepare & set when detaching external disp
     mutable Locker mExtLock;
+    /*Lock to set both mSecureMode and mSecuring as part
+      of binder thread without context switch to composition
+      thread. This lock is needed only for A-family targets
+      since the state of mSecureMode and mSecuring variables
+      are not checked in B-family targets.
+    */
+    mutable Locker mSecureLock;
     //Drawing round when we use GPU
     bool isPaddingRound;
     // External Orientation
     int mExtOrientation;
     //Flags the transition of a video session
     bool mVideoTransFlag;
+
+    //Used for SideSync feature
+    //which overrides the mExtOrientation
+    bool mBufferMirrorMode;
+
     qhwc::LayerRotMap *mLayerRotMap[HWC_NUM_DISPLAY_TYPES];
 };
 
diff --git a/libqservice/IQService.cpp b/libqservice/IQService.cpp
index a3ff150..e45f42e 100644
--- a/libqservice/IQService.cpp
+++ b/libqservice/IQService.cpp
@@ -78,6 +78,13 @@
         data.writeInt32(orientation);
         remote()->transact(EXTERNAL_ORIENTATION, data, &reply);
     }
+
+    virtual void setBufferMirrorMode(uint32_t enable) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IQService::getInterfaceDescriptor());
+        data.writeInt32(enable);
+        remote()->transact(BUFFER_MIRRORMODE, data, &reply);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(QService, "android.display.IQService");
@@ -160,6 +167,18 @@
             setExtOrientation(orientation);
             return NO_ERROR;
         } break;
+        case BUFFER_MIRRORMODE: {
+            CHECK_INTERFACE(IQService, data, reply);
+            if(callerUid != AID_SYSTEM) {
+                ALOGE("display.qservice BUFFER_MIRRORMODE access denied: \
+                      pid=%d uid=%d process=%s",callerPid,
+                      callerUid, callingProcName);
+                return PERMISSION_DENIED;
+            }
+            uint32_t enable = data.readInt32();
+            setBufferMirrorMode(enable);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index ff034be..149cd8b 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -42,6 +42,7 @@
         CONNECT,
         SCREEN_REFRESH,
         EXTERNAL_ORIENTATION,
+        BUFFER_MIRRORMODE,
     };
     enum {
         END = 0,
@@ -52,6 +53,7 @@
     virtual void connect(const android::sp<qClient::IQClient>& client) = 0;
     virtual android::status_t screenRefresh() = 0;
     virtual void setExtOrientation(uint32_t orientation) = 0;
+    virtual void setBufferMirrorMode(uint32_t enable) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libqservice/QService.cpp b/libqservice/QService.cpp
index f780a75..a8c5dca 100644
--- a/libqservice/QService.cpp
+++ b/libqservice/QService.cpp
@@ -77,6 +77,12 @@
     }
 }
 
+void QService::setBufferMirrorMode(uint32_t enable) {
+    if(mClient.get()) {
+        mClient->notifyCallback(BUFFER_MIRRORMODE, enable);
+    }
+}
+
 void QService::init()
 {
     if(!sQService) {
diff --git a/libqservice/QService.h b/libqservice/QService.h
index 8eefa21..a241d44 100644
--- a/libqservice/QService.h
+++ b/libqservice/QService.h
@@ -50,6 +50,7 @@
     virtual void connect(const android::sp<qClient::IQClient>& client);
     virtual android::status_t screenRefresh();
     virtual void setExtOrientation(uint32_t orientation);
+    virtual void setBufferMirrorMode(uint32_t enable);
     static void init();
 private:
     QService();
diff --git a/libtilerenderer/Android.mk b/libtilerenderer/Android.mk
deleted file mode 100644
index ca17fbc..0000000
--- a/libtilerenderer/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(LOCAL_PATH)/../common.mk
-include $(CLEAR_VARS)
-
-ifeq ($(USE_OPENGL_RENDERER),true)
-LOCAL_MODULE           := libtilerenderer
-LOCAL_MODULE_TAGS      := optional
-LOCAL_CFLAGS           := -DLOG_TAG=\"qdtilerenderer\"
-LOCAL_C_INCLUDES := \
-        frameworks/base/include/utils \
-        frameworks/base/libs/hwui \
-        external/skia/include/core \
-        external/skia/include/effects \
-        external/skia/include/images \
-        external/skia/src/ports \
-        external/skia/include/utils \
-        hardware/libhardware/include/hardware \
-        frameworks/base/opengl/include/GLES2
-LOCAL_SHARED_LIBRARIES := $(common_libs) libGLESv2 libhwui
-LOCAL_SRC_FILES        := tilerenderer.cpp
-
-include $(BUILD_SHARED_LIBRARY)
-endif
diff --git a/libtilerenderer/tilerenderer.cpp b/libtilerenderer/tilerenderer.cpp
deleted file mode 100644
index 03a0aea..0000000
--- a/libtilerenderer/tilerenderer.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <GLES2/gl2.h>
-#include <EGL/egl.h>
-#include <gl2ext.h>
-#include <OpenGLRenderer.h>
-#include "tilerenderer.h"
-
-namespace android {
-ANDROID_SINGLETON_STATIC_INSTANCE(uirenderer::TileRenderer) ;
-namespace uirenderer {
-
-TileRenderer::TileRenderer() {
-    mIsTiled = false;
-}
-
-TileRenderer::~TileRenderer() {
-}
-
-void TileRenderer::startTileRendering(OpenGLRenderer* renderer,
-                                      int left, int top,
-                                      int right, int bottom) {
-    int width = 0;
-    int height = 0;
-    GLenum status = GL_NO_ERROR;
-
-    if (renderer != NULL) {
-        renderer->getViewport(width, height);
-    }
-
-    if (!left && !right && !top && !bottom) {
-        left = 0;
-        top = 0;
-        right = width;
-        bottom = height;
-    }
-
-    if (!left && !right && !top && !bottom) {
-        //can't do tile rendering
-        ALOGE("can't tile render; drity region, width, height not available");
-        return;
-    }
-
-    int l = left, t = (height - bottom), w = (right - left), h = (bottom - top), preserve = 0;
-
-    if (l < 0 || t < 0) {
-        l = (l < 0) ? 0 : l;
-        t = (t < 0) ? 0 : t;
-        preserve = 1;
-    }
-
-    if (w > width || h > height) {
-        w = (w > width) ? width : w;
-        h = (h > height) ? height : h;
-        preserve = 1;
-    }
-
-    //clear off all errors before tiling, if any
-    while ((status = glGetError()) != GL_NO_ERROR);
-
-    if (preserve)
-        glStartTilingQCOM(l, t, w, h, GL_COLOR_BUFFER_BIT0_QCOM);
-    else
-        glStartTilingQCOM(l, t, w, h, GL_NONE);
-
-    status = glGetError();
-    if (status == GL_NO_ERROR)
-        mIsTiled = true;
-}
-
-void TileRenderer::endTileRendering(OpenGLRenderer*) {
-    if (!mIsTiled) {
-        return;
-    }
-    glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM);
-    mIsTiled = false;
-    GLenum status = GL_NO_ERROR;
-    while ((status = glGetError()) != GL_NO_ERROR);
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libtilerenderer/tilerenderer.h b/libtilerenderer/tilerenderer.h
deleted file mode 100644
index d894d33..0000000
--- a/libtilerenderer/tilerenderer.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef ANDROID_TILE_RENDERER_H
-#define ANDROID_TILE_RENDERER_H
-
-#include <utils/Singleton.h>
-
-namespace android {
-namespace uirenderer {
-
-class OpenGLRenderer;
-
-class TileRenderer: public Singleton<TileRenderer> {
-    public:
-    TileRenderer();
-    ~TileRenderer();
-
-    void startTileRendering(OpenGLRenderer* renderer, int left, int top, int right, int bottom);
-    void endTileRendering(OpenGLRenderer*);
-
-    private:
-    bool mIsTiled;
-};
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif
diff --git a/libvirtual/Android.mk b/libvirtual/Android.mk
index 1231f8d..beeef25 100644
--- a/libvirtual/Android.mk
+++ b/libvirtual/Android.mk
@@ -6,7 +6,7 @@
 LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES        := $(common_libs) liboverlay
+LOCAL_SHARED_LIBRARIES        := $(common_libs) liboverlay libqdutils
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdvirtual\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES               := virtual.cpp
diff --git a/libvirtual/virtual.cpp b/libvirtual/virtual.cpp
index e2f239a..8e96a56 100644
--- a/libvirtual/virtual.cpp
+++ b/libvirtual/virtual.cpp
@@ -47,6 +47,7 @@
 #include "virtual.h"
 #include "overlayUtils.h"
 #include "overlay.h"
+#include "mdp_version.h"
 
 using namespace android;
 
@@ -67,6 +68,11 @@
     return 0;
 }
 
+void VirtualDisplay::getAttributes(int& width, int& height) {
+    width = mVInfo.xres;
+    height = mVInfo.yres;
+}
+
 int VirtualDisplay::teardown() {
     closeFrameBuffer();
     memset(&mVInfo, 0, sizeof(mVInfo));
@@ -85,12 +91,35 @@
 }
 
 void VirtualDisplay::setAttributes() {
-    mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres = mVInfo.xres;
-    mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres = mVInfo.yres;
-    mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].vsync_period =
-        1000000000l /60;
-    ALOGD_IF(DEBUG,"%s: Setting Virtual Attr: res(%d x %d)",__FUNCTION__,
-             mVInfo.xres, mVInfo.yres);
+    if(mHwcContext) {
+        // Always set dpyAttr res to mVInfo res
+        mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres = mVInfo.xres;
+        mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres = mVInfo.yres;
+        mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = false;
+        if(!qdutils::MDPVersion::getInstance().is8x26()) {
+            uint32_t priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
+            uint32_t priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
+            // if primary resolution is more than the wfd resolution
+            // configure dpy attr to primary resolution and set
+            // downscale mode
+            if((priW * priH) > (mVInfo.xres * mVInfo.yres)) {
+                mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres = priW;
+                mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres = priH;
+                // WFD is always in landscape, so always assign the higher
+                // dimension to wfd's xres
+                if(priH > priW) {
+                    mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres = priH;
+                    mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres = priW;
+                }
+                // Set External Display MDP Downscale mode indicator
+                mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = true;
+            }
+        }
+        mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].vsync_period =
+                1000000000l /60;
+        ALOGD_IF(DEBUG,"%s: Setting Virtual Attr: res(%d x %d)",__FUNCTION__,
+                 mVInfo.xres, mVInfo.yres);
+    }
 }
 
 bool VirtualDisplay::openFrameBuffer()
diff --git a/libvirtual/virtual.h b/libvirtual/virtual.h
index cd0e7da..8003e23 100644
--- a/libvirtual/virtual.h
+++ b/libvirtual/virtual.h
@@ -43,6 +43,7 @@
     VirtualDisplay(hwc_context_t* ctx);
     ~VirtualDisplay();
     int  configure();
+    void getAttributes(int& width, int& height);
     int  teardown();
     bool isConnected() {
         return  mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].connected;