display: Enable vsync

* Use the vsync uevents from the kernel to start
surfaceflinger composition.
* This patch also does some code cleanup
    - Move copybit specific functions to copybit files.
    - Cleanup verbose logging.

Change-Id: I36936e4b0a082cfb0347d8ee7d2bc936e01808e6
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index 5067a2a..9808aa5 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -10,6 +10,6 @@
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"hwcomposer\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES               :=  hwc.cpp hwc_video.cpp hwc_utils.cpp \
-                                  hwc_uimirror.cpp hwc_ext_observer.cpp \
-                                  hwc_copybit.cpp
+                                  hwc_uimirror.cpp hwc_external.cpp \
+                                  hwc_uevents.cpp hwc_copybit.cpp
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 7826a5f..c0bca9d 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -20,8 +20,12 @@
 
 #include <cutils/log.h>
 #include <cutils/atomic.h>
+#include <EGL/egl.h>
 
+#include <overlay.h>
+#include <fb_priv.h>
 #include "hwc_utils.h"
+#include "hwc_qbuf.h"
 #include "hwc_video.h"
 #include "hwc_uimirror.h"
 #include "hwc_copybit.h"
@@ -93,6 +97,47 @@
     return 0;
 }
 
+static int hwc_eventControl(struct hwc_composer_device* dev,
+                             int event, int enabled)
+{
+    int ret = 0;
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+                ctx->mFbDev->common.module);
+    switch(event) {
+        case HWC_EVENT_VSYNC:
+            if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &enabled) < 0)
+                ret = -errno;
+           break;
+        default:
+            ret = -EINVAL;
+    }
+    return ret;
+}
+
+static int hwc_query(struct hwc_composer_device* dev,
+                     int param, int* value)
+{
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+        ctx->mFbDev->common.module);
+
+    switch (param) {
+    case HWC_BACKGROUND_LAYER_SUPPORTED:
+        // Not supported for now
+        value[0] = 0;
+        break;
+    case HWC_VSYNC_PERIOD:
+        value[0] = 1000000000.0 / m->fps;
+        ALOGI("fps: %d", value[0]);
+        break;
+    default:
+        return -EINVAL;
+    }
+    return 0;
+
+}
+
 static int hwc_set(hwc_composer_device_t *dev,
                    hwc_display_t dpy,
                    hwc_surface_t sur,
@@ -119,7 +164,7 @@
 static int hwc_device_close(struct hw_device_t *dev)
 {
     if(!dev) {
-        ALOGE("hwc_device_close null device pointer");
+        ALOGE("%s: NULL device pointer", __FUNCTION__);
         return -1;
     }
     closeContext((hwc_context_t*)dev);
@@ -137,14 +182,25 @@
         struct hwc_context_t *dev;
         dev = (hwc_context_t*)malloc(sizeof(*dev));
         memset(dev, 0, sizeof(*dev));
+
+        //Initialize hwc context
         initContext(dev);
+
+        //Setup HWC methods
+        hwc_methods_t *methods;
+        methods = (hwc_methods_t *)malloc(sizeof(*methods));
+        memset(methods, 0, sizeof(*methods));
+        methods->eventControl = hwc_eventControl;
+
         dev->device.common.tag     = HARDWARE_DEVICE_TAG;
-        dev->device.common.version = 0;
+        dev->device.common.version = HWC_DEVICE_API_VERSION_0_3;
         dev->device.common.module  = const_cast<hw_module_t*>(module);
         dev->device.common.close   = hwc_device_close;
         dev->device.prepare        = hwc_prepare;
         dev->device.set            = hwc_set;
         dev->device.registerProcs  = hwc_registerProcs;
+        dev->device.query          = hwc_query;
+        dev->device.methods        = methods;
         *device                    = &dev->device.common;
         status = 0;
     }
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index adcd4dc..7892632 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -18,8 +18,9 @@
  * limitations under the License.
  */
 
+#include <copybit.h>
+#include <genlock.h>
 #include "hwc_copybit.h"
-#include "hwc_copybitEngine.h"
 
 namespace qhwc {
 
@@ -71,6 +72,23 @@
 bool CopyBit::sIsLayerSkip = false;
 void* CopyBit::egl_lib = NULL;
 
+void CopyBit::openEglLibAndGethandle()
+{
+    egl_lib = ::dlopen("libEGL_adreno200.so", RTLD_GLOBAL | RTLD_LAZY);
+    if (!egl_lib) {
+        return;
+    }
+    updateEglHandles(egl_lib);
+}
+void CopyBit::closeEglLib()
+{
+    if(egl_lib)
+        ::dlclose(egl_lib);
+
+    egl_lib = NULL;
+    updateEglHandles(NULL);
+}
+
 void CopyBit::updateEglHandles(void* egl_lib)
 {
     if(egl_lib != NULL) {
@@ -365,7 +383,7 @@
     if(ctx->hasOverlay)
         return false;
 
-    framebuffer_device_t* fbDev = ctx->mFbDevice->getFb();
+    framebuffer_device_t* fbDev = ctx->mFbDev;
     if(!fbDev) {
         ALOGE("ERROR: canUseCopybit : fb device is invalid");
         return false;
@@ -402,27 +420,11 @@
 
     return (renderArea <= (2 * fb_w * fb_h));
 }
-void CopyBit::openEglLibAndGethandle()
-{
-    egl_lib = ::dlopen("libEGL_adreno200.so", RTLD_GLOBAL | RTLD_LAZY);
-    if (!egl_lib) {
-        return;
-    }
-    updateEglHandles(egl_lib);
-}
-void CopyBit::closeEglLib()
-{
-    if(egl_lib)
-        ::dlclose(egl_lib);
-
-    egl_lib = NULL;
-    updateEglHandles(NULL);
-}
 
 
 
 //CopybitEngine Class functions
-CopybitEngine* CopybitEngine::sInstance = 0;;
+CopybitEngine* CopybitEngine::sInstance = 0;
 
 struct copybit_device_t* CopybitEngine::getEngine() {
    return sEngine;
@@ -440,9 +442,11 @@
     } else {
        ALOGE("FATAL ERROR: copybit open failed.");
     }
+    CopyBit::openEglLibAndGethandle();
 }
 CopybitEngine::~CopybitEngine()
 {
+    CopyBit::closeEglLib();
     if(sEngine)
     {
         copybit_close(sEngine);
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index adf088b..602898e 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -31,6 +31,11 @@
 
 namespace qhwc {
 //Feature for using Copybit to display RGB layers.
+typedef EGLClientBuffer (*functype_eglGetRenderBufferANDROID) (
+                                              EGLDisplay dpy,
+                                              EGLSurface draw);
+typedef EGLSurface (*functype_eglGetCurrentSurface)(EGLint readdraw);
+
 class CopyBit {
 public:
     //Sets up members and prepares copybit if conditions are met
@@ -75,6 +80,20 @@
 
 };
 
+class CopybitEngine {
+public:
+    ~CopybitEngine();
+    // API to get copybit engine(non static)
+    struct copybit_device_t *getEngine();
+    // API to get singleton
+    static CopybitEngine* getInstance();
+private:
+    CopybitEngine();
+    struct copybit_device_t *sEngine;
+    static CopybitEngine* sInstance; // singleton
+};
+
+
 inline void CopyBit::setStats(int yuvCount, int yuvLayerIndex,
         bool isYuvLayerSkip) {
     sYuvCount = yuvCount;
diff --git a/libhwcomposer/hwc_copybitEngine.h b/libhwcomposer/hwc_copybitEngine.h
deleted file mode 100644
index d627e44..0000000
--- a/libhwcomposer/hwc_copybitEngine.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are retained
- * for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef HWC_COPYBIT_ENGINE_H
-#define HWC_COPYBIT_ENGINE_H
-
-namespace qhwc {
-class CopybitEngine {
-public:
-    ~CopybitEngine();
-    // API to get copybit engine(non static)
-    struct copybit_device_t *getEngine();
-    // API to get singleton
-    static CopybitEngine* getInstance();
-
-private:
-    CopybitEngine();
-    struct copybit_device_t *sEngine;
-    static CopybitEngine* sInstance; // singleton
-};
-
-}; //namespace qhwc
-
-#endif //HWC_COPYBIT_ENGINE_H
diff --git a/libhwcomposer/hwc_ext_observer.h b/libhwcomposer/hwc_ext_observer.h
deleted file mode 100644
index e7cb890..0000000
--- a/libhwcomposer/hwc_ext_observer.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are
- * retained for attribution purposes only.
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef HWC_EXT_OBSERVER_H
-#define HWC_EXT_OBSERVER_H
-
-#include <utils/threads.h>
-
-struct hwc_context_t;
-
-namespace qhwc {
-
-class ExtDisplayObserver : public android::Thread
-{
-    //Type of external display -  OFF, HDMI, WFD
-    enum external_display_type {
-        EXT_TYPE_NONE,
-        EXT_TYPE_HDMI,
-        EXT_TYPE_WIFI
-    };
-
-    // Mirroring state
-    enum external_mirroring_state {
-        EXT_MIRRORING_OFF,
-        EXT_MIRRORING_ON,
-    };
-    public:
-        /*Overrides*/
-        virtual bool        threadLoop();
-        virtual int         readyToRun();
-        virtual void        onFirstRef();
-
-        virtual ~ExtDisplayObserver();
-        static ExtDisplayObserver *getInstance();
-        int getExternalDisplay() const;
-        void setHwcContext(hwc_context_t* hwcCtx);
-
-    private:
-        ExtDisplayObserver();
-        void setExternalDisplayStatus(int connected);
-        bool readResolution();
-        int parseResolution(char* edidStr, int* edidModes, int len);
-        void setResolution(int ID);
-        bool openFramebuffer();
-        bool writeHPDOption(int userOption) const;
-        bool isValidMode(int ID);
-        void handleUEvent(char* str);
-        int getModeOrder(int mode);
-        int getBestMode();
-
-        int fd;
-        int mExternalDisplay;
-        int mCurrentID;
-        char mEDIDs[128];
-        int mEDIDModes[64];
-        int mModeCount;
-        hwc_context_t *mHwcContext;
-        static android::sp<ExtDisplayObserver> sExtDisplayObserverInstance;
-};
-
-}; //qhwc
-// ---------------------------------------------------------------------------
-#endif //HWC_EXT_OBSERVER_H
diff --git a/libhwcomposer/hwc_ext_observer.cpp b/libhwcomposer/hwc_external.cpp
similarity index 61%
rename from libhwcomposer/hwc_ext_observer.cpp
rename to libhwcomposer/hwc_external.cpp
index 2a5ec36..3507134 100644
--- a/libhwcomposer/hwc_ext_observer.cpp
+++ b/libhwcomposer/hwc_external.cpp
@@ -18,10 +18,9 @@
  * limitations under the License.
  */
 
-#define EXT_OBSERVER_DEBUG 0
+#define DEBUG 0
 #include <ctype.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
+#include <fcntl.h>
 #include <media/IAudioPolicyService.h>
 #include <media/AudioSystem.h>
 #include <utils/threads.h>
@@ -32,11 +31,10 @@
 #include <linux/fb.h>
 #include <sys/ioctl.h>
 #include <sys/poll.h>
-
-#include <hardware_legacy/uevent.h>
+#include <sys/resource.h>
 #include <cutils/properties.h>
 #include "hwc_utils.h"
-#include "hwc_ext_observer.h"
+#include "hwc_external.h"
 
 namespace qhwc {
 
@@ -49,88 +47,19 @@
 #define SYSFS_HPD               DEVICE_ROOT "/" DEVICE_NODE "/hpd"
 
 
-android::sp<ExtDisplayObserver> ExtDisplayObserver::
-                                         sExtDisplayObserverInstance(0);
-
-ExtDisplayObserver::ExtDisplayObserver() : Thread(false),
-    fd(-1), mCurrentID(-1), mHwcContext(NULL)
+ExternalDisplay::ExternalDisplay(hwc_context_t* ctx):fd(-1),
+    mCurrentID(-1), mHwcContext(ctx)
 {
     //Enable HPD for HDMI
     writeHPDOption(1);
 }
 
-ExtDisplayObserver::~ExtDisplayObserver() {
+ExternalDisplay::~ExternalDisplay()
+{
     if (fd > 0)
         close(fd);
 }
 
-ExtDisplayObserver *ExtDisplayObserver::getInstance() {
-    ALOGD_IF(EXT_OBSERVER_DEBUG, "%s ", __FUNCTION__);
-    if(sExtDisplayObserverInstance.get() == NULL)
-        sExtDisplayObserverInstance = new ExtDisplayObserver();
-    return sExtDisplayObserverInstance.get();
-}
-
-void ExtDisplayObserver::setHwcContext(hwc_context_t* hwcCtx) {
-    ALOGD_IF(EXT_OBSERVER_DEBUG, "%s", __FUNCTION__);
-    if(hwcCtx) {
-        mHwcContext = hwcCtx;
-    }
-    return;
-}
-void ExtDisplayObserver::onFirstRef() {
-    ALOGD_IF(EXT_OBSERVER_DEBUG, "%s", __FUNCTION__);
-    run("ExtDisplayObserver", ANDROID_PRIORITY_DISPLAY);
-}
-
-int ExtDisplayObserver::readyToRun() {
-    //Initialize the uevent
-    uevent_init();
-    ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: success", __FUNCTION__);
-    return android::NO_ERROR;
-}
-
-void ExtDisplayObserver::handleUEvent(char* str){
-    int connected = 0;
-    // TODO: check for fb2(WFD) driver also
-    if(!strcasestr(str, DEVICE_NODE))
-    {
-        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__);
-        return;
-    }
-    // Event will be of the form:
-    // change@/devices/virtual/graphics/fb1 ACTION=change
-    // DEVPATH=/devices/virtual/graphics/fb1
-    // SUBSYSTEM=graphics HDCP_STATE=FAIL MAJOR=29
-    // for now just parse the online or offline are important for us.
-    if(!(strncmp(str,"online@",strlen("online@")))) {
-        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: external disp online", __FUNCTION__);
-        connected = 1;
-        readResolution();
-        //Get the best mode and set
-        // TODO: DO NOT call this for WFD
-        setResolution(getBestMode());
-    } else if(!(strncmp(str,"offline@",strlen("offline@")))) {
-        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: external disp online", __FUNCTION__);
-        connected = 0;
-        close(fd);
-    }
-    setExternalDisplayStatus(connected);
-}
-
-bool ExtDisplayObserver::threadLoop()
-{
-    static char uEventString[1024];
-    memset(uEventString, 0, sizeof(uEventString));
-    int count = uevent_next_event(uEventString, sizeof(uEventString));
-    if(count) {
-        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: UeventString: %s len = %d",
-                                          __FUNCTION__, uEventString, count);
-        handleUEvent(uEventString);
-    }
-    return true;
-}
-
 struct disp_mode_timing_type {
     int  video_format;
 
@@ -213,7 +142,8 @@
     {m1920x1080p25_16_9, 1920, 1080, 528,  44, 148,  4, 5, 36,  74250, false},
     {m1920x1080p30_16_9, 1920, 1080,  88,  44, 148,  4, 5, 36,  74250, false},
 };
-int ExtDisplayObserver::parseResolution(char* edidStr, int* edidModes, int len)
+
+int ExternalDisplay::parseResolution(char* edidStr, int* edidModes, int len)
 {
     char delim = ',';
     int count = 0;
@@ -233,7 +163,7 @@
     }
     return count;
 }
-bool ExtDisplayObserver::readResolution()
+bool ExternalDisplay::readResolution()
 {
     int hdmiEDIDFile = open(SYSFS_EDID_MODES, O_RDONLY, 0);
     int len = -1;
@@ -242,16 +172,16 @@
     memset(mEDIDModes, 0, sizeof(mEDIDModes));
     mModeCount = 0;
     if (hdmiEDIDFile < 0) {
-        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: edid_modes file '%s' not found",
-                                          __FUNCTION__, SYSFS_EDID_MODES);
+        ALOGD_IF(DEBUG, "%s: edid_modes file '%s' not found",
+                 __FUNCTION__, SYSFS_EDID_MODES);
         return false;
     } else {
         len = read(hdmiEDIDFile, mEDIDs, sizeof(mEDIDs)-1);
-        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: EDID string: %s length = %d",
-                                               __FUNCTION__, mEDIDs, len);
+        ALOGD_IF(DEBUG, "%s: EDID string: %s length = %d",
+                 __FUNCTION__, mEDIDs, len);
         if ( len <= 0) {
-            ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: edid_modes file empty '%s'",
-                                           __FUNCTION__, SYSFS_EDID_MODES);
+            ALOGD_IF(DEBUG, "%s: edid_modes file empty '%s'",
+                     __FUNCTION__, SYSFS_EDID_MODES);
         }
         else {
             while (len > 1 && isspace(mEDIDs[len-1]))
@@ -263,26 +193,26 @@
     if(len > 0) {
         // GEt EDID modes from the EDID strings
         mModeCount = parseResolution(mEDIDs, mEDIDModes, len);
-        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: mModeCount = %d", __FUNCTION__,
-                                                                  mModeCount);
+        ALOGD_IF(DEBUG, "%s: mModeCount = %d", __FUNCTION__,
+                 mModeCount);
     }
 
     return (strlen(mEDIDs) > 0);
 }
 
-bool ExtDisplayObserver::openFramebuffer()
+bool ExternalDisplay::openFramebuffer()
 {
     if (fd == -1) {
         fd = open("/dev/graphics/fb1", O_RDWR);
         if (fd < 0)
-            ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: /dev/graphics/fb1 not available"
-                                               "\n", __FUNCTION__);
+            ALOGD_IF(DEBUG, "%s: /dev/graphics/fb1 not available"
+                     "\n", __FUNCTION__);
     }
     return (fd > 0);
 }
 
 
-int ExtDisplayObserver::getModeOrder(int mode)
+int ExternalDisplay::getModeOrder(int mode)
 {
     switch (mode) {
         default:
@@ -320,11 +250,11 @@
             return 16; //1080p@50Hz
         case m1920x1080p60_16_9:
             return 17; //1080p@60Hz
-        }
+    }
 }
 
 // Get the best mode for the current HD TV
-int ExtDisplayObserver::getBestMode() {
+int ExternalDisplay::getBestMode() {
     int bestOrder = 0;
     int bestMode = m640x480p60_4_3;
 
@@ -338,14 +268,14 @@
         }
     }
     return bestMode;
-    }
+}
 
-inline bool ExtDisplayObserver::isValidMode(int ID)
+inline bool ExternalDisplay::isValidMode(int ID)
 {
     return ((ID >= m640x480p60_4_3) && (ID <= m1920x1080p30_16_9));
 }
 
-void ExtDisplayObserver::setResolution(int ID)
+void ExternalDisplay::setResolution(int ID)
 {
     struct fb_var_screeninfo info;
     if (!openFramebuffer())
@@ -353,29 +283,29 @@
     //If its a valid mode and its a new ID - update var_screeninfo
     if ((isValidMode(ID)) && mCurrentID != ID) {
         const struct disp_mode_timing_type *mode =
-                                                  &supported_video_mode_lut[0];
+            &supported_video_mode_lut[0];
         unsigned count =  sizeof(supported_video_mode_lut)/sizeof
-                                                   (*supported_video_mode_lut);
+            (*supported_video_mode_lut);
         for (unsigned int i = 0; i < count; ++i) {
             const struct disp_mode_timing_type *cur =
-                                                 &supported_video_mode_lut[i];
+                &supported_video_mode_lut[i];
             if (cur->video_format == ID)
                 mode = cur;
         }
         ioctl(fd, FBIOGET_VSCREENINFO, &info);
-        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: GET Info<ID=%d %dx%d (%d,%d,%d),"
-                "(%d,%d,%d) %dMHz>", __FUNCTION__,
-                info.reserved[3], info.xres, info.yres,
-                info.right_margin, info.hsync_len, info.left_margin,
-                info.lower_margin, info.vsync_len, info.upper_margin,
-                info.pixclock/1000/1000);
+        ALOGD_IF(DEBUG, "%s: GET Info<ID=%d %dx%d (%d,%d,%d),"
+                 "(%d,%d,%d) %dMHz>", __FUNCTION__,
+                 info.reserved[3], info.xres, info.yres,
+                 info.right_margin, info.hsync_len, info.left_margin,
+                 info.lower_margin, info.vsync_len, info.upper_margin,
+                 info.pixclock/1000/1000);
         mode->set_info(info);
-        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx%d"
-                "(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, ID,
-                info.reserved[3], info.xres, info.yres,
-                info.right_margin, info.hsync_len, info.left_margin,
-                info.lower_margin, info.vsync_len, info.upper_margin,
-                info.pixclock/1000/1000);
+        ALOGD_IF(DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx%d"
+                 "(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, ID,
+                 info.reserved[3], info.xres, info.yres,
+                 info.right_margin, info.hsync_len, info.left_margin,
+                 info.lower_margin, info.vsync_len, info.upper_margin,
+                 info.pixclock/1000/1000);
         info.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
         ioctl(fd, FBIOPUT_VSCREENINFO, &info);
         mCurrentID = ID;
@@ -389,53 +319,61 @@
 }
 
 
-int  ExtDisplayObserver::getExternalDisplay() const
+int  ExternalDisplay::getExternalDisplay() const
 {
- return mExternalDisplay;
+    return mExternalDisplay;
 }
 
-void ExtDisplayObserver::setExternalDisplayStatus(int connected)
+void ExternalDisplay::setExternalDisplayStatus(int connected)
 {
 
     hwc_context_t* ctx = mHwcContext;
     if(ctx) {
-        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: status = %d", __FUNCTION__,
-                                                        connected);
+        ALOGD_IF(DEBUG, "%s: status = %d", __FUNCTION__,
+                 connected);
+        if(connected) {
+            readResolution();
+            //Get the best mode and set
+            // TODO: DO NOT call this for WFD
+            setResolution(getBestMode());
+        } else {
+            close(fd);
+        }
         // Store the external display
-        mExternalDisplay = connected;//(external_display_type)value;
+        mExternalDisplay = connected;
         //Invalidate
         hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0];
         if(!proc) {
-            ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: HWC proc not registered",
-                                                                __FUNCTION__);
+            ALOGD_IF(DEBUG, "%s: HWC proc not registered",
+                     __FUNCTION__);
         } else {
             /* Trigger redraw */
-            ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: Invalidate !!", __FUNCTION__);
+            ALOGD_IF(DEBUG, "%s: Invalidate !!", __FUNCTION__);
             proc->invalidate(proc);
         }
     }
     return;
 }
 
