hwc: Return failure from hwc_device_open when fb open fails

- When fb open fails during hwc initialization, it should be
  flagged as a fatal error and HAL should return error.
- Without this, the SF would make calls to HWC that would fail,
  and display being blank.

Change-Id: I20f08bdcb283d4805449c74a8214b871c2f1c80b
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index bf59217..496798a 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -966,7 +966,11 @@
         memset(dev, 0, sizeof(*dev));
 
         //Initialize hwc context
-        initContext(dev);
+        status = initContext(dev);
+        if (status < 0) {
+            free(dev);
+            return status;
+        }
 
         //Setup HWC methods
         dev->device.common.tag          = HARDWARE_DEVICE_TAG;
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 4d94647..6a70d06 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -202,7 +202,15 @@
                         "uevent thread", __FUNCTION__);
                 ctx->mWfdSyncLock.unlock();
             }
-            ctx->mHDMIDisplay->configure();
+            // If FB open fails ignore this hotplug event
+            int error = ctx->mHDMIDisplay->configure();
+            if (error < 0) {
+                ALOGE("%s: Open Framebuffer for dpy = %d", __FUNCTION__, dpy);
+                ctx->mDrawLock.lock();
+                ctx->dpyAttr[dpy].isConfiguring = false;
+                ctx->mDrawLock.unlock();
+                break;
+            }
             ctx->mHDMIDisplay->activateDisplay();
 
             ctx->mDrawLock.lock();
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index d176cd3..8a60f65 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -266,8 +266,26 @@
     }
 }
 
-void initContext(hwc_context_t *ctx)
+int initContext(hwc_context_t *ctx)
 {
+    int error = -1;
+    int compositionType = 0;
+
+    //Right now hwc starts the service but anybody could do it, or it could be
+    //independent process as well.
+    QService::init();
+    sp<IQClient> client = new QClient(ctx);
+    sp<IQService> iqs = interface_cast<IQService>(
+            defaultServiceManager()->getService(
+            String16("display.qservice")));
+    if (iqs.get()) {
+      iqs->connect(client);
+      ctx->mQService = reinterpret_cast<QService* >(iqs.get());
+    } else {
+      ALOGE("%s: Failed to acquire service pointer", __FUNCTION__);
+      return error;
+    }
+
     overlay::Overlay::initOverlay();
     ctx->mHDMIDisplay = new HDMIDisplay();
     uint32_t priW = 0, priH = 0;
@@ -280,15 +298,24 @@
     if(ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
         int connected = ctx->mHDMIDisplay->getConnectedState();
         if(connected == 1) {
-            ctx->mHDMIDisplay->configure();
+            error = ctx->mHDMIDisplay->configure();
+            if (error < 0) {
+                goto OpenFBError;
+            }
             updateDisplayInfo(ctx, HWC_DISPLAY_PRIMARY);
             ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
         } else {
-            openFramebufferDevice(ctx);
+            error = openFramebufferDevice(ctx);
+            if(error < 0) {
+                goto OpenFBError;
+            }
             ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = false;
         }
     } else {
-        openFramebufferDevice(ctx);
+        error = openFramebufferDevice(ctx);
+        if(error < 0) {
+            goto OpenFBError;
+        }
         ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
         // Send the primary resolution to the hdmi display class
         // to be used for MDP scaling functionality
@@ -314,8 +341,8 @@
 
     // Check if the target supports copybit compostion (dyn/mdp) to
     // decide if we need to open the copybit module.
-    int compositionType =
-        qdutils::QCCompositionType::getInstance().getCompositionType();
+    compositionType =
+                qdutils::QCCompositionType::getInstance().getCompositionType();
 
     // Only MDP copybit is used
     if ((compositionType & (qdutils::COMPOSITION_TYPE_DYN |
@@ -372,21 +399,6 @@
     ctx->mExtOrientation = 0;
     ctx->numActiveDisplays = 1;
 
-    //Right now hwc starts the service but anybody could do it, or it could be
-    //independent process as well.
-    QService::init();
-    sp<IQClient> client = new QClient(ctx);
-    sp<IQService> iqs = interface_cast<IQService>(
-            defaultServiceManager()->getService(
-            String16("display.qservice")));
-    if (iqs.get()) {
-      iqs->connect(client);
-      ctx->mQService = reinterpret_cast<QService* >(iqs.get());
-    } else {
-      ALOGE("%s: Failed to acquire service pointer", __FUNCTION__);
-      return;
-    }
-
     // Initialize device orientation to its default orientation
     ctx->deviceOrientation = 0;
     ctx->mBufferMirrorMode = false;
@@ -428,6 +440,13 @@
     ctx->mHPDEnabled = false;
     ALOGI("Initializing Qualcomm Hardware Composer");
     ALOGI("MDP version: %d", ctx->mMDP.version);
+
+    return 0;
+
+OpenFBError:
+    ALOGE("%s: Fatal Error: FB Open failed!!!", __FUNCTION__);
+    delete ctx->mHDMIDisplay;
+    return error;
 }
 
 void closeContext(hwc_context_t *ctx)
@@ -2932,7 +2951,11 @@
     // TODO: If HDMI is connected after the display has booted up,
     // and the best configuration is different from the default
     // then we need to deal with this appropriately.
-    ctx->mHDMIDisplay->configure();
+    int error = ctx->mHDMIDisplay->configure();
+    if (error < 0) {
+        ALOGE("Error opening FrameBuffer");
+        return;
+    }
     updateDisplayInfo(ctx, dpy);
     initCompositionResources(ctx, dpy);
     ctx->dpyAttr[dpy].connected = true;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 23157d4..ea8d652 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -280,7 +280,7 @@
 void dumpLayer(hwc_layer_1_t const* l);
 void setListStats(hwc_context_t *ctx, hwc_display_contents_1_t *list,
         int dpy);
-void initContext(hwc_context_t *ctx);
+int initContext(hwc_context_t *ctx);
 void closeContext(hwc_context_t *ctx);
 //Crops source buffer against destination and FB boundaries
 void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,