Make extensions test can cover any LensFacing*EffectMode combination
1. Add ExtensionsTestUtil class to provide common util functions.
2. Make tests run for any possible LensFacing*EffectMode combination if
its testing target might be vendor library.
3. Use assumeTure to check hasCameraWithLensFacing and
isExtensionAvailable if the testing target might be vendor library.
Bug: b/141965720
Test: ./gradlew camera:camera-extensions:build && ./gradlew camera:camera-extensions:connectedAndroidTest
Change-Id: I4d74b8552519492e8e2c60addce0c3d05a19dc91
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java
index 4aaac1f..77d0c5a 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java
@@ -21,7 +21,6 @@
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNotNull;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -34,9 +33,6 @@
import android.Manifest;
import android.app.Instrumentation;
import android.content.Context;
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CaptureRequest;
import android.os.Build;
import androidx.camera.camera2.Camera2AppConfig;
@@ -44,19 +40,16 @@
import androidx.camera.camera2.impl.CameraEventCallback;
import androidx.camera.camera2.impl.CameraEventCallbacks;
import androidx.camera.core.AppConfig;
-import androidx.camera.core.CameraInfoUnavailableException;
import androidx.camera.core.CameraX;
+import androidx.camera.core.CameraX.LensFacing;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureConfig;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.core.PreviewConfig;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
-import androidx.camera.extensions.impl.AutoPreviewExtenderImpl;
-import androidx.camera.extensions.impl.BeautyPreviewExtenderImpl;
-import androidx.camera.extensions.impl.BokehPreviewExtenderImpl;
-import androidx.camera.extensions.impl.HdrPreviewExtenderImpl;
-import androidx.camera.extensions.impl.NightPreviewExtenderImpl;
+import androidx.camera.extensions.ExtensionsManager.EffectMode;
+import androidx.camera.extensions.util.ExtensionsTestUtil;
import androidx.camera.testing.CameraUtil;
import androidx.camera.testing.fakes.FakeLifecycleOwner;
import androidx.test.core.app.ApplicationProvider;
@@ -73,12 +66,11 @@
import org.junit.runners.Parameterized;
import org.mockito.ArgumentCaptor;
-import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.ExecutionException;
-@RunWith(Parameterized.class)
@LargeTest
+@RunWith(Parameterized.class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.M)
public class ExtensionTest {
@@ -86,31 +78,18 @@
public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
Manifest.permission.CAMERA);
- private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
- private FakeLifecycleOwner mLifecycleOwner;
- private ExtensionsManager.EffectMode mEffectMode;
- private CameraX.LensFacing mLensFacing;
-
- private ImageCaptureConfig.Builder mImageCaptureConfigBuilder;
- private PreviewConfig.Builder mPreviewConfigBuilder;
-
@Parameterized.Parameters
public static Collection<Object[]> getParameters() {
- return Arrays.asList(new Object[][] {
- { ExtensionsManager.EffectMode.BOKEH, CameraX.LensFacing.FRONT },
- { ExtensionsManager.EffectMode.BOKEH, CameraX.LensFacing.BACK },
- { ExtensionsManager.EffectMode.HDR, CameraX.LensFacing.FRONT },
- { ExtensionsManager.EffectMode.HDR, CameraX.LensFacing.BACK },
- { ExtensionsManager.EffectMode.BEAUTY, CameraX.LensFacing.FRONT },
- { ExtensionsManager.EffectMode.BEAUTY, CameraX.LensFacing.BACK },
- { ExtensionsManager.EffectMode.NIGHT, CameraX.LensFacing.FRONT },
- { ExtensionsManager.EffectMode.NIGHT, CameraX.LensFacing.BACK },
- { ExtensionsManager.EffectMode.AUTO, CameraX.LensFacing.FRONT },
- { ExtensionsManager.EffectMode.AUTO, CameraX.LensFacing.BACK }
- });
+ return ExtensionsTestUtil.getAllEffectLensFacingCombinations();
}
- public ExtensionTest(ExtensionsManager.EffectMode effectMode, CameraX.LensFacing lensFacing) {
+ private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
+
+ private EffectMode mEffectMode;
+ private LensFacing mLensFacing;
+ private FakeLifecycleOwner mLifecycleOwner;
+
+ public ExtensionTest(EffectMode effectMode, LensFacing lensFacing) {
mEffectMode = effectMode;
mLensFacing = lensFacing;
}
@@ -123,43 +102,40 @@
AppConfig appConfig = Camera2AppConfig.create(context);
CameraX.init(context, appConfig);
+ assumeTrue(CameraUtil.hasCameraWithLensFacing(mLensFacing));
+ assumeTrue(ExtensionsManager.isExtensionAvailable(mEffectMode, mLensFacing));
+
mLifecycleOwner = new FakeLifecycleOwner();
mLifecycleOwner.startAndResume();
-
- mImageCaptureConfigBuilder = new ImageCaptureConfig.Builder();
- mPreviewConfigBuilder = new PreviewConfig.Builder();
}
@After
public void cleanUp() throws InterruptedException, ExecutionException {
- mInstrumentation.runOnMainSync(CameraX::unbindAll);
CameraX.deinit().get();
}
@Test
public void testCanBindToLifeCycleAndTakePicture() {
- assumeTrue(CameraUtil.hasCameraWithLensFacing(mLensFacing));
- assumeTrue(ExtensionsManager.isExtensionAvailable(mEffectMode, mLensFacing));
- assumeTrue(supportAFMode(mLensFacing));
-
- enableExtension(mEffectMode, mLensFacing);
-
Preview.OnPreviewOutputUpdateListener mockOnPreviewOutputUpdateListener = mock(
Preview.OnPreviewOutputUpdateListener.class);
ImageCapture.OnImageCapturedCallback mockOnImageCapturedCallback = mock(
ImageCapture.OnImageCapturedCallback.class);
// To test bind/unbind and take picture.
- ImageCapture imageCapture = new ImageCapture(mImageCaptureConfigBuilder.build());
- Preview preview = new Preview(mPreviewConfigBuilder.build());
+ ImageCapture imageCapture = ExtensionsTestUtil.createImageCaptureWithEffect(mEffectMode,
+ mLensFacing);
+ Preview preview = ExtensionsTestUtil.createPreviewWithEffect(mEffectMode, mLensFacing);
- CameraX.bindToLifecycle(mLifecycleOwner, preview, imageCapture);
+ mInstrumentation.runOnMainSync(
+ () -> {
+ CameraX.bindToLifecycle(mLifecycleOwner, preview, imageCapture);
- // To set the update listener and Preview will change to active state.
- preview.setOnPreviewOutputUpdateListener(mockOnPreviewOutputUpdateListener);
+ // To set the update listener and Preview will change to active state.
+ preview.setOnPreviewOutputUpdateListener(mockOnPreviewOutputUpdateListener);
- imageCapture.takePicture(CameraXExecutors.mainThreadExecutor(),
- mockOnImageCapturedCallback);
+ imageCapture.takePicture(CameraXExecutors.mainThreadExecutor(),
+ mockOnImageCapturedCallback);
+ });
// Verify the image captured.
ArgumentCaptor<ImageProxy> imageProxy = ArgumentCaptor.forClass(ImageProxy.class);
@@ -175,13 +151,9 @@
@Test
public void testEventCallbackInConfig() {
- assumeTrue(CameraUtil.hasCameraWithLensFacing(mLensFacing));
- assumeTrue(ExtensionsManager.isExtensionAvailable(mEffectMode, mLensFacing));
-
- enableExtension(mEffectMode, mLensFacing);
-
// Verify Preview config should have related callback.
- PreviewConfig previewConfig = mPreviewConfigBuilder.build();
+ PreviewConfig previewConfig = ExtensionsTestUtil.createPreviewConfigWithEffect(mEffectMode,
+ mLensFacing);
assertNotNull(previewConfig.getUseCaseEventListener());
CameraEventCallbacks callback1 = new Camera2Config(previewConfig).getCameraEventCallback(
null);
@@ -190,7 +162,8 @@
assertThat(callback1.getAllItems().get(0)).isInstanceOf(CameraEventCallback.class);
// Verify ImageCapture config should have related callback.
- ImageCaptureConfig imageCaptureConfig = mImageCaptureConfigBuilder.build();
+ ImageCaptureConfig imageCaptureConfig =
+ ExtensionsTestUtil.createImageCaptureConfigWithEffect(mEffectMode, mLensFacing);
assertNotNull(imageCaptureConfig.getUseCaseEventListener());
assertNotNull(imageCaptureConfig.getCaptureBundle());
CameraEventCallbacks callback2 = new Camera2Config(
@@ -199,92 +172,4 @@
assertEquals(callback2.getAllItems().size(), 1);
assertThat(callback2.getAllItems().get(0)).isInstanceOf(CameraEventCallback.class);
}
-
- /**
- * To invoke the enableExtension() method for different effect.
- */
- private void enableExtension(ExtensionsManager.EffectMode effectMode,
- CameraX.LensFacing lensFacing) {
-
- mImageCaptureConfigBuilder.setLensFacing(lensFacing);
- mPreviewConfigBuilder.setLensFacing(lensFacing);
-
- ImageCaptureExtender imageCaptureExtender = null;
- PreviewExtender previewExtender = null;
-
- switch (effectMode) {
- case HDR:
- imageCaptureExtender = HdrImageCaptureExtender.create(mImageCaptureConfigBuilder);
- previewExtender = HdrPreviewExtender.create(mPreviewConfigBuilder);
-
- // Make sure we are testing on the testlib/Vendor implementation.
- assertThat(previewExtender.mImpl).isInstanceOf(HdrPreviewExtenderImpl.class);
- break;
- case BOKEH:
- imageCaptureExtender = BokehImageCaptureExtender.create(
- mImageCaptureConfigBuilder);
- previewExtender = BokehPreviewExtender.create(mPreviewConfigBuilder);
-
- // Make sure we are testing on the testlib/Vendor implementation.
- assertThat(previewExtender.mImpl).isInstanceOf(BokehPreviewExtenderImpl.class);
- break;
- case BEAUTY:
- imageCaptureExtender = BeautyImageCaptureExtender.create(
- mImageCaptureConfigBuilder);
- previewExtender = BeautyPreviewExtender.create(mPreviewConfigBuilder);
-
- // Make sure we are testing on the testlib/Vendor implementation.
- assertThat(previewExtender.mImpl).isInstanceOf(BeautyPreviewExtenderImpl.class);
- break;
- case NIGHT:
- imageCaptureExtender = NightImageCaptureExtender.create(mImageCaptureConfigBuilder);
- previewExtender = NightPreviewExtender.create(mPreviewConfigBuilder);
-
- // Make sure we are testing on the testlib/Vendor implementation.
- assertThat(previewExtender.mImpl).isInstanceOf(NightPreviewExtenderImpl.class);
- break;
- case AUTO:
- imageCaptureExtender = AutoImageCaptureExtender.create(mImageCaptureConfigBuilder);
- previewExtender = AutoPreviewExtender.create(mPreviewConfigBuilder);
-
- // Make sure we are testing on the testlib/Vendor implementation.
- assertThat(previewExtender.mImpl).isInstanceOf(AutoPreviewExtenderImpl.class);
- break;
- }
-
- assertNotNull(imageCaptureExtender);
- assertNotNull(previewExtender);
-
- assertTrue(previewExtender.isExtensionAvailable());
- previewExtender.enableExtension();
- assertTrue(imageCaptureExtender.isExtensionAvailable());
- imageCaptureExtender.enableExtension();
- }
-
- private static boolean supportAFMode(CameraX.LensFacing lensFacing) {
- String cameraId = null;
- try {
- cameraId = CameraX.getCameraWithLensFacing(lensFacing);
- } catch (CameraInfoUnavailableException e) {
- return false;
- }
-
- CameraCharacteristics characteristics = null;
- try {
- characteristics = CameraUtil.getCameraManager().getCameraCharacteristics(cameraId);
- } catch (CameraAccessException e) {
- return false;
- }
-
- int[] afModes = characteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
-
- if (afModes == null) {
- return false;
- }
-
- // CameraX will use CONTROL_AF_MODE_AUTO or CONTROL_AF_MODE_CONTINUOUS_PICTURE to take
- // picture. To check if the camera can support the these AF modes.
- return Arrays.asList(afModes).contains(CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
- && Arrays.asList(afModes).contains(CaptureRequest.CONTROL_AF_MODE_AUTO);
- }
}
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsErrorListenerTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsErrorListenerTest.java
index 42cf699..114f49b 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsErrorListenerTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsErrorListenerTest.java
@@ -29,26 +29,16 @@
import androidx.annotation.NonNull;
import androidx.camera.camera2.Camera2AppConfig;
import androidx.camera.core.AppConfig;
-import androidx.camera.core.CameraControlInternal;
-import androidx.camera.core.CameraDeviceSurfaceManager;
import androidx.camera.core.CameraX;
import androidx.camera.core.CameraX.LensFacing;
-import androidx.camera.core.ConfigProvider;
-import androidx.camera.core.ExtendableUseCaseConfigFactory;
import androidx.camera.core.ImageCapture;
-import androidx.camera.core.ImageCaptureConfig;
import androidx.camera.core.Preview;
-import androidx.camera.core.PreviewConfig;
import androidx.camera.core.UseCase;
import androidx.camera.extensions.ExtensionsErrorListener.ExtensionsErrorCode;
+import androidx.camera.extensions.ExtensionsManager.EffectMode;
+import androidx.camera.extensions.util.ExtensionsTestUtil;
import androidx.camera.testing.CameraUtil;
-import androidx.camera.testing.fakes.FakeCamera;
-import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
-import androidx.camera.testing.fakes.FakeCameraFactory;
-import androidx.camera.testing.fakes.FakeCameraInfoInternal;
-import androidx.camera.testing.fakes.FakeUseCaseConfig;
import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.MediumTest;
import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
@@ -59,8 +49,10 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
@@ -68,7 +60,7 @@
import java.util.concurrent.atomic.AtomicReference;
@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
/**
* Unit tests for {@link androidx.camera.extensions.ExtensionsErrorListener}.
* */
@@ -78,6 +70,13 @@
public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
Manifest.permission.CAMERA);
+ @Parameterized.Parameters
+ public static Collection<Object[]> getParameters() {
+ return ExtensionsTestUtil.getAllEffectLensFacingCombinations();
+ }
+
+ private EffectMode mEffectMode;
+ private LensFacing mLensFacing;
private CountDownLatch mLatch;
final AtomicReference<ExtensionsErrorCode> mErrorCode = new AtomicReference<>();
@@ -89,40 +88,22 @@
}
};
+ public ExtensionsErrorListenerTest(EffectMode effectMode, LensFacing lensFacing) {
+ mEffectMode = effectMode;
+ mLensFacing = lensFacing;
+ }
+
@Before
public void setUp() {
- Context context = ApplicationProvider.getApplicationContext();
- CameraDeviceSurfaceManager surfaceManager = new FakeCameraDeviceSurfaceManager();
-
- // Pull out the Camera2 use case config factory because it provides correct defaults
- ExtendableUseCaseConfigFactory defaultConfigFactory =
- (ExtendableUseCaseConfigFactory) Camera2AppConfig.create(
- context).getUseCaseConfigRepository(null);
- defaultConfigFactory.installDefaultProvider(FakeUseCaseConfig.class,
- new ConfigProvider<FakeUseCaseConfig>() {
- @Override
- public FakeUseCaseConfig getConfig(CameraX.LensFacing lensFacing) {
- return new FakeUseCaseConfig.Builder().build();
- }
- });
-
- FakeCameraFactory cameraFactory = new FakeCameraFactory();
- cameraFactory.insertCamera(LensFacing.BACK, "0",
- () -> new FakeCamera(mock(CameraControlInternal.class),
- new FakeCameraInfoInternal(0, LensFacing.BACK)));
-
- AppConfig.Builder appConfigBuilder =
- new AppConfig.Builder()
- .setCameraFactory(cameraFactory)
- .setDeviceSurfaceManager(surfaceManager)
- .setUseCaseConfigFactory(defaultConfigFactory);
-
- // CameraX.init will actually init just once across all test cases. However we need to get
- // the real CameraFactory instance being injected into the init process. So here we store
- // the CameraFactory instance in static fields.
- CameraX.init(context, appConfigBuilder.build());
-
assumeTrue(CameraUtil.deviceHasCamera());
+
+ Context context = ApplicationProvider.getApplicationContext();
+ AppConfig appConfig = Camera2AppConfig.create(context);
+ CameraX.init(context, appConfig);
+
+ assumeTrue(CameraUtil.hasCameraWithLensFacing(mLensFacing));
+ assumeTrue(ExtensionsManager.isExtensionAvailable(mEffectMode, mLensFacing));
+
mLatch = new CountDownLatch(1);
}
@@ -136,21 +117,15 @@
public void receiveErrorCode_whenOnlyEnableImageCaptureExtender() throws InterruptedException {
ExtensionsManager.setExtensionsErrorListener(mExtensionsErrorListener);
- ImageCaptureConfig.Builder imageCaptureConfigBuilder =
- new ImageCaptureConfig.Builder().setLensFacing(LensFacing.BACK);
- HdrImageCaptureExtender imageCaptureExtender = HdrImageCaptureExtender.create(
- imageCaptureConfigBuilder);
- imageCaptureExtender.enableExtension();
- ImageCapture imageCapture = new ImageCapture(imageCaptureConfigBuilder.build());
+ ImageCapture imageCapture = ExtensionsTestUtil.createImageCaptureWithEffect(mEffectMode,
+ mLensFacing);
+ Preview noEffectPreview = ExtensionsTestUtil.createPreviewWithEffect(EffectMode.NORMAL,
+ mLensFacing);
- PreviewConfig.Builder previewConfigBuilder = new PreviewConfig.Builder().setLensFacing(
- LensFacing.BACK);
- Preview preview = new Preview(previewConfigBuilder.build());
-
- List<UseCase> useCaseList = Arrays.asList(imageCapture, preview);
+ List<UseCase> useCaseList = Arrays.asList(imageCapture, noEffectPreview);
mErrorCode.set(null);
- ImageCaptureExtender.checkPreviewEnabled(ExtensionsManager.EffectMode.HDR, useCaseList);
- PreviewExtender.checkImageCaptureEnabled(ExtensionsManager.EffectMode.HDR, useCaseList);
+ ImageCaptureExtender.checkPreviewEnabled(mEffectMode, useCaseList);
+ PreviewExtender.checkImageCaptureEnabled(mEffectMode, useCaseList);
// Waits for one second to get error code.
mLatch.await(1, TimeUnit.SECONDS);
@@ -161,20 +136,14 @@
public void receiveErrorCode_whenOnlyEnablePreviewExtender() throws InterruptedException {
ExtensionsManager.setExtensionsErrorListener(mExtensionsErrorListener);
- ImageCaptureConfig.Builder imageCaptureConfigBuilder =
- new ImageCaptureConfig.Builder().setLensFacing(LensFacing.BACK);
- ImageCapture imageCapture = new ImageCapture(imageCaptureConfigBuilder.build());
+ ImageCapture noEffectImageCapture =
+ ExtensionsTestUtil.createImageCaptureWithEffect(EffectMode.NORMAL, mLensFacing);
+ Preview preview = ExtensionsTestUtil.createPreviewWithEffect(mEffectMode, mLensFacing);
- PreviewConfig.Builder previewConfigBuilder = new PreviewConfig.Builder().setLensFacing(
- LensFacing.BACK);
- HdrPreviewExtender previewExtender = HdrPreviewExtender.create(previewConfigBuilder);
- previewExtender.enableExtension();
- Preview preview = new Preview(previewConfigBuilder.build());
-
- List<UseCase> useCaseList = Arrays.asList(imageCapture, preview);
+ List<UseCase> useCaseList = Arrays.asList(noEffectImageCapture, preview);
mErrorCode.set(null);
- ImageCaptureExtender.checkPreviewEnabled(ExtensionsManager.EffectMode.HDR, useCaseList);
- PreviewExtender.checkImageCaptureEnabled(ExtensionsManager.EffectMode.HDR, useCaseList);
+ ImageCaptureExtender.checkPreviewEnabled(mEffectMode, useCaseList);
+ PreviewExtender.checkImageCaptureEnabled(mEffectMode, useCaseList);
// Waits for one second to get error code.
mLatch.await(1, TimeUnit.SECONDS);
@@ -189,22 +158,13 @@
ExtensionsErrorListener mockExtensionsErrorListener = mock(ExtensionsErrorListener.class);
ExtensionsManager.setExtensionsErrorListener(mockExtensionsErrorListener);
- ImageCaptureConfig.Builder imageCaptureConfigBuilder =
- new ImageCaptureConfig.Builder().setLensFacing(LensFacing.BACK);
- HdrImageCaptureExtender imageCaptureExtender = HdrImageCaptureExtender.create(
- imageCaptureConfigBuilder);
- imageCaptureExtender.enableExtension();
- ImageCapture imageCapture = new ImageCapture(imageCaptureConfigBuilder.build());
-
- PreviewConfig.Builder previewConfigBuilder = new PreviewConfig.Builder().setLensFacing(
- LensFacing.BACK);
- HdrPreviewExtender previewExtender = HdrPreviewExtender.create(previewConfigBuilder);
- previewExtender.enableExtension();
- Preview preview = new Preview(previewConfigBuilder.build());
+ ImageCapture imageCapture = ExtensionsTestUtil.createImageCaptureWithEffect(mEffectMode,
+ mLensFacing);
+ Preview preview = ExtensionsTestUtil.createPreviewWithEffect(mEffectMode, mLensFacing);
List<UseCase> useCaseList = Arrays.asList(imageCapture, preview);
- ImageCaptureExtender.checkPreviewEnabled(ExtensionsManager.EffectMode.HDR, useCaseList);
- PreviewExtender.checkImageCaptureEnabled(ExtensionsManager.EffectMode.HDR, useCaseList);
+ ImageCaptureExtender.checkPreviewEnabled(mEffectMode, useCaseList);
+ PreviewExtender.checkImageCaptureEnabled(mEffectMode, useCaseList);
// Waits for one second to get error code.
mLatch.await(1, TimeUnit.SECONDS);
@@ -216,32 +176,38 @@
throws InterruptedException {
ExtensionsManager.setExtensionsErrorListener(mExtensionsErrorListener);
- ImageCaptureConfig.Builder imageCaptureConfigBuilder =
- new ImageCaptureConfig.Builder().setLensFacing(LensFacing.BACK);
- HdrImageCaptureExtender imageCaptureExtender = HdrImageCaptureExtender.create(
- imageCaptureConfigBuilder);
- imageCaptureExtender.enableExtension();
+ // Creates ImageCapture
+ ImageCapture imageCapture = ExtensionsTestUtil.createImageCaptureWithEffect(mEffectMode,
+ mLensFacing);
- ImageCapture imageCapture = new ImageCapture(imageCaptureConfigBuilder.build());
+ // Creates mismatched Preview
+ EffectMode mismatchedEffectMode;
- PreviewConfig.Builder previewConfigBuilder = new PreviewConfig.Builder().setLensFacing(
- LensFacing.BACK);
- BokehPreviewExtender previewExtender = BokehPreviewExtender.create(previewConfigBuilder);
- previewExtender.enableExtension();
- Preview preview = new Preview(previewConfigBuilder.build());
+ if (mEffectMode != EffectMode.BOKEH) {
+ assumeTrue(ExtensionsManager.isExtensionAvailable(EffectMode.BOKEH,
+ mLensFacing));
+ mismatchedEffectMode = EffectMode.BOKEH;
+ } else {
+ assumeTrue(ExtensionsManager.isExtensionAvailable(EffectMode.HDR,
+ mLensFacing));
+ mismatchedEffectMode = EffectMode.HDR;
+ }
+
+ Preview preview = ExtensionsTestUtil.createPreviewWithEffect(mismatchedEffectMode,
+ mLensFacing);
List<UseCase> useCaseList = Arrays.asList(imageCapture, preview);
mErrorCode.set(null);
// ImageCaptureExtender will find mismatched PreviewExtender is enabled.
- ImageCaptureExtender.checkPreviewEnabled(ExtensionsManager.EffectMode.HDR, useCaseList);
+ ImageCaptureExtender.checkPreviewEnabled(mEffectMode, useCaseList);
mLatch.await(1, TimeUnit.SECONDS);
assertThat(mErrorCode.get()).isEqualTo(ExtensionsErrorCode.MISMATCHED_EXTENSIONS_ENABLED);
mLatch = new CountDownLatch(1);
mErrorCode.set(null);
// PreviewExtender will find mismatched ImageCaptureExtender is enabled.
- PreviewExtender.checkImageCaptureEnabled(ExtensionsManager.EffectMode.BOKEH, useCaseList);
+ PreviewExtender.checkImageCaptureEnabled(mismatchedEffectMode, useCaseList);
mLatch.await(1, TimeUnit.SECONDS);
assertThat(mErrorCode.get()).isEqualTo(ExtensionsErrorCode.MISMATCHED_EXTENSIONS_ENABLED);
}
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java
index 3314ddc..4ccfa6d6 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java
@@ -31,23 +31,24 @@
import android.Manifest;
import android.app.Instrumentation;
import android.content.Context;
-import android.hardware.camera2.CameraAccessException;
+import android.graphics.ImageFormat;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.params.StreamConfigurationMap;
import android.util.Pair;
import android.util.Size;
+import androidx.annotation.NonNull;
import androidx.camera.camera2.Camera2AppConfig;
import androidx.camera.camera2.Camera2Config;
import androidx.camera.camera2.impl.CameraEventCallbacks;
-import androidx.camera.core.CameraDeviceConfig;
import androidx.camera.core.CameraInfoUnavailableException;
import androidx.camera.core.CameraX;
+import androidx.camera.core.CameraX.LensFacing;
import androidx.camera.core.CaptureProcessor;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureConfig;
import androidx.camera.extensions.ExtensionsManager.EffectMode;
-import androidx.camera.extensions.impl.BeautyImageCaptureExtenderImpl;
import androidx.camera.extensions.impl.CaptureStageImpl;
import androidx.camera.extensions.impl.ImageCaptureExtenderImpl;
import androidx.camera.testing.CameraUtil;
@@ -81,7 +82,9 @@
private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
private FakeLifecycleOwner mLifecycleOwner;
private ImageCaptureExtenderImpl mMockImageCaptureExtenderImpl;
- private ArrayList<CaptureStageImpl> mCaptureStages = new ArrayList<>(); {
+ private ArrayList<CaptureStageImpl> mCaptureStages = new ArrayList<>();
+
+ {
mCaptureStages.add(new FakeCaptureStage());
}
@@ -206,40 +209,27 @@
@Test
@SmallTest
- public void canSetSupportedResolutionsToConfigTest()
- throws CameraInfoUnavailableException, CameraAccessException {
- CameraX.LensFacing lensFacing = CameraX.LensFacing.BACK;
- assumeTrue(CameraUtil.hasCameraWithLensFacing(lensFacing));
- assumeTrue(ExtensionsManager.isExtensionAvailable(EffectMode.BEAUTY, lensFacing));
- ImageCaptureConfig.Builder configBuilder = new ImageCaptureConfig.Builder().setLensFacing(
- lensFacing);
-
- String cameraId = androidx.camera.extensions.CameraUtil.getCameraId(
- ((CameraDeviceConfig) configBuilder.build()));
- CameraCharacteristics cameraCharacteristics =
- CameraUtil.getCameraManager().getCameraCharacteristics(
- CameraX.getCameraWithLensFacing(lensFacing));
-
- // Only BeautyImageCaptureExtenderImpl has sample implementation for ImageCapture.
- // Retrieves the target format/resolutions pair list directly from
- // BeautyImageCaptureExtenderImpl.
- BeautyImageCaptureExtenderImpl impl = new BeautyImageCaptureExtenderImpl();
-
- impl.init(cameraId, cameraCharacteristics);
+ public void canSetSupportedResolutionsToConfigTest() throws CameraInfoUnavailableException {
+ assumeTrue(CameraUtil.deviceHasCamera());
+ LensFacing lensFacing = CameraX.getDefaultLensFacing();
+ ImageCaptureConfig.Builder configBuilder =
+ new ImageCaptureConfig.Builder().setLensFacing(lensFacing);
+ when(mMockImageCaptureExtenderImpl.isExtensionAvailable(any(), any())).thenReturn(true);
List<Pair<Integer, Size[]>> targetFormatResolutionsPairList =
- impl.getSupportedResolutions();
+ generateImageCaptureSupportedResolutions(lensFacing);
+ when(mMockImageCaptureExtenderImpl.getSupportedResolutions()).thenReturn(
+ targetFormatResolutionsPairList);
- assertThat(targetFormatResolutionsPairList).isNotNull();
+ ImageCaptureExtender fakeExtender = new FakeImageCaptureExtender(configBuilder,
+ mMockImageCaptureExtenderImpl);
- // Retrieves the target format/resolutions pair list from builder after applying beauty
- // mode.
- BeautyImageCaptureExtender extender = BeautyImageCaptureExtender.create(configBuilder);
+ // Checks the config does not include supported resolutions before applying effect mode.
assertThat(configBuilder.build().getSupportedResolutions(null)).isNull();
- extender.enableExtension();
+ // Checks the config includes supported resolutions after applying effect mode.
+ fakeExtender.enableExtension();
List<Pair<Integer, Size[]>> resultFormatResolutionsPairList =
configBuilder.build().getSupportedResolutions(null);
-
assertThat(resultFormatResolutionsPairList).isNotNull();
// Checks the result and target pair lists are the same
@@ -252,8 +242,46 @@
}
}
- assertThat(Arrays.asList(resultPair.second).equals(
- Arrays.asList(targetSizes))).isTrue();
+ assertThat(
+ Arrays.asList(resultPair.second).equals(Arrays.asList(targetSizes))).isTrue();
+ }
+ }
+
+ private List<Pair<Integer, Size[]>> generateImageCaptureSupportedResolutions(
+ @NonNull LensFacing lensFacing)
+ throws CameraInfoUnavailableException {
+ List<Pair<Integer, Size[]>> formatResolutionsPairList = new ArrayList<>();
+ String cameraId =
+ androidx.camera.extensions.CameraUtil.getCameraIdSetWithLensFacing(
+ lensFacing).iterator().next();
+
+ StreamConfigurationMap map =
+ androidx.camera.extensions.CameraUtil.getCameraCharacteristics(cameraId).get(
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+
+ if (map != null) {
+ // Retrieves originally supported resolutions from CameraCharacteristics for JPEG and
+ // YUV_420_888 formats to return.
+ Size[] outputSizes = map.getOutputSizes(ImageFormat.JPEG);
+
+ if (outputSizes != null) {
+ formatResolutionsPairList.add(Pair.create(ImageFormat.JPEG, outputSizes));
+ }
+
+ outputSizes = map.getOutputSizes(ImageFormat.YUV_420_888);
+
+ if (outputSizes != null) {
+ formatResolutionsPairList.add(Pair.create(ImageFormat.YUV_420_888, outputSizes));
+ }
+ }
+
+ return formatResolutionsPairList;
+ }
+
+ final class FakeImageCaptureExtender extends ImageCaptureExtender {
+ FakeImageCaptureExtender(ImageCaptureConfig.Builder builder,
+ ImageCaptureExtenderImpl impl) {
+ init(builder, impl, EffectMode.NORMAL);
}
}
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.java
new file mode 100644
index 0000000..38b1994
--- /dev/null
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2019 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.
+ */
+
+package androidx.camera.extensions;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.Manifest;
+import android.content.Context;
+import android.hardware.camera2.CameraAccessException;
+
+import androidx.camera.camera2.Camera2AppConfig;
+import androidx.camera.core.CameraInfoUnavailableException;
+import androidx.camera.core.CameraX;
+import androidx.camera.extensions.impl.ImageCaptureExtenderImpl;
+import androidx.camera.extensions.util.ExtensionsTestUtil;
+import androidx.camera.testing.CameraUtil;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.GrantPermissionRule;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.ExecutionException;
+
+@RunWith(AndroidJUnit4.class)
+public class ImageCaptureExtenderValidationTest {
+ @Rule
+ public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
+ Manifest.permission.CAMERA);
+
+ @Before
+ public void setUp() {
+ assumeTrue(CameraUtil.deviceHasCamera());
+ Context context = ApplicationProvider.getApplicationContext();
+ CameraX.init(context, Camera2AppConfig.create(context));
+ }
+
+ @After
+ public void tearDown() throws ExecutionException, InterruptedException {
+ // Wait for CameraX to finish deinitializing before the next test.
+ CameraX.deinit().get();
+ }
+
+ @Test
+ @SmallTest
+ public void getSupportedResolutionsImplementationTest()
+ throws CameraInfoUnavailableException, CameraAccessException {
+
+ // Uses for-loop to check all possible effect/lens facing combinations
+ for (Object[] EffectLensFacingPair :
+ ExtensionsTestUtil.getAllEffectLensFacingCombinations()) {
+ ExtensionsManager.EffectMode effectMode =
+ (ExtensionsManager.EffectMode) EffectLensFacingPair[0];
+ CameraX.LensFacing lensFacing = (CameraX.LensFacing) EffectLensFacingPair[1];
+
+ assumeTrue(CameraUtil.hasCameraWithLensFacing(lensFacing));
+ assumeTrue(ExtensionsManager.isExtensionAvailable(effectMode, lensFacing));
+
+ // Retrieves the target format/resolutions pair list from vendor library for the
+ // target effect mode.
+ ImageCaptureExtenderImpl impl = ExtensionsTestUtil.createImageCaptureExtenderImpl(
+ effectMode, lensFacing);
+
+ // NoSuchMethodError will be thrown if getSupportedResolutions is not
+ // implemented in vendor library, and then the test will fail.
+ impl.getSupportedResolutions();
+ }
+ }
+}
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java
index caa620e..d346503 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java
@@ -31,21 +31,23 @@
import android.Manifest;
import android.app.Instrumentation;
import android.content.Context;
-import android.hardware.camera2.CameraAccessException;
+import android.graphics.ImageFormat;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.util.Pair;
import android.util.Size;
+import androidx.annotation.NonNull;
import androidx.camera.camera2.Camera2AppConfig;
-import androidx.camera.core.CameraDeviceConfig;
import androidx.camera.core.CameraInfoUnavailableException;
import androidx.camera.core.CameraX;
+import androidx.camera.core.CameraX.LensFacing;
import androidx.camera.core.Preview;
import androidx.camera.core.PreviewConfig;
-import androidx.camera.extensions.impl.BeautyPreviewExtenderImpl;
+import androidx.camera.extensions.ExtensionsManager.EffectMode;
import androidx.camera.extensions.impl.CaptureStageImpl;
import androidx.camera.extensions.impl.PreviewExtenderImpl;
import androidx.camera.extensions.impl.PreviewImageProcessorImpl;
@@ -85,7 +87,7 @@
@Before
public void setUp() {
assumeTrue(CameraUtil.deviceHasCamera());
- assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraX.LensFacing.BACK));
+ assumeTrue(CameraUtil.hasCameraWithLensFacing(LensFacing.BACK));
Context context = ApplicationProvider.getApplicationContext();
CameraX.init(context, Camera2AppConfig.create(context));
@@ -119,7 +121,7 @@
any(CameraCharacteristics.class))).thenReturn(true);
PreviewConfig.Builder configBuilder = new PreviewConfig.Builder().setLensFacing(
- CameraX.LensFacing.BACK);
+ LensFacing.BACK);
FakePreviewExtender fakePreviewExtender = new FakePreviewExtender(configBuilder,
mockPreviewExtenderImpl);
@@ -192,7 +194,7 @@
when(mockPreviewExtenderImpl.getCaptureStage()).thenReturn(fakeCaptureStageImpl);
PreviewConfig.Builder configBuilder = new PreviewConfig.Builder().setLensFacing(
- CameraX.LensFacing.BACK);
+ LensFacing.BACK);
FakePreviewExtender fakePreviewExtender = new FakePreviewExtender(configBuilder,
mockPreviewExtenderImpl);
@@ -245,7 +247,7 @@
any(CameraCharacteristics.class))).thenReturn(true);
PreviewConfig.Builder configBuilder = new PreviewConfig.Builder().setLensFacing(
- CameraX.LensFacing.BACK);
+ LensFacing.BACK);
FakePreviewExtender fakePreviewExtender = new FakePreviewExtender(configBuilder,
mockPreviewExtenderImpl);
fakePreviewExtender.enableExtension();
@@ -268,38 +270,31 @@
@Test
@SmallTest
- public void canSetSupportedResolutionsToConfigTest()
- throws CameraInfoUnavailableException, CameraAccessException {
- CameraX.LensFacing lensFacing = CameraX.LensFacing.BACK;
- assumeTrue(CameraUtil.hasCameraWithLensFacing(lensFacing));
+ public void canSetSupportedResolutionsToConfigTest() throws CameraInfoUnavailableException {
+ assumeTrue(CameraUtil.deviceHasCamera());
+ LensFacing lensFacing = CameraX.getDefaultLensFacing();
PreviewConfig.Builder configBuilder = new PreviewConfig.Builder().setLensFacing(lensFacing);
- String cameraId = androidx.camera.extensions.CameraUtil.getCameraId(
- ((CameraDeviceConfig) configBuilder.build()));
- CameraCharacteristics cameraCharacteristics =
- CameraUtil.getCameraManager().getCameraCharacteristics(
- CameraX.getCameraWithLensFacing(lensFacing));
+ PreviewExtenderImpl mockPreviewExtenderImpl = mock(PreviewExtenderImpl.class);
+ when(mockPreviewExtenderImpl.isExtensionAvailable(any(), any())).thenReturn(true);
+ when(mockPreviewExtenderImpl.getProcessorType()).thenReturn(
+ PreviewExtenderImpl.ProcessorType.PROCESSOR_TYPE_NONE);
- // Only BeautyPreviewExtenderImpl has sample implementation for Preview.
- // Retrieves the target format/resolutions pair list directly from
- // BeautyPreviewExtenderImpl.
- BeautyPreviewExtenderImpl impl = new BeautyPreviewExtenderImpl();
-
- impl.init(cameraId, cameraCharacteristics);
List<Pair<Integer, Size[]>> targetFormatResolutionsPairList =
- impl.getSupportedResolutions();
+ generatePreviewSupportedResolutions(lensFacing);
+ when(mockPreviewExtenderImpl.getSupportedResolutions()).thenReturn(
+ targetFormatResolutionsPairList);
- assertThat(targetFormatResolutionsPairList).isNotNull();
+ PreviewExtender fakeExtender = new FakePreviewExtender(configBuilder,
+ mockPreviewExtenderImpl);
- // Retrieves the target format/resolutions pair list from builder after applying beauty
- // mode.
- BeautyPreviewExtender extender = BeautyPreviewExtender.create(configBuilder);
+ // Checks the config does not include supported resolutions before applying effect mode.
assertThat(configBuilder.build().getSupportedResolutions(null)).isNull();
- extender.enableExtension();
+ // Checks the config includes supported resolutions after applying effect mode.
+ fakeExtender.enableExtension();
List<Pair<Integer, Size[]>> resultFormatResolutionsPairList =
configBuilder.build().getSupportedResolutions(null);
-
assertThat(resultFormatResolutionsPairList).isNotNull();
// Checks the result and target pair lists are the same
@@ -312,14 +307,39 @@
}
}
- assertThat(Arrays.asList(resultPair.second).equals(
- Arrays.asList(targetSizes))).isTrue();
+ assertThat(
+ Arrays.asList(resultPair.second).equals(Arrays.asList(targetSizes))).isTrue();
}
}
+ private List<Pair<Integer, Size[]>> generatePreviewSupportedResolutions(
+ @NonNull LensFacing lensFacing)
+ throws CameraInfoUnavailableException {
+ List<Pair<Integer, Size[]>> formatResolutionsPairList = new ArrayList<>();
+ String cameraId =
+ androidx.camera.extensions.CameraUtil.getCameraIdSetWithLensFacing(
+ lensFacing).iterator().next();
+
+ StreamConfigurationMap map =
+ androidx.camera.extensions.CameraUtil.getCameraCharacteristics(cameraId).get(
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+
+ if (map != null) {
+ // Retrieves originally supported resolutions from CameraCharacteristics for PRIVATE
+ // format to return.
+ Size[] outputSizes = map.getOutputSizes(ImageFormat.PRIVATE);
+
+ if (outputSizes != null) {
+ formatResolutionsPairList.add(Pair.create(ImageFormat.PRIVATE, outputSizes));
+ }
+ }
+
+ return formatResolutionsPairList;
+ }
+
private class FakePreviewExtender extends PreviewExtender {
FakePreviewExtender(PreviewConfig.Builder builder, PreviewExtenderImpl impl) {
- init(builder, impl, ExtensionsManager.EffectMode.NORMAL);
+ init(builder, impl, EffectMode.NORMAL);
}
}
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.java
new file mode 100644
index 0000000..e9be0f6
--- /dev/null
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2019 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.
+ */
+
+package androidx.camera.extensions;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.Manifest;
+import android.content.Context;
+import android.hardware.camera2.CameraAccessException;
+
+import androidx.camera.camera2.Camera2AppConfig;
+import androidx.camera.core.CameraInfoUnavailableException;
+import androidx.camera.core.CameraX;
+import androidx.camera.extensions.impl.PreviewExtenderImpl;
+import androidx.camera.extensions.util.ExtensionsTestUtil;
+import androidx.camera.testing.CameraUtil;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.GrantPermissionRule;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.ExecutionException;
+
+@RunWith(AndroidJUnit4.class)
+public class PreviewExtenderValidationTest {
+ @Rule
+ public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
+ Manifest.permission.CAMERA);
+
+ @Before
+ public void setUp() {
+ assumeTrue(CameraUtil.deviceHasCamera());
+ Context context = ApplicationProvider.getApplicationContext();
+ CameraX.init(context, Camera2AppConfig.create(context));
+ }
+
+ @After
+ public void tearDown() throws ExecutionException, InterruptedException {
+ // Wait for CameraX to finish deinitializing before the next test.
+ CameraX.deinit().get();
+ }
+
+ @Test
+ @SmallTest
+ public void getSupportedResolutionsImplementationTest()
+ throws CameraInfoUnavailableException, CameraAccessException {
+
+ // Uses for-loop to check all possible effect/lens facing combinations
+ for (Object[] EffectLensFacingPair :
+ ExtensionsTestUtil.getAllEffectLensFacingCombinations()) {
+ ExtensionsManager.EffectMode effectMode =
+ (ExtensionsManager.EffectMode) EffectLensFacingPair[0];
+ CameraX.LensFacing lensFacing = (CameraX.LensFacing) EffectLensFacingPair[1];
+
+ assumeTrue(CameraUtil.hasCameraWithLensFacing(lensFacing));
+ assumeTrue(ExtensionsManager.isExtensionAvailable(effectMode, lensFacing));
+
+ // Retrieves the target format/resolutions pair list from vendor library for the
+ // target effect mode.
+ PreviewExtenderImpl impl = ExtensionsTestUtil.createPreviewExtenderImpl(effectMode,
+ lensFacing);
+
+ // NoSuchMethodError will be thrown if getSupportedResolutions is not
+ // implemented in vendor library, and then the test will fail.
+ impl.getSupportedResolutions();
+ }
+ }
+}
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java
new file mode 100644
index 0000000..2c2ecc9
--- /dev/null
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java
@@ -0,0 +1,403 @@
+/*
+ * Copyright 2019 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.
+ */
+
+package androidx.camera.extensions.util;
+
+import static junit.framework.TestCase.assertNotNull;
+
+import static org.junit.Assert.assertTrue;
+
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
+
+import androidx.annotation.NonNull;
+import androidx.camera.core.CameraDeviceConfig;
+import androidx.camera.core.CameraInfoUnavailableException;
+import androidx.camera.core.CameraX;
+import androidx.camera.core.CameraX.LensFacing;
+import androidx.camera.core.ImageCapture;
+import androidx.camera.core.ImageCaptureConfig;
+import androidx.camera.core.Preview;
+import androidx.camera.core.PreviewConfig;
+import androidx.camera.extensions.AutoImageCaptureExtender;
+import androidx.camera.extensions.AutoPreviewExtender;
+import androidx.camera.extensions.BeautyImageCaptureExtender;
+import androidx.camera.extensions.BeautyPreviewExtender;
+import androidx.camera.extensions.BokehImageCaptureExtender;
+import androidx.camera.extensions.BokehPreviewExtender;
+import androidx.camera.extensions.ExtensionsManager.EffectMode;
+import androidx.camera.extensions.HdrImageCaptureExtender;
+import androidx.camera.extensions.HdrPreviewExtender;
+import androidx.camera.extensions.ImageCaptureExtender;
+import androidx.camera.extensions.NightImageCaptureExtender;
+import androidx.camera.extensions.NightPreviewExtender;
+import androidx.camera.extensions.PreviewExtender;
+import androidx.camera.extensions.impl.AutoImageCaptureExtenderImpl;
+import androidx.camera.extensions.impl.AutoPreviewExtenderImpl;
+import androidx.camera.extensions.impl.BeautyImageCaptureExtenderImpl;
+import androidx.camera.extensions.impl.BeautyPreviewExtenderImpl;
+import androidx.camera.extensions.impl.BokehImageCaptureExtenderImpl;
+import androidx.camera.extensions.impl.BokehPreviewExtenderImpl;
+import androidx.camera.extensions.impl.HdrImageCaptureExtenderImpl;
+import androidx.camera.extensions.impl.HdrPreviewExtenderImpl;
+import androidx.camera.extensions.impl.ImageCaptureExtenderImpl;
+import androidx.camera.extensions.impl.NightImageCaptureExtenderImpl;
+import androidx.camera.extensions.impl.NightPreviewExtenderImpl;
+import androidx.camera.extensions.impl.PreviewExtenderImpl;
+import androidx.camera.testing.CameraUtil;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+public class ExtensionsTestUtil {
+ @NonNull
+ public static Collection<Object[]> getAllEffectLensFacingCombinations() {
+ return Arrays.asList(new Object[][]{
+ {EffectMode.BOKEH, LensFacing.FRONT},
+ {EffectMode.BOKEH, LensFacing.BACK},
+ {EffectMode.HDR, LensFacing.FRONT},
+ {EffectMode.HDR, LensFacing.BACK},
+ {EffectMode.BEAUTY, LensFacing.FRONT},
+ {EffectMode.BEAUTY, LensFacing.BACK},
+ {EffectMode.NIGHT, LensFacing.FRONT},
+ {EffectMode.NIGHT, LensFacing.BACK},
+ {EffectMode.AUTO, LensFacing.FRONT},
+ {EffectMode.AUTO, LensFacing.BACK}
+ });
+ }
+
+ /**
+ * Creates an {@link ImageCaptureConfig.Builder} object for specific {@link EffectMode} and
+ * {@link LensFacing}.
+ *
+ * @param effectMode The effect mode for the created object.
+ * @param lensFacing The lens facing for the created object.
+ * @return An {@link ImageCaptureConfig.Builder} object.
+ */
+ @NonNull
+ public static ImageCaptureConfig.Builder createImageCaptureConfigBuilderWithEffect(
+ @NonNull EffectMode effectMode, @NonNull LensFacing lensFacing) {
+ ImageCaptureConfig.Builder builder =
+ new ImageCaptureConfig.Builder().setLensFacing(lensFacing);
+ ImageCaptureExtender extender = null;
+
+ switch (effectMode) {
+ case HDR:
+ extender = HdrImageCaptureExtender.create(builder);
+ break;
+ case BOKEH:
+ extender = BokehImageCaptureExtender.create(builder);
+ break;
+ case BEAUTY:
+ extender = BeautyImageCaptureExtender.create(builder);
+ break;
+ case NIGHT:
+ extender = NightImageCaptureExtender.create(builder);
+ break;
+ case AUTO:
+ extender = AutoImageCaptureExtender.create(builder);
+ break;
+ }
+
+ // Applies effect configs if it is not normal mode.
+ if (effectMode != EffectMode.NORMAL) {
+ assertNotNull(extender);
+ assertTrue(extender.isExtensionAvailable());
+ extender.enableExtension();
+ }
+
+ return builder;
+ }
+
+ /**
+ * Creates a {@link PreviewConfig.Builder} object for specific {@link EffectMode} and
+ * {@link LensFacing}.
+ *
+ * @param effectMode The effect mode for the created object.
+ * @param lensFacing The lens facing for the created object.
+ * @return A {@link PreviewConfig.Builder} object.
+ */
+ @NonNull
+ public static PreviewConfig.Builder createPreviewConfigBuilderWithEffect(
+ @NonNull EffectMode effectMode,
+ @NonNull LensFacing lensFacing) {
+ PreviewConfig.Builder builder =
+ new PreviewConfig.Builder().setLensFacing(lensFacing);
+ PreviewExtender extender = null;
+
+ switch (effectMode) {
+ case HDR:
+ extender = HdrPreviewExtender.create(builder);
+ break;
+ case BOKEH:
+ extender = BokehPreviewExtender.create(builder);
+ break;
+ case BEAUTY:
+ extender = BeautyPreviewExtender.create(builder);
+ break;
+ case NIGHT:
+ extender = NightPreviewExtender.create(builder);
+ break;
+ case AUTO:
+ extender = AutoPreviewExtender.create(builder);
+ break;
+ }
+
+ // Applies effect configs if it is not normal mode.
+ if (effectMode != EffectMode.NORMAL) {
+ assertNotNull(extender);
+ assertTrue(extender.isExtensionAvailable());
+ extender.enableExtension();
+ }
+
+ return builder;
+ }
+
+ /**
+ * Creates an {@link ImageCaptureConfig} object for specific {@link EffectMode} and
+ * {@link LensFacing}.
+ *
+ * @param effectMode The effect mode for the created object.
+ * @param lensFacing The lens facing for the created object.
+ * @return An {@link ImageCaptureConfig} object.
+ */
+ @NonNull
+ public static ImageCaptureConfig createImageCaptureConfigWithEffect(
+ @NonNull EffectMode effectMode,
+ @NonNull LensFacing lensFacing) {
+ ImageCaptureConfig.Builder imageCaptureConfigBuilder =
+ createImageCaptureConfigBuilderWithEffect(effectMode, lensFacing);
+ ImageCaptureConfig imageCaptureConfig = imageCaptureConfigBuilder.build();
+
+ return imageCaptureConfig;
+ }
+
+ /**
+ * Creates a {@link PreviewConfig} object for specific {@link EffectMode} and
+ * {@link LensFacing}.
+ *
+ * @param effectMode The effect mode for the created object.
+ * @param lensFacing The lens facing for the created object.
+ * @return A {@link PreviewConfig} object.
+ */
+ @NonNull
+ public static PreviewConfig createPreviewConfigWithEffect(@NonNull EffectMode effectMode,
+ @NonNull LensFacing lensFacing) {
+ PreviewConfig.Builder previewConfigBuilder =
+ createPreviewConfigBuilderWithEffect(effectMode, lensFacing);
+ PreviewConfig previewConfig = previewConfigBuilder.build();
+
+ return previewConfig;
+ }
+
+ /**
+ * Creates an {@link ImageCapture} object for specific {@link EffectMode} and
+ * {@link LensFacing}.
+ *
+ * @param effectMode The effect mode for the created object.
+ * @param lensFacing The lens facing for the created object.
+ * @return An {@link ImageCapture} object.
+ */
+ @NonNull
+ public static ImageCapture createImageCaptureWithEffect(@NonNull EffectMode effectMode,
+ @NonNull LensFacing lensFacing) {
+ ImageCaptureConfig imageCaptureConfig = createImageCaptureConfigWithEffect(effectMode,
+ lensFacing);
+ ImageCapture imageCapture = new ImageCapture(imageCaptureConfig);
+
+ return imageCapture;
+ }
+
+ /**
+ * Creates a {@link Preview} object for specific {@link EffectMode} and {@link LensFacing}.
+ *
+ * @param effectMode The effect mode for the created object.
+ * @param lensFacing The lens facing for the created object.
+ * @return A {@link Preview} object.
+ */
+ @NonNull
+ public static Preview createPreviewWithEffect(@NonNull EffectMode effectMode,
+ @NonNull LensFacing lensFacing) {
+ PreviewConfig previewConfig = createPreviewConfigWithEffect(effectMode, lensFacing);
+ Preview preview = new Preview(previewConfig);
+
+ return preview;
+ }
+
+ /**
+ * Creates an {@link ImageCaptureExtenderImpl} object for specific {@link EffectMode} and
+ * {@link LensFacing}.
+ *
+ * @param effectMode The effect mode for the created object.
+ * @param lensFacing The lens facing for the created object.
+ * @return An {@link ImageCaptureExtenderImpl} object.
+ */
+ @NonNull
+ public static ImageCaptureExtenderImpl createImageCaptureExtenderImpl(
+ @NonNull EffectMode effectMode,
+ @NonNull LensFacing lensFacing)
+ throws CameraInfoUnavailableException, CameraAccessException {
+ ImageCaptureExtenderImpl impl = null;
+
+ switch (effectMode) {
+ case HDR:
+ impl = new HdrImageCaptureExtenderImpl();
+ break;
+ case BOKEH:
+ impl = new BokehImageCaptureExtenderImpl();
+ break;
+ case BEAUTY:
+ impl = new BeautyImageCaptureExtenderImpl();
+ break;
+ case NIGHT:
+ impl = new NightImageCaptureExtenderImpl();
+ break;
+ case AUTO:
+ impl = new AutoImageCaptureExtenderImpl();
+ break;
+ }
+ assertNotNull(impl);
+
+ ImageCaptureConfig.Builder configBuilder = new ImageCaptureConfig.Builder().setLensFacing(
+ lensFacing);
+
+ String cameraId = CameraX.getCameraWithCameraDeviceConfig(
+ ((CameraDeviceConfig) configBuilder.build()));
+ CameraCharacteristics cameraCharacteristics =
+ CameraUtil.getCameraManager().getCameraCharacteristics(
+ CameraX.getCameraWithLensFacing(lensFacing));
+
+ impl.init(cameraId, cameraCharacteristics);
+
+ return impl;
+ }
+
+ /**
+ * Creates a {@link PreviewExtenderImpl} object for specific {@link EffectMode} and
+ * {@link LensFacing}.
+ *
+ * @param effectMode The effect mode for the created object.
+ * @param lensFacing The lens facing for the created object.
+ * @return A {@link PreviewExtenderImpl} object.
+ */
+ @NonNull
+ public static PreviewExtenderImpl createPreviewExtenderImpl(@NonNull EffectMode effectMode,
+ @NonNull LensFacing lensFacing)
+ throws CameraInfoUnavailableException, CameraAccessException {
+ PreviewExtenderImpl impl = null;
+
+ switch (effectMode) {
+ case HDR:
+ impl = new HdrPreviewExtenderImpl();
+ break;
+ case BOKEH:
+ impl = new BokehPreviewExtenderImpl();
+ break;
+ case BEAUTY:
+ impl = new BeautyPreviewExtenderImpl();
+ break;
+ case NIGHT:
+ impl = new NightPreviewExtenderImpl();
+ break;
+ case AUTO:
+ impl = new AutoPreviewExtenderImpl();
+ break;
+ }
+ assertNotNull(impl);
+
+ PreviewConfig.Builder configBuilder = new PreviewConfig.Builder().setLensFacing(lensFacing);
+
+ String cameraId = CameraX.getCameraWithCameraDeviceConfig(
+ ((CameraDeviceConfig) configBuilder.build()));
+ CameraCharacteristics cameraCharacteristics =
+ CameraUtil.getCameraManager().getCameraCharacteristics(
+ CameraX.getCameraWithLensFacing(lensFacing));
+
+ impl.init(cameraId, cameraCharacteristics);
+
+ return impl;
+ }
+
+ /**
+ * Creates an {@link ImageCaptureExtender} object for specific {@link EffectMode} and
+ * {@link ImageCaptureConfig.Builder}.
+ *
+ * @param effectMode The effect mode for the created object.
+ * @param builder The {@link ImageCaptureConfig.Builder} for the created object.
+ * @return An {@link ImageCaptureExtender} object.
+ */
+ @NonNull
+ public static ImageCaptureExtender createImageCaptureExtender(@NonNull EffectMode effectMode,
+ @NonNull ImageCaptureConfig.Builder builder) {
+ ImageCaptureExtender extender = null;
+
+ switch (effectMode) {
+ case HDR:
+ extender = HdrImageCaptureExtender.create(builder);
+ break;
+ case BOKEH:
+ extender = BokehImageCaptureExtender.create(builder);
+ break;
+ case BEAUTY:
+ extender = BeautyImageCaptureExtender.create(builder);
+ break;
+ case NIGHT:
+ extender = NightImageCaptureExtender.create(builder);
+ break;
+ case AUTO:
+ extender = AutoImageCaptureExtender.create(builder);
+ break;
+ }
+ assertNotNull(extender);
+
+ return extender;
+ }
+
+ /**
+ * Creates a {@link PreviewExtender} object for specific {@link EffectMode} and
+ * {@link PreviewConfig.Builder}.
+ *
+ * @param effectMode The effect mode for the created object.
+ * @param builder The {@link PreviewConfig.Builder} for the created object.
+ * @return A {@link PreviewExtender} object.
+ */
+ @NonNull
+ public static PreviewExtender createPreviewExtender(@NonNull EffectMode effectMode,
+ @NonNull PreviewConfig.Builder builder) {
+ PreviewExtender extender = null;
+
+ switch (effectMode) {
+ case HDR:
+ extender = HdrPreviewExtender.create(builder);
+ break;
+ case BOKEH:
+ extender = BokehPreviewExtender.create(builder);
+ break;
+ case BEAUTY:
+ extender = BeautyPreviewExtender.create(builder);
+ break;
+ case NIGHT:
+ extender = NightPreviewExtender.create(builder);
+ break;
+ case AUTO:
+ extender = AutoPreviewExtender.create(builder);
+ break;
+ }
+ assertNotNull(extender);
+
+ return extender;
+ }
+}