pull/696/head
Mattia Iavarone 6 years ago
parent 1ed22b02ac
commit 893af4bc85
  1. 2
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/Camera1IntegrationTest.java
  2. 33
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/Camera2IntegrationTest.java
  3. 15
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java
  4. 9
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java

@ -19,7 +19,7 @@ import androidx.test.filters.RequiresDevice;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@LargeTest @LargeTest
// @RequiresDevice // @RequiresDevice
public class Camera1IntegrationTest extends CameraIntegrationTest { public class Camera1IntegrationTest extends CameraIntegrationTest<Camera1Engine> {
@NonNull @NonNull
@Override @Override

@ -1,7 +1,9 @@
package com.otaliastudios.cameraview.engine; package com.otaliastudios.cameraview.engine;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult; import android.hardware.camera2.TotalCaptureResult;
import android.os.Handler;
import com.otaliastudios.cameraview.controls.Engine; import com.otaliastudios.cameraview.controls.Engine;
import com.otaliastudios.cameraview.engine.action.ActionHolder; import com.otaliastudios.cameraview.engine.action.ActionHolder;
@ -25,7 +27,7 @@ import java.util.concurrent.CountDownLatch;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@LargeTest @LargeTest
// @RequiresDevice // @RequiresDevice
public class Camera2IntegrationTest extends CameraIntegrationTest { public class Camera2IntegrationTest extends CameraIntegrationTest<Camera2Engine> {
@NonNull @NonNull
@Override @Override
@ -39,7 +41,6 @@ public class Camera2IntegrationTest extends CameraIntegrationTest {
// Extra wait for the first frame to be dispatched. // Extra wait for the first frame to be dispatched.
// This is because various classes require getLastResult to be non-null // This is because various classes require getLastResult to be non-null
// and that's typically the case in a real app. // and that's typically the case in a real app.
Camera2Engine engine = (Camera2Engine) controller;
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
new BaseAction() { new BaseAction() {
@Override @Override
@ -50,7 +51,7 @@ public class Camera2IntegrationTest extends CameraIntegrationTest {
latch.countDown(); latch.countDown();
setState(STATE_COMPLETED); setState(STATE_COMPLETED);
} }
}.start(engine); }.start(controller);
try { latch.await(); } catch (InterruptedException ignore) {} try { latch.await(); } catch (InterruptedException ignore) {}
} }
@ -58,4 +59,30 @@ public class Camera2IntegrationTest extends CameraIntegrationTest {
protected long getMeteringTimeoutMillis() { protected long getMeteringTimeoutMillis() {
return Camera2Engine.METER_TIMEOUT; 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);
}
}
} }

@ -64,7 +64,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
public abstract class CameraIntegrationTest extends BaseTest { public abstract class CameraIntegrationTest<E extends CameraEngine> extends BaseTest {
private final static CameraLogger LOG = CameraLogger.create(CameraIntegrationTest.class.getSimpleName()); private final static CameraLogger LOG = CameraLogger.create(CameraIntegrationTest.class.getSimpleName());
private final static long DELAY = 8000; private final static long DELAY = 8000;
@ -72,8 +72,8 @@ public abstract class CameraIntegrationTest extends BaseTest {
@Rule @Rule
public ActivityTestRule<TestActivity> rule = new ActivityTestRule<>(TestActivity.class); public ActivityTestRule<TestActivity> rule = new ActivityTestRule<>(TestActivity.class);
private CameraView camera; protected CameraView camera;
protected CameraEngine controller; protected E controller;
private CameraListener listener; private CameraListener listener;
private Op<Throwable> uiExceptionOp; private Op<Throwable> uiExceptionOp;
@ -98,7 +98,8 @@ public abstract class CameraIntegrationTest extends BaseTest {
@NonNull @NonNull
@Override @Override
protected CameraEngine instantiateCameraEngine(@NonNull Engine engine, @NonNull CameraEngine.Callback callback) { 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; return controller;
} }
}; };
@ -246,11 +247,11 @@ public abstract class CameraIntegrationTest extends BaseTest {
return result; return result;
} }
private void takeVideoSync(boolean expectSuccess) { protected void takeVideoSync(boolean expectSuccess) {
takeVideoSync(expectSuccess,0); takeVideoSync(expectSuccess,0);
} }
private void takeVideoSync(boolean expectSuccess, int duration) { protected void takeVideoSync(boolean expectSuccess, int duration) {
final Op<Boolean> op = new Op<>(); final Op<Boolean> op = new Op<>();
doEndOp(op, true).when(listener).onVideoRecordingStart(); doEndOp(op, true).when(listener).onVideoRecordingStart();
doEndOp(op, false).when(listener).onCameraError(argThat(new ArgumentMatcher<CameraException>() { doEndOp(op, false).when(listener).onCameraError(argThat(new ArgumentMatcher<CameraException>() {
@ -261,6 +262,8 @@ public abstract class CameraIntegrationTest extends BaseTest {
})); }));
File file = new File(getContext().getFilesDir(), "video.mp4"); File file = new File(getContext().getFilesDir(), "video.mp4");
if (duration > 0) { 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); camera.takeVideo(file, duration);
} else { } else {
camera.takeVideo(file); camera.takeVideo(file);

@ -125,16 +125,17 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
//region Utilities //region Utilities
@VisibleForTesting
@NonNull @NonNull
private <T> T readCharacteristic(@NonNull CameraCharacteristics.Key<T> key, <T> T readCharacteristic(@NonNull CameraCharacteristics.Key<T> key,
@NonNull T fallback) { @NonNull T fallback) {
return readCharacteristic(mCameraCharacteristics, key, fallback); return readCharacteristic(mCameraCharacteristics, key, fallback);
} }
@NonNull @NonNull
private <T> T readCharacteristic(@NonNull CameraCharacteristics characteristics, private <T> T readCharacteristic(@NonNull CameraCharacteristics characteristics,
@NonNull CameraCharacteristics.Key<T> key, @NonNull CameraCharacteristics.Key<T> key,
@NonNull T fallback) { @NonNull T fallback) {
T value = characteristics.get(key); T value = characteristics.get(key);
return value == null ? fallback : value; return value == null ? fallback : value;
} }

Loading…
Cancel
Save