Merge "hwc: Set min panel refresh rate during idle timeout"
diff --git a/common.mk b/common.mk
index a2283c4..cdac0fa 100644
--- a/common.mk
+++ b/common.mk
@@ -7,11 +7,6 @@
 common_includes += $(LOCAL_PATH)/../libhdmi
 common_includes += $(LOCAL_PATH)/../libqservice
 
-ifeq ($(TARGET_USES_POST_PROCESSING),true)
-    common_flags     += -DUSES_POST_PROCESSING
-    common_includes  += $(TARGET_OUT_HEADERS)/pp/inc
-endif
-
 common_header_export_path := qcom/display
 
 #Common libraries external to display HAL
@@ -21,6 +16,11 @@
 common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
 common_flags += -Wconversion -Wall -Werror
 
+ifeq ($(TARGET_USES_POST_PROCESSING),true)
+    common_flags     += -DUSES_POST_PROCESSING
+    common_includes  += $(TARGET_OUT_HEADERS)/pp/inc
+endif
+
 ifeq ($(ARCH_ARM_HAVE_NEON),true)
     common_flags += -D__ARM_HAVE_NEON
 endif
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 9e2a6cf..17e7722 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -70,20 +70,17 @@
     GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY  =       0x00800000,
 };
 
-enum {
-    /* Gralloc perform enums
-    */
-    GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER = 1,
-    // This will be deprecated from latest graphics drivers. This is kept
-    // for those backward compatibility i.e., newer Display HAL + older graphics
-    // libraries
-    GRALLOC_MODULE_PERFORM_GET_STRIDE,
-    GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE,
-    GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE,
-    GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES,
-    GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE,
-    GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO,
-};
+/* define Gralloc perform */
+#define GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER 1
+// This will be used by the graphics drivers to know if certain features
+// are defined in this display HAL.
+// Ex: Newer GFX libraries + Older Display HAL
+#define GRALLOC_MODULE_PERFORM_GET_STRIDE 2
+#define GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE 3
+#define GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE 4
+#define GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES 5
+#define GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE 6
+#define GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO 7
 
 #define GRALLOC_HEAP_MASK   (GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |\
                              GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP    |\
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index c96eb1e..2bf421f 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -257,7 +257,8 @@
     bool fbComp = false;
     if (LIKELY(list && list->numHwLayers > 1) &&
             (ctx->dpyAttr[dpy].isActive ||
-             ctx->mHDMIDisplay->isHDMIPrimaryDisplay())) {
+             ctx->mHDMIDisplay->isHDMIPrimaryDisplay())
+            && !ctx->dpyAttr[dpy].isPause) {
 
         // When HDMI is primary we should rely on the first valid
         // draw call in order to activate the display
@@ -475,10 +476,11 @@
                 return -errno;
             }
 
-            if(mode == HWC_POWER_MODE_NORMAL) {
+            if(mode == HWC_POWER_MODE_NORMAL && !ctx->mHPDEnabled) {
                 // Enable HPD here, as during bootup POWER_MODE_NORMAL is set
                 // when SF is completely initialized
                 ctx->mHDMIDisplay->setHPD(1);
+                ctx->mHPDEnabled = true;
             }
 
             ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
@@ -585,7 +587,8 @@
     ATRACE_CALL();
     int ret = 0;
     const int dpy = HWC_DISPLAY_PRIMARY;
-    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive) {
+    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive
+            && !ctx->dpyAttr[dpy].isPause) {
         size_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/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 79a4249..e32ebbb 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -754,11 +754,11 @@
         return false;
     }
 
-    // No Idle fall back, if secure display or secure RGB layers are present or
-    // if there's only a single layer being composed
-    if(sIdleFallBack && (!ctx->listStats[mDpy].secureUI &&
-                    !ctx->listStats[mDpy].secureRGBCount) &&
-                    (ctx->listStats[mDpy].numAppLayers != 1)) {
+    /* No Idle fall back if secure display or secure RGB layers are present
+     * or if there is only a single layer being composed */
+    if(sIdleFallBack && !ctx->listStats[mDpy].secureUI &&
+                  !ctx->listStats[mDpy].secureRGBCount &&
+                  (ctx->listStats[mDpy].numAppLayers > 1)) {
         ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
         return false;
     }
@@ -1285,7 +1285,22 @@
         hwc_display_contents_1_t* list, bool secureOnly) {
     if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
         return false;
+
     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    if(!isSecurePresent(ctx, mDpy)) {
+       /* Bail out if we are processing only secured video layers
+        * and we dont have any */
+       if(secureOnly) {
+           ALOGD_IF(isDebug(),"%s: No Secure Video Layers", __FUNCTION__);
+           return false;
+       }
+       /* No Idle fall back for secure video layers and if there is only
+        * single layer being composed. */
+       if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
+           ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
+           return false;
+        }
+    }
 
     mCurrentFrame.reset(numAppLayers);
     mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
