Merge "h/q/d: Add binder-api support to change refresh-rate."
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index b77b997..975c195 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -1975,7 +1975,8 @@
 
 #ifdef DYNAMIC_FPS
     //For primary display, set the dynamic refreshrate
-    if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported()) {
+    if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
+                                        ctx->mUseMetaDataRefreshRate) {
         FrameInfo frame;
         frame.reset(mCurrentFrame.layerCount);
         memset(&frame.drop, 0, sizeof(frame.drop));
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index 398995a..b0ebb3a 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -34,6 +34,7 @@
 #include <hwc_mdpcomp.h>
 #include <hwc_virtual.h>
 #include <overlay.h>
+#include <display_config.h>
 
 #define QCLIENT_DEBUG 0
 
@@ -175,13 +176,13 @@
                                         dpy, getExternalDisplayState(status));
 
     if(dpy > HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
-        if(dpy == HWC_DISPLAY_VIRTUAL && status == EXTERNAL_OFFLINE) {
+        if(dpy == HWC_DISPLAY_VIRTUAL && status == qdutils::EXTERNAL_OFFLINE) {
             ctx->mWfdSyncLock.lock();
             ctx->mWfdSyncLock.signal();
             ctx->mWfdSyncLock.unlock();
-        } else if(status == EXTERNAL_PAUSE) {
+        } else if(status == qdutils::EXTERNAL_PAUSE) {
             handle_pause(ctx, dpy);
-        } else if(status == EXTERNAL_RESUME) {
+        } else if(status == qdutils::EXTERNAL_RESUME) {
             handle_resume(ctx, dpy);
         }
     } else {
@@ -263,6 +264,48 @@
     }
 }
 
+static void configureDynRefreshRate(hwc_context_t* ctx,
+                                    const Parcel* inParcel) {
+    uint32_t op = (uint32_t)inParcel->readInt32();
+    uint32_t refresh_rate = (uint32_t)inParcel->readInt32();
+    MDPVersion& mdpHw = MDPVersion::getInstance();
+    uint32_t dpy = HWC_DISPLAY_PRIMARY;
+
+    if(mdpHw.isDynFpsSupported()) {
+        Locker::Autolock _sl(ctx->mDrawLock);
+
+        switch (op) {
+        case DISABLE_METADATA_DYN_REFRESH_RATE:
+            ctx->mUseMetaDataRefreshRate = false;
+            setRefreshRate(ctx, dpy, ctx->dpyAttr[dpy].refreshRate);
+            break;
+        case ENABLE_METADATA_DYN_REFRESH_RATE:
+            ctx->mUseMetaDataRefreshRate = true;
+            setRefreshRate(ctx, dpy, ctx->dpyAttr[dpy].refreshRate);
+            break;
+        case SET_BINDER_DYN_REFRESH_RATE:
+            if(ctx->mUseMetaDataRefreshRate)
+                ALOGW("%s: Ignoring binder request to change refresh-rate",
+                      __FUNCTION__);
+            else {
+                uint32_t rate = roundOff(refresh_rate);
+                if((rate >= mdpHw.getMinFpsSupported() &&
+                    rate <= mdpHw.getMaxFpsSupported())) {
+                    setRefreshRate(ctx, dpy, rate);
+                } else {
+                    ALOGE("%s: Requested refresh-rate should be between \
+                          (%d) and (%d). Given (%d)", __FUNCTION__,
+                          mdpHw.getMinFpsSupported(),
+                          mdpHw.getMaxFpsSupported(), rate);
+                }
+            }
+            break;
+        default:
+            ALOGE("%s: Invalid op %d",__FUNCTION__,op);
+        }
+    }
+}
+
 status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
         Parcel* outParcel) {
     status_t ret = NO_ERROR;
@@ -314,6 +357,9 @@
         case IQService::TOGGLE_BWC:
             toggleBWC(mHwcContext, inParcel);
             break;
+        case IQService::CONFIGURE_DYN_REFRESH_RATE:
+            configureDynRefreshRate(mHwcContext, inParcel);
+            break;
         default:
             ret = NO_ERROR;
     }
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 9d53bda..ace0017 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -406,6 +406,12 @@
         ctx->mWindowboxFeature = true;
     }
 
