summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Rosenfeld <mrosenfeld@google.com>2021-12-06 16:35:20 -0800
committerMichael Rosenfeld <mrosenfeld@google.com>2021-12-07 17:08:56 -0800
commit27ca87215e3214b15f00a7190ff85a4f6599e5c3 (patch)
treea444ff1289398b44c8b4cc0924fc5b6caabc36ae
parentd2c2aeef3bb56c1ef604b4b88aebcc17d0733476 (diff)
downloadplatform_testing-27ca87215e3214b15f00a7190ff85a4f6599e5c3.tar.gz
Add an option to control screen recording quality.
Bug: 150140232 Test: added Change-Id: Ie4fd062a0c52cc4ad5a53c5ef9252d2eeb39d628
-rw-r--r--libraries/device-collectors/src/main/java/android/device/collectors/ScreenRecordCollector.java61
-rw-r--r--libraries/device-collectors/src/test/java/android/device/collectors/ScreenRecordCollectorTest.java98
2 files changed, 154 insertions, 5 deletions
diff --git a/libraries/device-collectors/src/main/java/android/device/collectors/ScreenRecordCollector.java b/libraries/device-collectors/src/main/java/android/device/collectors/ScreenRecordCollector.java
index 895ddd14a..76fc1f945 100644
--- a/libraries/device-collectors/src/main/java/android/device/collectors/ScreenRecordCollector.java
+++ b/libraries/device-collectors/src/main/java/android/device/collectors/ScreenRecordCollector.java
@@ -18,6 +18,7 @@ package android.device.collectors;
import static org.junit.Assert.assertNotNull;
import android.device.collectors.annotations.OptionClass;
+import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -41,6 +42,12 @@ import org.junit.runner.Description;
*/
@OptionClass(alias = "screen-record-collector")
public class ScreenRecordCollector extends BaseMetricListener {
+ // Quality is relative to screen resolution.
+ // * "medium" is 1/2 the resolution.
+ // * "low" is 1/8 the resolution.
+ // * Otherwise, use the resolution.
+ @VisibleForTesting static final String QUALITY_ARG = "video-quality";
+ // Maximum parts per test (each part is <= 3min).
@VisibleForTesting static final int MAX_RECORDING_PARTS = 5;
private static final long VIDEO_TAIL_BUFFER = 500;
@@ -51,13 +58,59 @@ public class ScreenRecordCollector extends BaseMetricListener {
private RecordingThread mCurrentThread;
+ private String mVideoDimensions;
+
// Tracks the test iterations to ensure that each failure gets unique filenames.
// Key: test description; value: number of iterations.
private Map<String, Integer> mTestIterations = new HashMap<String, Integer>();
+ public ScreenRecordCollector() {
+ super();
+ }
+
+ /** Constructors for overriding instrumentation arguments only. */
+ @VisibleForTesting
+ ScreenRecordCollector(Bundle args) {
+ super(args);
+ }
+
@Override
public void onTestRunStart(DataRecord runData, Description description) {
mDestDir = createAndEmptyDirectory(OUTPUT_DIR);
+
+ try {
+ long scaleDown = 1;
+ switch (getArgsBundle().getString(QUALITY_ARG, "default")) {
+ case "high":
+ scaleDown = 1;
+ break;
+
+ case "medium":
+ scaleDown = 2;
+ break;
+
+ case "low":
+ scaleDown = 8;
+ break;
+
+ default:
+ return;
+ }
+
+ // Display metrics isn't the absolute size, so use "wm size".
+ String[] dims =
+ getDevice()
+ .executeShellCommand("wm size")
+ .substring("Physical size: ".length())
+ .trim()
+ .split("x");
+ int width = Integer.parseInt(dims[0]);
+ int height = Integer.parseInt(dims[1]);
+ mVideoDimensions = String.format("%dx%d", width / scaleDown, height / scaleDown);
+ Log.v(getTag(), String.format("Using video dimensions: %s", mVideoDimensions));
+ } catch (Exception e) {
+ Log.e(getTag(), "Failed to query the device dimensions. Using default.", e);
+ }
}
@Override
@@ -167,9 +220,15 @@ public class ScreenRecordCollector extends BaseMetricListener {
// Make sure not to block on this background command in the main thread so
// that the test continues to run, but block in this thread so it does not
// trigger a new screen recording session before the prior one completes.
+ String dimensionsOpt =
+ mVideoDimensions == null
+ ? ""
+ : String.format("--size=%s", mVideoDimensions);
getDevice()
.executeShellCommand(
- String.format("screenrecord %s", output.getAbsolutePath()));
+ String.format(
+ "screenrecord %s %s",
+ dimensionsOpt, output.getAbsolutePath()));
}
} catch (IOException e) {
throw new RuntimeException("Caught exception while screen recording.");
diff --git a/libraries/device-collectors/src/test/java/android/device/collectors/ScreenRecordCollectorTest.java b/libraries/device-collectors/src/test/java/android/device/collectors/ScreenRecordCollectorTest.java
index 664a2947d..ce1bfa55c 100644
--- a/libraries/device-collectors/src/test/java/android/device/collectors/ScreenRecordCollectorTest.java
+++ b/libraries/device-collectors/src/test/java/android/device/collectors/ScreenRecordCollectorTest.java
@@ -21,8 +21,10 @@ import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.endsWith;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.matches;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -85,8 +87,13 @@ public class ScreenRecordCollectorTest {
}
}
- private ScreenRecordCollector initListener() throws IOException {
- ScreenRecordCollector listener = spy(new ScreenRecordCollector());
+ private ScreenRecordCollector initListener(Bundle b) throws IOException {
+ ScreenRecordCollector listener;
+ if (b != null) {
+ listener = spy(new ScreenRecordCollector(b));
+ } else {
+ listener = spy(new ScreenRecordCollector());
+ }
listener.setInstrumentation(mInstrumentation);
doReturn(mLogDir).when(listener).createAndEmptyDirectory(anyString());
doReturn(0L).when(listener).getTailBuffer();
@@ -102,7 +109,7 @@ public class ScreenRecordCollectorTest {
*/
@Test
public void testScreenRecord() throws Exception {
- mListener = initListener();
+ mListener = initListener(null);
// Verify output directories are created on test run start.
mListener.testRunStarted(mRunDesc);
@@ -158,7 +165,7 @@ public class ScreenRecordCollectorTest {
/** Test that screen recording is properly done for multiple tests and labels iterations. */
@Test
public void testScreenRecord_multipleTests() throws Exception {
- mListener = initListener();
+ mListener = initListener(null);
// Run through a sequence of `NUM_TEST_CASE` failing tests.
mListener.testRunStarted(mRunDesc);
@@ -190,4 +197,87 @@ public class ScreenRecordCollectorTest {
}
}
}
+
+ /** Test that quality options (high) are respected by screen recordings. */
+ @Test
+ public void testScreenRecord_qualityHigh() throws Exception {
+ Bundle args = new Bundle();
+ args.putString(ScreenRecordCollector.QUALITY_ARG, "high");
+ mListener = initListener(args);
+ doReturn("Physical size: 1080x720 ").when(mDevice).executeShellCommand("wm size");
+
+ mListener.testRunStarted(mRunDesc);
+ mListener.testStarted(mTestDesc);
+
+ // Delay verification by 100 ms to ensure the thread was started.
+ SystemClock.sleep(100);
+ verify(mDevice).executeShellCommand(matches("screenrecord --size=1080x720 .*video.mp4"));
+ }
+
+ /** Test that quality options (medium) are respected by screen recordings. */
+ @Test
+ public void testScreenRecord_qualityMedium() throws Exception {
+ Bundle args = new Bundle();
+ args.putString(ScreenRecordCollector.QUALITY_ARG, "medium");
+ mListener = initListener(args);
+ doReturn("Physical size: 1080x720 ").when(mDevice).executeShellCommand("wm size");
+
+ mListener.testRunStarted(mRunDesc);
+ mListener.testStarted(mTestDesc);
+
+ // Delay verification by 100 ms to ensure the thread was started.
+ SystemClock.sleep(100);
+ verify(mDevice).executeShellCommand(matches("screenrecord --size=540x360 .*video.mp4"));
+ }
+
+ /** Test that quality options (low) are respected by screen recordings. */
+ @Test
+ public void testScreenRecord_qualityLow() throws Exception {
+ Bundle args = new Bundle();
+ args.putString(ScreenRecordCollector.QUALITY_ARG, "low");
+ mListener = initListener(args);
+ doReturn("Physical size: 1080x720 ").when(mDevice).executeShellCommand("wm size");
+
+ mListener.testRunStarted(mRunDesc);
+ mListener.testStarted(mTestDesc);
+
+ // Delay verification by 100 ms to ensure the thread was started.
+ SystemClock.sleep(100);
+ verify(mDevice).executeShellCommand(matches("screenrecord --size=135x90 .*video.mp4"));
+ }
+
+ /** Test that quality options (invalid) defaults to 1x. */
+ @Test
+ public void testScreenRecord_qualityUnknown() throws Exception {
+ Bundle args = new Bundle();
+ args.putString(ScreenRecordCollector.QUALITY_ARG, "other");
+ mListener = initListener(args);
+
+ mListener.testRunStarted(mRunDesc);
+ mListener.testStarted(mTestDesc);
+
+ // Delay verification by 100 ms to ensure the thread was started.
+ SystemClock.sleep(100);
+ verify(mDevice, never()).executeShellCommand(matches("screenrecord.*size.*video.mp4"));
+ verify(mDevice, atLeastOnce())
+ .executeShellCommand(not(matches("screenrecord .*video.mp4")));
+ }
+
+ /** Test that unexpected wm size contents defaults to unspecified size/quality option. */
+ @Test
+ public void testScreenRecord_dimensionsInvalid() throws Exception {
+ Bundle args = new Bundle();
+ args.putString(ScreenRecordCollector.QUALITY_ARG, "high");
+ mListener = initListener(args);
+ doReturn("Physical size: axb ").when(mDevice).executeShellCommand("wm size");
+
+ mListener.testRunStarted(mRunDesc);
+ mListener.testStarted(mTestDesc);
+
+ // Delay verification by 100 ms to ensure the thread was started.
+ SystemClock.sleep(100);
+ verify(mDevice, never()).executeShellCommand(matches("screenrecord.*size.*video.mp4"));
+ verify(mDevice, atLeastOnce())
+ .executeShellCommand(not(matches("screenrecord .*video.mp4")));
+ }
}