-bool ExtDisplayObserver::writeHPDOption(int userOption) const
+bool ExternalDisplay::writeHPDOption(int userOption) const
 {
     bool ret = true;
     int hdmiHPDFile = open(SYSFS_HPD,O_RDWR, 0);
     if (hdmiHPDFile < 0) {
-        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: state file '%s' not found : ret%d"
-        "err str: %s",  __FUNCTION__, SYSFS_HPD, hdmiHPDFile, strerror(errno));
+        ALOGD_IF(DEBUG, "%s: state file '%s' not found : ret%d"
+                 "err str: %s",  __FUNCTION__, SYSFS_HPD, hdmiHPDFile, strerror(errno));
         ret = false;
     } else {
         int err = -1;
-        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: option = %d", __FUNCTION__,
-                                                            userOption);
+        ALOGD_IF(DEBUG, "%s: option = %d", __FUNCTION__,
+                 userOption);
         if(userOption)
             err = write(hdmiHPDFile, "1", 2);
         else
             err = write(hdmiHPDFile, "0" , 2);
         if (err <= 0) {
-            ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: file write failed '%s'",
-                                                __FUNCTION__, SYSFS_HPD);
+            ALOGD_IF(DEBUG, "%s: file write failed '%s'",
+                     __FUNCTION__, SYSFS_HPD);
             ret = false;
         }
         close(hdmiHPDFile);
