Merge changes I34dbae75,I582afae6 into ics-mr0

* changes:
  Augment CTS test for MediaPlayer.setSurface
  DO NOT MERGE: Add CTS test for MediaPlayer.setSurface() For bug 5088394.
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index b7f7cc6..9cdb13b 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -135,6 +135,14 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.media.cts.MediaPlayerSurfaceStubActivity"
+            android:label="MediaPlayerSurfaceStubActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="android.media.cts.RingtonePickerActivity"
             android:label="RingtonePickerActivity">
             <intent-filter>
diff --git a/tests/src/android/media/cts/MediaPlayerSurfaceStubActivity.java b/tests/src/android/media/cts/MediaPlayerSurfaceStubActivity.java
new file mode 100644
index 0000000..3cd6fc8
--- /dev/null
+++ b/tests/src/android/media/cts/MediaPlayerSurfaceStubActivity.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.cts;
+
+import com.android.cts.stub.R;
+
+import android.app.Activity;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.media.MediaPlayer;
+import android.os.Bundle;
+import android.util.Log;
+
+public class MediaPlayerSurfaceStubActivity extends Activity {
+
+    private static final String TAG = "MediaPlayerSurfaceStubActivity";
+
+    protected Resources mResources;
+
+    private VideoSurfaceView mVideoView = null;
+    private MediaPlayer mMediaPlayer = null;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mResources = getResources();
+        mMediaPlayer = new MediaPlayer();
+
+        try {
+            AssetFileDescriptor afd = mResources.openRawResourceFd(R.raw.testvideo);
+            mMediaPlayer.setDataSource(
+                    afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+            afd.close();
+        } catch (Exception e) {
+            Log.e(TAG, e.getMessage(), e);
+        }
+
+        mVideoView = new VideoSurfaceView(this, mMediaPlayer);
+        setContentView(mVideoView);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mVideoView.onResume();
+    }
+
+    public void playVideo() throws Exception {
+        mVideoView.startTest();
+    }
+
+}
diff --git a/tests/src/android/media/cts/VideoSurfaceView.java b/tests/src/android/media/cts/VideoSurfaceView.java
new file mode 100644
index 0000000..0f23a2d
--- /dev/null
+++ b/tests/src/android/media/cts/VideoSurfaceView.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import com.android.cts.stub.R;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.content.Context;
+import android.graphics.SurfaceTexture;
+import android.media.MediaPlayer;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+import android.opengl.Matrix;
+import android.util.Log;
+import android.view.Surface;
+
+class VideoSurfaceView extends GLSurfaceView {
+    private static final String TAG = "VideoSurfaceView";
+    private static final int SLEEP_TIME = 1000;
+
+    VideoRender mRenderer;
+    private MediaPlayer mMediaPlayer = null;
+
+    public VideoSurfaceView(Context context, MediaPlayer mp) {
+        super(context);
+
+        setEGLContextClientVersion(2);
+        mMediaPlayer = mp;
+        mRenderer = new VideoRender(context);
+        setRenderer(mRenderer);
+    }
+
+    @Override
+    public void onResume() {
+        queueEvent(new Runnable(){
+                public void run() {
+                    mRenderer.setMediaPlayer(mMediaPlayer);
+                }});
+
+        super.onResume();
+    }
+
+    public void startTest() throws Exception {
+        Thread.sleep(SLEEP_TIME);
+        mMediaPlayer.start();
+
+        Thread.sleep(SLEEP_TIME * 5);
+        mMediaPlayer.setSurface(null);
+
+        Thread.sleep(SLEEP_TIME * 1);
+        SurfaceTexture surfaceTexture = new SurfaceTexture(0);
+        Surface surface = new Surface(surfaceTexture);
+        surface.release();
+        try {
+            mMediaPlayer.setSurface(surface);
+            throw new RuntimeException("setSurface with released Surface object didn't throw " +
+                    "IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+
+        while (mMediaPlayer.isPlaying()) {
+            Thread.sleep(SLEEP_TIME);
+        }
+    }
+
+    private static class VideoRender
+        implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {
+        private static String TAG = "VideoRender";
+
+        private static final int FLOAT_SIZE_BYTES = 4;
+        private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
+        private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
+        private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
+        private final float[] mTriangleVerticesData = {
+            // X, Y, Z, U, V
+            -1.0f, -1.0f, 0, 0.f, 0.f,
+            1.0f, -1.0f, 0, 1.f, 0.f,
+            -1.0f,  1.0f, 0, 0.f, 1.f,
+            1.0f,  1.0f, 0, 1.f, 1.f,
+        };
+
+        private FloatBuffer mTriangleVertices;
+
+        private final String mVertexShader =
+                "uniform mat4 uMVPMatrix;\n" +
+                "uniform mat4 uSTMatrix;\n" +
+                "attribute vec4 aPosition;\n" +
+                "attribute vec4 aTextureCoord;\n" +
+                "varying vec2 vTextureCoord;\n" +
+                "void main() {\n" +
+                "  gl_Position = uMVPMatrix * aPosition;\n" +
+                "  vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
+                "}\n";
+
+        private final String mFragmentShader =
+                "#extension GL_OES_EGL_image_external : require\n" +
+                "precision mediump float;\n" +
+                "varying vec2 vTextureCoord;\n" +
+                "uniform samplerExternalOES sTexture;\n" +
+                "void main() {\n" +
+                "  gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
+                "}\n";
+
+        private float[] mMVPMatrix = new float[16];
+        private float[] mSTMatrix = new float[16];
+
+        private int mProgram;
+        private int mTextureID;
+        private int muMVPMatrixHandle;
+        private int muSTMatrixHandle;
+        private int maPositionHandle;
+        private int maTextureHandle;
+
+        private SurfaceTexture mSurface;
+        private boolean updateSurface = false;
+
+        private static int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
+
+        private MediaPlayer mMediaPlayer;
+
+        public VideoRender(Context context) {
+            mTriangleVertices = ByteBuffer.allocateDirect(
+                mTriangleVerticesData.length * FLOAT_SIZE_BYTES)
+                    .order(ByteOrder.nativeOrder()).asFloatBuffer();
+            mTriangleVertices.put(mTriangleVerticesData).position(0);
+
+            Matrix.setIdentityM(mSTMatrix, 0);
+        }
+
+        public void setMediaPlayer(MediaPlayer player) {
+            mMediaPlayer = player;
+        }
+
+        public void onDrawFrame(GL10 glUnused) {
+            synchronized(this) {
+                if (updateSurface) {
+                    mSurface.updateTexImage();
+                    mSurface.getTransformMatrix(mSTMatrix);
+                    updateSurface = false;
+                }
+            }
+
+            GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+            GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+
+            GLES20.glUseProgram(mProgram);
+            checkGlError("glUseProgram");
+
+            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
+            GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID);
+
+            mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
+            GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
+                TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
+            checkGlError("glVertexAttribPointer maPosition");
+            GLES20.glEnableVertexAttribArray(maPositionHandle);
+            checkGlError("glEnableVertexAttribArray maPositionHandle");
+
+            mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
+            GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT, false,
+                TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
+            checkGlError("glVertexAttribPointer maTextureHandle");
+            GLES20.glEnableVertexAttribArray(maTextureHandle);
+            checkGlError("glEnableVertexAttribArray maTextureHandle");
+
+            Matrix.setIdentityM(mMVPMatrix, 0);
+            GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
+            GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
+
+            GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
+            checkGlError("glDrawArrays");
+            GLES20.glFinish();
+
+        }
+
+        public void onSurfaceChanged(GL10 glUnused, int width, int height) {
+        }
+
+        public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
+            mProgram = createProgram(mVertexShader, mFragmentShader);
+            if (mProgram == 0) {
+                return;
+            }
+            maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
+            checkGlError("glGetAttribLocation aPosition");
+            if (maPositionHandle == -1) {
+                throw new RuntimeException("Could not get attrib location for aPosition");
+            }
+            maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
+            checkGlError("glGetAttribLocation aTextureCoord");
+            if (maTextureHandle == -1) {
+                throw new RuntimeException("Could not get attrib location for aTextureCoord");
+            }
+
+            muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
+            checkGlError("glGetUniformLocation uMVPMatrix");
+            if (muMVPMatrixHandle == -1) {
+                throw new RuntimeException("Could not get attrib location for uMVPMatrix");
+            }
+
+            muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix");
+            checkGlError("glGetUniformLocation uSTMatrix");
+            if (muSTMatrixHandle == -1) {
+                throw new RuntimeException("Could not get attrib location for uSTMatrix");
+            }
+
+
+            int[] textures = new int[1];
+            GLES20.glGenTextures(1, textures, 0);
+
+            mTextureID = textures[0];
+            GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID);
+            checkGlError("glBindTexture mTextureID");
+
+            GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER,
+                                   GLES20.GL_NEAREST);
+            GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER,
+                                   GLES20.GL_LINEAR);
+
+            /*
+             * Create the SurfaceTexture that will feed this textureID,
+             * and pass it to the MediaPlayer
+             */
+            mSurface = new SurfaceTexture(mTextureID);
+            mSurface.setOnFrameAvailableListener(this);
+
+            Surface surface = new Surface(mSurface);
+            mMediaPlayer.setSurface(surface);
+            surface.release();
+
+            try {
+                mMediaPlayer.prepare();
+            } catch (IOException t) {
+                Log.e(TAG, "media player prepare failed");
+            }
+
+            synchronized(this) {
+                updateSurface = false;
+            }
+        }
+
+        synchronized public void onFrameAvailable(SurfaceTexture surface) {
+            updateSurface = true;
+        }
+
+        private int loadShader(int shaderType, String source) {
+            int shader = GLES20.glCreateShader(shaderType);
+            if (shader != 0) {
+                GLES20.glShaderSource(shader, source);
+                GLES20.glCompileShader(shader);
+                int[] compiled = new int[1];
+                GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
+                if (compiled[0] == 0) {
+                    Log.e(TAG, "Could not compile shader " + shaderType + ":");
+                    Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
+                    GLES20.glDeleteShader(shader);
+                    shader = 0;
+                }
+            }
+            return shader;
+        }
+
+        private int createProgram(String vertexSource, String fragmentSource) {
+            int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
+            if (vertexShader == 0) {
+                return 0;
+            }
+            int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
+            if (pixelShader == 0) {
+                return 0;
+            }
+
+            int program = GLES20.glCreateProgram();
+            if (program != 0) {
+                GLES20.glAttachShader(program, vertexShader);
+                checkGlError("glAttachShader");
+                GLES20.glAttachShader(program, pixelShader);
+                checkGlError("glAttachShader");
+                GLES20.glLinkProgram(program);
+                int[] linkStatus = new int[1];
+                GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
+                if (linkStatus[0] != GLES20.GL_TRUE) {
+                    Log.e(TAG, "Could not link program: ");
+                    Log.e(TAG, GLES20.glGetProgramInfoLog(program));
+                    GLES20.glDeleteProgram(program);
+                    program = 0;
+                }
+            }
+            return program;
+        }
+
+        private void checkGlError(String op) {
+            int error;
+            while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
+                Log.e(TAG, op + ": glError " + error);
+                throw new RuntimeException(op + ": glError " + error);
+            }
+        }
+
+    }  // End of class VideoRender.
+
+}  // End of class VideoSurfaceView.
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerSurfaceTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerSurfaceTest.java
new file mode 100644
index 0000000..196382d
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerSurfaceTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.os.Bundle;
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ */
+public class MediaPlayerSurfaceTest extends ActivityInstrumentationTestCase2<MediaPlayerSurfaceStubActivity> {
+
+    public MediaPlayerSurfaceTest() {
+        super("com.android.cts.stub", MediaPlayerSurfaceStubActivity.class);
+    }
+
+    public void testSetSurface() throws Exception {
+        Bundle extras = new Bundle();
+        MediaPlayerSurfaceStubActivity activity = launchActivity("com.android.cts.stub",
+                MediaPlayerSurfaceStubActivity.class, extras);
+        activity.playVideo();
+        activity.finish();
+    }
+}