am af9e6a17: Merge "Properly connect/disconnect to/from the native window in MediaCodec." into jb-dev

* commit 'af9e6a17d7038b411b61a3cb0669694058511a05':
  Properly connect/disconnect to/from the native window in MediaCodec.
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index d96007b..e46e8e9 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -210,6 +210,9 @@
     void extractCSD(const sp<AMessage> &format);
     status_t queueCSDInputBuffer(size_t bufferIndex);
 
+    status_t setNativeWindow(
+            const sp<SurfaceTextureClient> &surfaceTextureClient);
+
     DISALLOW_EVIL_CONSTRUCTORS(MediaCodec);
 };
 
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index e032cfc..5b513a8 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -796,9 +796,6 @@
                 break;
             }
 
-            mReplyID = replyID;
-            setState(CONFIGURING);
-
             sp<RefBase> obj;
             if (!msg->findObject("native-window", &obj)) {
                 obj.clear();
@@ -810,15 +807,24 @@
             if (obj != NULL) {
                 format->setObject("native-window", obj);
 
-                if (mFlags & kFlagIsSoftwareCodec) {
-                    mNativeWindow =
-                        static_cast<NativeWindowWrapper *>(obj.get())
-                            ->getSurfaceTextureClient();
+                status_t err = setNativeWindow(
+                    static_cast<NativeWindowWrapper *>(obj.get())
+                        ->getSurfaceTextureClient());
+
+                if (err != OK) {
+                    sp<AMessage> response = new AMessage;
+                    response->setInt32("err", err);
+
+                    response->postReply(replyID);
+                    break;
                 }
             } else {
-                mNativeWindow.clear();
+                setNativeWindow(NULL);
             }
 
+            mReplyID = replyID;
+            setState(CONFIGURING);
+
             void *crypto;
             if (!msg->findPointer("crypto", &crypto)) {
                 crypto = NULL;
@@ -1180,12 +1186,12 @@
 }
 
 void MediaCodec::setState(State newState) {
-    if (newState == INITIALIZED) {
+    if (newState == INITIALIZED || newState == UNINITIALIZED) {
         delete mSoftRenderer;
         mSoftRenderer = NULL;
 
         mCrypto.clear();
-        mNativeWindow.clear();
+        setNativeWindow(NULL);
 
         mOutputFormat.clear();
         mFlags &= ~kFlagOutputFormatChanged;
@@ -1425,4 +1431,37 @@
     return index;
 }
 
+status_t MediaCodec::setNativeWindow(
+        const sp<SurfaceTextureClient> &surfaceTextureClient) {
+    status_t err;
+
+    if (mNativeWindow != NULL) {
+        err = native_window_api_disconnect(
+                mNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
+
+        if (err != OK) {
+            ALOGW("native_window_api_disconnect returned an error: %s (%d)",
+                    strerror(-err), err);
+        }
+
+        mNativeWindow.clear();
+    }
+
+    if (surfaceTextureClient != NULL) {
+        err = native_window_api_connect(
+                surfaceTextureClient.get(), NATIVE_WINDOW_API_MEDIA);
+
+        if (err != OK) {
+            ALOGE("native_window_api_connect returned an error: %s (%d)",
+                    strerror(-err), err);
+
+            return err;
+        }
+
+        mNativeWindow = surfaceTextureClient;
+    }
+
+    return OK;
+}
+
 }  // namespace android