diff --git a/libhwcomposer/hwc_external.h b/libhwcomposer/hwc_external.h
new file mode 100644
index 0000000..9e5f455
--- /dev/null
+++ b/libhwcomposer/hwc_external.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HWC_EXTERNAL_DISPLAY_H
+#define HWC_EXTERNAL_DISPLAY_H
+
+struct hwc_context_t;
+
+namespace qhwc {
+
+class ExternalDisplay
+{
+    //Type of external display -  OFF, HDMI, WFD
+    enum external_display_type {
+        EXT_TYPE_NONE,
+        EXT_TYPE_HDMI,
+        EXT_TYPE_WIFI
+    };
+
+    // Mirroring state
+    enum external_mirroring_state {
+        EXT_MIRRORING_OFF,
+        EXT_MIRRORING_ON,
+    };
+    public:
+    ExternalDisplay(hwc_context_t* ctx);
+    ~ExternalDisplay();
+    int getExternalDisplay() const;
+    void setExternalDisplayStatus(int connected);
+
+    private:
+    bool readResolution();
+    int parseResolution(char* edidStr, int* edidModes, int len);
+    void setResolution(int ID);
+    bool openFramebuffer();
+    bool writeHPDOption(int userOption) const;
+    bool isValidMode(int ID);
+    void handleUEvent(char* str, int len);
+    int getModeOrder(int mode);
+    int getBestMode();
+
+    int fd;
+    int mExternalDisplay;
+    int mCurrentID;
+    char mEDIDs[128];
+    int mEDIDModes[64];
+    int mModeCount;
+    hwc_context_t *mHwcContext;
+};
+
+}; //qhwc
+// ---------------------------------------------------------------------------
+#endif //HWC_EXTERNAL_DISPLAY_H
diff --git a/libhwcomposer/hwc_qbuf.h b/libhwcomposer/hwc_qbuf.h
index a0ade8c..6d75964 100644
--- a/libhwcomposer/hwc_qbuf.h
+++ b/libhwcomposer/hwc_qbuf.h
@@ -15,6 +15,9 @@
  * limitations under the License.
  */
 
+#include <gralloc_priv.h>
+#include <genlock.h>
+
 // -----------------------------------------------------------------------------
 // QueuedBufferStore
 //This class holds currently and previously queued buffers.
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
new file mode 100644
index 0000000..a1df74b
--- /dev/null
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define DEBUG 0
+#ifndef HWC_OBSERVER_H
+#define HWC_OBSERVER_H
+#include <hardware_legacy/uevent.h>
+#include <utils/Log.h>
+#include <sys/resource.h>
+#include <string.h>
+#include <stdlib.h>
+#include "hwc_utils.h"
+#include "hwc_external.h"
+
+namespace qhwc {
+
+const char* MSMFB_DEVICE_CHANGE = "change@/devices/virtual/graphics/fb0";
+const char* MSMFB_HDMI_NODE = "fb1";
+
+static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
+{
+    int vsync;
+    char* hdmi;
+    int64_t timestamp = 0;
+    const char *str = udata;
+    hwc_procs* proc = reinterpret_cast<hwc_procs*>(ctx->device.reserved_proc[0]);
+
+    vsync = !strncmp(str, MSMFB_DEVICE_CHANGE, strlen(MSMFB_DEVICE_CHANGE));
+    hdmi = strcasestr(str, MSMFB_HDMI_NODE);
+    if(!vsync && !hdmi)
+        return;
+    if(vsync) {
+        str += strlen(str) + 1;
+        while(*str) {
+            if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) {
+                timestamp = strtoull(str + strlen("VSYNC="), NULL, 0);
+                proc->vsync(proc, 0, timestamp);
+            }
+            str += strlen(str) + 1;
+            if(str - udata >= len)
+                break;
+        }
+    }
+
+    if(hdmi) {
+        // parse HDMI events
+        // The event will be of the form:
+        // change@/devices/virtual/graphics/fb1 ACTION=change
+        // DEVPATH=/devices/virtual/graphics/fb1
+        // SUBSYSTEM=graphics HDCP_STATE=FAIL MAJOR=29
+        // for now just parsing onlin/offline info is enough
+        str = udata;
+        int connected = 0;
+        if(!(strncmp(str,"online@",strlen("online@")))) {
+            connected = 1;
+        } else if(!(strncmp(str,"offline@",strlen("offline@")))) {
+            connected = 0;
+        }
+        ctx->mExtDisplay->setExternalDisplayStatus(connected);
+    }
+
+}
+
+static void *uevent_loop(void *param)
+{
+    int len = 0;
+    static char udata[4096];
+    memset(udata, 0, sizeof(udata));
+    hwc_context_t * ctx = reinterpret_cast<hwc_context_t *>(param);
+
+    setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+    uevent_init();
+
+    while(1) {
+        len = uevent_next_event(udata, sizeof(udata) - 2);
+        handle_uevent(ctx, udata, len);
+    }
+
+    return NULL;
+}
+
+void init_uevent_thread(hwc_context_t* ctx)
+{
+    pthread_t uevent_thread;
+    pthread_create(&uevent_thread, NULL, uevent_loop, (void*) ctx);
+}
+
+}; //namespace
+#endif //HWC_OBSERVER_H
diff --git a/libhwcomposer/hwc_uimirror.cpp b/libhwcomposer/hwc_uimirror.cpp
index 4540be8..9cf91af 100644
--- a/libhwcomposer/hwc_uimirror.cpp
+++ b/libhwcomposer/hwc_uimirror.cpp
@@ -18,12 +18,14 @@
  * limitations under the License.
  */
 
+#define HWC_UI_MIRROR 0
+#include <gralloc_priv.h>
+#include <fb_priv.h>
 #include "hwc_uimirror.h"
