add/remove displays properly on hotplug events

Bug: 7191563
Change-Id: I8f0fbf3b29658c9479443141798e6f288a1f2d52
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 330e09d..81ce27e 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -167,6 +167,13 @@
     setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
 }
 
+void DisplayDevice::setDisplayName(const String8& displayName) {
+    if (!displayName.isEmpty()) {
+        // never override the name with an empty name
+        mDisplayName = displayName;
+    }
+}
+
 uint32_t DisplayDevice::getPageFlipCount() const {
     return mPageFlipCount;
 }
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index d83625a..1d77154 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -119,9 +119,7 @@
     }
     inline Rect bounds() const { return getBounds(); }
 
-    void setDisplayName(const String8& displayName) {
-        mDisplayName = displayName;
-    }
+    void setDisplayName(const String8& displayName);
     const String8& getDisplayName() const { return mDisplayName; }
 
     static EGLBoolean makeCurrent(EGLDisplay dpy,
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 8107828..987cc64 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -337,7 +337,12 @@
         return err;
     }
 
-    mHwc->getDisplayAttributes(mHwc, disp, config, DISPLAY_ATTRIBUTES, values);
+    err = mHwc->getDisplayAttributes(mHwc, disp, config, DISPLAY_ATTRIBUTES, values);
+    if (err != NO_ERROR) {
+        // we can't get this display's info. turn it off.
+        mDisplayData[disp].connected = false;
+        return err;
+    }
 
     int32_t w = 0, h = 0;
     for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 8164d20..8372691 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -408,10 +408,10 @@
         DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
         mDefaultDisplays[i] = new BBinder();
         wp<IBinder> token = mDefaultDisplays[i];
-        mCurrentState.displays.add(token, DisplayDeviceState(type));
 
         // set-up the displays that are already connected
-        if (mHwc->isConnected(i)) {
+        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
+            mCurrentState.displays.add(token, DisplayDeviceState(type));
             sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i);
             sp<SurfaceTextureClient> stc = new SurfaceTextureClient(
                         static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));
@@ -688,7 +688,17 @@
         ALOGW("WARNING: EventThread not started, ignoring hotplug");
         return;
     }
+
     if (uint32_t(type) < DisplayDevice::NUM_DISPLAY_TYPES) {
+        Mutex::Autolock _l(mStateLock);
+        if (connected == false) {
+            mCurrentState.displays.removeItem(mDefaultDisplays[type]);
+        } else {
+            DisplayDeviceState info((DisplayDevice::DisplayType)type);
+            mCurrentState.displays.add(mDefaultDisplays[type], info);
+        }
+        setTransactionFlags(eDisplayTransactionNeeded);
+
         // we should only receive DisplayDevice::DisplayType from the vsync callback
         mEventThread->onHotplugReceived(type, connected);
     }