hwc: Fix locking in external connect and composition.

The external configuring flag should be set after holding locks.
Before opening FB for HDMI/WFD, composition should give up any
open external FB resources.

Locks should be held by composition for the entire duration.

Change-Id: I703f69f156c665bf422613567c00aae340f3ee12
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 2158611..6dd77b1 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -205,7 +205,8 @@
     int ret = 0;
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     Locker::Autolock _bl(ctx->mBlankLock);
-    Locker::Autolock _el(ctx->mExtLock);
+    //Will be unlocked at the end of set
+    ctx->mExtLock.lock();
     reset(ctx, numDisplays, displays);
 
     ctx->mOverlay->configBegin();
@@ -477,7 +478,6 @@
     int ret = 0;
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     Locker::Autolock _bl(ctx->mBlankLock);
-    Locker::Autolock _el(ctx->mExtLock);
     for (uint32_t i = 0; i <= numDisplays; i++) {
         hwc_display_contents_1_t* list = displays[i];
         switch(i) {
@@ -501,6 +501,8 @@
     CALC_FPS();
     MDPComp::resetIdleFallBack();
     ctx->mVideoTransFlag = false;
+    //Was locked at the beginning of prepare
+    ctx->mExtLock.unlock();
     return ret;
 }
 
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index abca20b..c658224 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -163,7 +163,23 @@
             }
         case EXTERNAL_ONLINE:
             {   // connect case
-                ctx->mExtDispConfiguring = true;
+                {
+                    //Force composition to give up resources like pipes and
+                    //close fb. For example if assertive display is going on,
+                    //fb2 could be open, thus connecting Layer Mixer#0 to
+                    //WriteBack module. If HDMI attempts to open fb1, the driver
+                    //will try to attach Layer Mixer#0 to HDMI INT, which will
+                    //fail, since Layer Mixer#0 is still connected to WriteBack.
+                    //This block will force composition to close fb2 in above
+                    //example.
+                    Locker::Autolock _l(ctx->mExtLock);
+                    ctx->mExtDispConfiguring = true;
+                    ctx->dpyAttr[dpy].connected = false;
+                    ctx->proc->invalidate(ctx->proc);
+                }
+                //2 cycles for slower content
+                usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+                        * 2 / 1000);
                 const char *s1 = udata + strlen(HWC_UEVENT_SWITCH_STR);
                 if(!strncmp(s1,"hdmi",strlen(s1))) {
                     // hdmi online event..!
@@ -194,13 +210,15 @@
                     // wfd online event..!
                     ctx->mExtDisplay->configureWFDDisplay();
                 }
-                ctx->dpyAttr[dpy].isPause = false;
-                setup(ctx, dpy, usecopybit);
-                ALOGD("%s sending hotplug: connected = %d", __FUNCTION__,
-                        connected);
-                ctx->dpyAttr[dpy].connected = true;
-                Locker::Autolock _l(ctx->mExtLock); //hwc comp could be on
-                ctx->proc->hotplug(ctx->proc, dpy, connected);
+                {
+                    Locker::Autolock _l(ctx->mExtLock);
+                    ctx->dpyAttr[dpy].isPause = false;
+                    setup(ctx, dpy, usecopybit);
+                    ALOGD("%s sending hotplug: connected = %d", __FUNCTION__,
+                            connected);
+                    ctx->dpyAttr[dpy].connected = true;
+                    ctx->proc->hotplug(ctx->proc, dpy, connected);
+                }
                 break;
             }
         case EXTERNAL_PAUSE:
@@ -214,12 +232,23 @@
         case EXTERNAL_RESUME:
             {  // resume case
                 ALOGD("%s Received resume event",__FUNCTION__);
-                // treat Resume as Online event
-                Locker::Autolock _l(ctx->mExtLock);
-                ctx->mExtDispConfiguring = true;
-                ctx->dpyAttr[dpy].isActive = true;
-                ctx->dpyAttr[dpy].isPause = false;
-                ctx->proc->invalidate(ctx->proc);
+                //Treat Resume as Online event
+                //Since external didnt have any pipes, force primary to give up
+                //its pipes; we don't allow inter-mixer pipe transfers.
+                {
+                    Locker::Autolock _l(ctx->mExtLock);
+                    ctx->mExtDispConfiguring = true;
+                    ctx->dpyAttr[dpy].isActive = true;
+                    ctx->proc->invalidate(ctx->proc);
+                }
+                usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+                        * 2 / 1000);
+                //At this point external has all the pipes it would need.
+                {
+                    Locker::Autolock _l(ctx->mExtLock);
+                    ctx->dpyAttr[dpy].isPause = false;
+                    ctx->proc->invalidate(ctx->proc);
+                }
                 break;
             }
         default: