Merge "hwc: Get notified on media player death."
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index 1c8f170..839d79a 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -168,11 +168,13 @@
 
 ExternalDisplay::ExternalDisplay(hwc_context_t* ctx):mFd(-1),
     mCurrentMode(-1), mConnected(0), mConnectedFbNum(0), mModeCount(0),
-     mUnderscanSupported(false), mHwcContext(ctx), mHdmiFbNum(-1), mWfdFbNum(-1)
+    mUnderscanSupported(false), mHwcContext(ctx), mHdmiFbNum(-1),
+    mWfdFbNum(-1), mExtDpyNum(HWC_DISPLAY_EXTERNAL)
 {
     memset(&mVInfo, 0, sizeof(mVInfo));
     //Determine the fb index for external display devices.
     updateExtDispDevFbIndex();
+
 }
 
 void ExternalDisplay::setEDIDMode(int resMode) {
@@ -441,7 +443,7 @@
             ALOGE("%s: %s is not available", __FUNCTION__,
                                             msmFbDevicePath[fbNum-1]);
         if(mHwcContext) {
-            mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].fd = mFd;
+            mHwcContext->dpyAttr[mExtDpyNum].fd = mFd;
         }
     }
     return (mFd > 0);
@@ -450,12 +452,12 @@
 bool ExternalDisplay::closeFrameBuffer()
 {
     int ret = 0;
-    if(mFd > 0) {
+    if(mFd >= 0) {
         ret = close(mFd);
         mFd = -1;
     }
     if(mHwcContext) {
-        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].fd = mFd;
+        mHwcContext->dpyAttr[mExtDpyNum].fd = mFd;
     }
     return (ret == 0);
 }
@@ -639,7 +641,7 @@
         // Store the external display
         mConnected = connected;
         mConnectedFbNum = extFbNum;
-        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].connected = connected;
+        mHwcContext->dpyAttr[mExtDpyNum].connected = connected;
         // Update external fb number in Overlay context
         overlay::Overlay::getInstance()->setExtFbNum(extFbNum);
     }
@@ -688,6 +690,7 @@
 {
     if(mFd == -1)
         return false;
+
     struct mdp_display_commit ext_commit;
     memset(&ext_commit, 0, sizeof(struct mdp_display_commit));
     ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY;
@@ -701,9 +704,9 @@
 
 void ExternalDisplay::setDpyWfdAttr() {
     if(mHwcContext) {
-        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = mVInfo.xres;
-        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = mVInfo.yres;
-        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].vsync_period =
+        mHwcContext->dpyAttr[mExtDpyNum].xres = mVInfo.xres;
+        mHwcContext->dpyAttr[mExtDpyNum].yres = mVInfo.yres;
+        mHwcContext->dpyAttr[mExtDpyNum].vsync_period =
                 1000000000l /60;
         ALOGD_IF(DEBUG,"%s: wfd...connected..!",__FUNCTION__);
     }
diff --git a/libexternal/external.h b/libexternal/external.h
index baf3598..39f8645 100644
--- a/libexternal/external.h
+++ b/libexternal/external.h
@@ -46,6 +46,7 @@
     bool isCEUnderscanSupported() { return mUnderscanSupported; }
     void setExternalDisplay(bool connected, int extFbNum = 0);
     bool isExternalConnected() { return mConnected;};
+    void  setExtDpyNum(int extDpyNum) { mExtDpyNum = extDpyNum;};
     bool post();
     void setHPD(uint32_t startEnd);
     void setEDIDMode(int resMode);
@@ -92,6 +93,7 @@
     fb_var_screeninfo mVInfo;
     int mHdmiFbNum;
     int mWfdFbNum;
+    int mExtDpyNum;
 };
 
 }; //qhwc
diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk
index f4e3834..749a672 100644
--- a/libgralloc/Android.mk
+++ b/libgralloc/Android.mk
@@ -35,7 +35,7 @@
 LOCAL_MODULE                  := libmemalloc
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libgenlock libqdutils
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libgenlock libqdutils libdl
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdmemalloc\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
 LOCAL_SRC_FILES               :=  ionalloc.cpp alloc_controller.cpp
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 5aca758..ebd7e98 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -29,6 +29,7 @@
 
 #include <cutils/log.h>
 #include <fcntl.h>
+#include <dlfcn.h>
 #include "gralloc_priv.h"
 #include "alloc_controller.h"
 #include "memalloc.h"
@@ -84,29 +85,72 @@
 }
 
 //-------------- AdrenoMemInfo-----------------------//
+AdrenoMemInfo::AdrenoMemInfo()
+{
+    libadreno_utils = ::dlopen("libadreno_utils.so", RTLD_NOW);
+    if (libadreno_utils) {
+        *(void **)&LINK_adreno_compute_padding = ::dlsym(libadreno_utils,
+                                           "compute_surface_padding");
+    }
+}
+
+AdrenoMemInfo::~AdrenoMemInfo()
+{
+    if (libadreno_utils) {
+        ::dlclose(libadreno_utils);
+    }
+}
+
 int AdrenoMemInfo::getStride(int width, int format)
 {
     int stride = ALIGN(width, 32);
-    switch (format)
-    {
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
-            stride = ALIGN(width, 32);
-            break;
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
-            stride = ALIGN(width, 128);
-            break;
-        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-        case HAL_PIXEL_FORMAT_YV12:
-        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
-        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
-            stride = ALIGN(width, 16);
-            break;
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
-            stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
-            break;
-        default: break;
+    // Currently surface padding is only computed for RGB* surfaces.
+    if (format < 0x7) {
+        int bpp = 4;
+        switch(format)
+        {
+            case HAL_PIXEL_FORMAT_RGB_888:
+                bpp = 3;
+                break;
+            case HAL_PIXEL_FORMAT_RGB_565:
+            case HAL_PIXEL_FORMAT_RGBA_5551:
+            case HAL_PIXEL_FORMAT_RGBA_4444:
+                bpp = 2;
+                break;
+            default: break;
+        }
+        if ((libadreno_utils) && (LINK_adreno_compute_padding)) {
+            int surface_tile_height = 1;   // Linear surface
+            int raster_mode         = 1;   // Adreno TW raster mode.
+            int padding_threshold   = 512; // Threshold for padding surfaces.
+            // the function below expects the width to be a multiple of
+            // 32 pixels, hence we pass stride instead of width.
+            stride = LINK_adreno_compute_padding(stride, bpp,
+                                      surface_tile_height, raster_mode,
+                                      padding_threshold);
+        }
+    } else {
+        switch (format)
+        {
+            case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+                stride = ALIGN(width, 32);
+                break;
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+                stride = ALIGN(width, 128);
+                break;
+            case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+            case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            case HAL_PIXEL_FORMAT_YV12:
+            case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+            case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+                stride = ALIGN(width, 16);
+                break;
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+                stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
+                break;
+            default: break;
+        }
     }
     return stride;
 }
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index c6bd137..5343c35 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -84,12 +84,25 @@
 class AdrenoMemInfo : public android::Singleton <AdrenoMemInfo>
 {
     public:
-    AdrenoMemInfo() {}
+    AdrenoMemInfo();
 
-    ~AdrenoMemInfo() {}
+    ~AdrenoMemInfo();
 
+    /*
+     * Function to compute the adreno stride based on the width and format.
+     *
+     * @return stride.
+     */
     int getStride(int width, int format);
 
     private:
+        // Pointer to the padding library.
+        void *libadreno_utils;
+
+        // link to the surface padding library.
+        int (*LINK_adreno_compute_padding) (int width, int bpp,
+                                                int surface_tile_height,
+                                                int screen_tile_height,
+                                                int padding_threshold);
 };
 #endif /* GR_H_ */
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 6a0e0ee..519126f 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -84,7 +84,7 @@
 static void reset(hwc_context_t *ctx, int numDisplays,
                   hwc_display_contents_1_t** displays) {
     memset(ctx->listStats, 0, sizeof(ctx->listStats));
-    for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++){
+    for(int i = 0; i < MAX_DISPLAYS; i++) {
         hwc_display_contents_1_t *list = displays[i];
         // XXX:SurfaceFlinger no longer guarantees that this
         // value is reset on every prepare. However, for the layer
@@ -148,25 +148,31 @@
 }
 
 static int hwc_prepare_external(hwc_composer_device_1 *dev,
-        hwc_display_contents_1_t *list) {
+        hwc_display_contents_1_t *list, int dpy) {
     hwc_context_t* ctx = (hwc_context_t*)(dev);
-    const int dpy = HWC_DISPLAY_EXTERNAL;
 
     if (LIKELY(list && list->numHwLayers > 1) &&
         ctx->dpyAttr[dpy].isActive &&
         ctx->dpyAttr[dpy].connected) {
-
         uint32_t last = list->numHwLayers - 1;
-        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
-        if(fbLayer->handle) {
-            setListStats(ctx, list, dpy);
-            reset_layer_prop(ctx, dpy);
-            VideoOverlay::prepare(ctx, list, dpy);
-            ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
-            ctx->mLayerCache[dpy]->updateLayerCache(list);
-            if(ctx->mCopyBit[dpy])
-                ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
-            ctx->mExtDispConfiguring = false;
+        if(!ctx->dpyAttr[dpy].isPause) {
+            hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+            if(fbLayer->handle) {
+                setListStats(ctx, list, dpy);
+                reset_layer_prop(ctx, dpy);
+                VideoOverlay::prepare(ctx, list, dpy);
+                ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
+                ctx->mLayerCache[dpy]->updateLayerCache(list);
+                if(ctx->mCopyBit[dpy])
+                    ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
+                ctx->mExtDispConfiguring = false;
+            }
+        } else {
+            // External Display is in Pause state.
+            // ToDo:
+            // Mark all application layers as OVERLAY so that
+            // GPU will not compose. This is done for power
+            // optimization
         }
     }
     return 0;
@@ -182,14 +188,15 @@
 
     ctx->mOverlay->configBegin();
 
-    for (int32_t i = numDisplays - 1; i >= 0; i--) {
+    for (int32_t i = numDisplays; i >= 0; i--) {
         hwc_display_contents_1_t *list = displays[i];
         switch(i) {
             case HWC_DISPLAY_PRIMARY:
                 ret = hwc_prepare_primary(dev, list);
                 break;
             case HWC_DISPLAY_EXTERNAL:
-                ret = hwc_prepare_external(dev, list);
+            case HWC_DISPLAY_VIRTUAL:
+                ret = hwc_prepare_external(dev, list, i);
                 break;
             default:
                 ret = -EINVAL;
@@ -244,8 +251,9 @@
             }
             break;
         case HWC_DISPLAY_EXTERNAL:
+        case HWC_DISPLAY_VIRTUAL:
             if(blank) {
-                // External Display post commits the changes to display
+                // External/Virtual Display post commits the changes to display
                 // Call this on blank, so that any pipe unsets gets committed
                 if (!ctx->mExtDisplay->post()) {
                     ret = -1;
@@ -342,13 +350,12 @@
 }
 
 static int hwc_set_external(hwc_context_t *ctx,
-        hwc_display_contents_1_t* list) {
+        hwc_display_contents_1_t* list, int dpy) {
     int ret = 0;
-    const int dpy = HWC_DISPLAY_EXTERNAL;
-
     Locker::Autolock _l(ctx->mExtSetLock);
 
     if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
+        !ctx->dpyAttr[dpy].isPause &&
         ctx->dpyAttr[dpy].connected) {
         uint32_t last = list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
@@ -388,14 +395,19 @@
     int ret = 0;
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     Locker::Autolock _l(ctx->mBlankLock);
-    for (uint32_t i = 0; i < numDisplays; i++) {
+    for (uint32_t i = 0; i <= numDisplays; i++) {
         hwc_display_contents_1_t* list = displays[i];
         switch(i) {
             case HWC_DISPLAY_PRIMARY:
                 ret = hwc_set_primary(ctx, list);
                 break;
             case HWC_DISPLAY_EXTERNAL:
-                ret = hwc_set_external(ctx, list);
+            case HWC_DISPLAY_VIRTUAL:
+            /* ToDo: We are using hwc_set_external path for both External and
+                     Virtual displays on HWC1.1. Eventually, we will have
+                     separate functions when we move to HWC1.2
+            */
+                ret = hwc_set_external(ctx, list, i);
                 break;
             default:
                 ret = -EINVAL;
@@ -487,13 +499,15 @@
 void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
 {
     hwc_context_t* ctx = (hwc_context_t*)(dev);
-    android::String8 buf("");
-    dumpsys_log(buf, "Qualcomm HWC state:\n");
-    dumpsys_log(buf, "  MDPVersion=%d\n", ctx->mMDP.version);
-    dumpsys_log(buf, "  DisplayPanel=%c\n", ctx->mMDP.panel);
-    ctx->mMDPComp->dump(buf);
-    //XXX: Call Other dump functions
-    strlcpy(buff, buf.string(), buff_len);
+    android::String8 aBuf("");
+    dumpsys_log(aBuf, "Qualcomm HWC state:\n");
+    dumpsys_log(aBuf, "  MDPVersion=%d\n", ctx->mMDP.version);
+    dumpsys_log(aBuf, "  DisplayPanel=%c\n", ctx->mMDP.panel);
+    ctx->mMDPComp->dump(aBuf);
+    char ovDump[2048] = {'\0'};
+    ctx->mOverlay->getDump(ovDump, 2048);
+    dumpsys_log(aBuf, ovDump);
+    strlcpy(buff, aBuf.string(), buff_len);
 }
 
 static int hwc_device_close(struct hw_device_t *dev)
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 6b8f4e3..752aaa2 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -35,6 +35,21 @@
 
 #define HWC_UEVENT_THREAD_NAME "hwcUeventThread"
 
+/* External Display states */
+enum {
+    EXTERNAL_OFFLINE = 0,
+    EXTERNAL_ONLINE,
+    EXTERNAL_PAUSE,
+    EXTERNAL_RESUME
+};
+
+static bool isHDMI(const char* str)
+{
+    if(strcasestr("change@/devices/virtual/switch/hdmi", str))
+        return true;
+    return false;
+}
+
 static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
 {
     int vsync = 0;
@@ -48,7 +63,6 @@
                            qdutils::COMPOSITION_TYPE_MDP |
                            qdutils::COMPOSITION_TYPE_C2D)) {
         usecopybit = true;
-
     }
 
     if(!strcasestr("change@/devices/virtual/switch/hdmi", str) &&
@@ -56,19 +70,35 @@
         ALOGD_IF(UEVENT_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__);
         return;
     }
-
     int connected = -1; // initial value - will be set to  1/0 based on hotplug
+    int extDpyNum = HWC_DISPLAY_EXTERNAL;
+    char property[PROPERTY_VALUE_MAX];
+    if((property_get("persist.sys.wfd.virtual", property, NULL) > 0) &&
+            (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+             (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+        // This means we are using Google API to trigger WFD Display
+        extDpyNum = HWC_DISPLAY_VIRTUAL;
+
+    }
+
+    int dpy = isHDMI(str) ? HWC_DISPLAY_EXTERNAL : extDpyNum;
+
+    // update extDpyNum
+    ctx->mExtDisplay->setExtDpyNum(dpy);
+
     // parse HDMI/WFD switch state for connect/disconnect
     // for HDMI:
     // The event will be of the form:
     // change@/devices/virtual/switch/hdmi ACTION=change
     // SWITCH_STATE=1 or SWITCH_STATE=0
-
     while(*str) {
         if (!strncmp(str, "SWITCH_STATE=", strlen("SWITCH_STATE="))) {
             connected = atoi(str + strlen("SWITCH_STATE="));
             //Disabled until SF calls unblank
             ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive = false;
+            //Ignored for Virtual Displays
+            //ToDo: we can do this in a much better way
+            ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = true;
             break;
         }
         str += strlen(str) + 1;
@@ -76,32 +106,63 @@
             break;
     }
 
-    if(connected != -1) { //either we got switch_state connected or disconnect
-        ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected = connected;
-        if (connected) {
-            ctx->mExtDispConfiguring = true;
-            ctx->mExtDisplay->processUEventOnline(udata);
-            ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL] =
-                IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].xres,
-                HWC_DISPLAY_EXTERNAL);
-            if(usecopybit)
-                ctx->mCopyBit[HWC_DISPLAY_EXTERNAL] = new CopyBit();
-        } else {
-            ctx->mExtDisplay->processUEventOffline(udata);
-            if(ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL]) {
+    switch(connected) {
+        case EXTERNAL_OFFLINE:
+            {   // disconnect event
+                ctx->mExtDisplay->processUEventOffline(udata);
+                if(ctx->mFBUpdate[dpy]) {
+                    Locker::Autolock _l(ctx->mExtSetLock);
+                    delete ctx->mFBUpdate[dpy];
+                    ctx->mFBUpdate[dpy] = NULL;
+                }
+                if(ctx->mCopyBit[dpy]){
+                    Locker::Autolock _l(ctx->mExtSetLock);
+                    delete ctx->mCopyBit[dpy];
+                    ctx->mCopyBit[dpy] = NULL;
+                }
+                ALOGD("%s sending hotplug: connected = %d and dpy:%d",
+                      __FUNCTION__, connected, dpy);
+                ctx->dpyAttr[dpy].connected = false;
                 Locker::Autolock _l(ctx->mExtSetLock);
-                delete ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL];
-                ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL] = NULL;
+                //hwc comp could be on
+                ctx->proc->hotplug(ctx->proc, dpy, connected);
+                break;
             }
-            if(ctx->mCopyBit[HWC_DISPLAY_EXTERNAL]){
-                Locker::Autolock _l(ctx->mExtSetLock);
-                delete ctx->mCopyBit[HWC_DISPLAY_EXTERNAL];
-                ctx->mCopyBit[HWC_DISPLAY_EXTERNAL] = NULL;
+        case EXTERNAL_ONLINE:
+            {   // connect case
+                ctx->mExtDispConfiguring = true;
+                ctx->mExtDisplay->processUEventOnline(udata);
+                ctx->mFBUpdate[dpy] =
+                        IFBUpdate::getObject(ctx->dpyAttr[dpy].xres, dpy);
+                ctx->dpyAttr[dpy].isPause = false;
+                if(usecopybit)
+                    ctx->mCopyBit[dpy] = new CopyBit();
+                ALOGD("%s sending hotplug: connected = %d", __FUNCTION__,
+                        connected);
+                ctx->dpyAttr[dpy].connected = true;
+                Locker::Autolock _l(ctx->mExtSetLock); //hwc comp could be on
+                ctx->proc->hotplug(ctx->proc, dpy, connected);
+                break;
             }
-        }
-        ALOGD("%s sending hotplug: connected = %d", __FUNCTION__, connected);
-        Locker::Autolock _l(ctx->mExtSetLock); //hwc comp could be on
-        ctx->proc->hotplug(ctx->proc, HWC_DISPLAY_EXTERNAL, connected);
+        case EXTERNAL_PAUSE:
+            {   // pause case
+                ALOGD("%s Received Pause event",__FUNCTION__);
+                ctx->dpyAttr[dpy].isActive = true;
+                ctx->dpyAttr[dpy].isPause = true;
+                break;
+            }
+        case EXTERNAL_RESUME:
+            {  // resume case
+                ALOGD("%s Received resume event",__FUNCTION__);
+                ctx->dpyAttr[dpy].isActive = true;
+                ctx->dpyAttr[dpy].isPause = false;
+                break;
+            }
+        default:
+            {
+                ALOGE("ignore event and connected:%d",connected);
+                break;
+            }
     }
 }
 
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 0c26bda..fe3401b 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -90,7 +90,7 @@
     }
 
     ctx->mExtDisplay = new ExternalDisplay(ctx);
-    for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++)
+    for (uint32_t i = 0; i < MAX_DISPLAYS; i++)
         ctx->mLayerCache[i] = new LayerCache();
     ctx->mMDPComp = MDPComp::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres);
     MDPComp::init(ctx);
@@ -119,7 +119,7 @@
         ctx->mOverlay = NULL;
     }
 
-    for(int i = 0; i< HWC_NUM_DISPLAY_TYPES; i++) {
+    for(int i = 0; i < MAX_DISPLAYS; i++) {
         if(ctx->mCopyBit[i]) {
             delete ctx->mCopyBit[i];
             ctx->mCopyBit[i] = NULL;
@@ -138,7 +138,7 @@
         ctx->mExtDisplay = NULL;
     }
 
-    for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+    for(int i = 0; i < MAX_DISPLAYS; i++) {
         if(ctx->mFBUpdate[i]) {
             delete ctx->mFBUpdate[i];
             ctx->mFBUpdate[i] = NULL;
@@ -405,11 +405,11 @@
         if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
            list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
             //Close the acquireFenceFds
-            if(list->hwLayers[i].acquireFenceFd > 0) {
+            if(list->hwLayers[i].acquireFenceFd >= 0) {
                 close(list->hwLayers[i].acquireFenceFd);
                 list->hwLayers[i].acquireFenceFd = -1;
             }
-            if(fd > 0) {
+            if(fd >= 0) {
                 close(fd);
                 fd = -1;
             }
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 525fd75..045ef7f 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -36,6 +36,10 @@
 #define MAX_NUM_LAYERS 32
 #define MAX_DISPLAY_DIM 2048
 
+// For support of virtual displays
+#define HWC_DISPLAY_VIRTUAL     (HWC_DISPLAY_EXTERNAL+1)
+#define MAX_DISPLAYS            (HWC_NUM_DISPLAY_TYPES+1)
+
 //Fwrd decls
 struct hwc_context_t;
 struct framebuffer_device_t;
@@ -70,6 +74,9 @@
     //Connected does not mean it ready to use.
     //It should be active also. (UNBLANKED)
     bool isActive;
+    // In pause state, composition is bypassed
+    // used for WFD displays only
+    bool isPause;
 };
 
 struct ListStats {
@@ -221,20 +228,20 @@
     framebuffer_device_t *mFbDev;
 
     //CopyBit objects
-    qhwc::CopyBit *mCopyBit[HWC_NUM_DISPLAY_TYPES];
+    qhwc::CopyBit *mCopyBit[MAX_DISPLAYS];
 
     //Overlay object - NULL for non overlay devices
     overlay::Overlay *mOverlay;
 
     //Primary and external FB updater
-    qhwc::IFBUpdate *mFBUpdate[HWC_NUM_DISPLAY_TYPES];
+    qhwc::IFBUpdate *mFBUpdate[MAX_DISPLAYS];
     // External display related information
     qhwc::ExternalDisplay *mExtDisplay;
     qhwc::MDPInfo mMDP;
-    qhwc::DisplayAttributes dpyAttr[HWC_NUM_DISPLAY_TYPES];
-    qhwc::ListStats listStats[HWC_NUM_DISPLAY_TYPES];
-    qhwc::LayerCache *mLayerCache[HWC_NUM_DISPLAY_TYPES];
-    qhwc::LayerProp *layerProp[HWC_NUM_DISPLAY_TYPES];
+    qhwc::DisplayAttributes dpyAttr[MAX_DISPLAYS];
+    qhwc::ListStats listStats[MAX_DISPLAYS];
+    qhwc::LayerCache *mLayerCache[MAX_DISPLAYS];
+    qhwc::LayerProp *layerProp[MAX_DISPLAYS];
     qhwc::MDPComp *mMDPComp;
 
     //Securing in progress indicator
diff --git a/libhwcomposer/hwc_video.h b/libhwcomposer/hwc_video.h
index 3612018..93cdaa5 100644
--- a/libhwcomposer/hwc_video.h
+++ b/libhwcomposer/hwc_video.h
@@ -45,12 +45,12 @@
     //Marks layer flags if this feature is used
     static void markFlags(hwc_layer_1_t *yuvLayer);
     //Flags if this feature is on.
-    static bool sIsModeOn[HWC_NUM_DISPLAY_TYPES];
-    static ovutils::eDest sDest[HWC_NUM_DISPLAY_TYPES];
+    static bool sIsModeOn[MAX_DISPLAYS];
+    static ovutils::eDest sDest[MAX_DISPLAYS];
 };
 
 inline void VideoOverlay::reset() {
-    for(uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+    for(uint32_t i = 0; i < MAX_DISPLAYS; i++) {
         sIsModeOn[i] = false;
         sDest[i] = ovutils::OV_INVALID;
     }
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index 04deee5..441b822 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -202,10 +202,28 @@
 
 void Overlay::dump() const {
     if(strlen(mDumpStr)) { //dump only on state change
-        ALOGD("%s\n", mDumpStr);
+        ALOGD_IF(PIPE_DEBUG, "%s\n", mDumpStr);
     }
 }
 
+void Overlay::getDump(char *buf, size_t len) {
+    int totalPipes = 0;
+    const char *str = "\nOverlay State\n==========================\n";
+    strncat(buf, str, strlen(str));
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        if(mPipeBook[i].valid()) {
+            mPipeBook[i].mPipe->getDump(buf, len);
+            char str[64] = {'\0'};
+            snprintf(str, 64, "Attached to dpy=%d\n\n", mPipeBook[i].mDisplay);
+            strncat(buf, str, strlen(str));
+            totalPipes++;
+        }
+    }
+    char str_pipes[64] = {'\0'};
+    snprintf(str_pipes, 64, "Pipes used=%d\n\n", totalPipes);
+    strncat(buf, str_pipes, strlen(str_pipes));
+}
+
 void Overlay::PipeBook::init() {
     mPipe = NULL;
     mDisplay = DPY_UNUSED;
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index a470f45..0f15baa 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -77,6 +77,10 @@
     void setExtFbNum(int fbNum);
     /* Returns framebuffer index of the current external display */
     int getExtFbNum();
+    /* Returns pipe dump. Expects a NULL terminated buffer of big enough size
+     * to populate.
+     */
+    void getDump(char *buf, size_t len);
 
 private:
     /* Ctor setup */
diff --git a/liboverlay/overlayCtrlData.h b/liboverlay/overlayCtrlData.h
index 0c49bdd..c9a4949 100644
--- a/liboverlay/overlayCtrlData.h
+++ b/liboverlay/overlayCtrlData.h
@@ -81,9 +81,6 @@
     /* retrieve cached crop data */
     utils::Dim getCrop() const;
 
-    /* dump the state of the object */
-    void dump() const;
-
     /* Perform transformation calculations */
     void doTransform();
 
@@ -96,6 +93,12 @@
     /* Update the src format */
     void updateSrcformat(const uint32_t& inputsrcFormat);
 
+    /* dump the state of the object */
+    void dump() const;
+
+    /* Return the dump in the specified buffer */
+    void getDump(char *buf, size_t len);
+
 private:
     /* Retrieve screen info from underlying mdp */
     bool getScreenInfo(utils::ScreenInfo& info);
@@ -134,6 +137,9 @@
     /* sump the state of the obj */
     void dump() const;
 
+    /* Return the dump in the specified buffer */
+    void getDump(char *buf, size_t len);
+
 private:
     // mdp data struct
     MdpData mMdp;
@@ -213,6 +219,10 @@
     return mMdp.getDownscalefactor();
 }
 
+inline void Ctrl::getDump(char *buf, size_t len) {
+    mMdp.getDump(buf, len);
+}
+
 inline Data::Data() {
     mMdp.reset();
 }
@@ -249,6 +259,9 @@
     ALOGE("== Dump Data MDP end ==");
 }
 
+inline void Data::getDump(char *buf, size_t len) {
+    mMdp.getDump(buf, len);
+}
 
 } // overlay
 
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 8bca85f..8f2e2b6 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -241,7 +241,8 @@
     return true;
 }
 
-//Adjust width, height, format if rotator is used.
+//Adjust width, height if rotator is used post transform calcs.
+//At this point the format is already updated by updateSrcFormat
 void MdpCtrl::adjustSrcWhf(const bool& rotUsed) {
     if(rotUsed) {
         utils::Whf whf = getSrcWhf();
@@ -250,25 +251,15 @@
             whf.w = utils::alignup(whf.w, 64);
             whf.h = utils::alignup(whf.h, 32);
         }
-        /*For example: If original format is tiled, rotator outputs non-tiled,
-         *so update mdp's src fmt to that.
-         */
-        whf.format = utils::getRotOutFmt(whf.format);
         setSrcWhf(whf);
-        /* The above format will be overwritten in function updateSrcformat
-         * after doing rotator start. Format is then set depending on
-         * whether the fastyuv mode is used by the rotator.
-         */
     }
 }
 
+//Update src format if rotator used based on rotator's destination format.
 void MdpCtrl::updateSrcformat(const uint32_t& inputformat) {
-    int version = qdutils::MDPVersion::getInstance().getMDPVersion();
-    if ((version >= qdutils::MDP_V4_2) && (version < qdutils::MDSS_V5)) {
-        utils::Whf whf = getSrcWhf();
-        whf.format =  inputformat;
-        setSrcWhf(whf);
-    }
+    utils::Whf whf = getSrcWhf();
+    whf.format =  inputformat;
+    setSrcWhf(whf);
 }
 
 void MdpCtrl::dump() const {
@@ -278,6 +269,10 @@
     ALOGE("== Dump MdpCtrl end ==");
 }
 
+void MdpCtrl::getDump(char *buf, size_t len) {
+    ovutils::getDump(buf, len, "Ctrl(mdp_overlay)", mOVInfo);
+}
+
 void MdpData::dump() const {
     ALOGE("== Dump MdpData start ==");
     mFd.dump();
@@ -285,6 +280,10 @@
     ALOGE("== Dump MdpData end ==");
 }
 
+void MdpData::getDump(char *buf, size_t len) {
+    ovutils::getDump(buf, len, "Data(msmfb_overlay_data)", mOvData);
+}
+
 void MdpCtrl3D::dump() const {
     ALOGE("== Dump MdpCtrl start ==");
     mFd.dump();
diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h
index c1684fc..55e2787 100644
--- a/liboverlay/overlayMdp.h
+++ b/liboverlay/overlayMdp.h
@@ -141,9 +141,6 @@
     /* using user_data, sets/unsets roationvalue in mdp flags */
     void setRotationFlags();
 
-    /* dump state of the object */
-    void dump() const;
-
     /* Perform transformation calculations */
     void doTransform();
 
@@ -156,6 +153,12 @@
     /* Update the src format */
     void updateSrcformat(const uint32_t& inputsrcFormat);
 
+    /* dump state of the object */
+    void dump() const;
+
+    /* Return the dump in the specified buffer */
+    void getDump(char *buf, size_t len);
+
 private:
 
     /* helper functions for overlayTransform */
@@ -237,6 +240,10 @@
 
     /* dump state of the object */
     void dump() const;
+
+    /* Return the dump in the specified buffer */
+    void getDump(char *buf, size_t len);
+
 private:
 
     /* actual overlay mdp data */
diff --git a/liboverlay/overlayMdpRot.cpp b/liboverlay/overlayMdpRot.cpp
old mode 100644
new mode 100755
index d0242d6..c9843f2
--- a/liboverlay/overlayMdpRot.cpp
+++ b/liboverlay/overlayMdpRot.cpp
@@ -58,15 +58,12 @@
 }
 
 void MdpRot::setDownscale(int ds) {
-    if (mRotImgInfo.src.format == MDP_Y_CR_CB_GH2V2 &&
-                            (mRotImgInfo.src_rect.h & 0xF)) {
-        mRotImgInfo.src_rect.h = utils::aligndown(mRotImgInfo.src_rect.h, 16);
-    } else if ((utils::ROT_DS_EIGHTH == ds) && (mRotImgInfo.src_rect.h & 0xF)) {
+    if ((utils::ROT_DS_EIGHTH == ds) && (mRotImgInfo.src_rect.h & 0xF)) {
         // Ensure src_rect.h is a multiple of 16 for 1/8 downscaling.
         // This is an undocumented MDP Rotator constraint.
         // Note that src_rect.h is already ensured to be 32 pixel height aligned
         // for MDP_Y_CRCB_H2V2_TILE and MDP_Y_CBCR_H2V2_TILE formats.
-        mRotImgInfo.src_rect.h = utils::alignup(mRotImgInfo.src_rect.h, 16);
+        mRotImgInfo.src_rect.h = utils::aligndown(mRotImgInfo.src_rect.h, 16);
     }
     mRotImgInfo.downscale_ratio = ds;
 }
@@ -111,8 +108,6 @@
 
     mRotImgInfo.dst.width = whf.w;
     mRotImgInfo.dst.height = whf.h;
-
-    mBufSize = awhf.size;
 }
 
 inline void MdpRot::setFlags(const utils::eMdpFlags& flags) {
@@ -157,6 +152,12 @@
     return true;
 }
 
+uint32_t MdpRot::calcOutputBufSize() {
+    ovutils::Whf destWhf(mRotImgInfo.dst.width,
+            mRotImgInfo.dst.height, mRotImgInfo.dst.format);
+    return Rotator::calcOutputBufSize(destWhf);
+}
+
 bool MdpRot::open_i(uint32_t numbufs, uint32_t bufsz)
 {
     OvMem mem;
@@ -201,8 +202,9 @@
 
 bool MdpRot::remap(uint32_t numbufs) {
     // if current size changed, remap
-    if(mBufSize == mMem.curr().size()) {
-        ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, mBufSize);
+    uint32_t opBufSize = calcOutputBufSize();
+    if(opBufSize == mMem.curr().size()) {
+        ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, opBufSize);
         return true;
     }
 
@@ -211,12 +213,12 @@
 
     // ++mMem will make curr to be prev, and prev will be curr
     ++mMem;
-    if(!open_i(numbufs, mBufSize)) {
+    if(!open_i(numbufs, opBufSize)) {
         ALOGE("%s Error could not open", __FUNCTION__);
         return false;
     }
     for (uint32_t i = 0; i < numbufs; ++i) {
-        mMem.curr().mRotOffset[i] = i * mBufSize;
+        mMem.curr().mRotOffset[i] = i * opBufSize;
     }
     return true;
 }
@@ -229,7 +231,6 @@
     ovutils::memset0(mMem.prev().mRotOffset);
     mMem.curr().mCurrOffset = 0;
     mMem.prev().mCurrOffset = 0;
-    mBufSize = 0;
     mOrientation = utils::OVERLAY_TRANSFORM_0;
 }
 
@@ -275,4 +276,9 @@
     ALOGE("== Dump MdpRot end ==");
 }
 
+void MdpRot::getDump(char *buf, size_t len) const {
+    ovutils::getDump(buf, len, "MdpRotCtrl(msm_rotator_img_info)", mRotImgInfo);
+    ovutils::getDump(buf, len, "MdpRotData(msm_rotator_data_info)", mRotDataInfo);
+}
+
 } // namespace overlay
diff --git a/liboverlay/overlayMdssRot.cpp b/liboverlay/overlayMdssRot.cpp
index d9cdc03..fd747dd 100644
--- a/liboverlay/overlayMdssRot.cpp
+++ b/liboverlay/overlayMdssRot.cpp
@@ -96,8 +96,6 @@
 
     mRotInfo.dst_rect.w = whf.w;
     mRotInfo.dst_rect.h = whf.h;
-
-    mBufSize = awhf.size;
 }
 
 inline void MdssRot::setDownscale(int ds) {}
@@ -131,7 +129,6 @@
 
 bool MdssRot::commit() {
     doTransform();
-    setBufSize(mRotInfo.src.format);
     mRotInfo.flags |= MDSS_MDP_ROT_ONLY;
     if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) {
         ALOGE("MdssRot commit failed!");
@@ -199,9 +196,11 @@
 }
 
 bool MdssRot::remap(uint32_t numbufs) {
-    // if current size changed, remap
-    if(mBufSize == mMem.curr().size()) {
-        ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, mBufSize);
+    // Calculate the size based on rotator's dst format, w and h.
+    uint32_t opBufSize = calcOutputBufSize();
+    // If current size changed, remap
+    if(opBufSize == mMem.curr().size()) {
+        ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, opBufSize);
         return true;
     }
 
@@ -210,12 +209,12 @@
 
     // ++mMem will make curr to be prev, and prev will be curr
     ++mMem;
-    if(!open_i(numbufs, mBufSize)) {
+    if(!open_i(numbufs, opBufSize)) {
         ALOGE("%s Error could not open", __FUNCTION__);
         return false;
     }
     for (uint32_t i = 0; i < numbufs; ++i) {
-        mMem.curr().mRotOffset[i] = i * mBufSize;
+        mMem.curr().mRotOffset[i] = i * opBufSize;
     }
     return true;
 }
@@ -251,7 +250,6 @@
     ovutils::memset0(mMem.prev().mRotOffset);
     mMem.curr().mCurrOffset = 0;
     mMem.prev().mCurrOffset = 0;
-    mBufSize = 0;
     mOrientation = utils::OVERLAY_TRANSFORM_0;
 }
 
@@ -264,24 +262,22 @@
     ALOGE("== Dump MdssRot end ==");
 }
 
-void MdssRot::setBufSize(int format) {
+uint32_t MdssRot::calcOutputBufSize() {
+    uint32_t opBufSize = 0;
+    ovutils::Whf destWhf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h,
+            mRotInfo.src.format); //mdss src and dst formats are same.
 
-    switch (format) {
-        case MDP_Y_CBCR_H2V2_VENUS:
-            mBufSize = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, mRotInfo.dst_rect.w,
-                                         mRotInfo.dst_rect.h);
-            break;
-
-        case MDP_Y_CR_CB_GH2V2:
-            int alignedw = utils::align(mRotInfo.dst_rect.w, 16);
-            int alignedh = mRotInfo.dst_rect.h;
-            mBufSize = (alignedw*alignedh) +
-                (utils::align(alignedw/2, 16) * (alignedh/2))*2;
-            mBufSize = utils::align(mBufSize, 4096);
-            break;
-    }
+    opBufSize = Rotator::calcOutputBufSize(destWhf);
 
     if (mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION)
-        mBufSize = utils::align(mBufSize, SIZE_1M);
+        opBufSize = utils::align(opBufSize, SIZE_1M);
+
+    return opBufSize;
 }
