/*
 * Copyright (C) 2013 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.app.Presentation;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.SurfaceTexture;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecInfo.CodecProfileLevel;
import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.opengl.Matrix;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.test.AndroidTestCase;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Size;
import android.view.Display;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import com.android.cts.media.R;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Tests to check if MediaCodec encoding works with composition of multiple virtual displays
 * The test also tries to destroy and create virtual displays repeatedly to
 * detect any issues. The test itself does not check the output as it is already done in other
 * tests.
 */
public class EncodeVirtualDisplayWithCompositionTest extends AndroidTestCase {
    private static final String TAG = "EncodeVirtualDisplayWithCompositionTest";
    private static final boolean DBG = true;
    private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;

    private static final long DEFAULT_WAIT_TIMEOUT_MS = 3000;
    private static final long DEFAULT_WAIT_TIMEOUT_US = 3000000;

    private static final int COLOR_RED =  makeColor(100, 0, 0);
    private static final int COLOR_BLUE =  makeColor(0, 100, 0);
    private static final int COLOR_GREEN =  makeColor(0, 0, 100);
    private static final int COLOR_GREY =  makeColor(100, 100, 100);

    private static final int BITRATE_1080p = 20000000;
    private static final int BITRATE_720p = 14000000;
    private static final int BITRATE_800x480 = 14000000;
    private static final int BITRATE_DEFAULT = 10000000;

    private static final int IFRAME_INTERVAL = 10;

    private static final int MAX_NUM_WINDOWS = 3;

    private static Handler sHandlerForRunOnMain = new Handler(Looper.getMainLooper());

    private Surface mEncodingSurface;
    private OutputSurface mDecodingSurface;
    private volatile boolean mCodecConfigReceived = false;
    private volatile boolean mCodecBufferReceived = false;
    private EncodingHelper mEncodingHelper;
    private MediaCodec mDecoder;
    private final ByteBuffer mPixelBuf = ByteBuffer.allocateDirect(4);
    private volatile boolean mIsQuitting = false;
    private Throwable mTestException;
    private VirtualDisplayPresentation mLocalPresentation;
    private RemoteVirtualDisplayPresentation mRemotePresentation;
    private ByteBuffer[] mDecoderInputBuffers;

    /** event listener for test without verifying output */
    private EncoderEventListener mEncoderEventListener = new EncoderEventListener() {
        @Override
        public void onCodecConfig(ByteBuffer data, MediaCodec.BufferInfo info) {
            mCodecConfigReceived = true;
        }
        @Override
        public void onBufferReady(ByteBuffer data, MediaCodec.BufferInfo info) {
            mCodecBufferReceived = true;
        }
        @Override
        public void onError(String errorMessage) {
            fail(errorMessage);
        }
    };

    /* TEST_COLORS static initialization; need ARGB for ColorDrawable */
    private static int makeColor(int red, int green, int blue) {
        return 0xff << 24 | (red & 0xff) << 16 | (green & 0xff) << 8 | (blue & 0xff);
    }

    public void testVirtualDisplayRecycles() throws Exception {
        doTestVirtualDisplayRecycles(3);
    }

    public void testRendering800x480Locally() throws Throwable {
        Log.i(TAG, "testRendering800x480Locally");
        if (isConcurrentEncodingDecodingSupported(800, 480, BITRATE_800x480)) {
            runTestRenderingInSeparateThread(800, 480, false, false);
        } else {
            Log.i(TAG, "SKIPPING testRendering800x480Locally(): codec not supported");
        }
    }

    public void testRenderingMaxResolutionLocally() throws Throwable {
        Log.i(TAG, "testRenderingMaxResolutionLocally");
        Size maxRes = checkMaxConcurrentEncodingDecodingResolution();
        if (maxRes == null) {
            Log.i(TAG, "SKIPPING testRenderingMaxResolutionLocally(): codec not supported");
        } else {
            Log.w(TAG, "Trying resolution " + maxRes);
            runTestRenderingInSeparateThread(maxRes.getWidth(), maxRes.getHeight(), false, false);
        }
    }

    public void testRendering800x480Remotely() throws Throwable {
        Log.i(TAG, "testRendering800x480Remotely");
        if (isConcurrentEncodingDecodingSupported(800, 480, BITRATE_800x480)) {
            runTestRenderingInSeparateThread(800, 480, true, false);
        } else {
            Log.i(TAG, "SKIPPING testRendering800x480Remotely(): codec not supported");
        }
    }

    public void testRenderingMaxResolutionRemotely() throws Throwable {
        Log.i(TAG, "testRenderingMaxResolutionRemotely");
        Size maxRes = checkMaxConcurrentEncodingDecodingResolution();
        if (maxRes == null) {
            Log.i(TAG, "SKIPPING testRenderingMaxResolutionRemotely(): codec not supported");
        } else {
            Log.w(TAG, "Trying resolution " + maxRes);
            runTestRenderingInSeparateThread(maxRes.getWidth(), maxRes.getHeight(), true, false);
        }
    }

    public void testRendering800x480RemotelyWith3Windows() throws Throwable {
        Log.i(TAG, "testRendering800x480RemotelyWith3Windows");
        if (isConcurrentEncodingDecodingSupported(800, 480, BITRATE_800x480)) {
            runTestRenderingInSeparateThread(800, 480, true, true);
        } else {
            Log.i(TAG, "SKIPPING testRendering800x480RemotelyWith3Windows(): codec not supported");
        }
    }

    public void testRendering800x480LocallyWith3Windows() throws Throwable {
        Log.i(TAG, "testRendering800x480LocallyWith3Windows");
        if (isConcurrentEncodingDecodingSupported(800, 480, BITRATE_800x480)) {
            runTestRenderingInSeparateThread(800, 480, false, true);
        } else {
            Log.i(TAG, "SKIPPING testRendering800x480LocallyWith3Windows(): codec not supported");
        }
    }

    /**
     * Run rendering test in a separate thread. This is necessary as {@link OutputSurface} requires
     * constructing it in a non-test thread.
     * @param w
     * @param h
     * @throws Exception
     */
    private void runTestRenderingInSeparateThread(final int w, final int h,
            final boolean runRemotely, final boolean multipleWindows) throws Throwable {
        mTestException = null;
        Thread renderingThread = new Thread(new Runnable() {
            public void run() {
                try {
                    doTestRenderingOutput(w, h, runRemotely, multipleWindows);
                } catch (Throwable t) {
                    t.printStackTrace();
                    mTestException = t;
                }
            }
        });
        renderingThread.start();
        renderingThread.join(60000);
        assertTrue(!renderingThread.isAlive());
        if (mTestException != null) {
            throw mTestException;
        }
    }

    private void doTestRenderingOutput(int w, int h, boolean runRemotely, boolean multipleWindows)
            throws Throwable {
        if (DBG) {
            Log.i(TAG, "doTestRenderingOutput for w:" + w + " h:" + h);
        }
        try {
            mIsQuitting = false;
            mDecoder = MediaCodec.createDecoderByType(MIME_TYPE);
            MediaFormat decoderFormat = MediaFormat.createVideoFormat(MIME_TYPE, w, h);
            mDecodingSurface = new OutputSurface(w, h);
            mDecoder.configure(decoderFormat, mDecodingSurface.getSurface(), null, 0);
            mDecoder.start();
            mDecoderInputBuffers = mDecoder.getInputBuffers();

            mEncodingHelper = new EncodingHelper();
            mEncodingSurface = mEncodingHelper.startEncoding(w, h,
                    new EncoderEventListener() {
                @Override
                public void onCodecConfig(ByteBuffer data, BufferInfo info) {
                    if (DBG) {
                        Log.i(TAG, "onCodecConfig l:" + info.size);
                    }
                    handleEncodedData(data, info);
                }

                @Override
                public void onBufferReady(ByteBuffer data, BufferInfo info) {
                    if (DBG) {
                        Log.i(TAG, "onBufferReady l:" + info.size);
                    }
                    handleEncodedData(data, info);
                }

                @Override
                public void onError(String errorMessage) {
                    fail(errorMessage);
                }

                private void handleEncodedData(ByteBuffer data, BufferInfo info) {
                    if (mIsQuitting) {
                        if (DBG) {
                            Log.i(TAG, "ignore data as test is quitting");
                        }
                        return;
                    }
                    int inputBufferIndex = mDecoder.dequeueInputBuffer(DEFAULT_WAIT_TIMEOUT_US);
                    if (inputBufferIndex < 0) {
                        if (DBG) {
                            Log.i(TAG, "dequeueInputBuffer returned:" + inputBufferIndex);
                        }
                        return;
                    }
                    assertTrue(inputBufferIndex >= 0);
                    ByteBuffer inputBuffer = mDecoderInputBuffers[inputBufferIndex];
                    inputBuffer.clear();
                    inputBuffer.put(data);
                    mDecoder.queueInputBuffer(inputBufferIndex, 0, info.size,
                            info.presentationTimeUs, info.flags);
                }
            });
            GlCompositor compositor = new GlCompositor();
            if (DBG) {
                Log.i(TAG, "start composition");
            }
            compositor.startComposition(mEncodingSurface, w, h, multipleWindows ? 3 : 1);

            if (DBG) {
                Log.i(TAG, "create display");
            }

            Renderer renderer = null;
            if (runRemotely) {
                mRemotePresentation = new RemoteVirtualDisplayPresentation(getContext(),
                        compositor.getWindowSurface(multipleWindows? 1 : 0), w, h);
                mRemotePresentation.connect();
                mRemotePresentation.start();
                renderer = mRemotePresentation;
            } else {
                mLocalPresentation = new VirtualDisplayPresentation(getContext(),
                        compositor.getWindowSurface(multipleWindows? 1 : 0), w, h);
                mLocalPresentation.createVirtualDisplay();
                mLocalPresentation.createPresentation();
                renderer = mLocalPresentation;
            }

            if (DBG) {
                Log.i(TAG, "start rendering and check");
            }
            renderColorAndCheckResult(renderer, w, h, COLOR_RED);
            renderColorAndCheckResult(renderer, w, h, COLOR_BLUE);
            renderColorAndCheckResult(renderer, w, h, COLOR_GREEN);
            renderColorAndCheckResult(renderer, w, h, COLOR_GREY);

            mIsQuitting = true;
            if (runRemotely) {
                mRemotePresentation.disconnect();
            } else {
                mLocalPresentation.dismissPresentation();
                mLocalPresentation.destroyVirtualDisplay();
            }

            compositor.stopComposition();
        } finally {
            if (mEncodingHelper != null) {
                mEncodingHelper.stopEncoding();
                mEncodingHelper = null;
            }
            if (mDecoder != null) {
                mDecoder.stop();
                mDecoder.release();
                mDecoder = null;
            }
            if (mDecodingSurface != null) {
                mDecodingSurface.release();
                mDecodingSurface = null;
            }
        }
    }

    private static final int NUM_MAX_RETRY = 120;
    private static final int IMAGE_WAIT_TIMEOUT_MS = 1000;

    private void renderColorAndCheckResult(Renderer renderer, int w, int h,
            int color) throws Exception {
        BufferInfo info = new BufferInfo();
        for (int i = 0; i < NUM_MAX_RETRY; i++) {
            renderer.doRendering(color);
            int bufferIndex = mDecoder.dequeueOutputBuffer(info,  DEFAULT_WAIT_TIMEOUT_US);
            if (DBG) {
                Log.i(TAG, "decoder dequeueOutputBuffer returned " + bufferIndex);
            }
            if (bufferIndex < 0) {
                continue;
            }
            mDecoder.releaseOutputBuffer(bufferIndex, true);
            if (mDecodingSurface.checkForNewImage(IMAGE_WAIT_TIMEOUT_MS)) {
                mDecodingSurface.drawImage();
                if (checkSurfaceFrameColor(w, h, color)) {
                    Log.i(TAG, "color " + Integer.toHexString(color) + " matched");
                    return;
                }
            } else if(DBG) {
                Log.i(TAG, "no rendering yet");
            }
        }
        fail("Color did not match");
    }

    private boolean checkSurfaceFrameColor(int w, int h, int color) {
        // Read a pixel from the center of the surface.  Might want to read from multiple points
        // and average them together.
        int x = w / 2;
        int y = h / 2;
        GLES20.glReadPixels(x, y, 1, 1, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mPixelBuf);
        int r = mPixelBuf.get(0) & 0xff;
        int g = mPixelBuf.get(1) & 0xff;
        int b = mPixelBuf.get(2) & 0xff;

        int redExpected = (color >> 16) & 0xff;
        int greenExpected = (color >> 8) & 0xff;
        int blueExpected = color & 0xff;
        if (approxEquals(redExpected, r) && approxEquals(greenExpected, g)
                && approxEquals(blueExpected, b)) {
            return true;
        }
        Log.i(TAG, "expected 0x" + Integer.toHexString(color) + " got 0x"
                + Integer.toHexString(makeColor(r, g, b)));
        return false;
    }

    /**
     * Determines if two color values are approximately equal.
     */
    private static boolean approxEquals(int expected, int actual) {
        final int MAX_DELTA = 4;
        return Math.abs(expected - actual) <= MAX_DELTA;
    }

    private static final int NUM_CODEC_CREATION = 5;
    private static final int NUM_DISPLAY_CREATION = 10;
    private static final int NUM_RENDERING = 10;
    private void doTestVirtualDisplayRecycles(int numDisplays) throws Exception {
        Size maxSize = getMaxSupportedEncoderSize();
        if (maxSize == null) {
            Log.i(TAG, "no codec found, skipping");
            return;
        }
        VirtualDisplayPresentation[] virtualDisplays = new VirtualDisplayPresentation[numDisplays];
        for (int i = 0; i < NUM_CODEC_CREATION; i++) {
            mCodecConfigReceived = false;
            mCodecBufferReceived = false;
            if (DBG) {
                Log.i(TAG, "start encoding");
            }
            EncodingHelper encodingHelper = new EncodingHelper();
            mEncodingSurface = encodingHelper.startEncoding(maxSize.getWidth(), maxSize.getHeight(),
                    mEncoderEventListener);
            GlCompositor compositor = new GlCompositor();
            if (DBG) {
                Log.i(TAG, "start composition");
            }
            compositor.startComposition(mEncodingSurface, maxSize.getWidth(), maxSize.getHeight(),
                    numDisplays);
            for (int j = 0; j < NUM_DISPLAY_CREATION; j++) {
                if (DBG) {
                    Log.i(TAG, "create display");
                }
                for (int k = 0; k < numDisplays; k++) {
                    virtualDisplays[k] =
                        new VirtualDisplayPresentation(getContext(),
                                compositor.getWindowSurface(k),
                                maxSize.getWidth()/numDisplays, maxSize.getHeight());
                    virtualDisplays[k].createVirtualDisplay();
                    virtualDisplays[k].createPresentation();
                }
                if (DBG) {
                    Log.i(TAG, "start rendering");
                }
                for (int k = 0; k < NUM_RENDERING; k++) {
                    for (int l = 0; l < numDisplays; l++) {
                        virtualDisplays[l].doRendering(COLOR_RED);
                    }
                    // do not care how many frames are actually rendered.
                    Thread.sleep(1);
                }
                for (int k = 0; k < numDisplays; k++) {
                    virtualDisplays[k].dismissPresentation();
                    virtualDisplays[k].destroyVirtualDisplay();
                }
                compositor.recreateWindows();
            }
            if (DBG) {
                Log.i(TAG, "stop composition");
            }
            compositor.stopComposition();
            if (DBG) {
                Log.i(TAG, "stop encoding");
            }
            encodingHelper.stopEncoding();
            assertTrue(mCodecConfigReceived);
            assertTrue(mCodecBufferReceived);
        }
    }

    interface EncoderEventListener {
        public void onCodecConfig(ByteBuffer data, MediaCodec.BufferInfo info);
        public void onBufferReady(ByteBuffer data, MediaCodec.BufferInfo info);
        public void onError(String errorMessage);
    }

    private class EncodingHelper {
        private MediaCodec mEncoder;
        private volatile boolean mStopEncoding = false;
        private EncoderEventListener mEventListener;
        private int mW;
        private int mH;
        private Thread mEncodingThread;
        private Surface mEncodingSurface;
        private Semaphore mInitCompleted = new Semaphore(0);

        Surface startEncoding(int w, int h, EncoderEventListener eventListener) {
            mStopEncoding = false;
            mW = w;
            mH = h;
            mEventListener = eventListener;
            mEncodingThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        doEncoding();
                    } catch (Exception e) {
                        e.printStackTrace();
                        mEventListener.onError(e.toString());
                    }
                }
            });
            mEncodingThread.start();
            try {
                if (DBG) {
                    Log.i(TAG, "wait for encoder init");
                }
                mInitCompleted.acquire();
                if (DBG) {
                    Log.i(TAG, "wait for encoder done");
                }
            } catch (InterruptedException e) {
                fail("should not happen");
            }
            return mEncodingSurface;
        }

        void stopEncoding() {
            try {
                mStopEncoding = true;
                mEncodingThread.join();
            } catch(InterruptedException e) {
                // just ignore
            } finally {
                mEncodingThread = null;
            }
        }

        private void doEncoding() throws Exception {
            final int TIMEOUT_USEC_NORMAL = 1000000;
            MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mW, mH);
            format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
                    MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
            int bitRate = BITRATE_DEFAULT;
            if (mW == 1920 && mH == 1080) {
                bitRate = BITRATE_1080p;
            } else if (mW == 1280 && mH == 720) {
                bitRate = BITRATE_720p;
            } else if (mW == 800 && mH == 480) {
                bitRate = BITRATE_800x480;
            }
            format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
            format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
            format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
            mEncoder = MediaCodec.createEncoderByType(MIME_TYPE);
            mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            mEncodingSurface = mEncoder.createInputSurface();
            mEncoder.start();
            mInitCompleted.release();
            if (DBG) {
                Log.i(TAG, "starting encoder");
            }
            try {
                ByteBuffer[] encoderOutputBuffers = mEncoder.getOutputBuffers();
                MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
                while (!mStopEncoding) {
                    int index = mEncoder.dequeueOutputBuffer(info, TIMEOUT_USEC_NORMAL);
                    if (DBG) {
                        Log.i(TAG, "encoder dequeOutputBuffer returned " + index);
                    }
                    if (index >= 0) {
                        if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
                            Log.i(TAG, "codec config data");
                            ByteBuffer encodedData = encoderOutputBuffers[index];
                            encodedData.position(info.offset);
                            encodedData.limit(info.offset + info.size);
                            mEventListener.onCodecConfig(encodedData, info);
                            mEncoder.releaseOutputBuffer(index, false);
                        } else if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                            Log.i(TAG, "EOS, stopping encoding");
                            break;
                        } else {
                            ByteBuffer encodedData = encoderOutputBuffers[index];
                            encodedData.position(info.offset);
                            encodedData.limit(info.offset + info.size);
                            mEventListener.onBufferReady(encodedData, info);
                            mEncoder.releaseOutputBuffer(index, false);
                        }
                    } else if (index == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED){
                        Log.i(TAG, "output buffer changed");
                        encoderOutputBuffers = mEncoder.getOutputBuffers();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw e;
            } finally {
                mEncoder.stop();
                mEncoder.release();
                mEncoder = null;
                mEncodingSurface.release();
                mEncodingSurface = null;
            }
        }
    }

    /**
     * Handles composition of multiple SurfaceTexture into a single Surface
     */
    private class GlCompositor implements SurfaceTexture.OnFrameAvailableListener {
        private Surface mSurface;
        private int mWidth;
        private int mHeight;
        private volatile int mNumWindows;
        private GlWindow mTopWindow;
        private Thread mCompositionThread;
        private Semaphore mStartCompletionSemaphore;
        private Semaphore mRecreationCompletionSemaphore;
        private Looper mLooper;
        private Handler mHandler;
        private InputSurface mEglHelper;
        private int mGlProgramId = 0;
        private int mGluMVPMatrixHandle;
        private int mGluSTMatrixHandle;
        private int mGlaPositionHandle;
        private int mGlaTextureHandle;
        private float[] mMVPMatrix = new float[16];
        private TopWindowVirtualDisplayPresentation mTopPresentation;

        private static final String VERTEX_SHADER =
                "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 static final String FRAGMENT_SHADER =
                "#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";

        void startComposition(Surface surface, int w, int h, int numWindows) throws Exception {
            mSurface = surface;
            mWidth = w;
            mHeight = h;
            mNumWindows = numWindows;
            mCompositionThread = new Thread(new CompositionRunnable());
            mStartCompletionSemaphore = new Semaphore(0);
            mCompositionThread.start();
            waitForStartCompletion();
        }

        void stopComposition() {
            try {
                if (mLooper != null) {
                    mLooper.quit();
                    mCompositionThread.join();
                }
            } catch (InterruptedException e) {
                // don't care
            }
            mCompositionThread = null;
            mSurface = null;
            mStartCompletionSemaphore = null;
        }

        Surface getWindowSurface(int windowIndex) {
            return mTopPresentation.getSurface(windowIndex);
        }

        void recreateWindows() throws Exception {
            mRecreationCompletionSemaphore = new Semaphore(0);
            Message msg = mHandler.obtainMessage(CompositionHandler.DO_RECREATE_WINDOWS);
            mHandler.sendMessage(msg);
            if(!mRecreationCompletionSemaphore.tryAcquire(DEFAULT_WAIT_TIMEOUT_MS,
                    TimeUnit.MILLISECONDS)) {
                fail("recreation timeout");
            }
            mTopPresentation.waitForSurfaceReady(DEFAULT_WAIT_TIMEOUT_MS);
        }

        @Override
        public void onFrameAvailable(SurfaceTexture surface) {
            if (DBG) {
                Log.i(TAG, "onFrameAvailable " + surface);
            }
            GlWindow w = mTopWindow;
            if (w != null) {
                w.markTextureUpdated();
                requestUpdate();
            } else {
                Log.w(TAG, "top window gone");
            }
        }

        private void requestUpdate() {
            Thread compositionThread = mCompositionThread;
            if (compositionThread == null || !compositionThread.isAlive()) {
                return;
            }
            Message msg = mHandler.obtainMessage(CompositionHandler.DO_RENDERING);
            mHandler.sendMessage(msg);
        }

        private int loadShader(int shaderType, String source) throws GlException {
            int shader = GLES20.glCreateShader(shaderType);
            checkGlError("glCreateShader type=" + shaderType);
            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) throws GlException {
            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();
            checkGlError("glCreateProgram");
            if (program == 0) {
                Log.e(TAG, "Could not create program");
            }
            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 initGl() throws GlException {
            mEglHelper = new InputSurface(mSurface);
            mEglHelper.makeCurrent();
            mGlProgramId = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
            mGlaPositionHandle = GLES20.glGetAttribLocation(mGlProgramId, "aPosition");
            checkGlError("glGetAttribLocation aPosition");
            if (mGlaPositionHandle == -1) {
                throw new RuntimeException("Could not get attrib location for aPosition");
            }
            mGlaTextureHandle = GLES20.glGetAttribLocation(mGlProgramId, "aTextureCoord");
            checkGlError("glGetAttribLocation aTextureCoord");
            if (mGlaTextureHandle == -1) {
                throw new RuntimeException("Could not get attrib location for aTextureCoord");
            }
            mGluMVPMatrixHandle = GLES20.glGetUniformLocation(mGlProgramId, "uMVPMatrix");
            checkGlError("glGetUniformLocation uMVPMatrix");
            if (mGluMVPMatrixHandle == -1) {
                throw new RuntimeException("Could not get attrib location for uMVPMatrix");
            }
            mGluSTMatrixHandle = GLES20.glGetUniformLocation(mGlProgramId, "uSTMatrix");
            checkGlError("glGetUniformLocation uSTMatrix");
            if (mGluSTMatrixHandle == -1) {
                throw new RuntimeException("Could not get attrib location for uSTMatrix");
            }
            Matrix.setIdentityM(mMVPMatrix, 0);
            Log.i(TAG, "initGl w:" + mWidth + " h:" + mHeight);
            GLES20.glViewport(0, 0, mWidth, mHeight);
            float[] vMatrix = new float[16];
            float[] projMatrix = new float[16];
            // max window is from (0,0) to (mWidth - 1, mHeight - 1)
            float wMid = mWidth / 2f;
            float hMid = mHeight / 2f;
            // look from positive z to hide windows in lower z
            Matrix.setLookAtM(vMatrix, 0, wMid, hMid, 5f, wMid, hMid, 0f, 0f, 1.0f, 0.0f);
            Matrix.orthoM(projMatrix, 0, -wMid, wMid, -hMid, hMid, 1, 10);
            Matrix.multiplyMM(mMVPMatrix, 0, projMatrix, 0, vMatrix, 0);
            createWindows();

        }

        private void createWindows() throws GlException {
            mTopWindow = new GlWindow(this, 0, 0, mWidth, mHeight);
            mTopWindow.init();
            mTopPresentation = new TopWindowVirtualDisplayPresentation(mContext,
                    mTopWindow.getSurface(), mWidth, mHeight, mNumWindows);
            mTopPresentation.createVirtualDisplay();
            mTopPresentation.createPresentation();
            ((TopWindowPresentation) mTopPresentation.getPresentation()).populateWindows();
        }

        private void cleanupGl() {
            if (mTopPresentation != null) {
                mTopPresentation.dismissPresentation();
                mTopPresentation.destroyVirtualDisplay();
            }
            if (mTopWindow != null) {
                mTopWindow.cleanup();
            }
            if (mEglHelper != null) {
                mEglHelper.release();
            }
        }

        private void doGlRendering() throws GlException {
            if (DBG) {
                Log.i(TAG, "doGlRendering");
            }
            mTopWindow.updateTexImageIfNecessary();
            GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
            GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

            GLES20.glUseProgram(mGlProgramId);
            GLES20.glUniformMatrix4fv(mGluMVPMatrixHandle, 1, false, mMVPMatrix, 0);
            mTopWindow.onDraw(mGluSTMatrixHandle, mGlaPositionHandle, mGlaTextureHandle);
            checkGlError("window draw");
            if (DBG) {
                final IntBuffer pixels = IntBuffer.allocate(1);
                GLES20.glReadPixels(mWidth / 2, mHeight / 2, 1, 1,
                        GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixels);
                Log.i(TAG, "glReadPixels returned 0x" + Integer.toHexString(pixels.get(0)));
            }
            mEglHelper.swapBuffers();
        }

        private void doRecreateWindows() throws GlException {
            mTopPresentation.dismissPresentation();
            mTopPresentation.destroyVirtualDisplay();
            mTopWindow.cleanup();
            createWindows();
            mRecreationCompletionSemaphore.release();
        }

        private void waitForStartCompletion() throws Exception {
            if (!mStartCompletionSemaphore.tryAcquire(DEFAULT_WAIT_TIMEOUT_MS,
                    TimeUnit.MILLISECONDS)) {
                fail("start timeout");
            }
            mStartCompletionSemaphore = null;
            mTopPresentation.waitForSurfaceReady(DEFAULT_WAIT_TIMEOUT_MS);
        }

        private class CompositionRunnable implements Runnable {
            @Override
            public void run() {
                try {
                    Looper.prepare();
                    mLooper = Looper.myLooper();
                    mHandler = new CompositionHandler();
                    initGl();
                    // init done
                    mStartCompletionSemaphore.release();
                    Looper.loop();
                } catch (GlException e) {
                    e.printStackTrace();
                    fail("got gl exception");
                } finally {
                    cleanupGl();
                    mHandler = null;
                    mLooper = null;
                }
            }
        }

        private class CompositionHandler extends Handler {
            private static final int DO_RENDERING = 1;
            private static final int DO_RECREATE_WINDOWS = 2;

            @Override
            public void handleMessage(Message msg) {
                try {
                    switch(msg.what) {
                        case DO_RENDERING: {
                            doGlRendering();
                        } break;
                        case DO_RECREATE_WINDOWS: {
                            doRecreateWindows();
                        } break;
                    }
                } catch (GlException e) {
                    //ignore as this can happen during tearing down
                }
            }
        }

        private class GlWindow {
            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 int mBlX;
            private int mBlY;
            private int mWidth;
            private int mHeight;
            private int mTextureId = 0; // 0 is invalid
            private volatile SurfaceTexture mSurfaceTexture;
            private volatile Surface mSurface;
            private FloatBuffer mVerticesData;
            private float[] mSTMatrix = new float[16];
            private AtomicInteger mNumTextureUpdated = new AtomicInteger(0);
            private GlCompositor mCompositor;

            /**
             * @param blX X coordinate of bottom-left point of window
             * @param blY Y coordinate of bottom-left point of window
             * @param w window width
             * @param h window height
             */
            public GlWindow(GlCompositor compositor, int blX, int blY, int w, int h) {
                mCompositor = compositor;
                mBlX = blX;
                mBlY = blY;
                mWidth = w;
                mHeight = h;
                int trX = blX + w;
                int trY = blY + h;
                float[] vertices = new float[] {
                        // x, y, z, u, v
                        mBlX, mBlY, 0, 0, 0,
                        trX, mBlY, 0, 1, 0,
                        mBlX, trY, 0, 0, 1,
                        trX, trY, 0, 1, 1
                };
                Log.i(TAG, "create window " + this + " blX:" + mBlX + " blY:" + mBlY + " trX:" +
                        trX + " trY:" + trY);
                mVerticesData = ByteBuffer.allocateDirect(
                        vertices.length * FLOAT_SIZE_BYTES)
                                .order(ByteOrder.nativeOrder()).asFloatBuffer();
                mVerticesData.put(vertices).position(0);
            }

            /**
             * initialize the window for composition. counter-part is cleanup()
             * @throws GlException
             */
            public void init() throws GlException {
                int[] textures = new int[1];
                GLES20.glGenTextures(1, textures, 0);

                mTextureId = textures[0];
                GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureId);
                checkGlError("glBindTexture mTextureID");

                GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
                        GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
                GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
                        GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
                GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S,
                        GLES20.GL_CLAMP_TO_EDGE);
                GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T,
                        GLES20.GL_CLAMP_TO_EDGE);
                checkGlError("glTexParameter");
                mSurfaceTexture = new SurfaceTexture(mTextureId);
                mSurfaceTexture.setDefaultBufferSize(mWidth, mHeight);
                mSurface = new Surface(mSurfaceTexture);
                mSurfaceTexture.setOnFrameAvailableListener(mCompositor);
            }

            public void cleanup() {
                mNumTextureUpdated.set(0);
                if (mTextureId != 0) {
                    int[] textures = new int[] {
                            mTextureId
                    };
                    GLES20.glDeleteTextures(1, textures, 0);
                }
                GLES20.glFinish();
                if (mSurface != null) {
                    mSurface.release();
                    mSurface = null;
                }
                if (mSurfaceTexture != null) {
                    mSurfaceTexture.release();
                    mSurfaceTexture = null;
                }
            }

            /**
             * make texture as updated so that it can be updated in the next rendering.
             */
            public void markTextureUpdated() {
                mNumTextureUpdated.incrementAndGet();
            }

            /**
             * update texture for rendering if it is updated.
             */
            public void updateTexImageIfNecessary() {
                int numTextureUpdated = mNumTextureUpdated.getAndDecrement();
                if (numTextureUpdated > 0) {
                    if (DBG) {
                        Log.i(TAG, "updateTexImageIfNecessary " + this);
                    }
                    mSurfaceTexture.updateTexImage();
                    mSurfaceTexture.getTransformMatrix(mSTMatrix);
                }
                if (numTextureUpdated < 0) {
                    fail("should not happen");
                }
            }

            /**
             * draw the window. It will not be drawn at all if the window is not visible.
             * @param uSTMatrixHandle shader handler for the STMatrix for texture coordinates
             * mapping
             * @param aPositionHandle shader handle for vertex position.
             * @param aTextureHandle shader handle for texture
             */
            public void onDraw(int uSTMatrixHandle, int aPositionHandle, int aTextureHandle) {
                GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
                GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureId);
                mVerticesData.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
                GLES20.glVertexAttribPointer(aPositionHandle, 3, GLES20.GL_FLOAT, false,
                    TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mVerticesData);
                GLES20.glEnableVertexAttribArray(aPositionHandle);

                mVerticesData.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
                GLES20.glVertexAttribPointer(aTextureHandle, 2, GLES20.GL_FLOAT, false,
                    TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mVerticesData);
                GLES20.glEnableVertexAttribArray(aTextureHandle);
                GLES20.glUniformMatrix4fv(uSTMatrixHandle, 1, false, mSTMatrix, 0);
                GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
            }

            public SurfaceTexture getSurfaceTexture() {
                return mSurfaceTexture;
            }

            public Surface getSurface() {
                return mSurface;
            }
        }
    }

    static void checkGlError(String op) throws GlException {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            Log.e(TAG, op + ": glError " + error);
            throw new GlException(op + ": glError " + error);
        }
    }

    public static class GlException extends Exception {
        public GlException(String msg) {
            super(msg);
        }
    }

    private interface Renderer {
        void doRendering(final int color) throws Exception;
    }

    private static class VirtualDisplayPresentation implements Renderer {
        protected final Context mContext;
        protected final Surface mSurface;
        protected final int mWidth;
        protected final int mHeight;
        protected VirtualDisplay mVirtualDisplay;
        protected TestPresentationBase mPresentation;
        private final DisplayManager mDisplayManager;

        VirtualDisplayPresentation(Context context, Surface surface, int w, int h) {
            mContext = context;
            mSurface = surface;
            mWidth = w;
            mHeight = h;
            mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
        }

        void createVirtualDisplay() {
            runOnMainSync(new Runnable() {
                @Override
                public void run() {
                    mVirtualDisplay = mDisplayManager.createVirtualDisplay(
                            TAG, mWidth, mHeight, 200, mSurface,
                            DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY |
                            DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION);
                }
            });
        }

        void destroyVirtualDisplay() {
            runOnMainSync(new Runnable() {
                @Override
                public void run() {
                    mVirtualDisplay.release();
                }
            });
        }

        void createPresentation() {
            runOnMainSync(new Runnable() {
                @Override
                public void run() {
                    mPresentation = doCreatePresentation();
                    mPresentation.show();
                }
            });
        }

        protected TestPresentationBase doCreatePresentation() {
            return new TestPresentation(mContext, mVirtualDisplay.getDisplay());
        }

        TestPresentationBase getPresentation() {
            return mPresentation;
        }

        void dismissPresentation() {
            runOnMainSync(new Runnable() {
                @Override
                public void run() {
                    mPresentation.dismiss();
                }
            });
        }

        @Override
        public void doRendering(final int color) throws Exception {
            runOnMainSync(new Runnable() {
                @Override
                public void run() {
                    mPresentation.doRendering(color);
                }
            });
        }
    }

    private static class TestPresentationBase extends Presentation {

        public TestPresentationBase(Context outerContext, Display display) {
            // This theme is required to prevent an extra view from obscuring the presentation
            super(outerContext, display,
                    android.R.style.Theme_Holo_Light_NoActionBar_TranslucentDecor);
            getWindow().setType(WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
        }

        public void doRendering(int color) {
            // to be implemented by child
        }
    }

    private static class TestPresentation extends TestPresentationBase {
        private ImageView mImageView;

        public TestPresentation(Context outerContext, Display display) {
            super(outerContext, display);
        }

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mImageView = new ImageView(getContext());
            mImageView.setImageDrawable(new ColorDrawable(COLOR_RED));
            mImageView.setLayoutParams(new LayoutParams(
                    LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
            setContentView(mImageView);
        }

        public void doRendering(int color) {
            if (DBG) {
                Log.i(TAG, "doRendering " + Integer.toHexString(color));
            }
            mImageView.setImageDrawable(new ColorDrawable(color));
        }
    }

    private static class TopWindowPresentation extends TestPresentationBase {
        private FrameLayout[] mWindowsLayout = new FrameLayout[MAX_NUM_WINDOWS];
        private CompositionTextureView[] mWindows = new CompositionTextureView[MAX_NUM_WINDOWS];
        private final int mNumWindows;
        private final Semaphore mWindowWaitSemaphore = new Semaphore(0);

        public TopWindowPresentation(int numWindows, Context outerContext, Display display) {
            super(outerContext, display);
            mNumWindows = numWindows;
        }

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            if (DBG) {
                Log.i(TAG, "TopWindowPresentation onCreate, numWindows " + mNumWindows);
            }
            setContentView(R.layout.composition_layout);
            mWindowsLayout[0] = (FrameLayout) findViewById(R.id.window0);
            mWindowsLayout[1] = (FrameLayout) findViewById(R.id.window1);
            mWindowsLayout[2] = (FrameLayout) findViewById(R.id.window2);
        }

        public void populateWindows() {
            runOnMain(new Runnable() {
                public void run() {
                    for (int i = 0; i < mNumWindows; i++) {
                        mWindows[i] = new CompositionTextureView(getContext());
                        mWindows[i].setLayoutParams(new ViewGroup.LayoutParams(
                                ViewGroup.LayoutParams.MATCH_PARENT,
                                ViewGroup.LayoutParams.MATCH_PARENT));
                        mWindowsLayout[i].setVisibility(View.VISIBLE);
                        mWindowsLayout[i].addView(mWindows[i]);
                        mWindows[i].startListening();
                    }
                    mWindowWaitSemaphore.release();
                }
            });
        }

        public void waitForSurfaceReady(long timeoutMs) throws Exception {
            mWindowWaitSemaphore.tryAcquire(DEFAULT_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
            for (int i = 0; i < mNumWindows; i++) {
                if(!mWindows[i].waitForSurfaceReady(timeoutMs)) {
                    fail("surface wait timeout");
                }
            }
        }

        public Surface getSurface(int windowIndex) {
            Surface surface = mWindows[windowIndex].getSurface();
            assertNotNull(surface);
            return surface;
        }
    }

    private static class TopWindowVirtualDisplayPresentation extends VirtualDisplayPresentation {
        private final int mNumWindows;

        TopWindowVirtualDisplayPresentation(Context context, Surface surface, int w, int h,
                int numWindows) {
            super(context, surface, w, h);
            assertNotNull(surface);
            mNumWindows = numWindows;
        }

        void waitForSurfaceReady(long timeoutMs) throws Exception {
            ((TopWindowPresentation) mPresentation).waitForSurfaceReady(timeoutMs);
        }

        Surface getSurface(int windowIndex) {
            return ((TopWindowPresentation) mPresentation).getSurface(windowIndex);
        }

        protected TestPresentationBase doCreatePresentation() {
            return new TopWindowPresentation(mNumWindows, mContext, mVirtualDisplay.getDisplay());
        }
    }

    private static class RemoteVirtualDisplayPresentation implements Renderer {
        /** argument: Surface, int w, int h, return none */
        private static final int BINDER_CMD_START = IBinder.FIRST_CALL_TRANSACTION;
        /** argument: int color, return none */
        private static final int BINDER_CMD_RENDER = IBinder.FIRST_CALL_TRANSACTION + 1;

        private final Context mContext;
        private final Surface mSurface;
        private final int mWidth;
        private final int mHeight;

        private IBinder mService;
        private final Semaphore mConnectionWait = new Semaphore(0);
        private final ServiceConnection mConnection = new ServiceConnection() {

            public void onServiceConnected(ComponentName arg0, IBinder arg1) {
                mService = arg1;
                mConnectionWait.release();
            }

            public void onServiceDisconnected(ComponentName arg0) {
                //ignore
            }

        };

        RemoteVirtualDisplayPresentation(Context context, Surface surface, int w, int h) {
            mContext = context;
            mSurface = surface;
            mWidth = w;
            mHeight = h;
        }

        void connect() throws Exception {
            Intent intent = new Intent();
            intent.setClassName("com.android.cts.media",
                    "android.media.cts.RemoteVirtualDisplayService");
            mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
            if (!mConnectionWait.tryAcquire(DEFAULT_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                fail("cannot bind to service");
            }
        }

        void disconnect() {
            mContext.unbindService(mConnection);
        }

        void start() throws Exception {
            Parcel parcel = Parcel.obtain();
            mSurface.writeToParcel(parcel, 0);
            parcel.writeInt(mWidth);
            parcel.writeInt(mHeight);
            mService.transact(BINDER_CMD_START, parcel, null, 0);
        }

        @Override
        public void doRendering(int color) throws Exception {
            Parcel parcel = Parcel.obtain();
            parcel.writeInt(color);
            mService.transact(BINDER_CMD_RENDER, parcel, null, 0);
        }
    }

    private static Size getMaxSupportedEncoderSize() {
        final Size[] standardSizes = new Size[] {
            new Size(1920, 1080),
            new Size(1280, 720),
            new Size(720, 480),
            new Size(352, 576)
        };

        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
        for (Size sz : standardSizes) {
            MediaFormat format = MediaFormat.createVideoFormat(
                MIME_TYPE, sz.getWidth(), sz.getHeight());
            format.setInteger(MediaFormat.KEY_FRAME_RATE, 15); // require at least 15fps
            if (mcl.findEncoderForFormat(format) != null) {
                return sz;
            }
        }
        return null;
    }

    /**
     * Check maximum concurrent encoding / decoding resolution allowed.
     * Some H/Ws cannot support maximum resolution reported in encoder if decoder is running
     * at the same time.
     * Check is done for 4 different levels: 1080p, 720p, 800x480, 480p
     * (The last one is required by CDD.)
     */
    private Size checkMaxConcurrentEncodingDecodingResolution() {
        if (isConcurrentEncodingDecodingSupported(1920, 1080, BITRATE_1080p)) {
            return new Size(1920, 1080);
        } else if (isConcurrentEncodingDecodingSupported(1280, 720, BITRATE_720p)) {
            return new Size(1280, 720);
        } else if (isConcurrentEncodingDecodingSupported(800, 480, BITRATE_800x480)) {
            return new Size(800, 480);
        } else if (isConcurrentEncodingDecodingSupported(720, 480, BITRATE_DEFAULT)) {
            return new Size(720, 480);
        }
        Log.i(TAG, "SKIPPING test: concurrent encoding and decoding is not supported");
        return null;
    }

    private boolean isConcurrentEncodingDecodingSupported(int w, int h, int bitRate) {
        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
        MediaFormat testFormat = MediaFormat.createVideoFormat(MIME_TYPE, w, h);
        testFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
        if (mcl.findDecoderForFormat(testFormat) == null
                || mcl.findEncoderForFormat(testFormat) == null) {
            return false;
        }

        MediaCodec decoder = null;
        OutputSurface decodingSurface = null;
        MediaCodec encoder = null;
        Surface encodingSurface = null;
        try {
            decoder = MediaCodec.createDecoderByType(MIME_TYPE);
            MediaFormat decoderFormat = MediaFormat.createVideoFormat(MIME_TYPE, w, h);
            decodingSurface = new OutputSurface(w, h);
            decodingSurface.makeCurrent();
            decoder.configure(decoderFormat, decodingSurface.getSurface(), null, 0);
            decoder.start();

            MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, w, h);
            format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
                    MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
            format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
            format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
            format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
            encoder = MediaCodec.createEncoderByType(MIME_TYPE);;
            encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            encodingSurface = encoder.createInputSurface();
            encoder.start();

            encoder.stop();
            decoder.stop();
        } catch (Exception e) {
            e.printStackTrace();
            Log.i(TAG, "This H/W does not support w:" + w + " h:" + h);
            return false;
        } finally {
            if (encodingSurface != null) {
                encodingSurface.release();
            }
            if (encoder != null) {
                encoder.release();
            }
            if (decoder != null) {
                decoder.release();
            }
            if (decodingSurface != null) {
                decodingSurface.release();
            }
        }
        return true;
    }

    private static void runOnMain(Runnable runner) {
        sHandlerForRunOnMain.post(runner);
    }

    private static void runOnMainSync(Runnable runner) {
        SyncRunnable sr = new SyncRunnable(runner);
        sHandlerForRunOnMain.post(sr);
        sr.waitForComplete();
    }

    private static final class SyncRunnable implements Runnable {
        private final Runnable mTarget;
        private boolean mComplete;

        public SyncRunnable(Runnable target) {
            mTarget = target;
        }

        public void run() {
            mTarget.run();
            synchronized (this) {
                mComplete = true;
                notifyAll();
            }
        }

        public void waitForComplete() {
            synchronized (this) {
                while (!mComplete) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        //ignore
                    }
                }
            }
        }
    }
}
