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