[go: nahoru, domu]

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;
+    }
+}