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 60 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 = 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 PassFailButtons.setTestResultAndFinish(PlayVideoActivity.this, 122 getTestId(), null, false); 123 } 124 }) 125 .show(); 126 default: 127 return super.onCreateDialog(id, args); 128 } 129 } 130 131 @Override 132 public String getTestId() { 133 return getTestId(mStream.code); 134 } 135 136 public static String getTestId(String code) { 137 return PlayVideoActivity.class.getName() + "_" + 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 60 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 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {} 207 @Override public void surfaceDestroyed(SurfaceHolder holder) {} 208 } 209