Composition preview tests with surfaces

Add abilitiy to use real surfaces in instrumentation tests
using the ActivityScenarioRule and an activity class for testing
purposes.

PiperOrigin-RevId: 611421490
This commit is contained in:
christosts 2024-02-29 04:15:32 -08:00 committed by Copybara-Service
parent bba45b8b35
commit 1355f4734d
4 changed files with 123 additions and 1 deletions

View File

@ -27,7 +27,11 @@
<application <application
android:allowBackup="false" android:allowBackup="false"
tools:ignore="MissingApplicationIcon,HardcodedDebugMode" tools:ignore="MissingApplicationIcon,HardcodedDebugMode"
android:usesCleartextTraffic="true"/> android:usesCleartextTraffic="true">
<activity android:name="androidx.media3.transformer.SurfaceTestActivity"
android:configChanges="keyboardHidden|orientation|screenSize"/>
</application>
<instrumentation <instrumentation
android:targetPackage="androidx.media3.transformer.test" android:targetPackage="androidx.media3.transformer.test"

View File

@ -31,6 +31,7 @@ public final class PlayerTestListener implements Player.Listener, AnalyticsListe
private final ConditionVariable playerReady; private final ConditionVariable playerReady;
private final ConditionVariable playerEnded; private final ConditionVariable playerEnded;
private final ConditionVariable firstFrameRendered;
private final AtomicReference<@NullableType PlaybackException> playbackException; private final AtomicReference<@NullableType PlaybackException> playbackException;
private final long testTimeoutMs; private final long testTimeoutMs;
private @MonotonicNonNull DecoderCounters decoderCounters; private @MonotonicNonNull DecoderCounters decoderCounters;
@ -44,6 +45,7 @@ public final class PlayerTestListener implements Player.Listener, AnalyticsListe
public PlayerTestListener(long testTimeoutMs) { public PlayerTestListener(long testTimeoutMs) {
playerReady = new ConditionVariable(); playerReady = new ConditionVariable();
playerEnded = new ConditionVariable(); playerEnded = new ConditionVariable();
firstFrameRendered = new ConditionVariable();
playbackException = new AtomicReference<>(); playbackException = new AtomicReference<>();
this.testTimeoutMs = testTimeoutMs; this.testTimeoutMs = testTimeoutMs;
} }
@ -58,6 +60,14 @@ public final class PlayerTestListener implements Player.Listener, AnalyticsListe
waitOrThrow(playerEnded); waitOrThrow(playerEnded);
} }
/**
* Waits until the {@link Player player} {@linkplain Player.Listener#onRenderedFirstFrame()
* renders the first frame}.
*/
public void waitUntilFirstFrameRendered() throws PlaybackException, TimeoutException {
waitOrThrow(firstFrameRendered);
}
/** /**
* Returns the {@link DecoderCounters} from {@link AnalyticsListener#onVideoEnabled(EventTime, * Returns the {@link DecoderCounters} from {@link AnalyticsListener#onVideoEnabled(EventTime,
* DecoderCounters)}, {@code null} if not available. * DecoderCounters)}, {@code null} if not available.
@ -78,11 +88,17 @@ public final class PlayerTestListener implements Player.Listener, AnalyticsListe
} }
} }
@Override
public void onRenderedFirstFrame() {
firstFrameRendered.open();
}
@Override @Override
public void onPlayerError(PlaybackException error) { public void onPlayerError(PlaybackException error) {
playbackException.set(error); playbackException.set(error);
playerReady.open(); playerReady.open();
playerEnded.open(); playerEnded.open();
firstFrameRendered.open();
} }
// AnalyticsListener methods // AnalyticsListener methods

View File

@ -0,0 +1,70 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.transformer;
import android.app.Activity;
import android.app.KeyguardManager;
import android.os.Bundle;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.WindowManager;
import androidx.media3.common.util.Util;
import androidx.media3.transformer.test.R;
/** An activity with surfaces for testing purposes. */
public final class SurfaceTestActivity extends Activity {
private SurfaceView surfaceView;
private TextureView textureView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setKeepScreenOn(this);
setContentView(R.layout.surface_test_activity);
surfaceView = findViewById(R.id.surface_view);
textureView = findViewById(R.id.texture_view);
}
/** Gets this activity's {@link SurfaceView}. */
public SurfaceView getSurfaceView() {
return surfaceView;
}
/** Gets this activity's {@link TextureView}. */
public TextureView getTextureView() {
return textureView;
}
private static void setKeepScreenOn(Activity activity) {
if (Util.SDK_INT >= 27) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
activity.setTurnScreenOn(true);
activity.setShowWhenLocked(true);
KeyguardManager keyguardManager =
(KeyguardManager) activity.getSystemService(KEYGUARD_SERVICE);
keyguardManager.requestDismissKeyguard(activity, /* callback= */ null);
} else {
activity
.getWindow()
.addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}
}
}

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2024 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root_view_group"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView
android:id="@+id/surface_view"
android:layout_width="30dp"
android:layout_height="40dp">
</SurfaceView>
<TextureView
android:id="@+id/texture_view"
android:layout_width="70dp"
android:layout_height="80dp">
</TextureView>
</LinearLayout>