Create builtin display tokens on demand

For hotpluggable builtin displays (currently just HDMI), create the
display device IBinder token when the display is connected and destroy
it when the display is disconnected. Previously we created the tokens
at startup and never changed them. This made it so that when comparing
current and drawing state, we couldn't tell whether a display had been
disconnected and reconnected.

Bug: 7491120
Change-Id: I23b77037dc0f548d549abf580339edd0e3c626e9
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ceb8411..614c529 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -191,12 +191,22 @@
     return token;
 }
 
+void SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type) {
+    ALOGW_IF(mBuiltinDisplays[type],
+            "Overwriting display token for display type %d", type);
+    mBuiltinDisplays[type] = new BBinder();
+    DisplayDeviceState info(type);
+    // All non-virtual displays are currently considered secure.
+    info.isSecure = true;
+    mCurrentState.displays.add(mBuiltinDisplays[type], info);
+}
+
 sp<IBinder> SurfaceFlinger::getBuiltInDisplay(int32_t id) {
     if (uint32_t(id) >= DisplayDevice::NUM_DISPLAY_TYPES) {
         ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id);
         return NULL;
     }
-    return mDefaultDisplays[id];
+    return mBuiltinDisplays[id];
 }
 
 sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
@@ -462,6 +472,8 @@
     ALOGI(  "SurfaceFlinger's main thread ready to run. "
             "Initializing graphics H/W...");
 
+    Mutex::Autolock _l(mStateLock);
+
     // initialize EGL for the default display
     mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     eglInitialize(mEGLDisplay, NULL, NULL);
@@ -482,14 +494,13 @@
     // initialize our non-virtual displays
     for (size_t i=0 ; i<DisplayDevice::NUM_DISPLAY_TYPES ; i++) {
         DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
-        mDefaultDisplays[i] = new BBinder();
-        wp<IBinder> token = mDefaultDisplays[i];
-
         // set-up the displays that are already connected
         if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
             // All non-virtual displays are currently considered secure.
             bool isSecure = true;
-            mCurrentState.displays.add(token, DisplayDeviceState(type));
+            createBuiltinDisplayLocked(type);
+            wp<IBinder> token = mBuiltinDisplays[i];
+
             sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i);
             sp<SurfaceTextureClient> stc = new SurfaceTextureClient(
                         static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));
@@ -601,9 +612,9 @@
 }
 
 status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) {
-    int32_t type = BAD_VALUE;
+    int32_t type = NAME_NOT_FOUND;
     for (int i=0 ; i<DisplayDevice::NUM_DISPLAY_TYPES ; i++) {
-        if (display == mDefaultDisplays[i]) {
+        if (display == mBuiltinDisplays[i]) {
             type = i;
             break;
         }
@@ -614,10 +625,6 @@
     }
 
     const HWComposer& hwc(getHwComposer());
-    if (!hwc.isConnected(type)) {
-        return NAME_NOT_FOUND;
-    }
-
     float xdpi = hwc.getDpiX(type);
     float ydpi = hwc.getDpiY(type);
 
@@ -745,11 +752,11 @@
 
     if (uint32_t(type) < DisplayDevice::NUM_DISPLAY_TYPES) {
         Mutex::Autolock _l(mStateLock);
-        if (connected == false) {
-            mCurrentState.displays.removeItem(mDefaultDisplays[type]);
+        if (connected) {
+            createBuiltinDisplayLocked((DisplayDevice::DisplayType)type);
         } else {
-            DisplayDeviceState info((DisplayDevice::DisplayType)type);
-            mCurrentState.displays.add(mDefaultDisplays[type], info);
+            mCurrentState.displays.removeItem(mBuiltinDisplays[type]);
+            mBuiltinDisplays[type].clear();
         }
         setTransactionFlags(eDisplayTransactionNeeded);
 
@@ -1163,7 +1170,6 @@
             for (size_t i=0 ; i<cc ; i++) {
                 if (draw.indexOfKey(curr.keyAt(i)) < 0) {
                     const DisplayDeviceState& state(curr[i]);
-                    bool isSecure = false;
 
                     sp<FramebufferSurface> fbs;
                     sp<SurfaceTextureClient> stc;
@@ -1174,10 +1180,6 @@
                                 "surface is provided (%p), ignoring it",
                                 state.surface.get());
 
-                        // All non-virtual displays are currently considered
-                        // secure.
-                        isSecure = true;
-
                         // for supported (by hwc) displays we provide our
                         // own rendering surface
                         fbs = new FramebufferSurface(*mHwc, state.type);
@@ -1188,13 +1190,12 @@
                         if (state.surface != NULL) {
                             stc = new SurfaceTextureClient(state.surface);
                         }
-                        isSecure = state.isSecure;
                     }
 
                     const wp<IBinder>& display(curr.keyAt(i));
                     if (stc != NULL) {
                         sp<DisplayDevice> hw = new DisplayDevice(this,
-                                state.type, isSecure, display, stc, fbs,
+                                state.type, state.isSecure, display, stc, fbs,
                                 mEGLConfig);
                         hw->setLayerStack(state.layerStack);
                         hw->setProjection(state.orientation,
@@ -2011,7 +2012,7 @@
     Vector<DisplayState> displays;
     DisplayState d;
     d.what = DisplayState::eDisplayProjectionChanged;
-    d.token = mDefaultDisplays[DisplayDevice::DISPLAY_PRIMARY];
+    d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY];
     d.orientation = DisplayState::eOrientationDefault;
     d.frame.makeInvalid();
     d.viewport.makeInvalid();