hwc: enable dual display on hwc 1.1

Enable dual display on HWC 1.1; video uses overlay.

Bug: 7124159
Change-Id: I8333e46cfc74072f6259fba2b82368f0dd52b6df
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index f8f7f13..c72d882 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -86,18 +86,17 @@
 static int hwc_prepare_primary(hwc_composer_device_1 *dev,
         hwc_display_contents_1_t *list) {
     hwc_context_t* ctx = (hwc_context_t*)(dev);
+    ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = false;
     if (LIKELY(list && list->numHwLayers)) {
         uint32_t last = list->numHwLayers - 1;
         hwc_layer_1_t *fblayer = &list->hwLayers[last];
         setListStats(ctx, list, HWC_DISPLAY_PRIMARY);
         if(VideoOverlay::prepare(ctx, list, HWC_DISPLAY_PRIMARY)) {
-            ctx->overlayInUse = true;
-        } else if(UIMirrorOverlay::prepare(ctx, fblayer)) {
-            ctx->overlayInUse = true;
+            ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = true;
         } else if(MDPComp::configure(ctx, list)) {
-            ctx->overlayInUse = true;
+            ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = true;
         } else {
-            ctx->overlayInUse = false;
+            ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = false;
         }
     }
     return 0;
@@ -107,9 +106,25 @@
         hwc_display_contents_1_t *list) {
 
     hwc_context_t* ctx = (hwc_context_t*)(dev);
-    if (LIKELY(list && list->numHwLayers)) {
-        //setListStats(ctx, list, HWC_DISPLAY_EXTERNAL);
-        //Nothing to do for now
+    ctx->overlayInUse[HWC_DISPLAY_EXTERNAL] = false;
+
+    if (LIKELY(list && list->numHwLayers) &&
+        ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive &&
+        ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
+
+        setListStats(ctx, list, HWC_DISPLAY_EXTERNAL);
+
+        uint32_t last = list->numHwLayers - 1;
+        hwc_layer_1_t *fblayer = &list->hwLayers[last];
+        if(UIMirrorOverlay::prepare(ctx, fblayer)) {
+            ctx->overlayInUse[HWC_DISPLAY_EXTERNAL] = true;
+        }
+
+        if(VideoOverlay::prepare(ctx, list, HWC_DISPLAY_EXTERNAL)) {
+            ctx->overlayInUse[HWC_DISPLAY_EXTERNAL] = true;
+        } else {
+            ctx->mOverlay[HWC_DISPLAY_EXTERNAL]->setState(ovutils::OV_UI_MIRROR);
+        }
     }
     return 0;
 }
@@ -119,7 +134,6 @@
 {
     int ret = 0;
     hwc_context_t* ctx = (hwc_context_t*)(dev);
-    ctx->overlayInUse = false;
 
     reset(ctx, numDisplays);
 
@@ -200,7 +214,7 @@
         case HWC_DISPLAY_PRIMARY:
             if(blank) {
                 Locker::Autolock _l(ctx->mBlankLock);
-                ctx->mOverlay->setState(ovutils::OV_CLOSED);
+                ctx->mOverlay[dpy]->setState(ovutils::OV_CLOSED);
                 ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
             } else {
                 ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK);
@@ -244,9 +258,8 @@
         ALOGI("fps: %d", value[0]);
         break;
     case HWC_DISPLAY_TYPES_SUPPORTED:
-        //TODO Enable later
-        //if(ctx->mMDP.hasOverlay)
-            //supported |= HWC_DISPLAY_EXTERNAL_BIT;
+        if(ctx->mMDP.hasOverlay)
+            supported |= HWC_DISPLAY_EXTERNAL_BIT;
         value[0] = supported;
         break;
     default:
@@ -257,24 +270,22 @@
 }
 
 static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+    if(!ctx->overlayInUse[HWC_DISPLAY_PRIMARY])
+        ctx->mOverlay[HWC_DISPLAY_PRIMARY]->setState(ovutils::OV_CLOSED);
+
     if (LIKELY(list && list->numHwLayers)) {
-        ctx->mFbDev->compositionComplete(ctx->mFbDev);
+        uint32_t last = list->numHwLayers - 1;
+        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+
         hwc_sync(ctx, list, HWC_DISPLAY_PRIMARY);
 
         VideoOverlay::draw(ctx, list, HWC_DISPLAY_PRIMARY);
         MDPComp::draw(ctx, list);
-        uint32_t last = list->numHwLayers - 1;
-        hwc_layer_1_t *fblayer = &list->hwLayers[last];
-        if(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive) {
-            UIMirrorOverlay::draw(ctx, fblayer);
-        }
-        if(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive) {
-            ctx->mExtDisplay->post();
-        }
+
         //TODO We dont check for SKIP flag on this layer because we need PAN
         //always. Last layer is always FB
         if(list->hwLayers[last].compositionType == HWC_FRAMEBUFFER_TARGET) {
-            ctx->mFbDev->post(ctx->mFbDev, list->hwLayers[last].handle);
+            ctx->mFbDev->post(ctx->mFbDev, fbLayer->handle);
         }
     }
     return 0;
@@ -282,17 +293,49 @@
 
 static int hwc_set_external(hwc_context_t *ctx,
         hwc_display_contents_1_t* list) {
-    if (LIKELY(list && list->numHwLayers)) {
-        //hwc_sync(ctx, list, HWC_DISPLAY_EXTERNAL);
+
+    if(!ctx->overlayInUse[HWC_DISPLAY_EXTERNAL])
+        ctx->mOverlay[HWC_DISPLAY_EXTERNAL]->setState(ovutils::OV_CLOSED);
+
+    if (LIKELY(list && list->numHwLayers) &&
+        ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive &&
+        ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
         uint32_t last = list->numHwLayers - 1;
-        if(list->hwLayers[last].compositionType == HWC_FRAMEBUFFER_TARGET &&
-            ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive) {
-            //ctx->mExtDisplay->post(list->hwLayers[last].handle);
+        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+
+        hwc_sync(ctx, list, HWC_DISPLAY_EXTERNAL);
+
+        VideoOverlay::draw(ctx, list, HWC_DISPLAY_EXTERNAL);
+
+        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
+        if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && hnd) {
+            UIMirrorOverlay::draw(ctx, fbLayer);
+            ctx->mExtDisplay->post();
         }
     }
     return 0;
 }
 
+static bool isGpuUsed(hwc_context_t *ctx,
+        size_t numDisplays,
+        hwc_display_contents_1_t** displays)
+{
+    bool isUsed = false;
+    for (uint32_t i = 0; i < numDisplays; i++) {
+        hwc_display_contents_1_t* list = displays[i];
+        if (list && list->numHwLayers) {
+            uint32_t last = list->numHwLayers - 1;
+            hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+            if(!(fbLayer->flags & HWC_SKIP_LAYER)) {
+                isUsed = true;
+                break;
+            }
+
+        }
+    }
+    return isUsed;
+}
+
 static int hwc_set(hwc_composer_device_1 *dev,
                    size_t numDisplays,
                    hwc_display_contents_1_t** displays)
@@ -300,16 +343,21 @@
     int ret = 0;
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     Locker::Autolock _l(ctx->mBlankLock);
-    if(!ctx->overlayInUse)
-        ctx->mOverlay->setState(ovutils::OV_CLOSED);
+
+    if(isGpuUsed(ctx, numDisplays, displays)) {
+        //Call glFinish, only if gpu is used
+        ctx->mFbDev->compositionComplete(ctx->mFbDev);
+    }
 
     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);
+                break;
             default:
                 ret = -EINVAL;
         }
@@ -320,18 +368,26 @@
 int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
         uint32_t* configs, size_t* numConfigs) {
     int ret = 0;
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
     //in 1.1 there is no way to choose a config, report as config id # 0
     //This config is passed to getDisplayAttributes. Ignore for now.
-    if(*numConfigs == 1)
-        *configs = 0;
     switch(disp) {
         case HWC_DISPLAY_PRIMARY:
-            ret = 0;
+            if(*numConfigs > 0) {
+                configs[0] = 0;
+                *numConfigs = 1;
+            }
+            ret = 0; //NO_ERROR
             break;
         case HWC_DISPLAY_EXTERNAL:
-            //Hack until hotplug is supported.
-            //This makes framework ignore external display.
-            ret = -1;
+            ret = -1; //Not connected
+            if(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
+                ret = 0; //NO_ERROR
+                if(*numConfigs > 0) {
+                    configs[0] = 0;
+                    *numConfigs = 1;
+                }
+            }
             break;
     }
     return ret;
@@ -341,6 +397,11 @@
         uint32_t config, const uint32_t* attributes, int32_t* values) {
 
     hwc_context_t* ctx = (hwc_context_t*)(dev);
+    //If hotpluggable displays are inactive return error
+    if(disp == HWC_DISPLAY_EXTERNAL && !ctx->dpyAttr[disp].connected) {
+        return -1;
+    }
+
     //From HWComposer
     static const uint32_t DISPLAY_ATTRIBUTES[] = {
         HWC_DISPLAY_VSYNC_PERIOD,
@@ -361,11 +422,13 @@
             break;
         case HWC_DISPLAY_WIDTH:
             values[i] = ctx->dpyAttr[disp].xres;
-            ALOGD("%s width = %d",__FUNCTION__, ctx->dpyAttr[disp].xres);
+            ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
+                    ctx->dpyAttr[disp].xres);
             break;
         case HWC_DISPLAY_HEIGHT:
             values[i] = ctx->dpyAttr[disp].yres;
-            ALOGD("%s height = %d",__FUNCTION__, ctx->dpyAttr[disp].yres);
+            ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
+                    ctx->dpyAttr[disp].yres);
             break;
         case HWC_DISPLAY_DPI_X:
             values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 6d40741..4c4a9a0 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -191,7 +191,7 @@
 
         private_handle_t *hnd = (private_handle_t *)layer->handle;
 
-        overlay::Overlay& ov = *(ctx->mOverlay);
+        overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
 
         if(!hnd) {
             ALOGE("%s: layer handle is NULL", __FUNCTION__);
@@ -610,7 +610,7 @@
     configure_var_pipe(ctx);
 #endif
 
-    overlay::Overlay& ov = *(ctx->mOverlay);
+    overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
     ovutils::eOverlayState state = ov.getState();
 
     if (current_frame.count == 1) {
@@ -667,7 +667,7 @@
         return -1;
     }
 
-    overlay::Overlay& ov = *(ctx->mOverlay);
+    overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
 
     int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
     for(int i = 0; i < numHwLayers; i++ )
diff --git a/libhwcomposer/hwc_uimirror.cpp b/libhwcomposer/hwc_uimirror.cpp
index 1b81421..62b7efd 100644
--- a/libhwcomposer/hwc_uimirror.cpp
+++ b/libhwcomposer/hwc_uimirror.cpp
@@ -26,30 +26,6 @@
 
 namespace qhwc {
 
-
-// Function to get the orientation of UI on primary.
-// When external display is connected, the primary UI is
-// fixed to landscape by the phone window manager.
-// Return the landscape orientation based on w and hw of primary
-int getDeviceOrientation() {
-    int orientation = 0;
-    //Calculate the rect for primary based on whether the supplied
-    //position
-    //is within or outside bounds.
-    const int fbWidth =
-        ovutils::FrameBufferInfo::getInstance()->getWidth();
-    const int fbHeight =
-        ovutils::FrameBufferInfo::getInstance()->getHeight();
-    if(fbWidth >= fbHeight) {
-        // landscape panel
-        orientation = overlay::utils::OVERLAY_TRANSFORM_0;
-    } else {
-        // portrait panel
-        orientation = overlay::utils::OVERLAY_TRANSFORM_ROT_90;
-    }
-    return orientation;
-}
-
 //Static Members
 ovutils::eOverlayState UIMirrorOverlay::sState = ovutils::OV_CLOSED;
 bool UIMirrorOverlay::sIsUiMirroringOn = false;
@@ -61,83 +37,75 @@
 
 //Prepare the overlay for the UI mirroring
 bool UIMirrorOverlay::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) {
-    sState = ovutils::OV_CLOSED;
-    sIsUiMirroringOn = false;
+    reset();
 
     if(!ctx->mMDP.hasOverlay) {
         ALOGD_IF(HWC_UI_MIRROR, "%s, this hw doesnt support mirroring",
                 __FUNCTION__);
        return false;
     }
-    // If external display is active
-    if(isExternalActive(ctx)) {
-        sState = ovutils::OV_UI_MIRROR;
-        configure(ctx, fblayer);
+
+    sState = ovutils::OV_UI_MIRROR;
+    ovutils::eOverlayState newState = ctx->mOverlay[HWC_DISPLAY_EXTERNAL]->getState();
+    if(newState == ovutils::OV_UI_VIDEO_TV) {
+        sState = newState;
     }
+
+    configure(ctx, fblayer);
     return sIsUiMirroringOn;
 }
 
 // Configure
 bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_layer_1_t *layer)
 {
-    if (LIKELY(ctx->mOverlay)) {
-        overlay::Overlay& ov = *(ctx->mOverlay);
+    if (LIKELY(ctx->mOverlay[HWC_DISPLAY_EXTERNAL])) {
+        overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_EXTERNAL]);
         // Set overlay state
         ov.setState(sState);
-        framebuffer_device_t *fbDev = ctx->mFbDev;
-        if(fbDev) {
-            private_handle_t *hnd = (private_handle_t *)layer->handle;
-            ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
-            // Determine the RGB pipe for UI depending on the state
-            ovutils::eDest dest = ovutils::OV_PIPE_ALL;
-            if (sState == ovutils::OV_2D_TRUE_UI_MIRROR) {
-                // True UI mirroring state: external RGB pipe is OV_PIPE2
-                dest = ovutils::OV_PIPE2;
-            } else if (sState == ovutils::OV_UI_MIRROR) {
-                // UI-only mirroring state: external RGB pipe is OV_PIPE0
-                dest = ovutils::OV_PIPE0;
-            }
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
+        // Determine the RGB pipe for UI depending on the state
+        ovutils::eDest dest = ovutils::OV_PIPE0;
 
-            ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
-            if(ctx->mSecureMode) {
-                ovutils::setMdpFlags(mdpFlags,
-                        ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
-            }
+        ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
+        if(ctx->mSecureMode) {
+            ovutils::setMdpFlags(mdpFlags,
+                    ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
+        }
 
-            ovutils::PipeArgs parg(mdpFlags,
-                    info,
-                    ovutils::ZORDER_0,
-                    ovutils::IS_FG_OFF,
-                    ovutils::ROT_FLAG_ENABLED);
-            ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
-            ov.setSource(pargs, dest);
+        ovutils::PipeArgs parg(mdpFlags,
+                info,
+                ovutils::ZORDER_0,
+                ovutils::IS_FG_OFF,
+                ovutils::ROT_FLAG_DISABLED);
+        ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
+        ov.setSource(pargs, dest);
 
-            hwc_rect_t sourceCrop = layer->sourceCrop;
-            // x,y,w,h
-            ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
+        hwc_rect_t sourceCrop = layer->sourceCrop;
+        // x,y,w,h
+        ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
                 sourceCrop.right - sourceCrop.left,
                 sourceCrop.bottom - sourceCrop.top);
-            ov.setCrop(dcrop, dest);
+        ov.setCrop(dcrop, dest);
 
-            //Get the current orientation on primary panel
-            int transform = getDeviceOrientation();
-            ovutils::eTransform orient =
-                    static_cast<ovutils::eTransform>(transform);
-            ov.setTransform(orient, dest);
+        int transform = layer->transform;
+        ovutils::eTransform orient =
+                static_cast<ovutils::eTransform>(transform);
+        ov.setTransform(orient, dest);
 
-            hwc_rect_t displayFrame = layer->displayFrame;
-            ovutils::Dim dpos(displayFrame.left,
+        hwc_rect_t displayFrame = layer->displayFrame;
+        ovutils::Dim dpos(displayFrame.left,
                 displayFrame.top,
                 displayFrame.right - displayFrame.left,
                 displayFrame.bottom - displayFrame.top);
-            ov.setPosition(dpos, dest);
+        ov.setPosition(dpos, dest);
 
-            if (!ov.commit(dest)) {
-                ALOGE("%s: commit fails", __FUNCTION__);
-                return false;
-            }
-            sIsUiMirroringOn = true;
+        if (!ov.commit(dest)) {
+            ALOGE("%s: commit fails", __FUNCTION__);
+            sIsUiMirroringOn = false;
+            return false;
         }
+        sIsUiMirroringOn = true;
     }
     return sIsUiMirroringOn;
 }
@@ -148,36 +116,20 @@
         return true;
     }
     bool ret = true;
-    overlay::Overlay& ov = *(ctx->mOverlay);
+    overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_EXTERNAL]);
     ovutils::eOverlayState state = ov.getState();
