Add ISurfaceComposer::destroyDisplay

Bug: 10191053
Change-Id: Ia89286f95421344a60ffedaaca5825c4e3cd7f9e
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 0606aff..5c3c99c 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -70,12 +70,17 @@
     /* return an IDisplayEventConnection */
     virtual sp<IDisplayEventConnection> createDisplayEventConnection() = 0;
 
-    /* create a display
+    /* create a virtual display
      * requires ACCESS_SURFACE_FLINGER permission.
      */
     virtual sp<IBinder> createDisplay(const String8& displayName,
             bool secure) = 0;
 
+    /* destroy a virtual display
+     * requires ACCESS_SURFACE_FLINGER permission.
+     */
+    virtual void destroyDisplay(const sp<IBinder>& display) = 0;
+
     /* get the token for the existing default displays. possible values
      * for id are eDisplayIdMain and eDisplayIdHdmi.
      */
@@ -130,6 +135,7 @@
         CREATE_GRAPHIC_BUFFER_ALLOC,
         CREATE_DISPLAY_EVENT_CONNECTION,
         CREATE_DISPLAY,
+        DESTROY_DISPLAY,
         GET_BUILT_IN_DISPLAY,
         SET_TRANSACTION_STATE,
         AUTHENTICATE_SURFACE,
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 643d7cf..e982bcd 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -48,7 +48,7 @@
 class SurfaceComposerClient : public RefBase
 {
     friend class Composer;
-public:    
+public:
                 SurfaceComposerClient();
     virtual     ~SurfaceComposerClient();
 
@@ -57,7 +57,7 @@
 
     // Return the connection of this client
     sp<IBinder> connection() const;
-    
+
     // Forcibly remove connection before all references have gone away.
     void        dispose();
 
@@ -86,9 +86,12 @@
             uint32_t flags = 0  // usage flags
     );
 
-    //! Create a display
+    //! Create a virtual display
     static sp<IBinder> createDisplay(const String8& displayName, bool secure);
 
+    //! Destroy a virtual display
+    static void destroyDisplay(const sp<IBinder>& display);
+
     //! Get the token for the existing default displays.
     //! Possible values for id are eDisplayIdMain and eDisplayIdHdmi.
     static sp<IBinder> getBuiltInDisplay(int32_t id);
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index a9217ca..aab0604 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -185,6 +185,14 @@
         return reply.readStrongBinder();
     }
 
+    virtual void destroyDisplay(const sp<IBinder>& display)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        data.writeStrongBinder(display);
+        remote()->transact(BnSurfaceComposer::DESTROY_DISPLAY, data, &reply);
+    }
+
     virtual sp<IBinder> getBuiltInDisplay(int32_t id)
     {
         Parcel data, reply;
@@ -233,12 +241,14 @@
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> b = createConnection()->asBinder();
             reply->writeStrongBinder(b);
-        } break;
+            return NO_ERROR;
+        }
         case CREATE_GRAPHIC_BUFFER_ALLOC: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
             reply->writeStrongBinder(b);
-        } break;
+            return NO_ERROR;
+        }
         case SET_TRANSACTION_STATE: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             size_t count = data.readInt32();
@@ -259,11 +269,13 @@
             }
             uint32_t flags = data.readInt32();
             setTransactionState(state, displays, flags);
-        } break;
+            return NO_ERROR;
+        }
         case BOOT_FINISHED: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             bootFinished();
-        } break;
+            return NO_ERROR;
+        }
         case CAPTURE_SCREEN: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> display = data.readStrongBinder();
@@ -276,20 +288,22 @@
             status_t res = captureScreen(display, producer,
                     reqWidth, reqHeight, minLayerZ, maxLayerZ);
             reply->writeInt32(res);
-        } break;
+            return NO_ERROR;
+        }
         case AUTHENTICATE_SURFACE: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IGraphicBufferProducer> bufferProducer =
                     interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
             int32_t result = authenticateSurfaceTexture(bufferProducer) ? 1 : 0;
             reply->writeInt32(result);
