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: