hwcomposer: Add support for UI mirroring

- Uevent observer as part of Hwcomposer
- HPD, enabling/disabling external display from HWC

Change-Id: I52b4f30c78e98c5b52c86722046389f458c2dbee
diff --git a/libgralloc/framebuffer.cpp b/libgralloc/framebuffer.cpp
index f689d52..31978f0 100644
--- a/libgralloc/framebuffer.cpp
+++ b/libgralloc/framebuffer.cpp
@@ -43,9 +43,6 @@
 #include <cutils/properties.h>
 #include <profiler.h>
 
-#include "overlay.h"
-namespace ovutils = overlay::utils;
-
 #define EVEN_OUT(x) if (x & 0x0001) {x--;}
 /** min of int a, b */
 static inline int min(int a, int b) {
@@ -101,402 +98,6 @@
     return 0;
 }
 
-#if defined(HDMI_DUAL_DISPLAY)
-static int closeHDMIChannel(private_module_t* m)
-{
-    // XXX - when enabling HDMI
-#if 0
-    Overlay* pTemp = m->pobjOverlay;
-    if(pTemp != NULL)
-        pTemp->closeChannel();
-#endif
-    return 0;
-}
-
-// XXX - Complete when enabling HDMI
-#if 0
-static void getSecondaryDisplayDestinationInfo(private_module_t* m, overlay_rect&
-                                               rect, int& orientation)
-{
-    Overlay* pTemp = m->pobjOverlay;
-    int width = pTemp->getFBWidth();
-    int height = pTemp->getFBHeight();
-    int fbwidth = m->info.xres, fbheight = m->info.yres;
-    rect.x = 0; rect.y = 0;
-    rect.w = width; rect.h = height;
-    int rot = m->orientation;
-    switch(rot) {
-        // ROT_0
-        case 0:
-            // ROT_180
-        case HAL_TRANSFORM_ROT_180:
-            pTemp->getAspectRatioPosition(fbwidth, fbheight,
-                                          &rect);
-            if(rot ==  HAL_TRANSFORM_ROT_180)
-                orientation = HAL_TRANSFORM_ROT_180;
-            else
-                orientation  = 0;
-            break;
-            // ROT_90
-        case HAL_TRANSFORM_ROT_90:
-            // ROT_270
-        case HAL_TRANSFORM_ROT_270:
-            //Calculate the Aspectratio for the UI
-            //in the landscape mode
-            //Width and height will be swapped as there
-            //is rotation
-            pTemp->getAspectRatioPosition(fbheight, fbwidth,
-                                          &rect);
-
-            if(rot == HAL_TRANSFORM_ROT_90)
-                orientation = HAL_TRANSFORM_ROT_270;
-            else if(rot == HAL_TRANSFORM_ROT_270)
-                orientation = HAL_TRANSFORM_ROT_90;
-            break;
-    }
-    return;
-}
-#endif
-
-/* Determine overlay state based on whether hardware supports true UI
-   mirroring and whether video is playing or not */
-static ovutils::eOverlayState getOverlayState(struct private_module_t* module)
-{
-    overlay2::Overlay& ov = *(Overlay::getInstance());
-
-    // Default to existing state
-    ovutils::eOverlayState state = ov.getState();
-
-    // Sanity check
-    if (!module) {
-        ALOGE("%s: NULL module", __FUNCTION__);
-        return state;
-    }
-
-    // Check if video is playing or not
-    if (module->videoOverlay) {
-        // Video is playing, check if hardware supports true UI mirroring
-        if (module->trueMirrorSupport) {
-            // True UI mirroring is supported by hardware
-            if (ov.getState() == ovutils::OV_2D_VIDEO_ON_PANEL) {
-                // Currently playing 2D video
-                state = ovutils::OV_2D_TRUE_UI_MIRROR;
-            } else if (ov.getState() == ovutils::OV_3D_VIDEO_ON_2D_PANEL) {
-                // Currently playing M3D video
-                // FIXME: Support M3D true UI mirroring
-                state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV;
-            }
-        } else {
-            // True UI mirroring is not supported by hardware
-            if (ov.getState() == ovutils::OV_2D_VIDEO_ON_PANEL) {
-                // Currently playing 2D video
-                state = ovutils::OV_2D_VIDEO_ON_PANEL_TV;
-            } else if (ov.getState() == ovutils::OV_3D_VIDEO_ON_2D_PANEL) {
-                // Currently playing M3D video
-                state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV;
-            }
-        }
-    } else {
-        // Video is not playing, true UI mirroring support is irrelevant
-        state = ovutils::OV_UI_MIRROR;
-    }
-
-    return state;
-}
-
-/* Set overlay state */
-static void setOverlayState(ovutils::eOverlayState state)
-{
-    overlay2::Overlay& ov = *(Overlay::getInstance());
-    ov.setState(state);
-}
-
-static void *hdmi_ui_loop(void *ptr)
-{
-    private_module_t* m = reinterpret_cast<private_module_t*>(ptr);
-    while (1) {
-        pthread_mutex_lock(&m->overlayLock);
-        while(!(m->hdmiStateChanged))
-            pthread_cond_wait(&(m->overlayPost), &(m->overlayLock));
-
-        m->hdmiStateChanged = false;
-        if (m->exitHDMIUILoop) {
-            pthread_mutex_unlock(&m->overlayLock);
-            return NULL;
-        }
-
-        // No need to mirror UI if HDMI is not on
-        if (!m->enableHDMIOutput) {
-            ALOGE_IF(FB_DEBUG, "%s: hdmi not ON", __FUNCTION__);
-            pthread_mutex_unlock(&m->overlayLock);
-            continue;
-        }
-
-        overlay2::OverlayMgr* ovMgr =
-            overlay2::OverlayMgrSingleton::getOverlayMgr();
-        overlay2::Overlay& ov = ovMgr->ov();
-
-        // Set overlay state
-        ovutils::eOverlayState state = getOverlayState(m);
-        setOverlayState(state);
-
-        // Determine the RGB pipe for UI depending on the state
-        ovutils::eDest dest = ovutils::OV_PIPE_ALL;
-        if (state == ovutils::OV_2D_TRUE_UI_MIRROR) {
-            // True UI mirroring state: external RGB pipe is OV_PIPE2
-            dest = ovutils::OV_PIPE2;
-        } else if (state == ovutils::OV_UI_MIRROR) {
-            // UI-only mirroring state: external RGB pipe is OV_PIPE0
-            dest = ovutils::OV_PIPE0;
-        } else {
-            // No UI in this case
-            pthread_mutex_unlock(&m->overlayLock);
-            continue;
-        }
-
-        if (m->hdmiMirroringState == HDMI_UI_MIRRORING) {
-            int alignedW = ALIGN(m->info.xres, 32);
-
-            private_handle_t const* hnd =
-                reinterpret_cast<private_handle_t const*>(m->framebuffer);
-            unsigned int width = alignedW;
-            unsigned int height = hnd->height;
-            unsigned int format = hnd->format;
-            unsigned int size = hnd->size/m->numBuffers;
-
-            ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
-            // External display connected during secure video playback
-            // Open secure UI session
-            // NOTE: when external display is already connected and then secure
-            // playback is started, we dont have to do anything
-            if (m->secureVideoOverlay) {
-                ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
-            }
-
-            ovutils::Whf whf(width, height, format, size);
-            ovutils::PipeArgs parg(mdpFlags,
-                                   ovutils::OVERLAY_TRANSFORM_0,
-                                   whf,
-                                   ovutils::ZORDER_0,
-                                   ovutils::IS_FG_OFF,
-                                   ovutils::ROT_FLAG_ENABLED);
-            ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
-            bool ret = ov.setSource(pargs, dest);
-            if (!ret) {
-                ALOGE("%s setSource failed", __FUNCTION__);
-            }
-
-            // we need to communicate m->orientation that will get some
-            // modifications within setParameter func.
-            // FIXME that is ugly.
-            const ovutils::Params prms (ovutils::OVERLAY_TRANSFORM_UI,
-                                        m->orientation);
-            ov.setParameter(prms, dest);
-            if (!ret) {
-                ALOGE("%s setParameter failed transform", __FUNCTION__);
-            }
-
-            // x,y,w,h
-            ovutils::Dim dcrop(0, 0, m->info.xres, m->info.yres);
-            ov.setMemoryId(m->framebuffer->fd, dest);
-            ret = ov.setCrop(dcrop, dest);
-            if (!ret) {
-                ALOGE("%s setCrop failed", __FUNCTION__);
-            }
-
-            ovutils::Dim pdim (m->info.xres,
-                               m->info.yres,
-                               0,
-                               0,
-                               m->orientation);
-            ret = ov.setPosition(pdim, dest);
-            if (!ret) {
-                ALOGE("%s setPosition failed", __FUNCTION__);
-            }
-
-            if (!ov.commit(dest)) {
-                ALOGE("%s commit fails", __FUNCTION__);
-            }
-
-            ret = ov.queueBuffer(m->currentOffset, dest);
-            if (!ret) {
-                ALOGE("%s queueBuffer failed", __FUNCTION__);
-            }
-        } else {
-            setOverlayState(ovutils::OV_CLOSED);
-        }
-        pthread_mutex_unlock(&m->overlayLock);
-    }
-    return NULL;
-}
-
-static int fb_videoOverlayStarted(struct framebuffer_device_t* dev, int started)
-{
-    ALOGE_IF(FB_DEBUG, "%s started=%d", __FUNCTION__, started);
-    private_module_t* m = reinterpret_cast<private_module_t*>(
-        dev->common.module);
-    pthread_mutex_lock(&m->overlayLock);
-    if(started != m->videoOverlay) {
-        m->videoOverlay = started;
-        m->hdmiStateChanged = true;
-        if (!m->trueMirrorSupport) {
-            if (started) {
-                m->hdmiMirroringState = HDMI_NO_MIRRORING;
-                ovutils::eOverlayState state = getOverlayState(m);
-                setOverlayState(state);
-            } else if (m->enableHDMIOutput)
-                m->hdmiMirroringState = HDMI_UI_MIRRORING;
-        } else {
-            if (m->videoOverlay == VIDEO_3D_OVERLAY_STARTED) {
-                ALOGE_IF(FB_DEBUG, "3D Video Started, stop mirroring!");
-                m->hdmiMirroringState = HDMI_NO_MIRRORING;
-                ovutils::eOverlayState state = getOverlayState(m);
-                setOverlayState(state);
-            }
-            else if (m->enableHDMIOutput) {
-                m->hdmiMirroringState = HDMI_UI_MIRRORING;
-            }
-        }
-    }
-    pthread_mutex_unlock(&m->overlayLock);
-    return 0;
-}
-
-static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int externaltype)
-{
-    ALOGE_IF(FB_DEBUG, "%s externaltype=%d", __FUNCTION__, externaltype);
-    private_module_t* m = reinterpret_cast<private_module_t*>(
-        dev->common.module);
-    pthread_mutex_lock(&m->overlayLock);
-    //Check if true mirroring can be supported
-    m->trueMirrorSupport = ovutils::FrameBufferInfo::getInstance()->supportTrueMirroring();
-    m->enableHDMIOutput = externaltype;
-    if(externaltype) {
-        if (m->trueMirrorSupport) {
-            m->hdmiMirroringState = HDMI_UI_MIRRORING;
-        } else {
-            if(!m->videoOverlay)
-                m->hdmiMirroringState = HDMI_UI_MIRRORING;
-        }
-    } else if (!externaltype) {
-        // Either HDMI is disconnected or suspend occurred
-        m->hdmiMirroringState = HDMI_NO_MIRRORING;
-        ovutils::eOverlayState state = getOverlayState(m);
-        setOverlayState(state);
-    }
-    m->hdmiStateChanged = true;
-    pthread_cond_signal(&(m->overlayPost));
-    pthread_mutex_unlock(&m->overlayLock);
-    return 0;
-}
-
-static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientation)
-{
-    private_module_t* m = reinterpret_cast<private_module_t*>(
-        dev->common.module);
-    pthread_mutex_lock(&m->overlayLock);
-    neworientation = orientation;
-    pthread_mutex_unlock(&m->overlayLock);
-    return 0;
-}
-
-static int handle_open_secure_start(private_module_t* m) {
-    pthread_mutex_lock(&m->overlayLock);
-    m->hdmiMirroringState = HDMI_NO_MIRRORING;
-    m->secureVideoOverlay = true;
-    pthread_mutex_unlock(&m->overlayLock);
-    return 0;
-}
-
-static int handle_open_secure_end(private_module_t* m) {
-    pthread_mutex_lock(&m->overlayLock);
-    if (m->enableHDMIOutput) {
-        if (m->trueMirrorSupport) {
-            m->hdmiMirroringState = HDMI_UI_MIRRORING;
-        } else if(!m->videoOverlay) {
-            m->hdmiMirroringState = HDMI_UI_MIRRORING;
-        }
-        m->hdmiStateChanged = true;
-        pthread_cond_signal(&(m->overlayPost));
-    }
-    pthread_mutex_unlock(&m->overlayLock);
-    return 0;
-}
-
-static int handle_close_secure_start(private_module_t* m) {
-    pthread_mutex_lock(&m->overlayLock);
-    m->hdmiMirroringState = HDMI_NO_MIRRORING;
-    m->secureVideoOverlay = false;
-    pthread_mutex_unlock(&m->overlayLock);
-    return 0;
-}
-
-static int handle_close_secure_end(private_module_t* m) {
-    pthread_mutex_lock(&m->overlayLock);
-    if (m->enableHDMIOutput) {
-        if (m->trueMirrorSupport) {
-            m->hdmiMirroringState = HDMI_UI_MIRRORING;
-        } else if(!m->videoOverlay) {
-            m->hdmiMirroringState = HDMI_UI_MIRRORING;
-        }
-        m->hdmiStateChanged = true;
-        pthread_cond_signal(&(m->overlayPost));
-    }
-    pthread_mutex_unlock(&m->overlayLock);
-    return 0;
-}
-#endif
-
-
-
-/* fb_perform - used to add custom event and handle them in fb HAL
- * Used for external display related functions as of now
- */
-static int fb_perform(struct framebuffer_device_t* dev, int event, int value)
-{
-    private_module_t* m = reinterpret_cast<private_module_t*>(
-        dev->common.module);
-    switch(event) {
-#if defined(HDMI_DUAL_DISPLAY)
-        case EVENT_EXTERNAL_DISPLAY:
-            fb_enableHDMIOutput(dev, value);
-            break;
-        case EVENT_VIDEO_OVERLAY:
-            fb_videoOverlayStarted(dev, value);
-            break;
-        case EVENT_ORIENTATION_CHANGE:
-            fb_orientationChanged(dev, value);
-            break;
-        case EVENT_OVERLAY_STATE_CHANGE:
-            if (value == OVERLAY_STATE_CHANGE_START) {
-                // When state change starts, get a lock on overlay
-                pthread_mutex_lock(&m->overlayLock);
-            } else if (value == OVERLAY_STATE_CHANGE_END) {
-                // When state change is complete, unlock overlay
-                pthread_mutex_unlock(&m->overlayLock);
-            }
-            break;
-        case EVENT_OPEN_SECURE_START:
-            handle_open_secure_start(m);
-            break;
-        case EVENT_OPEN_SECURE_END:
-            handle_open_secure_end(m);
-            break;
-        case EVENT_CLOSE_SECURE_START:
-            handle_close_secure_start(m);
-            break;
-        case EVENT_CLOSE_SECURE_END:
-            handle_close_secure_end(m);
-            break;
-#endif
-        default:
-            ALOGE("In %s: UNKNOWN Event = %d!!!", __FUNCTION__, event);
-            break;
-    }
-    return 0;
-}
-
-
 static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
 {
     if (private_handle_t::validate(buffer) < 0)
@@ -510,6 +111,7 @@
     private_module_t* m =
         reinterpret_cast<private_module_t*>(dev->common.module);
 
+
     if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
         genlock_lock_buffer(hnd, GENLOCK_READ_LOCK, GENLOCK_MAX_TIMEOUT);
 
@@ -519,6 +121,14 @@
         }
 
         const size_t offset = hnd->base - m->framebuffer->base;
+        // frame ready to be posted, signal so that hwc can update External
+        // display
+        pthread_mutex_lock(&m->fbPostLock);
+        m->currentOffset = offset;
+        m->fbPostDone = true;
+        pthread_cond_signal(&m->fbPostCond);
+        pthread_mutex_unlock(&m->fbPostLock);
+
         m->info.activate = FB_ACTIVATE_VBL;
         m->info.yoffset = offset / m->finfo.line_length;
         if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
@@ -579,11 +189,12 @@
     info.yoffset = 0;
     info.activate = FB_ACTIVATE_NOW;
 
-    /* Interpretation of offset for color fields: All offsets are from the right,
-     * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
-     * can use the offset as right argument to <<). A pixel afterwards is a bit
-     * stream and is written to video memory as that unmodified. This implies
-     * big-endian byte order if bits_per_pixel is greater than 8.
+    /* Interpretation of offset for color fields: All offsets are from the
+     * right, inside a "pixel" value, which is exactly 'bits_per_pixel' wide
+     * (means: you can use the offset as right argument to <<). A pixel
+     * afterwards is a bit stream and is written to video memory as that
+     * unmodified. This implies big-endian byte order if bits_per_pixel is
+     * greater than 8.
      */
 
     if(info.bits_per_pixel == 32) {
@@ -600,10 +211,11 @@
         info.transp.offset  = 0;
         info.transp.length  = 8;
 
-        /* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we do
-         * not use the MDP for composition (i.e. hw composition == 0), ask for
-         * RGBA instead of RGBX. */
-        if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0)
+        /* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we
+         * do not use the MDP for composition (i.e. hw composition == 0), ask
+         * for RGBA instead of RGBX. */
+        if (property_get("debug.sf.hw", property, NULL) > 0 &&
+                                                           atoi(property) == 0)
             module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
         else if(property_get("debug.composition.type", property, NULL) > 0 &&
                 (strncmp(property, "mdp", 3) == 0))
@@ -627,7 +239,8 @@
     }
 
     //adreno needs 4k aligned offsets. Max hole size is 4096-1
-    int  size = roundUpToPageSize(info.yres * info.xres * (info.bits_per_pixel/8));
+    int  size = roundUpToPageSize(info.yres * info.xres *
+                                                       (info.bits_per_pixel/8));
 
     /*
      * Request NUM_BUFFERS screens (at least 2 for page flipping)
@@ -738,9 +351,9 @@
     size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres)*
                     module->numBuffers;
     module->framebuffer = new private_handle_t(fd, fbSize,
-                                               private_handle_t::PRIV_FLAGS_USES_PMEM,
-                                               BUFFER_TYPE_UI,
-                                               module->fbFormat, info.xres, info.yres);
+                                        private_handle_t::PRIV_FLAGS_USES_PMEM,
+                                        BUFFER_TYPE_UI,
+                                        module->fbFormat, info.xres, info.yres);
     void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
     if (vaddr == MAP_FAILED) {
         ALOGE("Error mapping the framebuffer (%s)", strerror(errno));
@@ -748,20 +361,10 @@
     }
     module->framebuffer->base = intptr_t(vaddr);
     memset(vaddr, 0, fbSize);
-
-#if defined(HDMI_DUAL_DISPLAY)
-    /* Overlay for HDMI*/
-    pthread_mutex_init(&(module->overlayLock), NULL);
-    pthread_cond_init(&(module->overlayPost), NULL);
     module->currentOffset = 0;