@@ -1297,13 +1312,6 @@
         return false;
     }
 
-    /* Bail out if we are processing only secured video layers
-     * and we dont have any */
-    if(!isSecurePresent(ctx, mDpy) && secureOnly){
-        reset(ctx);
-        return false;
-    }
-
     if(mCurrentFrame.fbCount)
         mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
 
@@ -1344,14 +1352,22 @@
     if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
         return false;
 
-    /* Bail out if we are processing only secured video layers
-     * and we dont have any */
-    if(!isSecurePresent(ctx, mDpy) && secureOnly){
-        reset(ctx);
-        return false;
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    if(!isSecurePresent(ctx, mDpy) && !ctx->listStats[mDpy].secureUI) {
+        /* Bail out if we are processing only secured video/ui layers
+         * and we dont have any */
+        if(secureOnly) {
+            ALOGD_IF(isDebug(), "%s: No secure video/ui layers");
+            return false;
+        }
+        /* No Idle fall back for secure video/ui layers and if there is only
+         * single layer being composed. */
+        if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
+           ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
+           return false;
+       }
     }
 
-    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
     mCurrentFrame.reset(numAppLayers);
     mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
 
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index add5dc8..1a29b89 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -313,6 +313,23 @@
     return NO_ERROR;
 }
 
+static void toggleScreenUpdate(hwc_context_t* ctx, uint32_t on) {
+    ALOGD("%s: toggle update: %d", __FUNCTION__, on);
+    Locker::Autolock _sl(ctx->mDrawLock);
+    if (on == 0) {
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isPause = true;
+        ctx->mOverlay->configBegin();
+        ctx->mOverlay->configDone();
+        ctx->mRotMgr->clear();
+        if(!Overlay::displayCommit(ctx->dpyAttr[0].fd)) {
+            ALOGE("%s: Display commit failed", __FUNCTION__);
+        }
+    } else {
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isPause = false;
+        ctx->proc->invalidate(ctx->proc);
+    }
+}
+
 status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
         Parcel* outParcel) {
     status_t ret = NO_ERROR;
@@ -369,6 +386,9 @@
         case IQService::CONFIGURE_DYN_REFRESH_RATE:
             configureDynRefreshRate(mHwcContext, inParcel);
             break;
+        case IQService::TOGGLE_SCREEN_UPDATE:
+            toggleScreenUpdate(mHwcContext, inParcel->readInt32());
+            break;
         default:
             ret = NO_ERROR;
     }
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index ace0017..bcac4be 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -413,6 +413,7 @@
     }
 
     memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
+    ctx->mHPDEnabled = false;
     ALOGI("Initializing Qualcomm Hardware Composer");
     ALOGI("MDP version: %d", ctx->mMDP.version);
 }
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 11aa86d..18de082 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -96,7 +96,7 @@
     //It should be active also. (UNBLANKED)
     bool isActive;
     // In pause state, composition is bypassed
-    // used for WFD displays only
+    // used for WFD displays and in QDCM calibration mode
     bool isPause;
     // To trigger padding round to clean up mdp
     // pipes
@@ -639,6 +639,8 @@
     bool mBWCEnabled;
     // Provides a way for OEM's to disable setting dynfps via metadata.
     bool mUseMetaDataRefreshRate;
+   // Stores the hpd enabled status- avoids re-enabling HDP on suspend resume.
+    bool mHPDEnabled;
 };
 
 namespace qhwc {
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index e9c0a13..c250919 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -47,6 +47,9 @@
 
     initScalar();
     setDMAMultiplexingSupported();
+#ifdef USES_POST_PROCESSING
+    initPostProc();
+#endif
 }
 
 Overlay::~Overlay() {
@@ -54,6 +57,9 @@
         mPipeBook[i].destroy();
     }
     destroyScalar();
+#ifdef USES_POST_PROCESSING
+    destroyPostProc();
+#endif
 }
 
 void Overlay::configBegin() {
@@ -526,6 +532,23 @@
     }
 }
 
+void Overlay::initPostProc() {
+    sLibAblHandle = dlopen("libmm-abl.so", RTLD_NOW);
+    if (sLibAblHandle) {
+        *(void **)&sFnppParams = dlsym(sLibAblHandle,
+                                       "display_pp_compute_params");
+    } else {
+        ALOGE("%s: Not able to load libmm-abl.so", __FUNCTION__);
+    }
+}
+
+void Overlay::destroyPostProc() {
+    if (sLibAblHandle) {
+        dlclose(sLibAblHandle);
+        sLibAblHandle = NULL;
+    }
+}
+
 void Overlay::PipeBook::init() {
     mPipe = NULL;
     mDisplay = DPY_UNUSED;
@@ -557,5 +580,9 @@
     {utils::OV_MDP_PIPE_ANY};
 void *Overlay::sLibScaleHandle = NULL;
 int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
+/* Dynamically link ABL library */
+void *Overlay::sLibAblHandle = NULL;
+int (*Overlay::sFnppParams)(const struct compute_params *,
+                            struct mdp_overlay_pp_params *) = NULL;
 
 }; // namespace overlay
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 665e23f..984b439 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -33,6 +33,9 @@
 #include "overlayUtils.h"
 #include "mdp_version.h"
 #include "utils/threads.h"
+#ifdef USES_POST_PROCESSING
+#include "lib-postproc.h"
+#endif
 
 struct MetaData_t;
 
@@ -186,6 +189,12 @@
     /* Sets the pipe type RGB/VG/DMA*/
     void setPipeType(utils::eDest pipeIndex, const utils::eMdpPipeType pType);
 
+    /* Dynamically link ABL library */
+    static void initPostProc();
+    static void destroyPostProc();
+    static int (*getFnPpParams())(const struct compute_params *,
+                                 struct mdp_overlay_pp_params *);
+
     /* Just like a Facebook for pipes, but much less profile info */
     struct PipeBook {
         void init();
@@ -251,6 +260,10 @@
     static bool sDMAMultiplexingSupported;
     static void *sLibScaleHandle;
     static int (*sFnProgramScale)(struct mdp_overlay_list *);
+    /* Dynamically link ABL library */
+    static void *sLibAblHandle;
+    static int (*sFnppParams)(const struct compute_params *,
+                            struct mdp_overlay_pp_params *);
     static bool sDebugPipeLifecycle;
 
     friend class MdpCtrl;
@@ -345,6 +358,11 @@
     return sFnProgramScale;
 }
 
+inline int (*Overlay::getFnPpParams())(const struct compute_params *,
+                    struct mdp_overlay_pp_params *) {
+    return sFnppParams;
+}
+
 inline void Overlay::debugPipeLifecycle(const bool& enable) {
     sDebugPipeLifecycle = enable;
 }
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 4cd52a7..3932c4c 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -21,6 +21,7 @@
 #include "overlayMdp.h"
 #include "mdp_version.h"
 #include <overlay.h>
+#include <dlfcn.h>
 
 #define HSIC_SETTINGS_DEBUG 0
 
@@ -263,7 +264,7 @@
         }
 
         if (needUpdate) {
-            mParams.params.pa_params.hue = data.hsicData.hue;
+            mParams.params.pa_params.hue = (float)data.hsicData.hue;
             mParams.params.pa_params.sat = data.hsicData.saturation;
             mParams.params.pa_params.intensity = data.hsicData.intensity;
             mParams.params.pa_params.contrast = data.hsicData.contrast;
@@ -333,7 +334,15 @@
     }
 
     if (needUpdate) {
-        display_pp_compute_params(&mParams, &mOVInfo.overlay_pp_cfg);
+        int (*sFnppParams)(const struct compute_params *,
+                           struct mdp_overlay_pp_params *) =
+                           Overlay::getFnPpParams();
+        if(sFnppParams) {
+           int ret = sFnppParams(&mParams, &mOVInfo.overlay_pp_cfg);
+           if (ret) {
+             ALOGE("%s: Unable to set PP params", __FUNCTION__);
+           }
+        }
     }
 #endif
     return true;
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index a935131..ef47475 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -55,9 +55,10 @@
         DYNAMIC_DEBUG = 15,     // Enable more logging on the fly
         SET_IDLE_TIMEOUT = 16,  // Set idle timeout for GPU fallback
         TOGGLE_BWC = 17,           // Toggle BWC On/Off on targets that support
-        SET_PARTIAL_UPDATE = 18,   // Preference on partial update feature
         /* Enable/Disable/Set refresh rate dynamically */
-        CONFIGURE_DYN_REFRESH_RATE = 19,
+        CONFIGURE_DYN_REFRESH_RATE = 18,
+        SET_PARTIAL_UPDATE = 19,   // Preference on partial update feature
+        TOGGLE_SCREEN_UPDATE = 20, // Provides ability to disable screen updates
         COMMAND_LIST_END = 400,
     };
 
diff --git a/libqservice/QServiceUtils.h b/libqservice/QServiceUtils.h
index 5b61c8e..71277e8 100644
--- a/libqservice/QServiceUtils.h
+++ b/libqservice/QServiceUtils.h
@@ -74,6 +74,10 @@
     return sendSingleParam(qService::IQService::SCREEN_REFRESH, 1);
 }
 
+inline android::status_t toggleScreenUpdate(uint32_t on) {
+    return sendSingleParam(qService::IQService::TOGGLE_SCREEN_UPDATE, on);
+}
+
 inline android::status_t setPartialUpdate(uint32_t enable) {
     return sendSingleParam(qService::IQService::SET_PARTIAL_UPDATE, enable);
 }