Merge "display: Export headers"
diff --git a/common.mk b/common.mk
index 02867d7..aea5cf5 100644
--- a/common.mk
+++ b/common.mk
@@ -41,10 +41,10 @@
 ifeq ($(TARGET_USES_QCOM_BSP),true)
 # Enable QCOM Display features
     common_flags += -DQCOM_BSP
+endif
 ifneq ($(call is-platform-sdk-version-at-least,18),true)
     common_flags += -DANDROID_JELLYBEAN_MR1=1
 endif
-endif
 ifeq ($(call is-vendor-board-platform,QCOM),true)
 # This check is to pick the kernel headers from the right location.
 # If the macro above is defined, we make the assumption that we have the kernel
diff --git a/libexternal/external.h b/libexternal/external.h
index d35490f..7ab7c3f 100644
--- a/libexternal/external.h
+++ b/libexternal/external.h
@@ -58,6 +58,7 @@
     int  configureWFDDisplay();
     int  teardownHDMIDisplay();
     int  teardownWFDDisplay();
+    int getHDMIIndex() { return mHdmiFbNum; }
 
 private:
     void setSPDInfo(const char* node, const char* property);
diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp
index 46c7cb8..fd3abbc 100644
--- a/libgralloc/ionalloc.cpp
+++ b/libgralloc/ionalloc.cpp
@@ -109,10 +109,6 @@
             ioctl(mIonFd, ION_IOC_FREE, &handle_data);
             return err;
         }
-        memset(base, 0, ionAllocData.len);
-        // Clean cache after memset
-        clean_buffer(base, data.size, data.offset, fd_data.fd,
-                     CACHE_CLEAN_AND_INVALIDATE);
     }
 
     data.base = base;
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index e322357..75b9ecb 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -158,7 +158,6 @@
         hwc_display_contents_1_t *list, int dpy) {
 
     hwc_context_t* ctx = (hwc_context_t*)(dev);
-    Locker::Autolock _l(ctx->mExtLock);
 
     if (LIKELY(list && list->numHwLayers > 1) &&
             ctx->dpyAttr[dpy].isActive &&
@@ -209,7 +208,8 @@
 {
     int ret = 0;
     hwc_context_t* ctx = (hwc_context_t*)(dev);
-    Locker::Autolock _l(ctx->mBlankLock);
+    Locker::Autolock _bl(ctx->mBlankLock);
+    Locker::Autolock _el(ctx->mExtLock);
     reset(ctx, numDisplays, displays);
 
     ctx->mOverlay->configBegin();
@@ -417,7 +417,6 @@
 {
     ATRACE_CALL();
     int ret = 0;
-    Locker::Autolock _l(ctx->mExtLock);
 
     if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
         ctx->dpyAttr[dpy].connected) {
@@ -477,7 +476,8 @@
 {
     int ret = 0;
     hwc_context_t* ctx = (hwc_context_t*)(dev);
-    Locker::Autolock _l(ctx->mBlankLock);
+    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) {
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 28b1849..abca20b 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -206,6 +206,7 @@
         case EXTERNAL_PAUSE:
             {   // pause case
                 ALOGD("%s Received Pause event",__FUNCTION__);
+                Locker::Autolock _l(ctx->mExtLock);
                 ctx->dpyAttr[dpy].isActive = true;
                 ctx->dpyAttr[dpy].isPause = true;
                 break;
@@ -214,9 +215,11 @@
             {  // 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);
                 break;
             }
         default:
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 90038f2..552b526 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -478,8 +478,8 @@
 }
 
 
-static void calc_cut(float& leftCutRatio, float& topCutRatio,
-        float& rightCutRatio, float& bottomCutRatio, int orient) {
+static void calc_cut(double& leftCutRatio, double& topCutRatio,
+        double& rightCutRatio, double& bottomCutRatio, int orient) {
     if(orient & HAL_TRANSFORM_FLIP_H) {
         swap(leftCutRatio, rightCutRatio);
     }
@@ -488,7 +488,7 @@
     }
     if(orient & HAL_TRANSFORM_ROT_90) {
         //Anti clock swapping
-        float tmpCutRatio = leftCutRatio;
+        double tmpCutRatio = leftCutRatio;
         leftCutRatio = topCutRatio;
         topCutRatio = rightCutRatio;
         rightCutRatio = bottomCutRatio;
@@ -553,26 +553,26 @@
     int sci_w = abs(sci_r - sci_l);
     int sci_h = abs(sci_b - sci_t);
 
-    float leftCutRatio = 0.0f, rightCutRatio = 0.0f, topCutRatio = 0.0f,
-            bottomCutRatio = 0.0f;
+    double leftCutRatio = 0.0, rightCutRatio = 0.0, topCutRatio = 0.0,
+            bottomCutRatio = 0.0;
 
     if(dst_l < sci_l) {
-        leftCutRatio = (float)(sci_l - dst_l) / (float)dst_w;
+        leftCutRatio = (double)(sci_l - dst_l) / (double)dst_w;
         dst_l = sci_l;
     }
 
     if(dst_r > sci_r) {
-        rightCutRatio = (float)(dst_r - sci_r) / (float)dst_w;
+        rightCutRatio = (double)(dst_r - sci_r) / (double)dst_w;
         dst_r = sci_r;
     }
 
     if(dst_t < sci_t) {
-        topCutRatio = (float)(sci_t - dst_t) / (float)dst_h;
+        topCutRatio = (double)(sci_t - dst_t) / (double)dst_h;
         dst_t = sci_t;
     }
 
     if(dst_b > sci_b) {
-        bottomCutRatio = (float)(dst_b - sci_b) / (float)dst_h;
+        bottomCutRatio = (double)(dst_b - sci_b) / (double)dst_h;
         dst_b = sci_b;
     }
 
diff --git a/libhwcomposer/hwc_vsync.cpp b/libhwcomposer/hwc_vsync.cpp
index 2f4475e..e4da4f7 100644
--- a/libhwcomposer/hwc_vsync.cpp
+++ b/libhwcomposer/hwc_vsync.cpp
@@ -33,6 +33,7 @@
 namespace qhwc {
 
 #define HWC_VSYNC_THREAD_NAME "hwcVsyncThread"
+#define MAX_SYSFS_FILE_PATH             255
 
 int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable)
 {
@@ -49,10 +50,6 @@
 
 static void *vsync_loop(void *param)
 {
-    const char* vsync_timestamp_fb0 = "/sys/class/graphics/fb0/vsync_event";
-    const char* vsync_timestamp_fb1 = "/sys/class/graphics/fb1/vsync_event";
-    int dpy = HWC_DISPLAY_PRIMARY;
-
     hwc_context_t * ctx = reinterpret_cast<hwc_context_t *>(param);
 
     char thread_name[64] = HWC_VSYNC_THREAD_NAME;
@@ -61,16 +58,14 @@
                 android::PRIORITY_MORE_FAVORABLE);
 
     const int MAX_DATA = 64;
-    static char vdata[MAX_DATA];
-    struct pollfd pfd;
-
-    uint64_t cur_timestamp=0;
-    ssize_t len = -1;
-    int fb0_fd = -1;
-    int ret = 0;
-    bool fb1_vsync = false;
+    char vdata[MAX_DATA];
     bool logvsync = false;
 
+    struct pollfd pfd[2];
+    int fb_fd[2];
+    uint64_t timestamp[2];
+    int num_displays;
+
     char property[PROPERTY_VALUE_MAX];
     if(property_get("debug.hwc.fakevsync", property, NULL) > 0) {
         if(atoi(property) == 1)
@@ -82,62 +77,91 @@
             logvsync = true;
     }
 
-    /* Currently read vsync timestamp from drivers
-       e.g. VSYNC=41800875994
-       */
-    fb0_fd = open(vsync_timestamp_fb0, O_RDONLY);
-    pfd.fd = fb0_fd;
-    pfd.events = POLLPRI | POLLERR;
+    if (ctx->mExtDisplay->getHDMIIndex() > 0)
+        num_displays = 2;
+    else
+        num_displays = 1;
 
-    if (fb0_fd < 0) {
-        // Make sure fb device is opened before starting this thread so this
-        // never happens.
-        ALOGE ("FATAL:%s:not able to open file:%s, %s",  __FUNCTION__,
-               (fb1_vsync) ? vsync_timestamp_fb1 : vsync_timestamp_fb0,
-               strerror(errno));
-        ctx->vstate.fakevsync = true;
+    char vsync_node_path[MAX_SYSFS_FILE_PATH];
+    for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
+        snprintf(vsync_node_path, sizeof(vsync_node_path),
+                "/sys/class/graphics/fb%d/vsync_event",
+                dpy == HWC_DISPLAY_PRIMARY ? 0 :
+                ctx->mExtDisplay->getHDMIIndex());
+        ALOGI("%s: Reading vsync for dpy=%d from %s", __FUNCTION__, dpy,
+                vsync_node_path);
+        fb_fd[dpy] = open(vsync_node_path, O_RDONLY);
+
+        if (fb_fd[dpy] < 0) {
+            // Make sure fb device is opened before starting this thread so this
+            // never happens.
+            ALOGE ("%s:not able to open vsync node for dpy=%d, %s",
+                    __FUNCTION__, dpy, strerror(errno));
+            if (dpy == HWC_DISPLAY_PRIMARY) {
+                ctx->vstate.fakevsync = true;
+                break;
+            }
+        }
+
+        pfd[dpy].fd = fb_fd[dpy];
+        if (pfd[dpy].fd >= 0)
+            pfd[dpy].events = POLLPRI | POLLERR;
     }
 
-    do {
-        if (LIKELY(!ctx->vstate.fakevsync)) {
-            int err = poll(&pfd, 1, -1);
+    if (LIKELY(!ctx->vstate.fakevsync)) {
+        do {
+            int err = poll(pfd, num_displays, -1);
             if(err > 0) {
-                if (pfd.revents & POLLPRI) {
-                    len = pread(fb0_fd, vdata, MAX_DATA, 0);
-                    if (UNLIKELY(len < 0)) {
-                        // If the read was just interrupted - it is not a fatal
-                        // error. Just continue in this case
-                        ALOGE ("FATAL:%s:not able to read file:%s, %s",
-                               __FUNCTION__,
-                               vsync_timestamp_fb0, strerror(errno));
-                        continue;
-                    }
-                    // extract timestamp
-                    const char *str = vdata;
-                    if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) {
-                        cur_timestamp = strtoull(str + strlen("VSYNC="),
-                                                 NULL, 0);
+                for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
+                    if (pfd[dpy].revents & POLLPRI) {
+                        int len = pread(pfd[dpy].fd, vdata, MAX_DATA, 0);
+                        if (UNLIKELY(len < 0)) {
+                            // If the read was just interrupted - it is not a
+                            // fatal error. Just continue in this case
+                            ALOGE ("%s:Unable to read vsync for dpy=%d :%s",
+                                    __FUNCTION__, dpy, strerror(errno));
+                            continue;
+                        }
+                        // extract timestamp
+                        if (!strncmp(vdata, "VSYNC=", strlen("VSYNC="))) {
+                            timestamp[dpy] = strtoull(vdata + strlen("VSYNC="),
+                                    NULL, 0);
+                        }
+                        // send timestamp to SurfaceFlinger
+                        ALOGD_IF (logvsync,
+                                "%s: timestamp %llu sent to SF for dpy=%d",
+                                __FUNCTION__, timestamp[dpy], dpy);
+                        ctx->proc->vsync(ctx->proc, dpy, timestamp[dpy]);
                     }
                 }
+
             } else {
                 ALOGE("%s: vsync poll failed errno: %s", __FUNCTION__,
-                      strerror(errno));
+                        strerror(errno));
                 continue;
             }
-        } else {
-            usleep(16666);
-            cur_timestamp = systemTime();
-        }
-        // send timestamp to HAL
-        if(ctx->vstate.enable) {
-            ALOGD_IF (logvsync, "%s: timestamp %llu sent to HWC for %s",
-                      __FUNCTION__, cur_timestamp, "fb0");
-            ctx->proc->vsync(ctx->proc, dpy, cur_timestamp);
-        }
+        } while (true);
 
-    } while (true);
-    if(fb0_fd >= 0)
-        close (fb0_fd);
+    } else {
+
+        //Fake vsync is used only when set explicitly through a property or when
+        //the vsync timestamp node cannot be opened at bootup. There is no
+        //fallback to fake vsync from the true vsync loop, ever, as the
+        //condition can easily escape detection.
+        //Also, fake vsync is delivered only for the primary display.
+        do {
+            usleep(16666);
+            timestamp[HWC_DISPLAY_PRIMARY] = systemTime();
+            ctx->proc->vsync(ctx->proc, HWC_DISPLAY_PRIMARY,
+                    timestamp[HWC_DISPLAY_PRIMARY]);
+
+        } while (true);
+    }
+
+    for (int dpy = HWC_DISPLAY_PRIMARY; dpy <= HWC_DISPLAY_EXTERNAL; dpy++ ) {
+        if(fb_fd[dpy] >= 0)
+            close (fb_fd[dpy]);
+    }
 
     return NULL;
 }
diff --git a/liboverlay/overlayMdssRot.cpp b/liboverlay/overlayMdssRot.cpp
index 30d7ccd..b8a2417 100644
--- a/liboverlay/overlayMdssRot.cpp
+++ b/liboverlay/overlayMdssRot.cpp
@@ -279,7 +279,7 @@
     int aHeight = ovutils::align(mRotInfo.src_rect.h, 4);
     int rau_cnt = aWidth/64;
     int stride0 = (64 * 4 * rau_cnt) + rau_cnt/8;
-    int stride1 = (64 * 2 * rau_cnt) + rau_cnt/8;
+    int stride1 = ((64 * 2 * rau_cnt) + rau_cnt/8) * 2;
     int stride0_off = (aHeight/4);
     int stride1_off = (aHeight/2);
 
diff --git a/liboverlay/overlayMem.h b/liboverlay/overlayMem.h
index 5fbe91b..061d197 100644
--- a/liboverlay/overlayMem.h
+++ b/liboverlay/overlayMem.h
@@ -121,8 +121,9 @@
     if(isSecure) {
         allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
         allocFlags |= GRALLOC_USAGE_PROTECTED;
-        allocFlags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
     }
+    // Allocate uncached rotator buffers
+    allocFlags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
 
     int err = 0;
     OVASSERT(numbufs && bufSz, "numbufs=%d bufSz=%d", numbufs, bufSz);