+
+void MdssRot::getDump(char *buf, size_t len) const {
+    ovutils::getDump(buf, len, "MdssRotCtrl(mdp_overlay)", mRotInfo);
+    ovutils::getDump(buf, len, "MdssRotData(msmfb_overlay_data)", mRotData);
+}
+
 } // namespace overlay
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
index 956ea2b..90a1e7a 100644
--- a/liboverlay/overlayRotator.cpp
+++ b/liboverlay/overlayRotator.cpp
@@ -20,6 +20,7 @@
 #include "overlayRotator.h"
 #include "overlayUtils.h"
 #include "mdp_version.h"
+#include "gr.h"
 
 namespace ovutils = overlay::utils;
 
@@ -39,6 +40,15 @@
     }
 }
 
+uint32_t Rotator::calcOutputBufSize(const utils::Whf& destWhf) {
+    //dummy aligned w & h.
+    int alW = 0, alH = 0;
+    int halFormat = ovutils::getHALFormat(destWhf.format);
+    //A call into gralloc/memalloc
+    return getBufferSizeAndDimensions(
+            destWhf.w, destWhf.h, halFormat, alW, alH);
+}
+
 int Rotator::getRotatorHwType() {
     int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
     if (mdpVersion == qdutils::MDSS_V5)
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index f1a60e1..bd2fd7e 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -62,10 +62,12 @@
     virtual uint32_t getSessId() const = 0;
     virtual bool queueBuffer(int fd, uint32_t offset) = 0;
     virtual void dump() const = 0;
+    virtual void getDump(char *buf, size_t len) const = 0;
     static Rotator *getRotator();
 
 protected:
     explicit Rotator() {}
+    static uint32_t calcOutputBufSize(const utils::Whf& destWhf);
 
 private:
     /*Returns rotator h/w type */
@@ -133,6 +135,7 @@
     virtual uint32_t getSessId() const;
     virtual bool queueBuffer(int fd, uint32_t offset);
     virtual void dump() const;
+    virtual void getDump(char *buf, size_t len) const;
 
 private:
     explicit MdpRot();
@@ -143,13 +146,14 @@
     void doTransform();
     /* reset underlying data, basically memset 0 */
     void reset();
-
     /* return true if current rotator config is different
      * than last known config */
     bool rotConfChanged() const;
-
     /* save mRotImgInfo to be last known good config*/
     void save();
+    /* Calculates the rotator's o/p buffer size post the transform calcs and
+     * knowing the o/p format depending on whether fastYuv is enabled or not */
+    uint32_t calcOutputBufSize();
 
     /* rot info*/
     msm_rotator_img_info mRotImgInfo;
@@ -163,8 +167,6 @@
     OvFD mFd;
     /* Rotator memory manager */
     RotMem mMem;
-    /* Single Rotator buffer size */
-    uint32_t mBufSize;
 
     friend Rotator* Rotator::getRotator();
 };
@@ -195,6 +197,7 @@
     virtual uint32_t getSessId() const;
     virtual bool queueBuffer(int fd, uint32_t offset);
     virtual void dump() const;
+    virtual void getDump(char *buf, size_t len) const;
 
 private:
     explicit MdssRot();
@@ -205,7 +208,9 @@
     void doTransform();
     /* reset underlying data, basically memset 0 */
     void reset();
-    void setBufSize(int format);
+    /* Calculates the rotator's o/p buffer size post the transform calcs and
+     * knowing the o/p format depending on whether fastYuv is enabled or not */
+    uint32_t calcOutputBufSize();
 
     /* MdssRot info structure */
     mdp_overlay   mRotInfo;
@@ -217,8 +222,6 @@
     OvFD mFd;
     /* Rotator memory manager */
     RotMem mMem;
-    /* Single Rotator buffer size */
-    uint32_t mBufSize;
     /* Enable/Disable Mdss Rot*/
     bool mEnabled;
 
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index 9bffff0..de10c9f 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -243,7 +243,50 @@
             //HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO    = 0x7FA30C01
             //HAL_PIXEL_FORMAT_R_8                    = 0x10D
             //HAL_PIXEL_FORMAT_RG_88                  = 0x10E
-            ALOGE("%s: Unsupported format = 0x%x", __func__, format);
+            ALOGE("%s: Unsupported HAL format = 0x%x", __func__, format);
+            return -1;
+    }
+    // not reached
+    return -1;
+}
+
+//Takes mdp format as input and translates to equivalent HAL format
+//Refer to graphics.h, gralloc_priv.h, msm_mdp.h for formats.
+int getHALFormat(int mdpFormat) {
+    switch (mdpFormat) {
+        //From graphics.h
+        case MDP_RGBA_8888:
+            return HAL_PIXEL_FORMAT_RGBA_8888;
+        case MDP_RGBX_8888:
+            return HAL_PIXEL_FORMAT_RGBX_8888;
+        case MDP_RGB_888:
+            return HAL_PIXEL_FORMAT_RGB_888;
+        case MDP_RGB_565:
+            return HAL_PIXEL_FORMAT_RGB_565;
+        case MDP_BGRA_8888:
+            return HAL_PIXEL_FORMAT_BGRA_8888;
+        case MDP_Y_CR_CB_GH2V2:
+            return HAL_PIXEL_FORMAT_YV12;
+        case MDP_Y_CBCR_H2V1:
+            return HAL_PIXEL_FORMAT_YCbCr_422_SP;
+        case MDP_Y_CRCB_H2V2:
+            return HAL_PIXEL_FORMAT_YCrCb_420_SP;
+
+        //From gralloc_priv.h
+        case MDP_Y_CBCR_H2V2_TILE:
+            return HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED;
+        case MDP_Y_CBCR_H2V2:
+            return HAL_PIXEL_FORMAT_YCbCr_420_SP;
+        case MDP_Y_CRCB_H2V1:
+            return HAL_PIXEL_FORMAT_YCrCb_422_SP;
+        case MDP_Y_CBCR_H1V1:
+            return HAL_PIXEL_FORMAT_YCbCr_444_SP;
+        case MDP_Y_CRCB_H1V1:
+            return HAL_PIXEL_FORMAT_YCrCb_444_SP;
+        case MDP_Y_CBCR_H2V2_VENUS:
+            return HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS;
+        default:
+            ALOGE("%s: Unsupported MDP format = 0x%x", __func__, mdpFormat);
             return -1;
     }
     // not reached
@@ -335,6 +378,83 @@
     return (mdpVersion >= qdutils::MDSS_V5);
 }
 
+void getDump(char *buf, size_t len, const char *prefix,
+        const mdp_overlay& ov) {
+    char str[256] = {'\0'};
+    snprintf(str, 256,
+            "%s id=%d z=%d fg=%d alpha=%d mask=%d flags=0x%x\n",
+            prefix, ov.id, ov.z_order, ov.is_fg, ov.alpha,
+            ov.transp_mask, ov.flags);
+    strncat(buf, str, strlen(str));
+    getDump(buf, len, "\tsrc(msmfb_img)", ov.src);
+    getDump(buf, len, "\tsrc_rect(mdp_rect)", ov.src_rect);
+    getDump(buf, len, "\tdst_rect(mdp_rect)", ov.dst_rect);
+}
+
+void getDump(char *buf, size_t len, const char *prefix,
+        const msmfb_img& ov) {
+    char str_src[256] = {'\0'};
+    snprintf(str_src, 256,
+            "%s w=%d h=%d format=%d %s\n",
+            prefix, ov.width, ov.height, ov.format,
+            overlay::utils::getFormatString(ov.format));
+    strncat(buf, str_src, strlen(str_src));
+}
+
+void getDump(char *buf, size_t len, const char *prefix,
+        const mdp_rect& ov) {
+    char str_rect[256] = {'\0'};
+    snprintf(str_rect, 256,
+            "%s x=%d y=%d w=%d h=%d\n",
+            prefix, ov.x, ov.y, ov.w, ov.h);
+    strncat(buf, str_rect, strlen(str_rect));
+}
+
+void getDump(char *buf, size_t len, const char *prefix,
+        const msmfb_overlay_data& ov) {
+    char str[256] = {'\0'};
+    snprintf(str, 256,
+            "%s id=%d\n",
+            prefix, ov.id);
+    strncat(buf, str, strlen(str));
+    getDump(buf, len, "\tdata(msmfb_data)", ov.data);
+}
+
+void getDump(char *buf, size_t len, const char *prefix,
+        const msmfb_data& ov) {
+    char str_data[256] = {'\0'};
+    snprintf(str_data, 256,
+            "%s offset=%d memid=%d id=%d flags=0x%x priv=%d\n",
+            prefix, ov.offset, ov.memory_id, ov.id, ov.flags,
+            ov.priv);
+    strncat(buf, str_data, strlen(str_data));
+}
+
+void getDump(char *buf, size_t len, const char *prefix,
+        const msm_rotator_img_info& rot) {
+    char str[256] = {'\0'};
+    snprintf(str, 256, "%s sessid=%u rot=%d, enable=%d downscale=%d\n",
+            prefix, rot.session_id, rot.rotations, rot.enable,
+            rot.downscale_ratio);
+    strncat(buf, str, strlen(str));
+    getDump(buf, len, "\tsrc", rot.src);
+    getDump(buf, len, "\tdst", rot.dst);
+    getDump(buf, len, "\tsrc_rect", rot.src_rect);
+}
+
+void getDump(char *buf, size_t len, const char *prefix,
+        const msm_rotator_data_info& rot) {
+    char str[256] = {'\0'};
+    snprintf(str, 256,
+            "%s sessid=%u verkey=%d\n",
+            prefix, rot.session_id, rot.version_key);
+    strncat(buf, str, strlen(str));
+    getDump(buf, len, "\tsrc", rot.src);
+    getDump(buf, len, "\tdst", rot.dst);
+    getDump(buf, len, "\tsrc_chroma", rot.src_chroma);
+    getDump(buf, len, "\tdst_chroma", rot.dst_chroma);
+}
+
 } // utils
 
 } // overlay
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index 2f83374..45d1924 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -36,6 +36,7 @@
 #include <hardware/hardware.h>
 #include <hardware/gralloc.h> // buffer_handle_t
 #include <linux/msm_mdp.h> // flags
+#include <linux/msm_rotator.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -412,7 +413,8 @@
 };
 
 int getMdpFormat(int format);
-int getRotOutFmt(uint32_t format);
+int getHALFormat(int mdpFormat);
+
 /* flip is upside down and such. V, H flip
  * rotation is 90, 180 etc
  * It returns MDP related enum/define that match rot+flip*/
@@ -587,29 +589,6 @@
     return -1;
 }
 
-inline int getRotOutFmt(uint32_t format) {
-
-    if (isMdssRotator())
-        return format;
-
-    switch (format) {
-        case MDP_Y_CRCB_H2V2_TILE:
-            return MDP_Y_CRCB_H2V2;
-        case MDP_Y_CBCR_H2V2_TILE:
-            return MDP_Y_CBCR_H2V2;
-        case MDP_Y_CB_CR_H2V2:
-            return MDP_Y_CBCR_H2V2;
-        case MDP_Y_CR_CB_GH2V2:
-            return MDP_Y_CRCB_H2V2;
-        default:
-            return format;
-    }
-    // not reached
-    OVASSERT(false, "%s not reached", __FUNCTION__);
-    return -1;
-}
-
-
 inline uint32_t getColorFormat(uint32_t format)
 {
     return (format == HAL_PIXEL_FORMAT_YV12) ?
@@ -774,6 +753,17 @@
     return OV_MDP_PIPE_ANY;
 }
 
+void getDump(char *buf, size_t len, const char *prefix, const mdp_overlay& ov);
+void getDump(char *buf, size_t len, const char *prefix, const msmfb_img& ov);
+void getDump(char *buf, size_t len, const char *prefix, const mdp_rect& ov);
+void getDump(char *buf, size_t len, const char *prefix,
+        const msmfb_overlay_data& ov);
+void getDump(char *buf, size_t len, const char *prefix, const msmfb_data& ov);
+void getDump(char *buf, size_t len, const char *prefix,
+        const msm_rotator_img_info& ov);
+void getDump(char *buf, size_t len, const char *prefix,
+        const msm_rotator_data_info& ov);
+
 } // namespace utils ends
 
 //--------------------Class Res stuff (namespace overlay only) -----------
diff --git a/liboverlay/pipes/overlayGenPipe.cpp b/liboverlay/pipes/overlayGenPipe.cpp
index 0b864df..486cfda 100644
--- a/liboverlay/pipes/overlayGenPipe.cpp
+++ b/liboverlay/pipes/overlayGenPipe.cpp
@@ -241,6 +241,13 @@
     ALOGE("== Dump Generic pipe end ==");
 }
 
+void GenericPipe::getDump(char *buf, size_t len) {
+    mCtrlData.ctrl.getDump(buf, len);
+    mCtrlData.data.getDump(buf, len);
+    if(mRotUsed && mRot)
+        mRot->getDump(buf, len);
+}
+
 bool GenericPipe::isClosed() const  {
     return (pipeState == CLOSED);
 }
diff --git a/liboverlay/pipes/overlayGenPipe.h b/liboverlay/pipes/overlayGenPipe.h
index 604529a..1d1be25 100644
--- a/liboverlay/pipes/overlayGenPipe.h
+++ b/liboverlay/pipes/overlayGenPipe.h
@@ -84,6 +84,10 @@
 
     /* dump the state of the object */
     void dump() const;
+
+    /* Return the dump in the specified buffer */
+    void getDump(char *buf, size_t len);
+
 private:
     /* set Closed pipe */
     bool setClosed();