1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.cts.verifier.streamquality;
18
19import com.android.cts.verifier.PassFailButtons;
20import com.android.cts.verifier.R;
21import com.android.cts.verifier.streamquality.StreamingVideoActivity.Stream;
22
23import android.app.AlertDialog;
24import android.app.Dialog;
25import android.content.DialogInterface;
26import android.content.DialogInterface.OnClickListener;
27import android.graphics.Rect;
28import android.media.MediaPlayer;
29import android.media.MediaPlayer.OnErrorListener;
30import android.media.MediaPlayer.OnPreparedListener;
31import android.media.MediaPlayer.OnVideoSizeChangedListener;
32import android.os.Bundle;
33import android.os.Handler;
34import android.util.Log;
35import android.view.SurfaceHolder;
36import android.view.SurfaceView;
37import android.view.ViewGroup.LayoutParams;
38import android.widget.FrameLayout;
39
40import java.io.IOException;
41
42/**
43 * Activity that plays a video and allows the user to select pass/fail after 60 seconds.
44 */
45public class PlayVideoActivity extends PassFailButtons.Activity
46        implements SurfaceHolder.Callback, OnErrorListener, OnPreparedListener,
47        OnVideoSizeChangedListener {
48    /**
49     * Intent extra defining the {@link Stream} information
50     */
51    static final String EXTRA_STREAM = "com.android.cts.verifier.streamquality.EXTRA_STREAM";
52
53    private static final String TAG = PlayVideoActivity.class.getName();
54    private static final long ENABLE_PASS_DELAY = 60 * 1000;
55
56    private static final int FAIL_DIALOG_ID = 1;
57
58    private final Runnable enablePassButton = new Runnable() {
59        @Override public void run() {
60            setEnablePassButton(true);
61        }
62    };
63
64    private Stream mStream;
65    private SurfaceHolder mHolder;
66    private SurfaceView mSurfaceView;
67    private FrameLayout mVideoFrame;
68    private MediaPlayer mPlayer;
69    private Handler mHandler = new Handler();
70    private int mVideoWidth;
71    private int mVideoHeight;
72
73    @Override
74    protected void onCreate(Bundle savedInstanceState) {
75        super.onCreate(savedInstanceState);
76        setContentView(R.layout.sv_play);
77        setPassFailButtonClickListeners();
78
79        setEnablePassButton(false);
80
81        mSurfaceView = (SurfaceView) findViewById(R.id.surface);
82        mVideoFrame = (FrameLayout) findViewById(R.id.videoframe);
83        mHolder = mSurfaceView.getHolder();
84        mHolder.addCallback(this);
85        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
86
87        mStream = (Stream) getIntent().getSerializableExtra(EXTRA_STREAM);
88    }
89
90    private void setEnablePassButton(boolean enable) {
91        getPassButton().setEnabled(enable);
92    }
93
94    private void playVideo() {
95        mPlayer = new MediaPlayer();
96        mPlayer.setDisplay(mHolder);
97        mPlayer.setScreenOnWhilePlaying(true);
98        mPlayer.setOnVideoSizeChangedListener(this);
99        mPlayer.setOnErrorListener(this);
100        mPlayer.setOnPreparedListener(this);
101        try {
102            mPlayer.setDataSource(mStream.uri);
103        } catch (IOException e) {
104            Log.e(TAG, "Unable to play video, setDataSource failed", e);
105            showDialog(FAIL_DIALOG_ID);
106            return;
107        }
108        mPlayer.prepareAsync();
109    }
110
111    @Override
112    public Dialog onCreateDialog(int id, Bundle args) {
113        switch (id) {
114            case FAIL_DIALOG_ID:
115                return new AlertDialog.Builder(this)
116                        .setTitle(getString(R.string.sv_failed_title))
117                        .setMessage(getString(R.string.sv_failed_message))
118                        .setNegativeButton("Close", new OnClickListener() {
119                            @Override
120                            public void onClick(DialogInterface dialog, int which) {
121                                setTestResultAndFinish(false);
122                            }
123                        })
124                        .show();
125            default:
126                return super.onCreateDialog(id, args);
127        }
128    }
129
130    @Override
131    public String getTestId() {
132        return getTestId(mStream.code);
133    }
134
135    public static String getTestId(String code) {
136        return PlayVideoActivity.class.getName() + "_" + code;
137    }
138
139    @Override
140    protected void onPause() {
141        super.onPause();
142        // This test must be completed in one session
143        mHandler.removeCallbacks(enablePassButton);
144        finish();
145    }
146
147    @Override
148    protected void onDestroy() {
149        super.onDestroy();
150        if (mPlayer != null) {
151            mPlayer.release();
152            mPlayer = null;
153        }
154    }
155
156    @Override
157    public void surfaceCreated(SurfaceHolder holder) {
158        playVideo();
159    }
160
161    @Override
162    public boolean onError(MediaPlayer mp, int what, int extra) {
163        Log.e(TAG, "Unable to play video, got onError with code " + what + ", extra " + extra);
164        showDialog(FAIL_DIALOG_ID);
165        return true;
166    }
167
168    @Override
169    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
170        if (width != 0 && height != 0) {
171            mVideoWidth = width;
172            mVideoHeight = height;
173            fillScreen();
174        }
175    }
176
177    private void startVideoPlayback() {
178        mPlayer.start();
179
180        // Enable Pass button after 60 seconds
181        mHandler.postDelayed(enablePassButton, ENABLE_PASS_DELAY);
182    }
183
184    @Override
185    public void onPrepared(MediaPlayer mp) {
186        startVideoPlayback();
187    }
188
189    private void fillScreen() {
190        mHolder.setFixedSize(mVideoWidth, mVideoHeight);
191        Rect rect = new Rect();
192        mVideoFrame.getDrawingRect(rect);
193        LayoutParams lp = mSurfaceView.getLayoutParams();
194        float aspectRatio = ((float) mVideoWidth) / mVideoHeight;
195        if (rect.width() / aspectRatio <= rect.height()) {
196            lp.width = rect.width();
197            lp.height = (int) (rect.width() / aspectRatio);
198        } else {
199            lp.width = (int) (rect.height() * aspectRatio);
200            lp.height = rect.height();
201        }
202        mSurfaceView.setLayoutParams(lp);
203    }
204
205    @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
206    @Override public void surfaceDestroyed(SurfaceHolder holder) {}
207}
208