-    ovutils::eDest dest = ovutils::OV_PIPE_ALL;
-    framebuffer_device_t *fbDev = ctx->mFbDev;
-    if(fbDev) {
-        private_module_t* m = reinterpret_cast<private_module_t*>(
-                              fbDev->common.module);
-        private_handle_t *hnd = (private_handle_t *)layer->handle;
-        switch (state) {
-            case ovutils::OV_UI_MIRROR:
-                //TODO why is this primary fd
-                if (!ov.queueBuffer(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd,
-                            hnd->offset,  //div by line_length like in PAN?
-                            ovutils::OV_PIPE0)) {
-                    ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
-                    ret = false;
-                }
-                break;
-            case ovutils::OV_2D_TRUE_UI_MIRROR:
-                if (!ov.queueBuffer(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd,
-                            hnd->offset,
-                            ovutils::OV_PIPE2)) {
-                    ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
-                    ret = false;
-                }
-                break;
-
+    ovutils::eDest dest = ovutils::OV_PIPE0;
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    switch (state) {
+        case ovutils::OV_UI_MIRROR:
+        case ovutils::OV_UI_VIDEO_TV:
+            if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
+                ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
+                ret = false;
+            }
+            break;
         default:
             break;
-        }
     }
     return ret;
 }
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index e198de3..ee9cc54 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -51,7 +51,10 @@
 void initContext(hwc_context_t *ctx)
 {
     openFramebufferDevice(ctx);
-    ctx->mOverlay = overlay::Overlay::getInstance();
+    overlay::Overlay::initOverlay();
+    for(uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+        ctx->mOverlay[i] = overlay::Overlay::getInstance(i);
+    }
     ctx->mQService = qService::QService::getInstance(ctx);
     ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
     ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
@@ -69,9 +72,11 @@
 
 void closeContext(hwc_context_t *ctx)
 {
-    if(ctx->mOverlay) {
-        delete ctx->mOverlay;
-        ctx->mOverlay = NULL;
+    for(uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+        if(ctx->mOverlay[i]) {
+            delete ctx->mOverlay[i];
+            ctx->mOverlay[i] = NULL;
+        }
     }
 
     if(ctx->mFbDev) {
@@ -111,6 +116,9 @@
 
     ctx->listStats[dpy].numAppLayers = list->numHwLayers - 1;
     ctx->listStats[dpy].fbLayerIndex = list->numHwLayers - 1;
+    ctx->listStats[dpy].yuvCount = 0;
+    ctx->listStats[dpy].yuvIndex = -1;
+    ctx->listStats[dpy].skipCount = 0;
 
     for (size_t i = 0; i < list->numHwLayers; i++) {
         private_handle_t *hnd =
@@ -198,7 +206,7 @@
     int count = 0;
     int releaseFd = -1;
     int fbFd = -1;
-    data.flags = 0;
+    data.flags = MDP_BUF_SYNC_FLAG_WAIT;
     data.acq_fen_fd = acquireFd;
     data.rel_fen_fd = &releaseFd;
     //Accumulate acquireFenceFds
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 0bde003..37708e6 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -60,6 +60,9 @@
     float xdpi;
     float ydpi;
     int fd;
+    bool connected; //Applies only to pluggable disp.
+    //Connected does not mean it ready to use.
+    //It should be active also. (UNBLANKED)
     bool isActive;
 };
 
@@ -166,13 +169,13 @@
     hwc_composer_device_1_t device;
     const hwc_procs_t* proc;
     int numHwLayers;
-    int overlayInUse;
+    int overlayInUse[HWC_NUM_DISPLAY_TYPES];
 
     //Framebuffer device
     framebuffer_device_t *mFbDev;
 
     //Overlay object - NULL for non overlay devices
-    overlay::Overlay *mOverlay;
+    overlay::Overlay *mOverlay[HWC_NUM_DISPLAY_TYPES];
 
     //QService object
     qService::QService *mQService;
diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp
index 2e4342a..7bbfaf9 100644
--- a/libhwcomposer/hwc_video.cpp
+++ b/libhwcomposer/hwc_video.cpp
@@ -25,19 +25,22 @@
 #define FINAL_TRANSFORM_MASK 0x000F
 
 //Static Members
-ovutils::eOverlayState VideoOverlay::sState = ovutils::OV_CLOSED;
-bool VideoOverlay::sIsModeOn = false;
+ovutils::eOverlayState VideoOverlay::sState[] = {ovutils::OV_CLOSED};
+bool VideoOverlay::sIsModeOn[] = {false};
 
 //Cache stats, figure out the state, config overlay
 bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
         int dpy) {
+
     int yuvIndex =  ctx->listStats[dpy].yuvIndex;
+    sIsModeOn[dpy] = false;
 
     if(!ctx->mMDP.hasOverlay) {
        ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__);
        return false;
     }
-    if(yuvIndex == -1) {
+
+    if(yuvIndex == -1 || ctx->listStats[dpy].yuvCount != 1) {
         return false;
     }
 
@@ -55,16 +58,16 @@
     chooseState(ctx, dpy, yuvLayer);
     if(configure(ctx, dpy, yuvLayer)) {
         markFlags(yuvLayer);
-        sIsModeOn = true;
+        sIsModeOn[dpy] = true;
     }
 
-    return sIsModeOn;
+    return sIsModeOn[dpy];
 }
 
 void VideoOverlay::chooseState(hwc_context_t *ctx, int dpy,
         hwc_layer_1_t *yuvLayer) {
     ALOGD_IF(VIDEO_DEBUG, "%s: old state = %s", __FUNCTION__,
-            ovutils::getStateString(sState));
+            ovutils::getStateString(sState[dpy]));
 
     private_handle_t *hnd = NULL;
     if(yuvLayer) {
@@ -74,38 +77,27 @@
     switch(dpy) {
         case HWC_DISPLAY_PRIMARY:
             if(ctx->listStats[dpy].yuvCount == 1) {
-                newState = isExternalActive(ctx) ?
-                    ovutils::OV_2D_VIDEO_ON_PANEL_TV : ovutils::OV_2D_VIDEO_ON_PANEL;
+                newState = ovutils::OV_2D_VIDEO_ON_PANEL;
                 if(isSkipLayer(yuvLayer) && !isSecureBuffer(hnd)) {
-                    newState = isExternalActive(ctx) ?
-                        ovutils::OV_2D_VIDEO_ON_TV : ovutils::OV_CLOSED;
+                    newState = ovutils::OV_CLOSED;
                 }
             }
             break;
         case HWC_DISPLAY_EXTERNAL:
-        //TODO needs overlay state change for UI also
-            newState = sState; //Previously set by HWC_DISPLAY_PRIMARY
-            /*if(ctx->listStats[dpy].yuvCount == 1 && isExternalActive(ctx)) {
+            newState = ctx->mOverlay[HWC_DISPLAY_EXTERNAL]->getState(); //If we are here, external is active
+            if(ctx->listStats[dpy].yuvCount == 1) {
                 if(!isSkipLayer(yuvLayer) || isSecureBuffer(hnd)) {
-                    switch(sState) { //set by primary chooseState
-                        case ovutils::OV_2D_VIDEO_ON_PANEL:
-                            //upgrade
-                            sState = ovutils::OV_2D_VIDEO_PANEL_TV;
-                            break;
-                        case ovutils::OV_CLOSED:
-                            sState = ovutils::OV_2D_VIDEO_ON_TV;
-                            break;
-                    }
+                    newState = ovutils::OV_UI_VIDEO_TV;
                 }
-            }*/
+            }
             break;
         default:
             break;
     }
 
-    sState = newState;
+    sState[dpy] = newState;
     ALOGD_IF(VIDEO_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
-            ovutils::getStateString(sState));
+            ovutils::getStateString(sState[dpy]));
 }
 
 void VideoOverlay::markFlags(hwc_layer_1_t *yuvLayer) {
@@ -117,7 +109,7 @@
 
 /* Helpers */
 bool configPrimVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
-    overlay::Overlay& ov = *(ctx->mOverlay);
+    overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_PRIMARY]);
     private_handle_t *hnd = (private_handle_t *)layer->handle;
     ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
 
@@ -184,7 +176,7 @@
 }
 
 bool configExtVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
-    overlay::Overlay& ov = *(ctx->mOverlay);
+    overlay::Overlay& ov = *(ctx->mOverlay[HWC_DISPLAY_EXTERNAL]);
     private_handle_t *hnd = (private_handle_t *)layer->handle;
     ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
 
@@ -201,10 +193,9 @@
 
     ovutils::PipeArgs parg(mdpFlags,
             info,
-            ovutils::ZORDER_0,
+            ovutils::ZORDER_1,
             isFgFlag,
-            ovutils::ROT_FLAG_ENABLED); //TODO remove this hack when sync for
-            //ext is done
+            ovutils::ROT_FLAG_DISABLED);
     ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
     ov.setSource(pargs, ovutils::OV_PIPE1);
 
@@ -216,9 +207,10 @@
     //Only for External
     ov.setCrop(dcrop, ovutils::OV_PIPE1);
 
-    // FIXME: Use source orientation for TV when source is portrait
-    //Only for External
-    ov.setTransform(0, ovutils::OV_PIPE1);
+    int transform = layer->transform;
+    ovutils::eTransform orient =
+            static_cast<ovutils::eTransform>(transform);
+    ov.setTransform(orient, ovutils::OV_PIPE1);
 
     ovutils::Dim dpos;
     hwc_rect_t displayFrame = layer->displayFrame;
@@ -240,31 +232,23 @@
 bool VideoOverlay::configure(hwc_context_t *ctx, int dpy,
         hwc_layer_1_t *yuvLayer) {
     bool ret = true;
-    overlay::Overlay& ov = *(ctx->mOverlay);
+    overlay::Overlay& ov = *(ctx->mOverlay[dpy]);
     switch(dpy) {
         case HWC_DISPLAY_PRIMARY:
             // Set overlay state
-            ov.setState(sState);
-            switch(sState) {
+            ov.setState(sState[dpy]);
+            switch(sState[dpy]) {
                 case ovutils::OV_2D_VIDEO_ON_PANEL:
                     ret &= configPrimVid(ctx, yuvLayer);
                     break;
-                case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
-                    ret &= configPrimVid(ctx, yuvLayer);
-                    ret &= configExtVid(ctx, yuvLayer);
-                    break;
-                case ovutils::OV_2D_VIDEO_ON_TV:
-                    ret &= configExtVid(ctx, yuvLayer);
-                    break;
                 default:
                     return false;
             }
             break;
         case HWC_DISPLAY_EXTERNAL:
-            ov.setState(sState);
-            switch(sState) {
-                case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
-                case ovutils::OV_2D_VIDEO_ON_TV:
+            ov.setState(sState[dpy]);
+            switch(sState[dpy]) {
+                case ovutils::OV_UI_VIDEO_TV:
                     ret = configExtVid(ctx, yuvLayer);
                     break;
                 default:
@@ -278,8 +262,12 @@
 bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
         int dpy)
 {
+    if(!sIsModeOn[dpy]) {
+        return true;
+    }
+
     int yuvIndex = ctx->listStats[dpy].yuvIndex;
-    if(!sIsModeOn || yuvIndex == -1) {
+    if(yuvIndex == -1) {
         return true;
     }
 
@@ -287,7 +275,7 @@
             list->hwLayers[yuvIndex].handle;
 
     bool ret = true;
-    overlay::Overlay& ov = *(ctx->mOverlay);
+    overlay::Overlay& ov = *(ctx->mOverlay[dpy]);
     ovutils::eOverlayState state = ov.getState();
 
     switch(dpy) {
@@ -300,24 +288,6 @@
                         ret = false;
                     }
                     break;
-                case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
-                    if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
-                        ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
-                        ret = false;
-                    }
-                    // Play external
-                    if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
-                        ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
-                        ret = false;
-                    }
-                    break;
-                case ovutils::OV_2D_VIDEO_ON_TV:
-                    // Play external
-                    if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
-                        ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
-                        ret = false;
-                    }
-                    break;
                 default:
                     ret = false;
                     break;
@@ -325,8 +295,7 @@
             break;
         case HWC_DISPLAY_EXTERNAL:
             switch(state) {
-                case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
-                case ovutils::OV_2D_VIDEO_ON_TV:
+                case ovutils::OV_UI_VIDEO_TV:
                     // Play external
                     if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
                         ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
diff --git a/libhwcomposer/hwc_video.h b/libhwcomposer/hwc_video.h
index f5a9709..dbfc236 100644
--- a/libhwcomposer/hwc_video.h
+++ b/libhwcomposer/hwc_video.h
@@ -43,14 +43,16 @@
     //Marks layer flags if this feature is used
     static void markFlags(hwc_layer_1_t *yuvLayer);
     //The chosen overlay state.
-    static ovutils::eOverlayState sState;
+    static ovutils::eOverlayState sState[HWC_NUM_DISPLAY_TYPES];
     //Flags if this feature is on.
-    static bool sIsModeOn;
+    static bool sIsModeOn[HWC_NUM_DISPLAY_TYPES];
 };
 
 inline void VideoOverlay::reset() {
-    sIsModeOn = false;
-    sState = ovutils::OV_CLOSED;
+    for(uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+        sIsModeOn[i] = false;
+        sState[i] = ovutils::OV_CLOSED;
+    }
 }
 }; //namespace qhwc