Surface: Add force disconnection method.

Add a new method forceScopedDisconnect to Surface. This will
be used by the framework to force disconnection at times where
the underlying GraphicBufferProducer may be about to be reused.
This is scoped by PID to avoid conflicting with remote producers.

Bug: 30236166
Change-Id: I857216483c0b550f240b3baea41977cbc58a67ed
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 47ab6f2..48b1db8 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -28,6 +28,7 @@
 
 #define EGL_EGLEXT_PROTOTYPES
 
+#include <binder/IPCThreadState.h>
 #include <gui/BufferItem.h>
 #include <gui/BufferQueueCore.h>
 #include <gui/BufferQueueProducer.h>
@@ -1130,7 +1131,7 @@
             status = BAD_VALUE;
             break;
     }
-
+    mCore->mConnectedPid = IPCThreadState::self()->getCallingPid();
     mCore->mBufferHasBeenQueued = false;
     mCore->mDequeueBufferCannotBlock = false;
     if (mDequeueTimeout < 0) {
@@ -1143,7 +1144,7 @@
     return status;
 }
 
-status_t BufferQueueProducer::disconnect(int api) {
+status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) {
     ATRACE_CALL();
     BQ_LOGV("disconnect: api %d", api);
 
@@ -1151,6 +1152,14 @@
     sp<IConsumerListener> listener;
     { // Autolock scope
         Mutex::Autolock lock(mCore->mMutex);
+
+        if (mode == DisconnectMode::AllLocal) {
+            if (IPCThreadState::self()->getCallingPid() != mCore->mConnectedPid) {
+                return NO_ERROR;
+            }
+            api = BufferQueueCore::CURRENTLY_CONNECTED_API;
+        }
+
         mCore->waitWhileAllocatingLocked();
 
         if (mCore->mIsAbandoned) {
@@ -1189,6 +1198,7 @@
                             BufferQueueCore::INVALID_BUFFER_SLOT;
                     mCore->mConnectedProducerListener = NULL;
                     mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
+                    mCore->mConnectedPid = -1;
                     mCore->mSidebandStream.clear();
                     mCore->mDequeueCondition.broadcast();
                     listener = mCore->mConsumerListener;
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index fbd704d..f4ba3bf 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -270,10 +270,11 @@
         return result;
     }
 
-    virtual status_t disconnect(int api) {
+    virtual status_t disconnect(int api, DisconnectMode mode) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
         data.writeInt32(api);
+        data.writeInt32(static_cast<int32_t>(mode));
         status_t result =remote()->transact(DISCONNECT, data, &reply);
         if (result != NO_ERROR) {
             return result;
@@ -621,7 +622,8 @@
         case DISCONNECT: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
             int api = data.readInt32();
-            status_t res = disconnect(api);
+            DisconnectMode mode = static_cast<DisconnectMode>(data.readInt32());
+            status_t res = disconnect(api, mode);
             reply->writeInt32(res);
             return NO_ERROR;
         }
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index ab223ff..0838290 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -844,14 +844,14 @@
 }
 
 
-int Surface::disconnect(int api) {
+int Surface::disconnect(int api, IGraphicBufferProducer::DisconnectMode mode) {
     ATRACE_CALL();
     ALOGV("Surface::disconnect");
     Mutex::Autolock lock(mMutex);
     mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
     mSharedBufferHasBeenQueued = false;
     freeAllBuffers();
-    int err = mGraphicBufferProducer->disconnect(api);
+    int err = mGraphicBufferProducer->disconnect(api, mode);
     if (!err) {
         mReqFormat = 0;
         mReqWidth = 0;