-    module->exitHDMIUILoop = false;
-    module->hdmiStateChanged = false;
-    pthread_t hdmiUIThread;
-    pthread_create(&hdmiUIThread, NULL, &hdmi_ui_loop, (void *) module);
-    module->hdmiMirroringState = HDMI_NO_MIRRORING;
-    module->trueMirrorSupport = false;
-#endif
-
+    module->fbPostDone = false;
+    pthread_mutex_init(&(module->fbPostLock), NULL);
+    pthread_cond_init(&(module->fbPostCond), NULL);
     return 0;
 }
 
@@ -778,14 +381,6 @@
 static int fb_close(struct hw_device_t *dev)
 {
     fb_context_t* ctx = (fb_context_t*)dev;
-#if defined(HDMI_DUAL_DISPLAY)
-    private_module_t* m = reinterpret_cast<private_module_t*>(
-        ctx->device.common.module);
-    pthread_mutex_lock(&m->overlayLock);
-    m->exitHDMIUILoop = true;
-    pthread_cond_signal(&(m->overlayPost));
-    pthread_mutex_unlock(&m->overlayLock);
-#endif
     if (ctx) {
         free(ctx);
     }
@@ -828,8 +423,10 @@
             const_cast<float&>(dev->device.xdpi) = m->xdpi;
             const_cast<float&>(dev->device.ydpi) = m->ydpi;
             const_cast<float&>(dev->device.fps) = m->fps;
-            const_cast<int&>(dev->device.minSwapInterval) = PRIV_MIN_SWAP_INTERVAL;
-            const_cast<int&>(dev->device.maxSwapInterval) = PRIV_MAX_SWAP_INTERVAL;
+            const_cast<int&>(dev->device.minSwapInterval) =
+                                                        PRIV_MIN_SWAP_INTERVAL;
+            const_cast<int&>(dev->device.maxSwapInterval) =
+                                                        PRIV_MAX_SWAP_INTERVAL;
             const_cast<int&>(dev->device.numFramebuffers) = m->numBuffers;
             if (m->finfo.reserved[0] == 0x5444 &&
                 m->finfo.reserved[1] == 0x5055) {