-        } break;
+            return NO_ERROR;
+        }
         case CREATE_DISPLAY_EVENT_CONNECTION: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IDisplayEventConnection> connection(createDisplayEventConnection());
             reply->writeStrongBinder(connection->asBinder());
             return NO_ERROR;
-        } break;
+        }
         case CREATE_DISPLAY: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             String8 displayName = data.readString8();
@@ -297,24 +311,32 @@
             sp<IBinder> display(createDisplay(displayName, secure));
             reply->writeStrongBinder(display);
             return NO_ERROR;
-        } break;
+        }
+        case DESTROY_DISPLAY: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> display = data.readStrongBinder();
+            destroyDisplay(display);
+            return NO_ERROR;
+        }
         case GET_BUILT_IN_DISPLAY: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             int32_t id = data.readInt32();
             sp<IBinder> display(getBuiltInDisplay(id));
             reply->writeStrongBinder(display);
             return NO_ERROR;
-        } break;
+        }
         case BLANK: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> display = data.readStrongBinder();
             blank(display);
-        } break;
+            return NO_ERROR;
+        }
         case UNBLANK: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> display = data.readStrongBinder();
             unblank(display);
-        } break;
+            return NO_ERROR;
+        }
         case GET_DISPLAY_INFO: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             DisplayInfo info;
@@ -322,10 +344,13 @@
             status_t result = getDisplayInfo(display, &info);
             memcpy(reply->writeInplace(sizeof(DisplayInfo)), &info, sizeof(DisplayInfo));
             reply->writeInt32(result);
-        } break;
-        default:
+            return NO_ERROR;
+        }
+        default: {
             return BBinder::onTransact(code, data, reply, flags);
+        }
     }
+    // should be unreachable
     return NO_ERROR;
 }
 
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index e067479..aafc4d2 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -135,6 +135,7 @@
 
 public:
     sp<IBinder> createDisplay(const String8& displayName, bool secure);
+    void destroyDisplay(const sp<IBinder>& display);
     sp<IBinder> getBuiltInDisplay(int32_t id);
 
     status_t setPosition(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
@@ -188,6 +189,10 @@
             secure);
 }
 
+void Composer::destroyDisplay(const sp<IBinder>& display) {
+    return ComposerService::getComposerService()->destroyDisplay(display);
+}
+
 sp<IBinder> Composer::getBuiltInDisplay(int32_t id) {
     return ComposerService::getComposerService()->getBuiltInDisplay(id);
 }
@@ -490,6 +495,10 @@
     return Composer::getInstance().createDisplay(displayName, secure);
 }
 
+void SurfaceComposerClient::destroyDisplay(const sp<IBinder>& display) {
+    Composer::getInstance().destroyDisplay(display);
+}
+
 sp<IBinder> SurfaceComposerClient::getBuiltInDisplay(int32_t id) {
     return Composer::getInstance().getBuiltInDisplay(id);
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b38ad10..bc10853 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -205,6 +205,25 @@
     return token;
 }
 
+void SurfaceFlinger::destroyDisplay(const sp<IBinder>& display) {
+    Mutex::Autolock _l(mStateLock);
+
+    ssize_t idx = mCurrentState.displays.indexOfKey(display);
+    if (idx < 0) {
+        ALOGW("destroyDisplay: invalid display token");
+        return;
+    }
+
+    const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx));
+    if (!info.isVirtualDisplay()) {
+        ALOGE("destroyDisplay called for non-virtual display");
+        return;
+    }
+
+    mCurrentState.displays.removeItemsAt(idx);
+    setTransactionFlags(eDisplayTransactionNeeded);
+}
+
 void SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type) {
     ALOGW_IF(mBuiltinDisplays[type],
             "Overwriting display token for display type %d", type);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index acc8fab..92fcc25 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -184,6 +184,7 @@
     virtual sp<ISurfaceComposerClient> createConnection();
     virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
     virtual sp<IBinder> createDisplay(const String8& displayName, bool secure);
+    virtual void destroyDisplay(const sp<IBinder>& display);
     virtual sp<IBinder> getBuiltInDisplay(int32_t id);
     virtual void setTransactionState(const Vector<ComposerState>& state,
             const Vector<DisplayState>& displays, uint32_t flags);