implement connect/disconnect in our native_window_t implementations

the framebuffer implementation doesn't do anything special with this
but the surfaceflinger implementation makes sure the surface is not used
by two APIs simultaneously.

Change-Id: Id4ca8ef7093d68846abc2ac814327cc40a64b66b
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 9808832..0279d84 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -210,9 +210,16 @@
 
     status_t dequeueBuffer(sp<GraphicBuffer>* buffer);
 
+    void dispatch_setUsage(va_list args);
+    int  dispatch_connect(va_list args);
+    int  dispatch_disconnect(va_list args);
     
     void setUsage(uint32_t reqUsage);
+    int  connect(int api);
+    int  disconnect(int api);
+
     uint32_t getUsage() const;
+    int      getConnectedApi() const;
     
     // constants
     sp<SurfaceComposerClient>   mClient;
@@ -227,6 +234,7 @@
     // protected by mSurfaceLock
     Rect                        mSwapRectangle;
     uint32_t                    mUsage;
+    int                         mConnected;
     
     // protected by mSurfaceLock. These are also used from lock/unlock
     // but in that case, they must be called form the same thread.
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index eb3457b..5dd75c3 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -353,6 +353,7 @@
     const_cast<uint32_t&>(android_native_window_t::flags) = 0;
     // be default we request a hardware surface
     mUsage = GRALLOC_USAGE_HW_RENDER;
+    mConnected = 0;
     mNeedFullUpdate = false;
 }
 
@@ -579,28 +580,93 @@
 {
     int res = NO_ERROR;
     switch (operation) {
-        case NATIVE_WINDOW_SET_USAGE:
-            setUsage( va_arg(args, int) );
-            break;
-        default:
-            res = NAME_NOT_FOUND;
-            break;
+    case NATIVE_WINDOW_SET_USAGE:
+        dispatch_setUsage( args );
+        break;
+    case NATIVE_WINDOW_CONNECT:
+        res = dispatch_connect( args );
+        break;
+    case NATIVE_WINDOW_DISCONNECT:
+        res = dispatch_disconnect( args );
+        break;
+    default:
+        res = NAME_NOT_FOUND;
+        break;
     }
     return res;
 }
 
+void Surface::dispatch_setUsage(va_list args) {
+    int usage = va_arg(args, int);
+    setUsage( usage );
+}
+int Surface::dispatch_connect(va_list args) {
+    int api = va_arg(args, int);
+    return connect( api );
+}
+int Surface::dispatch_disconnect(va_list args) {
+    int api = va_arg(args, int);
+    return disconnect( api );
+}
+
+
 void Surface::setUsage(uint32_t reqUsage)
 {
     Mutex::Autolock _l(mSurfaceLock);
     mUsage = reqUsage;
 }
 
+int Surface::connect(int api)
+{
+    Mutex::Autolock _l(mSurfaceLock);
+    int err = NO_ERROR;
+    switch (api) {
+        case NATIVE_WINDOW_API_EGL:
+            if (mConnected) {
+                err = -EINVAL;
+            } else {
+                mConnected = api;
+            }
+            break;
+        default:
+            err = -EINVAL;
+            break;
+    }
+    return err;
+}
+
+int Surface::disconnect(int api)
+{
+    Mutex::Autolock _l(mSurfaceLock);
+    int err = NO_ERROR;
+    switch (api) {
+        case NATIVE_WINDOW_API_EGL:
+            if (mConnected == api) {
+                mConnected = 0;
+            } else {
+                err = -EINVAL;
+            }
+            break;
+        default:
+            err = -EINVAL;
+            break;
+    }
+    return err;
+}
+
 uint32_t Surface::getUsage() const
 {
     Mutex::Autolock _l(mSurfaceLock);
     return mUsage;
 }
 
+int Surface::getConnectedApi() const
+{
+    Mutex::Autolock _l(mSurfaceLock);
+    return mConnected;
+}
+
+
 // ----------------------------------------------------------------------------
 
 status_t Surface::lock(SurfaceInfo* info, bool blocking) {
@@ -609,11 +675,20 @@
 
 status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) 
 {
+    if (getConnectedApi()) {
+        LOGE("Surface::lock(%p) failed. Already connected to another API",
+                (android_native_window_t*)this);
+        CallStack stack;
+        stack.update();
+        stack.dump("");
+        return INVALID_OPERATION;
+    }
+
     if (mApiLock.tryLock() != NO_ERROR) {
         LOGE("calling Surface::lock from different threads!");
         CallStack stack;
         stack.update();
-        stack.dump("Surface::lock called from different threads");
+        stack.dump("");
         return WOULD_BLOCK;
     }
 
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index 1fa2c68..52380a0 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -250,6 +250,8 @@
 {
     switch (operation) {
         case NATIVE_WINDOW_SET_USAGE:
+        case NATIVE_WINDOW_CONNECT:
+        case NATIVE_WINDOW_DISCONNECT:
             break;
         default:
             return NAME_NOT_FOUND;