hwc: Processing of HDMI connection request when WFD is active

  when HDMI is connected during active WFD session, teardown
  WFD and process HDMI connection request.

CRs-Fixed: 442226
Change-Id: I4b22ff9f1ab3175bab47babdaf040cb2289ebe4d
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index 3f13906..b336b84 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -99,6 +99,8 @@
     setResolution(mode);
     setDpyHdmiAttr();
     setExternalDisplay(true, mHdmiFbNum);
+    // set system property
+    property_set("hw.hdmiON", "1");
     return 0;
 }
 
@@ -128,6 +130,8 @@
         closeFrameBuffer();
         resetInfo();
         setExternalDisplay(false);
+        // unset system property
+        property_set("hw.hdmiON", "0");
     }
     return 0;
 }
@@ -142,29 +146,17 @@
     return 0;
 }
 
-void ExternalDisplay::processUEventOnline(const char *str) {
+int ExternalDisplay::ignoreRequest(const char *str) {
     const char *s1 = str + strlen("change@/devices/virtual/switch/");
-    if(!strncmp(s1,"hdmi",strlen(s1))) {
-        // hdmi online event..!
-        configureHDMIDisplay();
-        // set system property
-        property_set("hw.hdmiON", "1");
-    }else if(!strncmp(s1,"wfd",strlen(s1))) {
-        // wfd online event..!
-        configureWFDDisplay();
+    if(!strncmp(s1,"wfd",strlen(s1))) {
+        if(mConnectedFbNum == mHdmiFbNum) {
+            ALOGE("Ignore wfd event when HDMI is active");
+            return true;
+        }
     }
+    return false;
 }
 
-void ExternalDisplay::processUEventOffline(const char *str) {
-    const char *s1 = str + strlen("change@/devices/virtual/switch/");
-    if(!strncmp(s1,"hdmi",strlen(s1))) {
-        teardownHDMIDisplay();
-        // unset system property
-        property_set("hw.hdmiON", "0");
-    }else if(!strncmp(s1,"wfd",strlen(s1))) {
-        teardownWFDDisplay();
-    }
-}
 
 ExternalDisplay::ExternalDisplay(hwc_context_t* ctx):mFd(-1),
     mCurrentMode(-1), mConnected(0), mConnectedFbNum(0), mModeCount(0),
diff --git a/libexternal/external.h b/libexternal/external.h
index d46eec1..847b25c 100644
--- a/libexternal/external.h
+++ b/libexternal/external.h
@@ -47,11 +47,16 @@
     void setExternalDisplay(bool connected, int extFbNum = 0);
     bool isExternalConnected() { return mConnected;};
     void  setExtDpyNum(int extDpyNum) { mExtDpyNum = extDpyNum;};
+    int  getExternalType() {return mConnectedFbNum;};
+    bool isWFDActive() {return (mConnectedFbNum == mWfdFbNum);};
     void setHPD(uint32_t startEnd);
     void setEDIDMode(int resMode);
     void setActionSafeDimension(int w, int h);
-    void processUEventOnline(const char *str);
-    void processUEventOffline(const char *str);
+    int ignoreRequest(const char *str);
+    int  configureHDMIDisplay();
+    int  configureWFDDisplay();
+    int  teardownHDMIDisplay();
+    int  teardownWFDDisplay();
 
 private:
     void readCEUnderscanInfo();
@@ -72,10 +77,6 @@
     void setDpyWfdAttr();
     void getAttrForMode(int& width, int& height, int& fps);
     void updateExtDispDevFbIndex();
-    int  configureHDMIDisplay();
-    int  configureWFDDisplay();
-    int  teardownHDMIDisplay();
-    int  teardownWFDDisplay();
     int  getExtFbNum(int &fbNum);
 
     mutable android::Mutex mExtDispLock;
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index d27128e..c6d00cb 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -33,7 +33,7 @@
 #include "external.h"
 
 namespace qhwc {
-
+#define HWC_UEVENT_SWITCH_STR  "change@/devices/virtual/switch/"
 #define HWC_UEVENT_THREAD_NAME "hwcUeventThread"
 
 /* External Display states */
@@ -51,6 +51,32 @@
     return false;
 }
 
+static void setup(hwc_context_t* ctx, int dpy, bool usecopybit)
+{
+    ctx->mFBUpdate[dpy] =
+            IFBUpdate::getObject(ctx->dpyAttr[dpy].xres, dpy);
+    if(usecopybit)
+        ctx->mCopyBit[dpy] = new CopyBit();
+    ctx->mVidOv[dpy] =
+            IVideoOverlay::getObject(ctx->dpyAttr[dpy].xres, dpy);
+}
+
+static void clear(hwc_context_t* ctx, int dpy)
+{
+    if(ctx->mFBUpdate[dpy]) {
+        delete ctx->mFBUpdate[dpy];
+        ctx->mFBUpdate[dpy] = NULL;
+    }
+    if(ctx->mCopyBit[dpy]){
+        delete ctx->mCopyBit[dpy];
+        ctx->mCopyBit[dpy] = NULL;
+    }
+    if(ctx->mVidOv[dpy]) {
+        delete ctx->mVidOv[dpy];
+        ctx->mVidOv[dpy] = NULL;
+    }
+}
+
 static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
 {
     int vsync = 0;
@@ -65,7 +91,6 @@
                            qdutils::COMPOSITION_TYPE_C2D)) {
         usecopybit = true;
     }
-
     if(!strcasestr("change@/devices/virtual/switch/hdmi", str) &&
        !strcasestr("change@/devices/virtual/switch/wfd", str)) {
         ALOGD_IF(UEVENT_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__);
@@ -84,9 +109,6 @@
 
     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:
@@ -106,30 +128,33 @@
         if (str - udata >= len)
             break;
     }
+    ALOGD_IF(UEVENT_DEBUG, "Received str:%s",udata);
 
+    if(connected != EXTERNAL_ONLINE) {
+        if(ctx->mExtDisplay->ignoreRequest(udata)) {
+            ALOGD_IF(UEVENT_DEBUG,"No need to process this connection request"
+                                  "str:%s",udata);
+           ctx->dpyAttr[dpy].isActive = true;
+           return;
+        }
+    }
+
+    // update extDpyNum
+    ctx->mExtDisplay->setExtDpyNum(dpy);
     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;
+                const char *s1 = udata + strlen(HWC_UEVENT_SWITCH_STR);
+                if(!strncmp(s1,"hdmi",strlen(s1))) {
+                    ctx->mExtDisplay->teardownHDMIDisplay();
+                }else if(!strncmp(s1,"wfd",strlen(s1))) {
+                    ctx->mExtDisplay->teardownWFDDisplay();
                 }
-                if(ctx->mVidOv[dpy]) {
-                    Locker::Autolock _l(ctx->mExtSetLock);
-                    delete ctx->mVidOv[dpy];
-                    ctx->mVidOv[dpy] = NULL;
-                }
-                if(ctx->mCopyBit[dpy]){
-                    Locker::Autolock _l(ctx->mExtSetLock);
-                    delete ctx->mCopyBit[dpy];
-                    ctx->mCopyBit[dpy] = NULL;
-                }
+                Locker::Autolock _l(ctx->mExtSetLock);
+                clear(ctx, dpy);
                 ALOGD("%s sending hotplug: connected = %d and dpy:%d",
                       __FUNCTION__, connected, dpy);
                 ctx->dpyAttr[dpy].connected = false;
-                Locker::Autolock _l(ctx->mExtSetLock);
                 //hwc comp could be on
                 ctx->proc->hotplug(ctx->proc, dpy, connected);
                 break;
@@ -137,14 +162,38 @@
         case EXTERNAL_ONLINE:
             {   // connect case
                 ctx->mExtDispConfiguring = true;
-                ctx->mExtDisplay->processUEventOnline(udata);
-                ctx->mFBUpdate[dpy] =
-                        IFBUpdate::getObject(ctx->dpyAttr[dpy].xres, dpy);
-                ctx->mVidOv[dpy] =
-                        IVideoOverlay::getObject(ctx->dpyAttr[dpy].xres, dpy);
+                const char *s1 = udata + strlen(HWC_UEVENT_SWITCH_STR);
+                if(!strncmp(s1,"hdmi",strlen(s1))) {
+                    // hdmi online event..!
+                    // check if WFD is configured
+                    if(ctx->mExtDisplay->isWFDActive()) {
+                        ALOGD_IF(UEVENT_DEBUG,"Received HDMI connection request"
+                                "when WFD is active");
+                        // teardown Active WFD Display
+                        ctx->mExtDisplay->teardownWFDDisplay();
+                        {
+                            Locker::Autolock _l(ctx->mExtSetLock);
+                            clear(ctx, dpy);
+                            //send hotplug disconnect event
+                            ALOGD_IF(UEVENT_DEBUG, "sending hotplug: disconnect"
+                                    "for WFD");
+                            // hwc comp could be on
+                            ctx->proc->hotplug(ctx->proc, dpy, EXTERNAL_OFFLINE);
+                        }
+                        //Invalidate
+                        ctx->proc->invalidate(ctx->proc);
+                        //wait for 1 second
+                        ALOGE_IF(UEVENT_DEBUG, "wait for 1 second -- padding"
+                                "round");
+                        sleep(1);
+                    }
+                    ctx->mExtDisplay->configureHDMIDisplay();
+                } else if(!strncmp(s1,"wfd",strlen(s1))) {
+                    // wfd online event..!
+                    ctx->mExtDisplay->configureWFDDisplay();
+                }
                 ctx->dpyAttr[dpy].isPause = false;
-                if(usecopybit)
-                    ctx->mCopyBit[dpy] = new CopyBit();
+                setup(ctx, dpy, usecopybit);
                 ALOGD("%s sending hotplug: connected = %d", __FUNCTION__,
                         connected);
                 ctx->dpyAttr[dpy].connected = true;