Merge "hwc: Dynamic Resolution support on Primary"
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 8048f32..b45a7cd 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -105,17 +105,27 @@
 //Helper
 static void reset(hwc_context_t *ctx, int numDisplays,
                   hwc_display_contents_1_t** displays) {
+
+    ctx->numActiveDisplays = 0;
     for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
         hwc_display_contents_1_t *list = displays[i];
         // XXX:SurfaceFlinger no longer guarantees that this
         // value is reset on every prepare. However, for the layer
         // cache we need to reset it.
         // We can probably rethink that later on
-        if (LIKELY(list && list->numHwLayers > 1)) {
+        if (LIKELY(list && list->numHwLayers > 0)) {
             for(uint32_t j = 0; j < list->numHwLayers; j++) {
                 if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
                     list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
             }
+
+            /* For display devices like SSD and screenrecord, we cannot
+             * rely on isActive and connected attributes of dpyAttr to
+             * determine if the displaydevice is active. Hence in case if
+             * the layer-list is non-null and numHwLayers > 0, we assume
+             * the display device to be active.
+             */
+            ctx->numActiveDisplays += 1;
         }
 
         if(ctx->mFBUpdate[i])
@@ -124,6 +134,7 @@
             ctx->mCopyBit[i]->reset();
         if(ctx->mLayerRotMap[i])
             ctx->mLayerRotMap[i]->reset();
+
     }
 
     ctx->mAD->reset();
@@ -242,7 +253,7 @@
     ctx->mRotMgr->configBegin();
     overlay::Writeback::configBegin();
 
-    for (int32_t i = numDisplays; i >= 0; i--) {
+    for (int32_t i = (numDisplays-1); i >= 0; i--) {
         hwc_display_contents_1_t *list = displays[i];
         int dpy = getDpyforExternalDisplay(ctx, i);
         switch(dpy) {
@@ -574,7 +585,7 @@
 {
     int ret = 0;
     hwc_context_t* ctx = (hwc_context_t*)(dev);
-    for (uint32_t i = 0; i <= numDisplays; i++) {
+    for (uint32_t i = 0; i < numDisplays; i++) {
         hwc_display_contents_1_t* list = displays[i];
         int dpy = getDpyforExternalDisplay(ctx, i);
         switch(dpy) {
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index e84b345..0d89c79 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -451,6 +451,7 @@
         if(!isValidRect(visibleRect)) {
             mCurrentFrame.drop[i] = true;
             mCurrentFrame.dropCount++;
+            continue;
         }
 
         const hwc_layer_1_t* layer =  &list->hwLayers[i];
@@ -472,17 +473,17 @@
         }else {
             /* Reset frame ROI when any layer which needs scaling also needs ROI
              * cropping */
-            if((res_w != dst_w || res_h != dst_h) &&
-                    needsScaling (layer)) {
+            if((res_w != dst_w || res_h != dst_h) && needsScaling (layer)) {
                 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
                 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
                 mCurrentFrame.dropCount = 0;
                 return false;
             }
-        }
 
-        if (layer->blending == HWC_BLENDING_NONE)
-            visibleRect = deductRect(visibleRect, res);
+            /* deduct any opaque region from visibleRect */
+            if (layer->blending == HWC_BLENDING_NONE)
+                visibleRect = deductRect(visibleRect, res);
+        }
     }
     return true;
 }
@@ -1628,7 +1629,7 @@
 
     /* reset Invalidator */
     if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
-        idleInvalidator->markForSleep();
+        idleInvalidator->handleUpdateEvent();
 
     overlay::Overlay& ov = *ctx->mOverlay;
     LayerProp *layerProp = ctx->layerProp[mDpy];
@@ -1975,7 +1976,7 @@
 
     /* reset Invalidator */
     if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
-        idleInvalidator->markForSleep();
+        idleInvalidator->handleUpdateEvent();
 
     overlay::Overlay& ov = *ctx->mOverlay;
     LayerProp *layerProp = ctx->layerProp[mDpy];
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index dce1e0e..ececa70 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -219,6 +219,7 @@
     ctx->vstate.enable = false;
     ctx->vstate.fakevsync = false;
     ctx->mExtOrientation = 0;
+    ctx->numActiveDisplays = 1;
 
     //Right now hwc starts the service but anybody could do it, or it could be
     //independent process as well.
@@ -464,8 +465,8 @@
     xRatio = (inPos.x - viewFrame.left)/actualWidth;
     yRatio = (inPos.y - viewFrame.top)/actualHeight;
     // Use viewframe width and height to compute wRatio and hRatio.
-    wRatio = inPos.w/(viewFrame.right - viewFrame.left);
-    hRatio = inPos.h/(viewFrame.bottom - viewFrame.top);
+    wRatio = (float)inPos.w/(float)(viewFrame.right - viewFrame.left);
+    hRatio = (float)inPos.h/(float)(viewFrame.bottom - viewFrame.top);
 
 
     //Calculate the position...
@@ -1351,6 +1352,10 @@
                 ovutils::OV_MDP_BLEND_FG_PREMULT);
     }
 
+    if (layer->flags & HWC_VPU_PIPE) {
+        ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_VPU_PIPE);
+    }
+
     if(isYuvBuffer(hnd)) {
         if(isSecureBuffer(hnd)) {
             ovutils::setMdpFlags(mdpFlags,
@@ -1938,6 +1943,32 @@
     ctx->layerProp[dpy] = new LayerProp[numAppLayers];
 }
 
+/* Since we fake non-Hybrid WFD solution as external display, this
+ * function helps us in determining the priority between external
+ * (hdmi/non-Hybrid WFD display) and virtual display devices(SSD/
+ * screenrecord). This can be removed once wfd-client migrates to
+ * using virtual-display api's.
+ */
+bool canUseMDPforVirtualDisplay(hwc_context_t* ctx,
+                                const hwc_display_contents_1_t *list) {
+
+    /* We rely on the fact that for pure virtual display solution
+     * list->outbuf will be a non-NULL handle.
+     *
+     * If there are three active displays (which means there is one
+     * primary, one external and one virtual active display)
+     * we give mdss/mdp hw resources(pipes,smp,etc) for external
+     * display(hdmi/non-Hybrid WFD display) rather than for virtual
+     * display(SSD/screenrecord)
+     */
+
+    if(list->outbuf and (ctx->numActiveDisplays == HWC_NUM_DISPLAY_TYPES)) {
+        return false;
+    }
+
+    return true;
+}
+
 void BwcPM::setBwc(hwc_context_t *ctx, const hwc_rect_t& crop,
             const hwc_rect_t& dst, const int& transform,
             ovutils::eMdpFlags& mdpFlags) {
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 22debaf..9ccfa1b 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -151,6 +151,7 @@
 enum {
     HWC_COLOR_FILL = 0x00000008,
     HWC_FORMAT_RB_SWAP = 0x00000040,
+    HWC_VPU_PIPE = 0x00000200,
 };
 
 class LayerRotMap {
@@ -234,6 +235,9 @@
 bool isGLESOnlyComp(hwc_context_t *ctx, const int& dpy);
 void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers);
 
+bool canUseMDPforVirtualDisplay(hwc_context_t* ctx,
+                                const hwc_display_contents_1_t *list);
+
 //Helper function to dump logs
 void dumpsys_log(android::String8& buf, const char* fmt, ...);
 
@@ -495,15 +499,14 @@
     int mExtOrientation;
     //Flags the transition of a video session
     bool mVideoTransFlag;
-
     //Used for SideSync feature
     //which overrides the mExtOrientation
     bool mBufferMirrorMode;
-
     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;
 };
 
 namespace qhwc {
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
index 51ade32..600ba8d 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -67,9 +67,7 @@
     int dpy = HWC_DISPLAY_VIRTUAL;
 
     //Cleanup virtual display objs, since there is no explicit disconnect
-    if(ctx->dpyAttr[dpy].connected &&
-        (numDisplays <= HWC_NUM_PHYSICAL_DISPLAY_TYPES ||
-        displays[dpy] == NULL)) {
+    if(ctx->dpyAttr[dpy].connected && (displays[dpy] == NULL)) {
         ctx->dpyAttr[dpy].connected = false;
 
         if(ctx->mFBUpdate[dpy]) {
@@ -132,8 +130,11 @@
         if(fbLayer->handle && !isSecondaryConfiguring(ctx) &&
                 !ctx->mMDPComp[dpy]->isGLESOnlyComp()) {
             private_handle_t *ohnd = (private_handle_t *)list->outbuf;
+            int format = ohnd->format;
+            if (format == HAL_PIXEL_FORMAT_RGBA_8888)
+                format = HAL_PIXEL_FORMAT_RGBX_8888;
             Writeback::getInstance()->setOutputFormat(
-                                    utils::getMdpFormat(ohnd->format));
+                                    utils::getMdpFormat(format));
 
             int fd = -1; //FenceFD from the Copybit
             hwc_sync(ctx, list, dpy, fd);
@@ -180,7 +181,8 @@
 
     if (LIKELY(list && list->numHwLayers > 1) &&
             ctx->dpyAttr[dpy].isActive &&
-            ctx->dpyAttr[dpy].connected) {
+            ctx->dpyAttr[dpy].connected &&
+            canUseMDPforVirtualDisplay(ctx,list)) {
         reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
         if(!ctx->dpyAttr[dpy].isPause) {
             ctx->dpyAttr[dpy].isConfiguring = false;
@@ -211,7 +213,8 @@
 
     if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
             ctx->dpyAttr[dpy].connected &&
-            !ctx->dpyAttr[dpy].isPause) {
+            (!ctx->dpyAttr[dpy].isPause) &&
+            canUseMDPforVirtualDisplay(ctx,list)) {
         uint32_t last = list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
         int fd = -1; //FenceFD from the Copybit(valid in async mode)
diff --git a/libmemtrack/memtrack_msm.c b/libmemtrack/memtrack_msm.c
index 6626b89..ac93f44 100644
--- a/libmemtrack/memtrack_msm.c
+++ b/libmemtrack/memtrack_msm.c
@@ -27,7 +27,7 @@
 
 int msm_memtrack_get_memory(const struct memtrack_module *module,
                                 pid_t pid,
-                                enum memtrack_type type,
+                                int type,
                                 struct memtrack_record *records,
                                 size_t *num_records)
 {
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index 33802e5..24fba33 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -272,6 +272,7 @@
     OV_MDSS_MDP_BWC_EN = MDP_BWC_EN,
     OV_MDSS_MDP_DUAL_PIPE = MDSS_MDP_DUAL_PIPE,
     OV_MDP_SOLID_FILL = MDP_SOLID_FILL,
+    OV_MDP_VPU_PIPE = MDP_VPU_PIPE,
 };
 
 enum eZorder {
diff --git a/libqdutils/idle_invalidator.cpp b/libqdutils/idle_invalidator.cpp
index 97176a4..b53f1a3 100644
--- a/libqdutils/idle_invalidator.cpp
+++ b/libqdutils/idle_invalidator.cpp
@@ -54,16 +54,43 @@
 }
 
 bool IdleInvalidator::threadLoop() {
+    struct timeval lastUpdateTime;
     ALOGD_IF(II_DEBUG, "%s", __func__);
-    usleep(mSleepTime * 500);
+
+    {
+        //If we are here, update(s) happened, i.e mSleepAgain is set
+        Locker::Autolock _l(mLock);
+        mSleepAgain = false;
+        lastUpdateTime = mLastUpdateTime;
+    }
+
+    struct timeval currentTime;
+    gettimeofday(&currentTime, NULL);
+    int timeSinceUpdateUs = (currentTime.tv_sec - lastUpdateTime.tv_sec) *
+            1000000 + (currentTime.tv_usec - lastUpdateTime.tv_usec);
+    int sleepDurationUs = mSleepTime * 1000 - timeSinceUpdateUs;
+
+    //Sleep only if the duration required is > 1ms, otherwise its not worth it.
+    if(sleepDurationUs > 1000) {
+        usleep(sleepDurationUs);
+        ALOGD_IF(II_DEBUG, "Slept for %d ms", sleepDurationUs / 1000);
+    }
 
     Locker::Autolock _l(mLock);
+    //If an update happened while we were asleep, sleep again
     if(mSleepAgain) {
         //We need to sleep again!
         mSleepAgain = false;
         return true;
     }
 
+#if II_DEBUG
+    gettimeofday(&currentTime, NULL);
+    timeSinceUpdateUs = (currentTime.tv_sec - lastUpdateTime.tv_sec) *
+            1000000 + (currentTime.tv_usec - lastUpdateTime.tv_usec);
+    ALOGD("Idle refresh after %dms", timeSinceUpdateUs / 1000);
+#endif
+
     mHandler((void*)mHwcContext);
     return false;
 }
@@ -77,8 +104,9 @@
     ALOGD_IF(II_DEBUG, "%s", __func__);
 }
 
-void IdleInvalidator::markForSleep() {
+void IdleInvalidator::handleUpdateEvent() {
     Locker::Autolock _l(mLock);
+    gettimeofday(&mLastUpdateTime, NULL);
     mSleepAgain = true;
     //Triggers the threadLoop to run, if not already running.
     run(threadName, android::PRIORITY_AUDIO);
diff --git a/libqdutils/idle_invalidator.h b/libqdutils/idle_invalidator.h
index abd9b29..f41c15e 100644
--- a/libqdutils/idle_invalidator.h
+++ b/libqdutils/idle_invalidator.h
@@ -38,6 +38,7 @@
 
 class IdleInvalidator : public android::Thread {
     void *mHwcContext;
+    struct timeval mLastUpdateTime;
     bool mSleepAgain;
     unsigned int mSleepTime;
     static InvalidatorHandler mHandler;
@@ -49,7 +50,7 @@
     /* init timer obj */
     int init(InvalidatorHandler reg_handler, void* user_data, unsigned int
              idleSleepTime);
-    void markForSleep();
+    void handleUpdateEvent();
     /*Overrides*/
     virtual bool        threadLoop();
     virtual int         readyToRun();
diff --git a/libqdutils/profiler.cpp b/libqdutils/profiler.cpp
index 031fdc3..997c839 100644
--- a/libqdutils/profiler.cpp
+++ b/libqdutils/profiler.cpp
@@ -28,6 +28,9 @@
  */
 
 #define LOG_NDDEBUG 0
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+
 #include "profiler.h"
 
 #ifdef DEBUG_CALC_FPS
@@ -104,7 +107,7 @@
     debug_fps_metadata.curr_frame = 0;
 
     ALOGD("period: %d", debug_fps_metadata.period);
-    ALOGD("ignorethresh_us: %lld", debug_fps_metadata.ignorethresh_us);
+    ALOGD("ignorethresh_us: %"PRId64, debug_fps_metadata.ignorethresh_us);
 }
 
 void CalcFps::print_fps(float fps)
@@ -124,7 +127,7 @@
         for (unsigned int i = 0;
              i < ((debug_fps_metadata.framearrival_steps / 6) + 1);
              i++) {
-            ALOGD("%lld %lld %lld %lld %lld %lld",
+            ALOGD("%"PRId64" %"PRId64" %"PRId64" %"PRId64" %"PRId64" %"PRId64,
                   debug_fps_metadata.accum_framearrivals[i*6],
                   debug_fps_metadata.accum_framearrivals[i*6+1],
                   debug_fps_metadata.accum_framearrivals[i*6+2],
diff --git a/libqdutils/qd_utils.cpp b/libqdutils/qd_utils.cpp
index 5a457d0..0698b33 100644
--- a/libqdutils/qd_utils.cpp
+++ b/libqdutils/qd_utils.cpp
@@ -31,7 +31,6 @@
 
 
 #define MAX_FRAME_BUFFER_NAME_SIZE      (80)
-#define MAX_DISPLAY_DEVICES             (3)
 
 int getHDMINode(void)
 {
@@ -40,7 +39,7 @@
     char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
     int j = 0;
 
-    for(j = 0; j < MAX_DISPLAY_DEVICES; j++) {
+    for(j = 0; j < HWC_NUM_DISPLAY_TYPES; j++) {
         snprintf (msmFbTypePath, sizeof(msmFbTypePath),
                   "/sys/class/graphics/fb%d/msm_fb_type", j);
         displayDeviceFP = fopen(msmFbTypePath, "r");
@@ -58,7 +57,7 @@
         }
     }
 
-    if (j < MAX_DISPLAY_DEVICES)
+    if (j < HWC_NUM_DISPLAY_TYPES)
         return j;
     else
         ALOGE("%s: Failed to find HDMI node", __func__);
diff --git a/libqdutils/qd_utils.h b/libqdutils/qd_utils.h
index cca55d5..db6d367 100644
--- a/libqdutils/qd_utils.h
+++ b/libqdutils/qd_utils.h
@@ -42,6 +42,7 @@
 #include <sys/poll.h>
 #include <sys/resource.h>
 #include <cutils/properties.h>
+#include <hardware/hwcomposer.h>
 
 #define EDID_RAW_DATA_SIZE 640