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/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;
     }