hwc/overlay: validate and prepare frame

Send the entire frame (array of overlays) to driver, so that it would
check pipes params and the whole frame wrt bandwidth and SMP.

Now, the overlay's commit API just prepares an overlay object but
makes no ioctl calls.

If the driver finds the frame, as a whole, to be not ok, the
validation fails and overlay/hwc return silently.

If a certain overlay object is mis-configured or pipes are
unavailable, the driver sets the number of objects it processed.
Overlay uses this to dump the incorrect config.

Change-Id: Ifb2b7fadc6bd6d9d94a35ba3908fbd832f41447f
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 431757d..229a912 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -199,7 +199,7 @@
 
         if (fbComp) {
             const int fbZ = 0;
-            ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
+            ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
         }
 
         if (ctx->mMDP.version < qdutils::MDP_V4_0) {
@@ -225,7 +225,7 @@
             setListStats(ctx, list, dpy);
             if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
                 const int fbZ = 0;
-                ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
+                ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
             }
         } else {
             /* External Display is in Pause state.
diff --git a/libhwcomposer/hwc_ad.cpp b/libhwcomposer/hwc_ad.cpp
index 929ccc4..93aa204 100644
--- a/libhwcomposer/hwc_ad.cpp
+++ b/libhwcomposer/hwc_ad.cpp
@@ -249,6 +249,14 @@
             adWrite(on);
         }
     }
+
+    if(!ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK,
+            mWbFd)) {
+        ALOGE("%s: Failed to validate and set overlay for dpy %d"
+                ,__FUNCTION__, overlay::Overlay::DPY_WRITEBACK);
+        return false;
+    }
+
     return true;
 }
 
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 0123452..b81494d 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -60,6 +60,12 @@
     mRot = NULL;
 }
 
+bool IFBUpdate::prepareAndValidate(hwc_context_t *ctx,
+            hwc_display_contents_1 *list, int fbZorder) {
+    return prepare(ctx, list, fbZorder) &&
+            ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd);
+}
+
 //================= Low res====================================
 FBUpdateNonSplit::FBUpdateNonSplit(hwc_context_t *ctx, const int& dpy):
         IFBUpdate(ctx, dpy) {}
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index 4b449c8..da4cdfc 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -39,7 +39,9 @@
     virtual ~IFBUpdate() {};
     // Sets up members and prepares overlay if conditions are met
     virtual bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
-                                                       int fbZorder) = 0;
+            int fbZorder) = 0;
+    virtual bool prepareAndValidate(hwc_context_t *ctx,
+            hwc_display_contents_1 *list, int fbZorder);
     // Draws layer
     virtual bool draw(hwc_context_t *ctx, private_handle_t *hnd) = 0;
     //Reset values
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index dbd05ae..91bc233 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -1288,6 +1288,12 @@
         }
     }
 
+    if(!ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd)) {
+        ALOGD_IF(isDebug(), "%s: Failed to validate and set overlay for dpy %d"
+                ,__FUNCTION__, mDpy);
+        return false;
+    }
+
     setRedraw(ctx, list);
     return true;
 }
diff --git a/liboverlay/mdpWrapper.h b/liboverlay/mdpWrapper.h
index d96317c..1bfa058 100644
--- a/liboverlay/mdpWrapper.h
+++ b/liboverlay/mdpWrapper.h
@@ -42,6 +42,8 @@
 #include <errno.h>
 #include "overlayUtils.h"
 
+#define IOCTL_DEBUG 0
+
 namespace overlay{
 
 namespace mdp_wrapper{
@@ -63,6 +65,9 @@
 /* MSMFB_OVERLAY_SET */
 bool setOverlay(int fd, mdp_overlay& ov);
 
+/* MSMFB_OVERLAY_PREPARE */
+bool validateAndSet(const int& fd, mdp_overlay_list& list);
+
 /* MSM_ROTATOR_IOCTL_FINISH */
 bool endRotator(int fd, int sessionId);
 
@@ -167,6 +172,15 @@
     return true;
 }
 
+inline bool validateAndSet(const int& fd, mdp_overlay_list& list) {
+    if (ioctl(fd, MSMFB_OVERLAY_PREPARE, &list) < 0) {
+        ALOGD_IF(IOCTL_DEBUG, "Failed to call ioctl MSMFB_OVERLAY_PREPARE "
+                "err=%s", strerror(errno));
+        return false;
+    }
+    return true;
+}
+
 inline bool endRotator(int fd, uint32_t sessionId) {
     if (ioctl(fd, MSM_ROTATOR_IOCTL_FINISH, &sessionId) < 0) {
         ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_FINISH err=%s",
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index ad23e84..6feffc4 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -69,13 +69,6 @@
         PipeBook::resetAllocation(i);
     }
     mDumpStr[0] = '\0';
-
-#ifdef USES_QSEED_SCALAR
-    Scale *scalar = getScalar();
-    if(scalar) {
-        scalar->configBegin();
-    }
-#endif
 }
 
 void Overlay::configDone() {
@@ -98,13 +91,6 @@
     }
     dump();
     PipeBook::save();
-
-#ifdef USES_QSEED_SCALAR
-    Scale *scalar = getScalar();
-    if(scalar) {
-        scalar->configDone();
-    }
-#endif
 }
 
 int Overlay::getPipeId(utils::eDest dest) {
@@ -435,6 +421,22 @@
     }
 }
 
+bool Overlay::validateAndSet(const int& dpy, const int& fbFd) {
+    GenericPipe* pipeArray[PipeBook::NUM_PIPES];
+    memset(&pipeArray, 0, sizeof(pipeArray));
+
+    int num = 0;
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        if(PipeBook::isUsed(i) && mPipeBook[i].valid() &&
+                mPipeBook[i].mDisplay == dpy) {
+            pipeArray[num++] = mPipeBook[i].mPipe;
+        }
+    }
+
+    //Protect against misbehaving clients
+    return num ? GenericPipe::validateAndSet(pipeArray, num, fbFd) : true;
+}
+
 void Overlay::initScalar() {
 #ifdef USES_QSEED_SCALAR
     if(sLibScaleHandle == NULL) {
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index fe855c1..d8615cd 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -120,6 +120,8 @@
     void getDump(char *buf, size_t len);
     /* Reset usage and allocation bits on all pipes for given display */
     void clear(int dpy);
+    /* Validate the set of pipes for a display and set them in driver */
+    bool validateAndSet(const int& dpy, const int& fbFd);
 
     /* Closes open pipes, called during startup */
     static int initOverlay();
@@ -131,8 +133,6 @@
     static int getFbForDpy(const int& dpy);
     static bool displayCommit(const int& fd, const utils::Dim& roi);
     static bool displayCommit(const int& fd);
-    /* Returns the scalar object */
-    static scale::Scale *getScalar();
 
 private:
     /* Ctor setup */
@@ -141,6 +141,8 @@
     void validate(int index);
     static void setDMAMultiplexingSupported();
     void dump() const;
+    /* Returns the scalar object */
+    static scale::Scale *getScalar();
     /* Creates a scalar object using libscale.so */
     static void initScalar();
     /* Destroys the scalar object using libscale.so */
@@ -212,6 +214,8 @@
     static bool sDMAMultiplexingSupported;
     static void *sLibScaleHandle;
     static scale::Scale *sScale;
+
+    friend class MdpCtrl;
 };
 
 inline void Overlay::validate(int index) {
diff --git a/liboverlay/overlayCtrlData.h b/liboverlay/overlayCtrlData.h
index dbf328a..26202ec 100644
--- a/liboverlay/overlayCtrlData.h
+++ b/liboverlay/overlayCtrlData.h
@@ -84,6 +84,8 @@
     /* Return the dump in the specified buffer */
     void getDump(char *buf, size_t len);
 
+    static bool validateAndSet(Ctrl* ctrlArray[], const int& count,
+            const int& fbFd);
 private:
     // mdp ctrl struct(info e.g.)
     MdpCtrl *mMdp;
@@ -181,6 +183,19 @@
     mMdp->updateSrcFormat(rotDstFmt);
 }
 
+inline bool Ctrl::validateAndSet(Ctrl* ctrlArray[], const int& count,
+        const int& fbFd) {
+    MdpCtrl* mdpCtrlArray[count];
+    memset(&mdpCtrlArray, 0, sizeof(mdpCtrlArray));
+
+    for(int i = 0; i < count; i++) {
+        mdpCtrlArray[i] = ctrlArray[i]->mMdp;
+    }
+
+    bool ret = MdpCtrl::validateAndSet(mdpCtrlArray, count, fbFd);
+    return ret;
+}
+
 inline utils::Dim Ctrl::getCrop() const {
     return mMdp->getSrcRectDim();
 }
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 3ec0405..a25dc5e 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -206,35 +206,6 @@
     }
 
     doDownscale();
-
-    if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) {
-        ALOGE("MdpCtrl failed to setOverlay");
-        mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo);
-#ifdef USES_QSEED_SCALAR
-        if(Overlay::getScalar()) {
-            Overlay::getScalar()->configAbort(mDpy);
-        }
-#endif
-        return false;
-    }
-
-#ifdef USES_QSEED_SCALAR
-    if(Overlay::getScalar()) {
-        Overlay::getScalar()->configSet(mOVInfo, mDpy, mFd.getFD());
-    }
-#endif
-
-    return true;
-}
-
-bool MdpCtrl::get() {
-    mdp_overlay ov;
-    ov.id = mOVInfo.id;
-    if (!mdp_wrapper::getOverlay(mFd.getFD(), ov)) {
-        ALOGE("MdpCtrl get failed");
-        return false;
-    }
-    mOVInfo = ov;
     return true;
 }
 
@@ -389,6 +360,38 @@
     return true;
 }
 
+bool MdpCtrl::validateAndSet(MdpCtrl* mdpCtrlArray[], const int& count,
+        const int& fbFd) {
+    mdp_overlay* ovArray[count];
+    memset(&ovArray, 0, sizeof(ovArray));
+
+    for(int i = 0; i < count; i++) {
+        ovArray[i] = &mdpCtrlArray[i]->mOVInfo;
+    }
+
+    struct mdp_overlay_list list;
+    memset(&list, 0, sizeof(struct mdp_overlay_list));
+    list.num_overlays = count;
+    list.overlay_list = ovArray;
+
+#ifdef USES_QSEED_SCALAR
+    Scale *scalar = Overlay::getScalar();
+    if(scalar) {
+        scalar->applyScale(&list);
+    }
+#endif
+
+    if(!mdp_wrapper::validateAndSet(fbFd, list)) {
+        if(list.processed_overlays < list.num_overlays) {
+            mdp_wrapper::dump("Bad ov dump: ",
+                *list.overlay_list[list.processed_overlays]);
+        }
+        return false;
+    }
+
+    return true;
+}
+
 
 //// MdpData ////////////
 bool MdpData::init(const int& dpy) {
diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h
index daaeaf2..843556b 100644
--- a/liboverlay/overlayMdp.h
+++ b/liboverlay/overlayMdp.h
@@ -72,7 +72,6 @@
     void dump() const;
     /* Return the dump in the specified buffer */
     void getDump(char *buf, size_t len);
-
     /* returns session id */
     int getPipeId() const;
     /* returns the fd associated to ctrl*/
@@ -84,14 +83,14 @@
     /* setVisualParam */
     bool setVisualParams(const MetaData_t& data);
 
+    static bool validateAndSet(MdpCtrl* mdpCtrlArray[], const int& count,
+            const int& fbFd);
 private:
     /* Perform transformation calculations */
     void doTransform();
     void doDownscale();
     /* get orient / user_data[0] */
-        int getOrient() const;
-    /* overlay get */
-    bool get();
+    int getOrient() const;
     /* returns flags from mdp structure */
     int getFlags() const;
     /* set flags to mdp structure */
diff --git a/liboverlay/pipes/overlayGenPipe.cpp b/liboverlay/pipes/overlayGenPipe.cpp
index 394a56e..9e57223 100644
--- a/liboverlay/pipes/overlayGenPipe.cpp
+++ b/liboverlay/pipes/overlayGenPipe.cpp
@@ -137,4 +137,16 @@
     return mCtrl->getPipeId();
 }
 
+bool GenericPipe::validateAndSet(GenericPipe* pipeArray[], const int& count,
+        const int& fbFd) {
+    Ctrl* ctrlArray[count];
+    memset(&ctrlArray, 0, sizeof(ctrlArray));
+
+    for(int i = 0; i < count; i++) {
+        ctrlArray[i] = pipeArray[i]->mCtrl;
+    }
+
+    return Ctrl::validateAndSet(ctrlArray, count, fbFd);
+}
+
 } //namespace overlay
diff --git a/liboverlay/pipes/overlayGenPipe.h b/liboverlay/pipes/overlayGenPipe.h
index 57e1758..813a2b3 100644
--- a/liboverlay/pipes/overlayGenPipe.h
+++ b/liboverlay/pipes/overlayGenPipe.h
@@ -75,6 +75,8 @@
     void getDump(char *buf, size_t len);
     int getPipeId();
 
+    static bool validateAndSet(GenericPipe* pipeArray[], const int& count,
+            const int& fbFd);
 private:
     /* set Closed pipe */
     bool setClosed();