-#include "hwc_ext_observer.h"
+#include "hwc_external.h"
 
 namespace qhwc {
 
-#define HWC_UI_MIRROR 0
 
 // Function to get the primary device orientation
 // Loops thru the hardware layers and returns the orientation of the max.
@@ -59,7 +61,7 @@
     sState = ovutils::OV_CLOSED;
     sIsUiMirroringOn = false;
     // If external display is connected
-    if(ctx->mExtDisplayObserver->getExternalDisplay()) {
+    if(ctx->mExtDisplay->getExternalDisplay()) {
         sState = ovutils::OV_UI_MIRROR;
         configure(ctx, list);
     }
@@ -73,7 +75,7 @@
         overlay::Overlay& ov = *(ctx->mOverlay);
         // Set overlay state
         ov.setState(sState);
-        framebuffer_device_t *fbDev = ctx->mFbDevice->getFb();
+        framebuffer_device_t *fbDev = ctx->mFbDev;
         if(fbDev) {
             private_module_t* m = reinterpret_cast<private_module_t*>(
                     fbDev->common.module);
@@ -143,7 +145,7 @@
     overlay::Overlay& ov = *(ctx->mOverlay);
     ovutils::eOverlayState state = ov.getState();
     ovutils::eDest dest = ovutils::OV_PIPE_ALL;
-    framebuffer_device_t *fbDev = ctx->mFbDevice->getFb();
+    framebuffer_device_t *fbDev = ctx->mFbDev;
     if(fbDev) {
         private_module_t* m = reinterpret_cast<private_module_t*>(
                               fbDev->common.module);
diff --git a/libhwcomposer/hwc_uimirror.h b/libhwcomposer/hwc_uimirror.h
index af43848..98f7896 100644
--- a/libhwcomposer/hwc_uimirror.h
+++ b/libhwcomposer/hwc_uimirror.h
@@ -20,6 +20,7 @@
 #ifndef HWC_UIMIRROR_H
 #define HWC_UIMIRROR_H
 #include "hwc_utils.h"
+#include "overlay.h"
 
 #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
 #define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index ae5c526..870a758 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -15,26 +15,39 @@
  * limitations under the License.
  */
 
+#include <overlay.h>
 #include "hwc_utils.h"
 #include "mdp_version.h"
 #include "hwc_video.h"
-#include "hwc_ext_observer.h"
+#include "hwc_qbuf.h"
 #include "hwc_copybit.h"
+#include "hwc_external.h"
+
 namespace qhwc {
+
+// Opens Framebuffer device
+static void openFramebufferDevice(hwc_context_t *ctx)
+{
+    hw_module_t const *module;
+    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
+        framebuffer_open(module, &(ctx->mFbDev));
+    }
+}
+
 void initContext(hwc_context_t *ctx)
 {
-    //XXX: target specific initializations here
+    openFramebufferDevice(ctx);
     ctx->mOverlay = overlay::Overlay::getInstance();
     ctx->qbuf = new QueuedBufferStore();
     ctx->mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
     ctx->hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
-    ALOGI("MDP version: %d",ctx->mdpVersion);
-
-    ctx->mExtDisplayObserver = ExtDisplayObserver::getInstance();
-    ctx->mExtDisplayObserver->setHwcContext(ctx);
-    ctx->mFbDevice = FbDevice::getInstance();
     ctx->mCopybitEngine = CopybitEngine::getInstance();
-    CopyBit::openEglLibAndGethandle();
+    ctx->mExtDisplay = new ExternalDisplay(ctx);
+
+    init_uevent_thread(ctx);
+
+    ALOGI("Initializing Qualcomm Hardware Composer");
+    ALOGI("MDP version: %d", ctx->mdpVersion);
 }
 
 void closeContext(hwc_context_t *ctx)
@@ -48,15 +61,25 @@
         delete ctx->mCopybitEngine;
         ctx->mCopybitEngine = NULL;
     }
-    if(ctx->mFbDevice) {
-        delete ctx->mFbDevice;
-        ctx->mFbDevice = NULL;
+
+    if(ctx->mFbDev) {
+        framebuffer_close(ctx->mFbDev);
+        ctx->mFbDev = NULL;
     }
+
     if(ctx->qbuf) {
         delete ctx->qbuf;
         ctx->qbuf = NULL;
     }
-    CopyBit::closeEglLib();
+
+    if(ctx->mExtDisplay) {
+        delete ctx->mExtDisplay;
+        ctx->mExtDisplay = NULL;
+    }
+
+
+    free(const_cast<hwc_methods_t *>(ctx->device.methods));
+
 }
 
 void dumpLayer(hwc_layer_t const* l)
@@ -163,33 +186,4 @@
     }
 }
 
-//FbDevice class functions
-FbDevice* FbDevice::sInstance = 0;;
-struct framebuffer_device_t* FbDevice::getFb() {
-   return sFb;
-}
-
-FbDevice* FbDevice::getInstance() {
-   if(sInstance == NULL)
-       sInstance = new FbDevice();
-   return sInstance;
-}
-
-FbDevice::FbDevice(){
-    hw_module_t const *module;
-    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
-        framebuffer_open(module, &sFb);
-    } else {
-       ALOGE("FATAL ERROR: framebuffer open failed.");
-    }
-}
-FbDevice::~FbDevice()
-{
-    if(sFb)
-    {
-       framebuffer_close(sFb);
-       sFb = NULL;
-    }
-}
-
 };//namespace
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 0bf30c9..1e405f7 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -17,28 +17,26 @@
 
 #ifndef HWC_UTILS_H
 #define HWC_UTILS_H
-#include <cutils/log.h>
-#include <gralloc_priv.h>
+
 #include <hardware/hwcomposer.h>
-#include <hardware/hardware.h>
-#include <hardware/gralloc.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fb_priv.h>
-#include <overlay.h>
-#include <copybit.h>
-#include <hwc_copybitEngine.h>
-#include <genlock.h>
-#include "hwc_qbuf.h"
-#include <EGL/egl.h>
+#include <gralloc_priv.h>
 
 #define ALIGN_TO(x, align)     (((x) + ((align)-1)) & ~((align)-1))
 #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
 #define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
 #define FINAL_TRANSFORM_MASK 0x000F
 
+//Fwrd decls
 struct hwc_context_t;
+struct framebuffer_device_t;
+
+namespace overlay {
+class Overlay;
+}
+
 namespace qhwc {
+//fwrd decl
+class QueuedBufferStore;
 
 enum external_display_type {
     EXT_TYPE_NONE,
@@ -53,7 +51,8 @@
 };
 
 
-class ExtDisplayObserver;
+class ExternalDisplay;
+class CopybitEngine;
 // -----------------------------------------------------------------------------
 // Utility functions - implemented in hwc_utils.cpp
 void dumpLayer(hwc_layer_t const* l);
@@ -78,32 +77,12 @@
 static inline bool isBufferLocked(const private_handle_t* hnd) {
     return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
 }
-// -----------------------------------------------------------------------------
-// Copybit specific - inline or implemented in hwc_copybit.cpp
-typedef EGLClientBuffer (*functype_eglGetRenderBufferANDROID) (
-                                                     EGLDisplay dpy,
-                                                    EGLSurface draw);
-typedef EGLSurface (*functype_eglGetCurrentSurface)(EGLint readdraw);
 
-// -----------------------------------------------------------------------------
-// Singleton for Framebuffer device
-class FbDevice{
-public:
-    ~FbDevice();
-    // API to get Fb device(non static)
-    struct framebuffer_device_t *getFb();
-    // API to get singleton
-    static FbDevice* getInstance();
-
-private:
-    FbDevice();
-    struct framebuffer_device_t *sFb;
-    static FbDevice* sInstance; // singleton
-};
+// Initialize uevent thread
+void init_uevent_thread(hwc_context_t* ctx);
 
 }; //qhwc namespace
 
-
 // -----------------------------------------------------------------------------
 // HWC context
 // This structure contains overall state
@@ -115,7 +94,7 @@
     int overlayInUse;
 
     //Framebuffer device
-    qhwc::FbDevice* mFbDevice;
+    framebuffer_device_t *mFbDev;
 
     //Copybit Engine
     qhwc::CopybitEngine* mCopybitEngine;
@@ -127,7 +106,8 @@
     qhwc::QueuedBufferStore *qbuf;
 
     // External display related information
-    qhwc::ExtDisplayObserver*mExtDisplayObserver;
+    qhwc::ExternalDisplay *mExtDisplay;
+
 };
 
 #endif //HWC_UTILS_H
diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp
index 180ab86..190e31b 100644
--- a/libhwcomposer/hwc_video.cpp
+++ b/libhwcomposer/hwc_video.cpp
@@ -15,13 +15,15 @@
  * limitations under the License.
  */
 
+#define VIDEO_DEBUG 0
+#include <overlay.h>
+#include "hwc_qbuf.h"
 #include "hwc_video.h"
-#include "hwc_ext_observer.h"
+#include "hwc_external.h"
 
 namespace qhwc {
 
 #define FINAL_TRANSFORM_MASK 0x000F
-#define VIDEO_DEBUG 0
 
 //Static Members
 ovutils::eOverlayState VideoOverlay::sState = ovutils::OV_CLOSED;
@@ -62,12 +64,12 @@
     //Support 1 video layer
     if(sYuvCount == 1) {
         //Skip on primary, display on ext.
-        if(sIsLayerSkip && ctx->mExtDisplayObserver->getExternalDisplay()) {
+        if(sIsLayerSkip && ctx->mExtDisplay->getExternalDisplay()) {
             //TODO
             //VIDEO_ON_TV_ONLY
         } else if(sIsLayerSkip) { //skip on primary, no ext
             newState = ovutils::OV_CLOSED;
-        } else if(ctx->mExtDisplayObserver->getExternalDisplay()) {
+        } else if(ctx->mExtDisplay->getExternalDisplay()) {
             //display on both
             newState = ovutils::OV_2D_VIDEO_ON_PANEL_TV;
         } else { //display on primary only