Merge "hwc: Reset layer-to-rotator map and fences on configuration failure"
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 6077ae8..bb9adbf 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -178,6 +178,8 @@
                 sourceCrop, mdpFlags, rotFlags);
         if(!ret) {
             ALOGE("%s: preRotate for external Failed!", __FUNCTION__);
+            ctx->mOverlay->clear(mDpy);
+            ctx->mLayerRotMap[mDpy]->clear();
             return false;
         }
         //For the mdp, since either we are pre-rotating or MDP does flips
@@ -192,6 +194,7 @@
         if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
                     NULL, mDest) < 0) {
             ALOGE("%s: configMdp failed for dpy %d", __FUNCTION__, mDpy);
+            ctx->mLayerRotMap[mDpy]->clear();
             ret = false;
         }
     }
@@ -365,6 +368,9 @@
             ALOGE("%s: commit fails for right", __FUNCTION__);
             ret = false;
         }
+        if(ret == false) {
+            ctx->mLayerRotMap[mDpy]->clear();
+        }
     }
     return ret;
 }
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index baa2146..6f2cb9c 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -1518,6 +1518,7 @@
         if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
             ALOGE("%s: configRotator failed!", __FUNCTION__);
             ctx->mOverlay->clear(dpy);
+            ctx->mLayerRotMap[dpy]->clear();
             return -1;
         }
         ctx->mLayerRotMap[dpy]->add(layer, *rot);
@@ -1535,6 +1536,7 @@
 
     if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) {
         ALOGE("%s: commit failed for low res panel", __FUNCTION__);
+        ctx->mLayerRotMap[dpy]->clear();
         return -1;
     }
     return 0;
@@ -1644,6 +1646,7 @@
         if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
             ALOGE("%s: configRotator failed!", __FUNCTION__);
             ctx->mOverlay->clear(dpy);
+            ctx->mLayerRotMap[dpy]->clear();
             return -1;
         }
         ctx->mLayerRotMap[dpy]->add(layer, *rot);
@@ -1709,6 +1712,7 @@
         if(configMdp(ctx->mOverlay, pargL, orient,
                 tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
             ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
+            ctx->mLayerRotMap[dpy]->clear();
             return -1;
         }
     }
@@ -1724,6 +1728,7 @@
         if(configMdp(ctx->mOverlay, pargR, orient,
                 tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
             ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
+            ctx->mLayerRotMap[dpy]->clear();
             return -1;
         }
     }
@@ -1948,6 +1953,21 @@
     mCount = 0;
 }
 
+void LayerRotMap::clear() {
+    for (uint32_t i = 0; i < mCount; i++) {
+        //mCount represents rotator objects for just this display.
+        //We could have popped mCount topmost objects from mRotMgr, but if each
+        //round has the same failure, typical of stability runs, it would lead
+        //to unnecessary memory allocation, deallocation each time. So we let
+        //the rotator objects be around, but just knock off the fences they
+        //hold. Ultimately the rotator objects will be GCed when not required.
+        //Also resetting fences is required if at least one rotation round has
+        //succeeded before. It'll be a NOP otherwise.
+        mRot[i]->resetReleaseFd();
+    }
+    reset();
+}
+
 void LayerRotMap::setReleaseFd(const int& fence) {
     for(uint32_t i = 0; i < mCount; i++) {
         mRot[i]->setReleaseFd(dup(fence));
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 29b38fc..2503e43 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -142,7 +142,11 @@
     LayerRotMap() { reset(); }
     enum { MAX_SESS = 3 };
     void add(hwc_layer_1_t* layer, overlay::Rotator *rot);
+    //Resets the mapping of layer to rotator
     void reset();
+    //Clears mappings and existing rotator fences
+    //Intended to be used during errors
+    void clear();
     uint32_t getCount() const;
     hwc_layer_1_t* getLayer(uint32_t index) const;
     overlay::Rotator* getRot(uint32_t index) const;
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
index 7b3dda1..4b6a8bc 100644
--- a/liboverlay/overlayRotator.cpp
+++ b/liboverlay/overlayRotator.cpp
@@ -107,6 +107,12 @@
     mRelFence[mCurrOffset] = fence;
 }
 
+void RotMem::Mem::resetReleaseFd() {
+    //Will wait for previous offline rotation to finish, close fence fd
+    //and reset
+    setReleaseFd(-1);
+}
+
 //============RotMgr=========================
 
 RotMgr::RotMgr() {
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index 7c1095f..6bb94a6 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -56,6 +56,7 @@
         bool close() { return m.close(); }
         uint32_t size() const { return m.bufSz(); }
         void setReleaseFd(const int& fence);
+        void resetReleaseFd();
         // Max rotator buffers
         enum { ROT_NUM_BUFS = 2 };
         // rotator data info dst offset
@@ -72,6 +73,7 @@
     Mem& prev() { return m[(_curr+1) % MAX_ROT_MEM]; }
     RotMem& operator++() { ++_curr; return *this; }
     void setReleaseFd(const int& fence) { curr().setReleaseFd(fence); }
+    void resetReleaseFd() { curr().resetReleaseFd(); }
     bool close();
     uint32_t _curr;
     Mem m[MAX_ROT_MEM];
@@ -96,6 +98,7 @@
     virtual void dump() const = 0;
     virtual void getDump(char *buf, size_t len) const = 0;
     void setReleaseFd(const int& fence) { mMem.setReleaseFd(fence); }
+    void resetReleaseFd() { mMem.resetReleaseFd(); }
     static Rotator *getRotator();
 
 protected: