Merge "hwc: Handle validateAndSet failures in AD prepare call"
diff --git a/libhwcomposer/hwc_ad.cpp b/libhwcomposer/hwc_ad.cpp
index fdf6e67..49e7e2a 100644
--- a/libhwcomposer/hwc_ad.cpp
+++ b/libhwcomposer/hwc_ad.cpp
@@ -41,37 +41,6 @@
 using namespace overlay::utils;
 namespace qhwc {
 
-//Opens writeback framebuffer and returns fd.
-static int openWbFb() {
-    int wbFd = -1;
-    //Check opening which FB would connect LM to WB
-    const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
-    if(wbFbNum >= 0) {
-        char wbFbPath[256];
-        snprintf (wbFbPath, sizeof(wbFbPath),
-                "/sys/class/graphics/fb%d", wbFbNum);
-        //Opening writeback fb first time would create ad node if the device
-        //supports adaptive display
-        wbFd = open(wbFbPath, O_RDONLY);
-        if(wbFd < 0) {
-            ALOGE("%s: Failed to open /sys/class/graphics/fb%d with error %s",
-                    __func__, wbFbNum, strerror(errno));
-        }
-    } else {
-        ALOGD_IF(DEBUG, "%s: No writeback available", __func__);
-    }
-    return wbFd;
-}
-
-static inline void closeWbFb(int& fd) {
-    if(fd >= 0) {
-        close(fd);
-        fd = -1;
-    } else {
-        ALOGE("%s: Invalid fd %d", __func__, fd);
-    }
-}
-
 //Helper to write data to ad node
 static void adWrite(const int& value) {
     const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
@@ -124,32 +93,31 @@
     return ret;
 }
 
-AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) : mWbFd(-1),
-        mDoable(false), mFeatureEnabled(false),
-        mDest(overlay::utils::OV_INVALID) {
-    int fd = openWbFb();
-    if(fd >= 0) {
-        //Values in ad node:
-        //-1 means feature is disabled on device
-        // 0 means feature exists but turned off, will be turned on by hwc
-        // 1 means feature is turned on by hwc
-        // Plus, we do this feature only on split primary displays.
-        // Plus, we do this feature only if ro.qcom.ad=2
+AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) :
+     mTurnedOff(true), mFeatureEnabled(false),
+     mDest(overlay::utils::OV_INVALID)
+{
+    //Values in ad node:
+    //-1 means feature is disabled on device
+    // 0 means feature exists but turned off, will be turned on by hwc
+    // 1 means feature is turned on by hwc
+    // Plus, we do this feature only on split primary displays.
+    // Plus, we do this feature only if ro.qcom.ad=2
 
-        char property[PROPERTY_VALUE_MAX];
-        const int ENABLED = 2;
-        int val = 0;
+    char property[PROPERTY_VALUE_MAX];
+    const int ENABLED = 2;
+    int val = 0;
 
-        if(property_get("ro.qcom.ad", property, "0") > 0) {
-            val = atoi(property);
-        }
+    if(property_get("ro.qcom.ad", property, "0") > 0) {
+        val = atoi(property);
+    }
 
-        if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
-                val == ENABLED) {
-            ALOGD_IF(DEBUG, "Assertive display feature supported");
-            mFeatureEnabled = true;
-        }
-        closeWbFb(fd);
+    if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
+            val == ENABLED) {
+        ALOGD_IF(DEBUG, "Assertive display feature supported");
+        mFeatureEnabled = true;
+        // If feature exists but is turned off, set mTurnedOff to true
+        mTurnedOff = adRead() > 0 ? false : true;
     }
 }
 
@@ -168,17 +136,24 @@
     }
 }
 
+void AssertiveDisplay::turnOffAD() {
+    if(mFeatureEnabled) {
+        if(!mTurnedOff) {
+            const int off = 0;
+            adWrite(off);
+            mTurnedOff = true;
+        }
+    }
+    mDoable = false;
+}
+
 bool AssertiveDisplay::prepare(hwc_context_t *ctx,
         const hwc_rect_t& crop,
         const Whf& whf,
         const private_handle_t *hnd) {
     if(!isDoable()) {
-        if(isModeOn()) {
-            //Cleanup one time during this switch
-            const int off = 0;
-            adWrite(off);
-            closeWbFb(mWbFd);
-        }
+        //Cleanup one time during this switch
+        turnOffAD();
         return false;
     }
 
@@ -246,27 +221,30 @@
     }
 
     mDest = dest;
-    if(!isModeOn()) {
-        mWbFd = openWbFb();
-        if(mWbFd >= 0) {
-            //write to sysfs, one time during this switch
-            const int on = 1;
-            adWrite(on);
-        }
-    }
-
-    if(!ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK,
-            mWbFd)) {
+    int wbFd = wb->getFbFd();
+    if(mFeatureEnabled && wbFd >= 0 &&
+        !ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK, wbFd))
+    {
         ALOGE("%s: Failed to validate and set overlay for dpy %d"
                 ,__FUNCTION__, overlay::Overlay::DPY_WRITEBACK);
+        turnOffAD();
         return false;
     }
 
+    // Only turn on AD if there are no errors during configuration stage
+    // and if it was previously in OFF state.
+    if(mFeatureEnabled && mTurnedOff) {
+        //write to sysfs, one time during this switch
+        const int on = 1;
+        adWrite(on);
+        mTurnedOff = false;
+    }
+
     return true;
 }
 
 bool AssertiveDisplay::draw(hwc_context_t *ctx, int fd, uint32_t offset) {
-    if(!isDoable() || !isModeOn()) {
+    if(!isDoable()) {
         return false;
     }
 
diff --git a/libhwcomposer/hwc_ad.h b/libhwcomposer/hwc_ad.h
index 3bfde17..0be5f5d 100644
--- a/libhwcomposer/hwc_ad.h
+++ b/libhwcomposer/hwc_ad.h
@@ -50,17 +50,16 @@
             mDest = overlay::utils::OV_INVALID;
     }
     bool isDoable() const { return mDoable; }
-    bool isModeOn() const { return (mWbFd >= 0); }
     int getDstFd() const;
     uint32_t getDstOffset() const;
 
 private:
-    //State of feature turned on and off
-    int mWbFd;
     bool mDoable;
+    bool mTurnedOff;
     //State of feature existence on certain devices and configs.
     bool mFeatureEnabled;
     overlay::utils::eDest mDest;
+    void turnOffAD();
 };
 
 }
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 8a717c0..7c67641 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -1766,11 +1766,9 @@
             int fd = hnd->fd;
             int offset = (uint32_t)hnd->offset;
 
-            if(ctx->mAD->isModeOn()) {
-                if(ctx->mAD->draw(ctx, fd, offset)) {
-                    fd = ctx->mAD->getDstFd();
-                    offset = ctx->mAD->getDstOffset();
-                }
+            if(ctx->mAD->draw(ctx, fd, offset)) {
+                fd = ctx->mAD->getDstFd();
+                offset = ctx->mAD->getDstOffset();
             }
 
             if(rot) {