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: