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 
17 package com.android.cts.verifier.streamquality;
18 
19 import com.android.cts.verifier.PassFailButtons;
20 import com.android.cts.verifier.R;
21 import com.android.cts.verifier.streamquality.StreamingVideoActivity.Stream;
22 
23 import android.app.AlertDialog;
24 import android.app.Dialog;
25 import android.content.DialogInterface;
26 import android.content.DialogInterface.OnClickListener;
27 import android.graphics.Rect;
28 import android.media.MediaPlayer;
29 import android.media.MediaPlayer.OnErrorListener;
30 import android.media.MediaPlayer.OnPreparedListener;
31 import android.media.MediaPlayer.OnVideoSizeChangedListener;
32 import android.os.Bundle;
33 import android.os.Handler;
34 import android.util.Log;
35 import android.view.SurfaceHolder;
36 import android.view.SurfaceView;
37 import android.view.ViewGroup.LayoutParams;
38 import android.widget.FrameLayout;
39 
40 import java.io.IOException;
41 
42 /**
43  * Activity that plays a video and allows the user to select pass/fail after 5 seconds.
44  */
45 public 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 = 5 * 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
onCreate(Bundle savedInstanceState)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 
setEnablePassButton(boolean enable)90     private void setEnablePassButton(boolean enable) {
91         getPassButton().setEnabled(enable);
92     }
93 
playVideo()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
onCreateDialog(int id, Bundle args)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 5 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