+    ctx->mUseMetaDataRefreshRate = true;
+    if(property_get("persist.metadata_dynfps.disable", value, "false")
+            && !strcmp(value, "true")) {
+        ctx->mUseMetaDataRefreshRate = false;
+    }
+
     memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
     ALOGI("Initializing Qualcomm Hardware Composer");
     ALOGI("MDP version: %d", ctx->mMDP.version);
@@ -465,7 +471,7 @@
 }
 
 //Helper to roundoff the refreshrates
-static uint32_t roundOff(uint32_t refreshRate) {
+uint32_t roundOff(uint32_t refreshRate) {
     int count =  (int) (sizeof(stdRefreshRates)/sizeof(stdRefreshRates[0]));
     uint32_t rate = refreshRate;
     for(int i=0; i< count; i++) {
@@ -1057,7 +1063,7 @@
             ctx->listStats[dpy].preMultipliedAlpha = true;
 
 #ifdef DYNAMIC_FPS
-        if (dpy == HWC_DISPLAY_PRIMARY && mdpHw.isDynFpsSupported()) {
+        if (!dpy && mdpHw.isDynFpsSupported() && ctx->mUseMetaDataRefreshRate){
             //dyn fps: get refreshrate from metadata
             //Support multiple refresh rates if they are same
             //else set to  default
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index f629574..286ae22 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -326,6 +326,8 @@
 void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
                                 hwc_rect_t& inRect, hwc_rect_t& outRect);
 
+uint32_t roundOff(uint32_t refreshRate);
+
 void setRefreshRate(hwc_context_t *ctx, int dpy, uint32_t refreshRate);
 
 bool isPrimaryPortrait(hwc_context_t *ctx);
@@ -640,6 +642,8 @@
     float mAspectRatioToleranceLevel;
     // Runtime switch for BWC for targets that support it
     bool mBWCEnabled;
+    // Provides a way for OEM's to disable setting dynfps via metadata.
+    bool mUseMetaDataRefreshRate;
 };
 
 namespace qhwc {
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 4fdf19e..03a7046 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -152,6 +152,24 @@
     return err;
 }
 
+int configureDynRefreshRate(uint32_t op, uint32_t refreshRate) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(op);
+    inParcel.writeInt32(refreshRate);
+
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::CONFIGURE_DYN_REFRESH_RATE,
+                               &inParcel, &outParcel);
+    }
+
+    if(err)
+        ALOGE("%s: Failed setting op %d err=%d", __FUNCTION__, op, err);
+
+    return err;
+}
+
 }; //namespace
 
 // ----------------------------------------------------------------------------
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index 9b6ab56..8bafe91 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -39,6 +39,12 @@
 
 namespace qdutils {
 
+
+/* TODO: Have all the common enums that need be exposed to clients and which
+ * are also needed in hwc defined here. Remove such definitions we have in
+ * hwc_utils.h
+ */
+
 // Use this enum to specify the dpy parameters where needed
 enum {
     DISPLAY_PRIMARY = 0,
@@ -55,6 +61,12 @@
     EXTERNAL_RESUME,
 };
 
+enum {
+    DISABLE_METADATA_DYN_REFRESH_RATE = 0,
+    ENABLE_METADATA_DYN_REFRESH_RATE,
+    SET_BINDER_DYN_REFRESH_RATE,
+};
+
 // Display Attributes that are available to clients of this library
 // Not to be confused with a similar struct in hwc_utils (in the hwc namespace)
 struct DisplayAttributes_t {
@@ -89,4 +101,7 @@
 
 // Set the secondary display status(pause/resume/offline etc.,)
 int setSecondaryDisplayStatus(int dpy, uint32_t status);
+
+// Enable/Disable/Set refresh rate dynamically
+int configureDynRefreshRate(uint32_t op, uint32_t refreshRate);
 }; //namespace
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index ea40334..683c93c 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -55,6 +55,8 @@
         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
+        /* Enable/Disable/Set refresh rate dynamically */
+        CONFIGURE_DYN_REFRESH_RATE = 18,
         COMMAND_LIST_END = 400,
     };