From 893af4bc855f58d8557aa4454d25599890bf08d6 Mon Sep 17 00:00:00 2001 From: Mattia Iavarone Date: Mon, 9 Dec 2019 14:14:01 +0100 Subject: [PATCH] Test --- .../engine/Camera1IntegrationTest.java | 2 +- .../engine/Camera2IntegrationTest.java | 33 +++++++++++++++++-- .../engine/CameraIntegrationTest.java | 15 +++++---- .../cameraview/engine/Camera2Engine.java | 9 ++--- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/Camera1IntegrationTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/Camera1IntegrationTest.java index 0a27884a..41e2d3d7 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/Camera1IntegrationTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/Camera1IntegrationTest.java @@ -19,7 +19,7 @@ import androidx.test.filters.RequiresDevice; @RunWith(AndroidJUnit4.class) @LargeTest // @RequiresDevice -public class Camera1IntegrationTest extends CameraIntegrationTest { +public class Camera1IntegrationTest extends CameraIntegrationTest { @NonNull @Override diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/Camera2IntegrationTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/Camera2IntegrationTest.java index 2adf59b0..1e56d352 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/Camera2IntegrationTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/Camera2IntegrationTest.java @@ -1,7 +1,9 @@ package com.otaliastudios.cameraview.engine; +import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.TotalCaptureResult; +import android.os.Handler; import com.otaliastudios.cameraview.controls.Engine; import com.otaliastudios.cameraview.engine.action.ActionHolder; @@ -25,7 +27,7 @@ import java.util.concurrent.CountDownLatch; @RunWith(AndroidJUnit4.class) @LargeTest // @RequiresDevice -public class Camera2IntegrationTest extends CameraIntegrationTest { +public class Camera2IntegrationTest extends CameraIntegrationTest { @NonNull @Override @@ -39,7 +41,6 @@ public class Camera2IntegrationTest extends CameraIntegrationTest { // Extra wait for the first frame to be dispatched. // This is because various classes require getLastResult to be non-null // and that's typically the case in a real app. - Camera2Engine engine = (Camera2Engine) controller; final CountDownLatch latch = new CountDownLatch(1); new BaseAction() { @Override @@ -50,7 +51,7 @@ public class Camera2IntegrationTest extends CameraIntegrationTest { latch.countDown(); setState(STATE_COMPLETED); } - }.start(engine); + }.start(controller); try { latch.await(); } catch (InterruptedException ignore) {} } @@ -58,4 +59,30 @@ public class Camera2IntegrationTest extends CameraIntegrationTest { protected long getMeteringTimeoutMillis() { return Camera2Engine.METER_TIMEOUT; } + + @Override + protected void takeVideoSync(boolean expectSuccess, final int duration) { + if (duration > 0 && (controller.readCharacteristic( + CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL, -1) + == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)) { + // setMaxDuration can crash on legacy devices (most emulator are), and I don't see + // any way to fix this in code. They shouldn't use Camera2 at all. + // For tests, use a handler to trigger the stop. + final int delay = Math.round(duration * 1.2F); // Compensate for thread jumps, ... + uiSync(new Runnable() { + @Override + public void run() { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + camera.stopVideo(); + } + }, delay); + } + }); + super.takeVideoSync(expectSuccess, 0); + } else { + super.takeVideoSync(expectSuccess, duration); + } + } } diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java index 46fb0121..0c1958ea 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java @@ -64,7 +64,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -public abstract class CameraIntegrationTest extends BaseTest { +public abstract class CameraIntegrationTest extends BaseTest { private final static CameraLogger LOG = CameraLogger.create(CameraIntegrationTest.class.getSimpleName()); private final static long DELAY = 8000; @@ -72,8 +72,8 @@ public abstract class CameraIntegrationTest extends BaseTest { @Rule public ActivityTestRule rule = new ActivityTestRule<>(TestActivity.class); - private CameraView camera; - protected CameraEngine controller; + protected CameraView camera; + protected E controller; private CameraListener listener; private Op uiExceptionOp; @@ -98,7 +98,8 @@ public abstract class CameraIntegrationTest extends BaseTest { @NonNull @Override protected CameraEngine instantiateCameraEngine(@NonNull Engine engine, @NonNull CameraEngine.Callback callback) { - controller = super.instantiateCameraEngine(getEngine(), callback); + //noinspection unchecked + controller = (E) super.instantiateCameraEngine(getEngine(), callback); return controller; } }; @@ -246,11 +247,11 @@ public abstract class CameraIntegrationTest extends BaseTest { return result; } - private void takeVideoSync(boolean expectSuccess) { + protected void takeVideoSync(boolean expectSuccess) { takeVideoSync(expectSuccess,0); } - private void takeVideoSync(boolean expectSuccess, int duration) { + protected void takeVideoSync(boolean expectSuccess, int duration) { final Op op = new Op<>(); doEndOp(op, true).when(listener).onVideoRecordingStart(); doEndOp(op, false).when(listener).onCameraError(argThat(new ArgumentMatcher() { @@ -261,6 +262,8 @@ public abstract class CameraIntegrationTest extends BaseTest { })); File file = new File(getContext().getFilesDir(), "video.mp4"); if (duration > 0) { + // On Camera2, on Legacy sensors, this call can crash (see FullVideoRecorder). + // For this reasons, tests that call this should not be run on such devices. camera.takeVideo(file, duration); } else { camera.takeVideo(file); diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java index fd88cda7..a34e9883 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java @@ -125,16 +125,17 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv //region Utilities + @VisibleForTesting @NonNull - private T readCharacteristic(@NonNull CameraCharacteristics.Key key, - @NonNull T fallback) { + T readCharacteristic(@NonNull CameraCharacteristics.Key key, + @NonNull T fallback) { return readCharacteristic(mCameraCharacteristics, key, fallback); } @NonNull private T readCharacteristic(@NonNull CameraCharacteristics characteristics, - @NonNull CameraCharacteristics.Key key, - @NonNull T fallback) { + @NonNull CameraCharacteristics.Key key, + @NonNull T fallback) { T value = characteristics.get(key); return value == null ? fallback : value; }