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_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: