diff --git a/libgralloc/gr.h b/libgralloc/gr.h index d88db9d7..fbde8c29 100644 --- a/libgralloc/gr.h +++ b/libgralloc/gr.h @@ -74,6 +74,7 @@ void free_buffer(private_handle_t *hnd); class Locker { pthread_mutex_t mutex; + pthread_cond_t cond; public: class Autolock { Locker& locker; @@ -81,10 +82,18 @@ class Locker { inline Autolock(Locker& locker) : locker(locker) { locker.lock(); } inline ~Autolock() { locker.unlock(); } }; - inline Locker() { pthread_mutex_init(&mutex, 0); } - inline ~Locker() { pthread_mutex_destroy(&mutex); } + inline Locker() { + pthread_mutex_init(&mutex, 0); + pthread_cond_init(&cond, 0); + } + inline ~Locker() { + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&cond); + } inline void lock() { pthread_mutex_lock(&mutex); } + inline void wait() { pthread_cond_wait(&cond, &mutex); } inline void unlock() { pthread_mutex_unlock(&mutex); } + inline void signal() { pthread_cond_signal(&cond); } }; diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp index 5313795d..976b23d0 100644 --- a/libhwcomposer/hwc_qclient.cpp +++ b/libhwcomposer/hwc_qclient.cpp @@ -157,6 +157,9 @@ static status_t getDisplayVisibleRegion(hwc_context_t* ctx, int dpy, } static void pauseWFD(hwc_context_t *ctx, uint32_t pause) { + /* TODO: Will remove pauseWFD once all the clients start using + * setWfdStatus to indicate the status of WFD display + */ int dpy = HWC_DISPLAY_VIRTUAL; if(pause) { //WFD Pause @@ -167,6 +170,24 @@ static void pauseWFD(hwc_context_t *ctx, uint32_t pause) { } } +static void setWfdStatus(hwc_context_t *ctx, uint32_t wfdStatus) { + + ALOGD_IF(HWC_WFDDISPSYNC_LOG, + "%s: Received a binder call that WFD state is %s", + __FUNCTION__,getExternalDisplayState(wfdStatus)); + int dpy = HWC_DISPLAY_VIRTUAL; + + if(wfdStatus == EXTERNAL_OFFLINE) { + ctx->mWfdSyncLock.lock(); + ctx->mWfdSyncLock.signal(); + ctx->mWfdSyncLock.unlock(); + } else if(wfdStatus == EXTERNAL_PAUSE) { + handle_pause(ctx, dpy); + } else if(wfdStatus == EXTERNAL_RESUME) { + handle_resume(ctx, dpy); + } +} + status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel, Parcel* outParcel) { status_t ret = NO_ERROR; @@ -199,15 +220,17 @@ status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel, break; case IQService::SET_HSIC_DATA: setHSIC(inParcel); + break; case IQService::PAUSE_WFD: pauseWFD(mHwcContext, inParcel->readInt32()); break; + case IQService::SET_WFD_STATUS: + setWfdStatus(mHwcContext,inParcel->readInt32()); + break; default: ret = NO_ERROR; } return ret; } - - } diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp index e1f7827a..fed6f3cc 100644 --- a/libhwcomposer/hwc_uevents.cpp +++ b/libhwcomposer/hwc_uevents.cpp @@ -39,14 +39,6 @@ namespace qhwc { #define HWC_UEVENT_SWITCH_STR "change@/devices/virtual/switch/" #define HWC_UEVENT_THREAD_NAME "hwcUeventThread" -/* External Display states */ -enum { - EXTERNAL_OFFLINE = 0, - EXTERNAL_ONLINE, - EXTERNAL_PAUSE, - EXTERNAL_RESUME -}; - static void setup(hwc_context_t* ctx, int dpy) { ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx, dpy); @@ -145,9 +137,24 @@ static void teardownWfd(hwc_context_t* ctx) { ctx->mVirtualonExtActive = false; } } - /* Wait for few frames for SF to tear down the WFD session. */ - usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period - * 2 / 1000); + + if(ctx->mVDSEnabled) { + ctx->mWfdSyncLock.lock(); + ALOGD_IF(HWC_WFDDISPSYNC_LOG, + "%s: Waiting for wfd-teardown to be signalled",__FUNCTION__); + ctx->mWfdSyncLock.wait(); + ALOGD_IF(HWC_WFDDISPSYNC_LOG, + "%s: Teardown signalled. Completed waiting in uevent thread", + __FUNCTION__); + ctx->mWfdSyncLock.unlock(); + } else { + /*TODO: Remove this else block and have wait rather than usleep + once wfd module issues binder call on teardown.*/ + + /* For now, Wait for few frames for SF to tear down the WFD session.*/ + usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period + * 2 / 1000); + } } static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) @@ -166,7 +173,7 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) int switch_state = getConnectedState(udata, len); - ALOGE_IF(UEVENT_DEBUG,"%s: uevent recieved: %s switch state: %d", + ALOGE_IF(UEVENT_DEBUG,"%s: uevent received: %s switch state: %d", __FUNCTION__,udata, switch_state); switch(switch_state) { diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp index ceb09ea6..19978adf 100644 --- a/libhwcomposer/hwc_utils.cpp +++ b/libhwcomposer/hwc_utils.cpp @@ -184,6 +184,7 @@ static int openFramebufferDevice(hwc_context_t *ctx) void initContext(hwc_context_t *ctx) { openFramebufferDevice(ctx); + char value[PROPERTY_VALUE_MAX]; ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion(); ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay(); ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType(); @@ -225,7 +226,14 @@ void initContext(hwc_context_t *ctx) ctx->mMDPComp[HWC_DISPLAY_PRIMARY] = MDPComp::getObject(ctx, HWC_DISPLAY_PRIMARY); ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true; - ctx->mHWCVirtual = HWCVirtualBase::getObject(); + + ctx->mVDSEnabled = false; + if((property_get("persist.hwc.enable_vds", value, NULL) > 0)) { + if(atoi(value) != 0) { + ctx->mVDSEnabled = true; + } + } + ctx->mHWCVirtual = HWCVirtualBase::getObject(ctx->mVDSEnabled); for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) { ctx->mHwcDebug[i] = new HwcDebug(i); @@ -262,7 +270,6 @@ void initContext(hwc_context_t *ctx) // Read the system property to determine if downscale feature is enabled. ctx->mMDPDownscaleEnabled = false; - char value[PROPERTY_VALUE_MAX]; if(property_get("sys.hwc.mdp_downscale_enabled", value, "false") && !strcmp(value, "true")) { ctx->mMDPDownscaleEnabled = true; @@ -642,6 +649,21 @@ int getMirrorModeOrientation(hwc_context_t *ctx) { return extOrientation; } +/* Get External State names */ +const char* getExternalDisplayState(uint32_t external_state) { + static const char* externalStates[EXTERNAL_MAXSTATES] = {0}; + externalStates[EXTERNAL_OFFLINE] = STR(EXTERNAL_OFFLINE); + externalStates[EXTERNAL_ONLINE] = STR(EXTERNAL_ONLINE); + externalStates[EXTERNAL_PAUSE] = STR(EXTERNAL_PAUSE); + externalStates[EXTERNAL_RESUME] = STR(EXTERNAL_RESUME); + + if(external_state >= EXTERNAL_MAXSTATES) { + return "EXTERNAL_INVALID"; + } + + return externalStates[external_state]; +} + bool isDownscaleRequired(hwc_layer_1_t const* layer) { hwc_rect_t displayFrame = layer->displayFrame; hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf); diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h index ed689889..726311b0 100644 --- a/libhwcomposer/hwc_utils.h +++ b/libhwcomposer/hwc_utils.h @@ -39,6 +39,8 @@ #define MAX_NUM_APP_LAYERS 32 #define MIN_DISPLAY_XRES 200 #define MIN_DISPLAY_YRES 200 +#define HWC_WFDDISPSYNC_LOG 0 +#define STR(f) #f; //Fwrd decls struct hwc_context_t; @@ -154,6 +156,15 @@ enum { HWC_FORMAT_RB_SWAP = 0x00000040, }; +/* External Display states */ +enum { + EXTERNAL_OFFLINE = 0, + EXTERNAL_ONLINE, + EXTERNAL_PAUSE, + EXTERNAL_RESUME, + EXTERNAL_MAXSTATES +}; + class LayerRotMap { public: LayerRotMap() { reset(); } @@ -280,6 +291,9 @@ void calcExtDisplayPosition(hwc_context_t *ctx, // BufferMirrirMode(Sidesync) int getMirrorModeOrientation(hwc_context_t *ctx); +/* Get External State names */ +const char* getExternalDisplayState(uint32_t external_state); + // Handles wfd Pause and resume events void handle_pause(hwc_context_t *ctx, int dpy); void handle_resume(hwc_context_t *ctx, int dpy); @@ -516,14 +530,21 @@ struct hwc_context_t { //Used for SideSync feature //which overrides the mExtOrientation bool mBufferMirrorMode; + // Used to synchronize between WFD and Display modules + mutable Locker mWfdSyncLock; + qhwc::LayerRotMap *mLayerRotMap[HWC_NUM_DISPLAY_TYPES]; // Panel reset flag will be set if BTA check fails bool mPanelResetStatus; // number of active Displays int numActiveDisplays; - // Downscale feature switch, set via system the property + // Downscale feature switch, set via system property // sys.hwc.mdp_downscale_enabled bool mMDPDownscaleEnabled; + // Is WFD enabled through VDS solution ? + // This can be set via system property + // persist.hwc.enable_vds + bool mVDSEnabled; struct gpu_hint_info mGPUHintInfo; }; diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp index f68d08f0..10ed9d1c 100644 --- a/libhwcomposer/hwc_virtual.cpp +++ b/libhwcomposer/hwc_virtual.cpp @@ -35,19 +35,17 @@ using namespace qhwc; using namespace overlay; -HWCVirtualBase* HWCVirtualBase::getObject() { - char property[PROPERTY_VALUE_MAX]; +HWCVirtualBase* HWCVirtualBase::getObject(bool isVDSEnabled) { - if((property_get("persist.hwc.enable_vds", property, NULL) > 0)) { - if(atoi(property) != 0) { - ALOGD_IF(HWCVIRTUAL_LOG, "%s: VDS is enabled for Virtual display", - __FUNCTION__); - return new HWCVirtualVDS(); - } + if(isVDSEnabled) { + ALOGD_IF(HWCVIRTUAL_LOG, "%s: VDS is enabled for Virtual display", + __FUNCTION__); + return new HWCVirtualVDS(); + } else { + ALOGD_IF(HWCVIRTUAL_LOG, "%s: V4L2 is enabled for Virtual display", + __FUNCTION__); + return new HWCVirtualV4L2(); } - ALOGD_IF(HWCVIRTUAL_LOG, "%s: V4L2 is enabled for Virtual display", - __FUNCTION__); - return new HWCVirtualV4L2(); } void HWCVirtualVDS::init(hwc_context_t *ctx) { @@ -84,6 +82,9 @@ void HWCVirtualVDS::destroy(hwc_context_t *ctx, size_t /*numDisplays*/, if(!Writeback::getInstance()->setSecure(false)) { ALOGE("Failure while attempting to reset WB session."); } + ctx->mWfdSyncLock.lock(); + ctx->mWfdSyncLock.signal(); + ctx->mWfdSyncLock.unlock(); } } diff --git a/libhwcomposer/hwc_virtual.h b/libhwcomposer/hwc_virtual.h index 6bc38984..87004c3f 100644 --- a/libhwcomposer/hwc_virtual.h +++ b/libhwcomposer/hwc_virtual.h @@ -33,7 +33,7 @@ public: explicit HWCVirtualBase(){}; virtual ~HWCVirtualBase(){}; // instantiates and returns the pointer to VDS or V4L2 object. - static HWCVirtualBase* getObject(); + static HWCVirtualBase* getObject(bool isVDSEnabled); virtual int prepare(hwc_composer_device_1 *dev, hwc_display_contents_1_t* list) = 0; virtual int set(hwc_context_t *ctx, hwc_display_contents_1_t *list) = 0; diff --git a/libqservice/IQService.h b/libqservice/IQService.h index 6c1bba6b..02f73412 100644 --- a/libqservice/IQService.h +++ b/libqservice/IQService.h @@ -50,6 +50,7 @@ public: SET_HSIC_DATA, // Set HSIC on dspp GET_DISPLAY_VISIBLE_REGION, // Get the visibleRegion for dpy PAUSE_WFD, // Pause/Resume WFD + SET_WFD_STATUS, // Set if wfd connection is on/off COMMAND_LIST_END = 400, }; diff --git a/libqservice/QServiceUtils.h b/libqservice/QServiceUtils.h index 699164dc..08cab317 100644 --- a/libqservice/QServiceUtils.h +++ b/libqservice/QServiceUtils.h @@ -87,4 +87,7 @@ inline android::status_t pauseWFD(uint32_t pause) { return sendSingleParam(qService::IQService::PAUSE_WFD, pause); } +inline android::status_t setWfdStatus(uint32_t wfdStatus) { + return sendSingleParam(qService::IQService::SET_WFD_STATUS, wfdStatus); +} #endif /* end of include guard: QSERVICEUTILS_H */