Turn screen on when activity is on resume.
Also try getting the to-be-rendered surface a few times and allow it to
fail instead of waiting for timeout if no surface is available after all retries.
Bug:29636897, 31219737
Change-Id: I5d2896bf0bd98e7228e1dab66e9c9cd80d7130b7
diff --git a/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java b/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
index 0a3165b..7b74ba7 100644
--- a/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
+++ b/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
@@ -20,6 +20,7 @@
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
+import android.util.Log;
import android.view.View;
@TargetApi(24)
@@ -32,6 +33,20 @@
private static final int ALLOWED_GREATEST_PIXEL_DIFFERENCE = 90;
private static final int OFFSET = 10;
+ private View videoView;
+ private VideoViewFactory videoViewFactory;
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (videoView != null) {
+ getHelper().cleanUpView(videoView);
+ }
+ if (videoViewFactory != null) {
+ videoViewFactory.release();
+ }
+ super.tearDown();
+ }
+
/* <------------- Tests Using H264 -------------> */
public void testH264GLViewVideoDecode() throws Exception {
runH264DecodeAccuracyTest(
@@ -136,24 +151,33 @@
private void runDecodeAccuracyTest(
VideoViewFactory videoViewFactory, VideoFormat videoFormat, int goldenResId) {
- checkNotNull(videoViewFactory);
checkNotNull(videoFormat);
- View videoView = videoViewFactory.createView(getHelper().getContext());
- // If view is intended and available to display.
- if (videoView != null) {
- getHelper().generateView(videoView);
+ this.videoViewFactory = checkNotNull(videoViewFactory);
+ this.videoView = videoViewFactory.createView(getHelper().getContext());
+ final int maxRetries = 3;
+ for (int retry = 1; retry <= maxRetries; retry++) {
+ // If view is intended and available to display.
+ if (videoView != null) {
+ getHelper().generateView(videoView);
+ }
+ try {
+ videoViewFactory.waitForViewIsAvailable();
+ break;
+ } catch (Exception exception) {
+ Log.e(TAG, exception.getMessage());
+ if (retry == maxRetries) {
+ fail("Timeout waiting for a valid surface.");
+ } else {
+ Log.w(TAG, "Try again...");
+ bringActivityToFront();
+ }
+ }
}
- videoViewFactory.waitForViewIsAvailable();
// In the case of SurfaceView, VideoViewSnapshot can only capture incoming frames,
// so it needs to be created before start decoding.
final VideoViewSnapshot videoViewSnapshot = videoViewFactory.getVideoViewSnapshot();
decodeVideo(videoFormat, videoViewFactory);
validateResult(videoFormat, videoViewSnapshot, goldenResId);
-
- if (videoView != null) {
- getHelper().cleanUpView(videoView);
- }
- videoViewFactory.release();
}
private void decodeVideo(VideoFormat videoFormat, VideoViewFactory videoViewFactory) {
diff --git a/tests/tests/media/src/android/media/cts/DecodeAccuracyTestActivity.java b/tests/tests/media/src/android/media/cts/DecodeAccuracyTestActivity.java
index da06844..8994c78 100644
--- a/tests/tests/media/src/android/media/cts/DecodeAccuracyTestActivity.java
+++ b/tests/tests/media/src/android/media/cts/DecodeAccuracyTestActivity.java
@@ -27,7 +27,13 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_runner_activity);
+ }
+
+ @Override
+ protected void onResume() {
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ super.onResume();
}
}
diff --git a/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java b/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
index 47029d6b..fae1bb4 100644
--- a/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
+++ b/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
@@ -20,6 +20,7 @@
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -101,6 +102,12 @@
super.tearDown();
}
+ protected void bringActivityToFront() {
+ Intent intent = new Intent(mContext, DecodeAccuracyTestActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
+ mActivity.startActivity(intent);
+ }
+
protected TestHelper getHelper() {
return testHelper;
}
@@ -165,6 +172,7 @@
* This must be called before decodeFramesAndDisplay.
*/
private boolean prepare(Surface surface, VideoFormat videoFormat) {
+ Log.i(TAG, "Preparing to decode the media file.");
if (!setExtractorDataSource(videoFormat)) {
return false;
}
@@ -181,6 +189,7 @@
/* The function decode video frames and display in a surface. */
private PlayerResult decodeFramesAndDisplay(
Surface surface, int numOfTotalFrames, long timeOutMs) {
+ Log.i(TAG, "Starting decoding.");
checkNotNull(decoder);
int numOfDecodedFrames = 0;
long decodeStart = 0;
@@ -219,11 +228,12 @@
numOfDecodedFrames++;
}
} catch (IllegalStateException exception) {
- Log.e(TAG, "IllegalStateException in decodeFramesAndDisplay " + exception);
+ Log.e(TAG, "IllegalStateException in decodeFramesAndDisplay", exception);
break;
}
}
long totalTime = SystemClock.elapsedRealtime() - decodeStart;
+ Log.i(TAG, "Finishing decoding.");
return new PlayerResult(true, true, numOfTotalFrames == numOfDecodedFrames, totalTime);
}
@@ -290,12 +300,12 @@
decoder.stop();
} catch (IllegalStateException exception) {
// IllegalStateException happens when decoder fail to start.
- Log.e(TAG, "IllegalStateException in decoder stop" + exception);
+ Log.e(TAG, "IllegalStateException in decoder stop", exception);
} finally {
try {
decoder.release();
} catch (IllegalStateException exception) {
- Log.e(TAG, "IllegalStateException in decoder release" + exception);
+ Log.e(TAG, "IllegalStateException in decoder release", exception);
}
}
decoder = null;
@@ -308,7 +318,7 @@
try {
extractor.release();
} catch (IllegalStateException exception) {
- Log.e(TAG, "IllegalStateException in extractor release" + exception);
+ Log.e(TAG, "IllegalStateException in extractor release", exception);
}
}
@@ -521,7 +531,8 @@
/* Factory for manipulating a {@link View}. */
abstract class VideoViewFactory {
- public final long VIEW_AVAILABLE_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(1);
+ public static final long VIEW_WAITTIME_MS = TimeUnit.SECONDS.toMillis(1);
+ public static final long DEFAULT_VIEW_AVAILABLE_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(3);
public static final int VIEW_WIDTH = 480;
public static final int VIEW_HEIGHT = 360;
@@ -533,12 +544,20 @@
public abstract View createView(Context context);
- public abstract void waitForViewIsAvailable();
+ public void waitForViewIsAvailable() throws Exception {
+ waitForViewIsAvailable(DEFAULT_VIEW_AVAILABLE_TIMEOUT_MS);
+ };
+
+ public abstract void waitForViewIsAvailable(long timeOutMs) throws Exception;
public abstract Surface getSurface();
public abstract VideoViewSnapshot getVideoViewSnapshot();
+ public boolean hasLooper() {
+ return Looper.myLooper() != null;
+ }
+
}
/* Factory for building a {@link TextureView}. */
@@ -555,6 +574,7 @@
@Override
public TextureView createView(Context context) {
+ Log.i(TAG, "Creating a " + NAME);
textureView = DecodeAccuracyTestBase.checkNotNull(new TextureView(context));
textureView.setSurfaceTextureListener(this);
return textureView;
@@ -581,16 +601,22 @@
}
@Override
- public void waitForViewIsAvailable() {
- while (!textureView.isAvailable()) {
+ public void waitForViewIsAvailable(long timeOutMs) throws Exception {
+ final long start = SystemClock.elapsedRealtime();
+ while (SystemClock.elapsedRealtime() - start < timeOutMs && !textureView.isAvailable()) {
synchronized (syncToken) {
try {
- syncToken.wait(VIEW_AVAILABLE_TIMEOUT_MS);
- } catch (InterruptedException exception) {
- Log.e(TAG, "Taking too long to attach a TextureView to a window.", exception);
+ syncToken.wait(VIEW_WAITTIME_MS);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Exception occurred when attaching a TextureView to a window.", e);
+ throw new InterruptedException(e.getMessage());
}
}
}
+ if (!textureView.isAvailable()) {
+ throw new InterruptedException("Taking too long to attach a TextureView to a window.");
+ }
+ Log.i(TAG, NAME + " is available.");
}
@Override
@@ -646,7 +672,10 @@
@Override
public View createView(Context context) {
- Looper.prepare();
+ Log.i(TAG, "Creating a " + NAME);
+ if (!super.hasLooper()) {
+ Looper.prepare();
+ }
surfaceView = new SurfaceView(context);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
@@ -654,16 +683,22 @@
}
@Override
- public void waitForViewIsAvailable() {
- while (!getSurface().isValid()) {
+ public void waitForViewIsAvailable(long timeOutMs) throws Exception {
+ final long start = SystemClock.elapsedRealtime();
+ while (SystemClock.elapsedRealtime() - start < timeOutMs && !getSurface().isValid()) {
synchronized (syncToken) {
try {
- syncToken.wait(VIEW_AVAILABLE_TIMEOUT_MS);
- } catch (InterruptedException exception) {
- Log.e(TAG, "Taking too long to attach a SurfaceView to a window.", exception);
+ syncToken.wait(VIEW_WAITTIME_MS);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Exception occurred when attaching a SurfaceView to a window.", e);
+ throw new InterruptedException(e.getMessage());
}
}
}
+ if (!getSurface().isValid()) {
+ throw new InterruptedException("Taking too long to attach a SurfaceView to a window.");
+ }
+ Log.i(TAG, NAME + " is available.");
}
@Override
@@ -722,6 +757,7 @@
@Override
public View createView(Context context) {
+ Log.i(TAG, "Creating a " + NAME);
// Do all GL rendering in the GL thread.
glSurfaceViewThread = new GLSurfaceViewThread();
glSurfaceViewThread.start();
@@ -730,16 +766,25 @@
}
@Override
- public void waitForViewIsAvailable() {
- while (glSurfaceViewThread.getSurface() == null) {
+ public void waitForViewIsAvailable(long timeOutMs) throws Exception {
+ final long start = SystemClock.elapsedRealtime();
+ while (SystemClock.elapsedRealtime() - start < timeOutMs
+ && glSurfaceViewThread.getSurface() == null) {
synchronized (surfaceSyncToken) {
try {
- surfaceSyncToken.wait(VIEW_AVAILABLE_TIMEOUT_MS);
- } catch (InterruptedException exception) {
- Log.e(TAG, "Taking too long for the surface to become available.", exception);
+ surfaceSyncToken.wait(VIEW_WAITTIME_MS);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Exception occurred when waiting for the surface from"
+ + " GLSurfaceView to become available.", e);
+ throw new InterruptedException(e.getMessage());
}
}
}
+ if (glSurfaceViewThread.getSurface() == null) {
+ throw new InterruptedException("Taking too long for the surface from"
+ + " GLSurfaceView to become available.");
+ }
+ Log.i(TAG, NAME + " is available.");
}
@Override
@@ -1144,8 +1189,8 @@
}
Thread.sleep(PIXELCOPY_REQUEST_SLEEP_MS);
}
- } catch (InterruptedException ex) {
- Log.w(TAG, "Pixel Copy is stopped/interrupted before it finishes", ex);
+ } catch (InterruptedException e) {
+ Log.w(TAG, "Pixel Copy is stopped/interrupted before it finishes.", e);
}
copyHelper.release();
}
@@ -1191,8 +1236,13 @@
public int request(SurfaceView source, Bitmap dest) {
synchronized (this) {
- PixelCopy.request(source, dest, this, handler);
- return getResultLocked();
+ try {
+ PixelCopy.request(source, dest, this, handler);
+ return getResultLocked();
+ } catch (Exception e) {
+ Log.e(TAG, "Exception occurred when copying a SurfaceView.", e);
+ return -1;
+ }
}
}
@@ -1243,8 +1293,8 @@
public synchronized void run() {
try {
waitForByteBuffer();
- } catch (InterruptedException exception) {
- Log.w(TAG, exception.getMessage());
+ } catch (InterruptedException e) {
+ Log.w(TAG, e.getMessage());
Log.w(TAG, "ByteBuffer may contain incorrect pixels.");
}
// Get ByteBuffer anyway. Let the test fail if ByteBuffer contains incorrect pixels.