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
This commit is contained in:
Amara Venkata Mastan Manoj Kumar
2013-02-07 16:42:50 -08:00
parent 22dd8e7ef2
commit b156a2f7f2
3 changed files with 95 additions and 53 deletions

View File

@@ -99,6 +99,8 @@ int ExternalDisplay::configureHDMIDisplay() {
setResolution(mode); setResolution(mode);
setDpyHdmiAttr(); setDpyHdmiAttr();
setExternalDisplay(true, mHdmiFbNum); setExternalDisplay(true, mHdmiFbNum);
// set system property
property_set("hw.hdmiON", "1");
return 0; return 0;
} }
@@ -128,6 +130,8 @@ int ExternalDisplay::teardownHDMIDisplay() {
closeFrameBuffer(); closeFrameBuffer();
resetInfo(); resetInfo();
setExternalDisplay(false); setExternalDisplay(false);
// unset system property
property_set("hw.hdmiON", "0");
} }
return 0; return 0;
} }
@@ -142,29 +146,17 @@ int ExternalDisplay::teardownWFDDisplay() {
return 0; return 0;
} }
void ExternalDisplay::processUEventOnline(const char *str) { int ExternalDisplay::ignoreRequest(const char *str) {
const char *s1 = str + strlen("change@/devices/virtual/switch/"); const char *s1 = str + strlen("change@/devices/virtual/switch/");
if(!strncmp(s1,"hdmi",strlen(s1))) { if(!strncmp(s1,"wfd",strlen(s1))) {
// hdmi online event..! if(mConnectedFbNum == mHdmiFbNum) {
configureHDMIDisplay(); ALOGE("Ignore wfd event when HDMI is active");
// set system property return true;
property_set("hw.hdmiON", "1");
}else if(!strncmp(s1,"wfd",strlen(s1))) {
// wfd online event..!
configureWFDDisplay();
} }
} }
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), ExternalDisplay::ExternalDisplay(hwc_context_t* ctx):mFd(-1),
mCurrentMode(-1), mConnected(0), mConnectedFbNum(0), mModeCount(0), mCurrentMode(-1), mConnected(0), mConnectedFbNum(0), mModeCount(0),

View File

@@ -47,11 +47,16 @@ public:
void setExternalDisplay(bool connected, int extFbNum = 0); void setExternalDisplay(bool connected, int extFbNum = 0);
bool isExternalConnected() { return mConnected;}; bool isExternalConnected() { return mConnected;};
void setExtDpyNum(int extDpyNum) { mExtDpyNum = extDpyNum;}; void setExtDpyNum(int extDpyNum) { mExtDpyNum = extDpyNum;};
int getExternalType() {return mConnectedFbNum;};
bool isWFDActive() {return (mConnectedFbNum == mWfdFbNum);};
void setHPD(uint32_t startEnd); void setHPD(uint32_t startEnd);
void setEDIDMode(int resMode); void setEDIDMode(int resMode);
void setActionSafeDimension(int w, int h); void setActionSafeDimension(int w, int h);
void processUEventOnline(const char *str); int ignoreRequest(const char *str);
void processUEventOffline(const char *str); int configureHDMIDisplay();
int configureWFDDisplay();
int teardownHDMIDisplay();
int teardownWFDDisplay();
private: private:
void readCEUnderscanInfo(); void readCEUnderscanInfo();
@@ -72,10 +77,6 @@ private:
void setDpyWfdAttr(); void setDpyWfdAttr();
void getAttrForMode(int& width, int& height, int& fps); void getAttrForMode(int& width, int& height, int& fps);
void updateExtDispDevFbIndex(); void updateExtDispDevFbIndex();
int configureHDMIDisplay();
int configureWFDDisplay();
int teardownHDMIDisplay();
int teardownWFDDisplay();
int getExtFbNum(int &fbNum); int getExtFbNum(int &fbNum);
mutable android::Mutex mExtDispLock; mutable android::Mutex mExtDispLock;

View File

@@ -33,7 +33,7 @@
#include "external.h" #include "external.h"
namespace qhwc { namespace qhwc {
#define HWC_UEVENT_SWITCH_STR "change@/devices/virtual/switch/"
#define HWC_UEVENT_THREAD_NAME "hwcUeventThread" #define HWC_UEVENT_THREAD_NAME "hwcUeventThread"
/* External Display states */ /* External Display states */
@@ -51,6 +51,32 @@ static bool isHDMI(const char* str)
return false; 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) static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
{ {
int vsync = 0; int vsync = 0;
@@ -65,7 +91,6 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
qdutils::COMPOSITION_TYPE_C2D)) { qdutils::COMPOSITION_TYPE_C2D)) {
usecopybit = true; usecopybit = true;
} }
if(!strcasestr("change@/devices/virtual/switch/hdmi", str) && if(!strcasestr("change@/devices/virtual/switch/hdmi", str) &&
!strcasestr("change@/devices/virtual/switch/wfd", str)) { !strcasestr("change@/devices/virtual/switch/wfd", str)) {
ALOGD_IF(UEVENT_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__); ALOGD_IF(UEVENT_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__);
@@ -84,9 +109,6 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
int dpy = isHDMI(str) ? HWC_DISPLAY_EXTERNAL : extDpyNum; int dpy = isHDMI(str) ? HWC_DISPLAY_EXTERNAL : extDpyNum;
// update extDpyNum
ctx->mExtDisplay->setExtDpyNum(dpy);
// parse HDMI/WFD switch state for connect/disconnect // parse HDMI/WFD switch state for connect/disconnect
// for HDMI: // for HDMI:
// The event will be of the form: // The event will be of the form:
@@ -106,30 +128,33 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
if (str - udata >= len) if (str - udata >= len)
break; 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) { switch(connected) {
case EXTERNAL_OFFLINE: case EXTERNAL_OFFLINE:
{ // disconnect event { // disconnect event
ctx->mExtDisplay->processUEventOffline(udata); const char *s1 = udata + strlen(HWC_UEVENT_SWITCH_STR);
if(ctx->mFBUpdate[dpy]) { if(!strncmp(s1,"hdmi",strlen(s1))) {
Locker::Autolock _l(ctx->mExtSetLock); ctx->mExtDisplay->teardownHDMIDisplay();
delete ctx->mFBUpdate[dpy]; }else if(!strncmp(s1,"wfd",strlen(s1))) {
ctx->mFBUpdate[dpy] = NULL; ctx->mExtDisplay->teardownWFDDisplay();
} }
if(ctx->mVidOv[dpy]) {
Locker::Autolock _l(ctx->mExtSetLock); Locker::Autolock _l(ctx->mExtSetLock);
delete ctx->mVidOv[dpy]; clear(ctx, dpy);
ctx->mVidOv[dpy] = NULL;
}
if(ctx->mCopyBit[dpy]){
Locker::Autolock _l(ctx->mExtSetLock);
delete ctx->mCopyBit[dpy];
ctx->mCopyBit[dpy] = NULL;
}
ALOGD("%s sending hotplug: connected = %d and dpy:%d", ALOGD("%s sending hotplug: connected = %d and dpy:%d",
__FUNCTION__, connected, dpy); __FUNCTION__, connected, dpy);
ctx->dpyAttr[dpy].connected = false; ctx->dpyAttr[dpy].connected = false;
Locker::Autolock _l(ctx->mExtSetLock);
//hwc comp could be on //hwc comp could be on
ctx->proc->hotplug(ctx->proc, dpy, connected); ctx->proc->hotplug(ctx->proc, dpy, connected);
break; break;
@@ -137,14 +162,38 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
case EXTERNAL_ONLINE: case EXTERNAL_ONLINE:
{ // connect case { // connect case
ctx->mExtDispConfiguring = true; ctx->mExtDispConfiguring = true;
ctx->mExtDisplay->processUEventOnline(udata); const char *s1 = udata + strlen(HWC_UEVENT_SWITCH_STR);
ctx->mFBUpdate[dpy] = if(!strncmp(s1,"hdmi",strlen(s1))) {
IFBUpdate::getObject(ctx->dpyAttr[dpy].xres, dpy); // hdmi online event..!
ctx->mVidOv[dpy] = // check if WFD is configured
IVideoOverlay::getObject(ctx->dpyAttr[dpy].xres, dpy); 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; ctx->dpyAttr[dpy].isPause = false;
if(usecopybit) setup(ctx, dpy, usecopybit);
ctx->mCopyBit[dpy] = new CopyBit();
ALOGD("%s sending hotplug: connected = %d", __FUNCTION__, ALOGD("%s sending hotplug: connected = %d", __FUNCTION__,
connected); connected);
ctx->dpyAttr[dpy].connected = true; ctx->dpyAttr[dpy].connected = true;