minSdk -> RequiresApi for camera-extensions

 This rolls back the minSdkVersion to the AndroidX default (14) and
 instead enforces SDK requirements with lint and the @RequiresApi(21)
 annotation.

 Also includes the same change for camera-testlib-extensions.

 For camera-extensions-stub, we are able to remove the minSdkVersion,
 but because this library only contains stubs and no implementation
 code, we do not need to annotate any of the classes.

 See aosp/1838237 for more information.

Bug: 198449102
Test: ./gradlew camera:camera-extensions:lint
      && ./gradlew camera:camera-extensions-stub:lint
      && ./gradlew camera:camera-testlib-extensions:lint
Change-Id: I1f903da70a330ba7f9e9c183699d10fc8e3ed73f
diff --git a/camera/camera-extensions-stub/build.gradle b/camera/camera-extensions-stub/build.gradle
index 6d234f3..2ed55c3 100644
--- a/camera/camera-extensions-stub/build.gradle
+++ b/camera/camera-extensions-stub/build.gradle
@@ -26,12 +26,6 @@
     api("androidx.annotation:annotation:1.0.0")
 }
 
-android {
-    defaultConfig {
-        minSdkVersion 21
-    }
-}
-
 androidx {
     name = "Jetpack Camera Library OEM Extensions Stub"
     publish = Publish.NONE
diff --git a/camera/camera-extensions/build.gradle b/camera/camera-extensions/build.gradle
index 6830280..e137b58 100644
--- a/camera/camera-extensions/build.gradle
+++ b/camera/camera-extensions/build.gradle
@@ -54,6 +54,7 @@
     androidTestImplementation(libs.kotlinStdlib)
     androidTestImplementation(libs.mockitoCore, excludes.bytebuddy) // DexMaker has its own MockMaker
     androidTestImplementation(libs.truth)
+    androidTestImplementation(libs.multidex)
     androidTestImplementation(project(":camera:camera-lifecycle"))
     androidTestImplementation(project(":camera:camera-testing"))
     androidTestImplementation(project(":internal-testutils-truth"))
@@ -63,7 +64,7 @@
 
 android {
     defaultConfig {
-        minSdkVersion 21
+        multiDexEnabled = true
     }
 
     buildTypes.all {
diff --git a/camera/camera-extensions/lint.xml b/camera/camera-extensions/lint.xml
new file mode 100644
index 0000000..0843ecf
--- /dev/null
+++ b/camera/camera-extensions/lint.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+    <!-- Disable NewApi lint check temporarily for unit tests.
+    This file can be removed once b/200599470 is resolved. -->
+    <issue id="NewApi">
+        <ignore path="src/test/**" />
+    </issue>
+</lint>
\ No newline at end of file
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsManagerTest.kt b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsManagerTest.kt
index e15deb5..65b0b5c 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsManagerTest.kt
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsManagerTest.kt
@@ -30,6 +30,7 @@
 import androidx.camera.testing.CameraUtil
 import androidx.camera.testing.fakes.FakeLifecycleOwner
 import androidx.camera.testing.fakes.FakeUseCase
+import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.testutils.assertThrows
@@ -48,6 +49,7 @@
 
 @SmallTest
 @RunWith(Parameterized::class)
+@SdkSuppress(minSdkVersion = 21)
 class ExtensionsManagerTest(
     @field:ExtensionMode.Mode @param:ExtensionMode.Mode private val extensionMode: Int,
     @field:CameraSelector.LensFacing @param:CameraSelector.LensFacing private val lensFacing: Int
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.kt b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.kt
index a0c448b..7753a7e 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.kt
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.kt
@@ -51,6 +51,7 @@
 
 @SmallTest
 @RunWith(Parameterized::class)
+@SdkSuppress(minSdkVersion = 21)
 class ImageCaptureExtenderValidationTest(
     @field:Mode @param:Mode private val extensionMode: Int,
     @field:CameraSelector.LensFacing @param:CameraSelector.LensFacing private val lensFacing: Int
@@ -137,7 +138,7 @@
     }
 
     @Test
-    @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.O_MR1)
+    @SdkSuppress(minSdkVersion = 21, maxSdkVersion = Build.VERSION_CODES.O_MR1)
     fun returnsNullFromOnPresetSession_whenAPILevelOlderThan28() {
         // Creates the ImageCaptureExtenderImpl to check that onPresetSession() returns null when
         // API level is older than 28.
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.kt b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.kt
index d5da017..e68cfb8 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.kt
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.kt
@@ -48,6 +48,7 @@
 
 @SmallTest
 @RunWith(Parameterized::class)
+@SdkSuppress(minSdkVersion = 21)
 class PreviewExtenderValidationTest(
     @field:Mode @param:Mode private val extensionMode: Int,
     @field:CameraSelector.LensFacing @param:CameraSelector.LensFacing private val lensFacing: Int
@@ -131,7 +132,7 @@
     }
 
     @Test
-    @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.O_MR1)
+    @SdkSuppress(minSdkVersion = 21, maxSdkVersion = Build.VERSION_CODES.O_MR1)
     fun returnsNullFromOnPresetSession_whenAPILevelOlderThan28() {
         // Creates the ImageCaptureExtenderImpl to check that onPresetSession() returns null when
         // API level is older than 28.
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/ImageCaptureConfigProviderTest.kt b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/ImageCaptureConfigProviderTest.kt
index cef523b..cd987ab 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/ImageCaptureConfigProviderTest.kt
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/ImageCaptureConfigProviderTest.kt
@@ -36,6 +36,7 @@
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
 import com.google.common.truth.Truth
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.runBlocking
@@ -56,7 +57,7 @@
 
 @MediumTest
 @RunWith(AndroidJUnit4::class)
-
+@SdkSuppress(minSdkVersion = 21)
 class ImageCaptureConfigProviderTest {
     @get:Rule
     val useCamera = CameraUtil.grantCameraPermissionAndPreTest()
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/PreviewConfigProviderTest.kt b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/PreviewConfigProviderTest.kt
index 7be9086..1f25c2c 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/PreviewConfigProviderTest.kt
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/internal/PreviewConfigProviderTest.kt
@@ -42,6 +42,7 @@
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.runBlocking
@@ -64,6 +65,7 @@
 
 @MediumTest
 @RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = 21)
 class PreviewConfigProviderTest {
     @get:Rule
     val useCamera = CameraUtil.grantCameraPermissionAndPreTest()
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
index c4d0e15..4f61e65 100644
--- 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
@@ -27,6 +27,7 @@
 import android.hardware.camera2.CameraCharacteristics;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 import androidx.camera.core.CameraSelector;
 import androidx.camera.extensions.ExtensionMode;
 import androidx.camera.extensions.impl.AutoImageCaptureExtenderImpl;
@@ -48,6 +49,7 @@
 /**
  * Extension test util functions.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class ExtensionsTestUtil {
     @NonNull
     public static Collection<Object[]> getAllExtensionsLensFacingCombinations() {
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionCameraFilter.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionCameraFilter.java
index 73e7c9e..0da3b2b 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionCameraFilter.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionCameraFilter.java
@@ -20,6 +20,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.OptIn;
+import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.interop.Camera2CameraInfo;
 import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
 import androidx.camera.core.CameraFilter;
@@ -37,6 +38,7 @@
  * A filter that filters camera based on extender implementation. If the implementation is
  * unavailable, the camera will be considered available.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 final class ExtensionCameraFilter implements CameraFilter {
     private final Identifier mId;
     private final VendorExtender mVendorExtender;
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionMode.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionMode.java
index d14c35b..89bc006 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionMode.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionMode.java
@@ -17,6 +17,7 @@
 package androidx.camera.extensions;
 
 import androidx.annotation.IntDef;
+import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 import androidx.camera.core.Camera;
 import androidx.camera.core.CameraProvider;
@@ -28,6 +29,7 @@
 /**
  * The available modes for the extensions.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class ExtensionMode {
     /** Normal mode without any specific effect applied. */
     public static final int NONE = 0;
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsConfig.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsConfig.java
index e44e5cc..5aab6b2 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsConfig.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsConfig.java
@@ -17,6 +17,7 @@
 package androidx.camera.extensions;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 import androidx.camera.core.impl.CameraConfig;
 import androidx.camera.core.impl.Config;
 import androidx.camera.core.impl.Identifier;
@@ -27,6 +28,7 @@
 /**
  * Implementation of CameraConfig which provides the extensions capability.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 class ExtensionsConfig implements CameraConfig {
     // Option Declarations:
     // *********************************************************************************************
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsInfo.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsInfo.java
index 8a0d53c..059eb4e 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsInfo.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsInfo.java
@@ -23,6 +23,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.OptIn;
+import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
 import androidx.camera.core.CameraFilter;
 import androidx.camera.core.CameraInfo;
@@ -53,6 +54,7 @@
  * call can be used to get the specified {@link CameraSelector} to bind use cases and enable the
  * extension mode on the camera.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 final class ExtensionsInfo {
     private static final String EXTENDED_CAMERA_CONFIG_PROVIDER_ID_PREFIX = ":camera:camera"
             + "-extensions-";
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java
index 47e658a..7748d56 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java
@@ -22,6 +22,7 @@
 import androidx.annotation.GuardedBy;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.CameraProvider;
@@ -82,6 +83,7 @@
  * }
  * </pre>
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class ExtensionsManager {
     private static final String TAG = "ExtensionsManager";
 
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingCaptureProcessor.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingCaptureProcessor.java
index 07799cd..88c4207 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingCaptureProcessor.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingCaptureProcessor.java
@@ -24,6 +24,7 @@
 import android.view.Surface;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.impl.Camera2CameraCaptureResultConverter;
 import androidx.camera.core.ExperimentalGetImage;
 import androidx.camera.core.ImageInfo;
@@ -46,6 +47,7 @@
 /**
  * A {@link CaptureProcessor} that calls a vendor provided implementation.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class AdaptingCaptureProcessor implements CaptureProcessor {
     private final CaptureProcessorImpl mImpl;
 
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingCaptureStage.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingCaptureStage.java
index 3276023..225da9a 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingCaptureStage.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingCaptureStage.java
@@ -20,12 +20,14 @@
 import android.util.Pair;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.impl.Camera2ImplConfig;
 import androidx.camera.core.impl.CaptureConfig;
 import androidx.camera.core.impl.CaptureStage;
 import androidx.camera.extensions.impl.CaptureStageImpl;
 
 /** A {@link CaptureStage} that calls a vendor provided implementation. */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class AdaptingCaptureStage implements CaptureStage {
 
     private final CaptureConfig mCaptureRequestConfiguration;
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingPreviewProcessor.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingPreviewProcessor.java
index fad4afa..2b2a6b3 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingPreviewProcessor.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingPreviewProcessor.java
@@ -24,6 +24,7 @@
 import android.view.Surface;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.impl.Camera2CameraCaptureResultConverter;
 import androidx.camera.core.ExperimentalGetImage;
 import androidx.camera.core.ImageInfo;
@@ -44,6 +45,7 @@
 /**
  * A {@link CaptureProcessor} that calls a vendor provided preview processing implementation.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class AdaptingPreviewProcessor implements CaptureProcessor, CloseableProcessor {
     private static final String TAG = "AdaptingPreviewProcesso";
     private final PreviewImageProcessorImpl mImpl;
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingRequestUpdateProcessor.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingRequestUpdateProcessor.java
index c1445b9..c8ff32f 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingRequestUpdateProcessor.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingRequestUpdateProcessor.java
@@ -21,6 +21,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.impl.Camera2CameraCaptureResultConverter;
 import androidx.camera.core.ImageInfo;
 import androidx.camera.core.impl.CameraCaptureResult;
@@ -35,6 +36,7 @@
 /**
  * A {@link ImageInfoProcessor} that calls a vendor provided preview processing implementation.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class AdaptingRequestUpdateProcessor implements ImageInfoProcessor,
         CloseableProcessor {
     private final PreviewExtenderImpl mPreviewExtenderImpl;
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdvancedVendorExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdvancedVendorExtender.java
index 7915f33..08a60e7 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdvancedVendorExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdvancedVendorExtender.java
@@ -26,6 +26,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.OptIn;
+import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.interop.Camera2CameraInfo;
 import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
 import androidx.camera.core.CameraInfo;
@@ -48,6 +49,7 @@
 /**
  * Advanced vendor interface implementation
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class AdvancedVendorExtender implements VendorExtender {
     private final AdvancedExtenderImpl mAdvancedExtenderImpl;
     private String mCameraId;
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/BasicVendorExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/BasicVendorExtender.java
index 783554f..e31e8d9 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/BasicVendorExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/BasicVendorExtender.java
@@ -27,6 +27,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.OptIn;
+import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.interop.Camera2CameraInfo;
 import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
 import androidx.camera.core.CameraInfo;
@@ -54,6 +55,7 @@
 /**
  * Basic vendor interface implementation
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class BasicVendorExtender implements VendorExtender {
     private static final String TAG = "BasicVendorExtender";
     private final @ExtensionMode.Mode int mMode;
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/BlockingCloseAccessCounter.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/BlockingCloseAccessCounter.java
index dc03bef..b41659e 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/BlockingCloseAccessCounter.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/BlockingCloseAccessCounter.java
@@ -17,6 +17,7 @@
 package androidx.camera.extensions.internal;
 
 import androidx.annotation.GuardedBy;
+import androidx.annotation.RequiresApi;
 
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.Condition;
@@ -45,6 +46,7 @@
  * }
  * }</pre>
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 final class BlockingCloseAccessCounter {
     @GuardedBy("mLock")
     private AtomicInteger mAccessCount = new AtomicInteger(0);
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/CloseableProcessor.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/CloseableProcessor.java
index 5fb4252..495a6b8d 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/CloseableProcessor.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/CloseableProcessor.java
@@ -16,10 +16,13 @@
 
 package androidx.camera.extensions.internal;
 
+import androidx.annotation.RequiresApi;
+
 /**
  * A processor that can be closed so that the underlying processing implementation is skipped,
  * if it has been closed.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface CloseableProcessor {
 
     /**
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ExtensionVersion.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ExtensionVersion.java
index cf7a8fb..6b58434 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ExtensionVersion.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ExtensionVersion.java
@@ -17,12 +17,14 @@
 package androidx.camera.extensions.internal;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.camera.core.Logger;
 import androidx.camera.extensions.impl.ExtensionVersionImpl;
 
 /**
  * Provides interfaces to check the extension version.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public abstract class ExtensionVersion {
     private static final String TAG = "ExtenderVersion";
 
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ExtensionsUseCaseConfigFactory.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ExtensionsUseCaseConfigFactory.java
index d3180d1..b792fe7 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ExtensionsUseCaseConfigFactory.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ExtensionsUseCaseConfigFactory.java
@@ -20,6 +20,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.camera.core.impl.Config;
 import androidx.camera.core.impl.MutableOptionsBundle;
 import androidx.camera.core.impl.OptionsBundle;
@@ -30,6 +31,7 @@
  * Implementation of UseCaseConfigFactory to provide the default extensions configurations for use
  * cases.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class ExtensionsUseCaseConfigFactory implements UseCaseConfigFactory {
     private final ImageCaptureConfigProvider mImageCaptureConfigProvider;
     private final PreviewConfigProvider mPreviewConfigProvider;
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ImageCaptureConfigProvider.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ImageCaptureConfigProvider.java
index c51e759..d3a3bea 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ImageCaptureConfigProvider.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ImageCaptureConfigProvider.java
@@ -26,6 +26,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.OptIn;
+import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.impl.Camera2ImplConfig;
 import androidx.camera.camera2.impl.CameraEventCallback;
 import androidx.camera.camera2.impl.CameraEventCallbacks;
@@ -53,6 +54,7 @@
 /**
  * Provides extensions related configs for image capture
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class ImageCaptureConfigProvider implements ConfigProvider<ImageCaptureConfig> {
     private static final String TAG = "ImageCaptureConfigProvider";
     static final Config.Option<Integer> OPTION_IMAGE_CAPTURE_CONFIG_PROVIDER_MODE =
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/PreviewConfigProvider.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/PreviewConfigProvider.java
index 0d21105..14e3138a 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/PreviewConfigProvider.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/PreviewConfigProvider.java
@@ -26,6 +26,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.OptIn;
+import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.impl.Camera2ImplConfig;
 import androidx.camera.camera2.impl.CameraEventCallback;
 import androidx.camera.camera2.impl.CameraEventCallbacks;
@@ -49,6 +50,7 @@
 /**
  * For providing extensions config for preview.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class PreviewConfigProvider implements ConfigProvider<PreviewConfig> {
     private static final String TAG = "PreviewConfigProvider";
     static final Config.Option<Integer> OPTION_PREVIEW_CONFIG_PROVIDER_MODE = Config.Option.create(
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/VendorExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/VendorExtender.java
index 81b5807..e1f7380 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/VendorExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/VendorExtender.java
@@ -25,6 +25,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.camera.core.CameraInfo;
 import androidx.camera.core.impl.SessionProcessor;
 
@@ -35,6 +36,7 @@
  * A unified vendor extensions interface which interacts with both basic and advanced extender
  * vendor implementation.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface VendorExtender {
     /**
      * Indicates whether the extension is supported on the device.
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/Version.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/Version.java
index 7f13db4..d37eeb4 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/Version.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/Version.java
@@ -20,6 +20,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import com.google.auto.value.AutoValue;
 
@@ -31,6 +32,7 @@
 /**
  * Class encapsulating a version with major, minor, patch and description values.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 @AutoValue
 public abstract class Version implements Comparable<Version> {
     public static final Version VERSION_1_0 = Version.create(1, 0, 0, "");
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/VersionName.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/VersionName.java
index 19a4e1d..99ad205 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/VersionName.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/VersionName.java
@@ -17,10 +17,12 @@
 package androidx.camera.extensions.internal;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 
 /**
  * The version of CameraX extension releases.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class VersionName {
     // Current version of vendor library implementation that the CameraX extension supports. This
     // needs to be increased along with the version of vendor library interface.
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/AdvancedSessionProcessor.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/AdvancedSessionProcessor.java
index b4a33c9..a9dc65d 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/AdvancedSessionProcessor.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/AdvancedSessionProcessor.java
@@ -28,6 +28,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.impl.Camera2CameraCaptureResultConverter;
 import androidx.camera.camera2.impl.Camera2ImplConfig;
 import androidx.camera.camera2.interop.CaptureRequestOptions;
@@ -54,6 +55,7 @@
 /**
  * A {@link SessionProcessor} based on OEMs' {@link SessionProcessorImpl}.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class AdvancedSessionProcessor extends SessionProcessorBase {
     private final SessionProcessorImpl mImpl;
     private final Context mContext;
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2OutputConfig.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2OutputConfig.java
index 712026f..7ffecb8 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2OutputConfig.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2OutputConfig.java
@@ -18,6 +18,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import java.util.List;
 
@@ -25,6 +26,7 @@
  * A config representing a {@link android.hardware.camera2.params.OutputConfiguration} where
  * Surface will be created by the information in this config.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 interface Camera2OutputConfig {
     /**
      * Gets the id of this output config. The id can be used to identify the stream in vendor
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2OutputConfigBuilder.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2OutputConfigBuilder.java
index 5bd3240..c461f5b 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2OutputConfigBuilder.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2OutputConfigBuilder.java
@@ -21,6 +21,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.camera.extensions.impl.advanced.Camera2OutputConfigImpl;
 import androidx.camera.extensions.impl.advanced.ImageReaderOutputConfigImpl;
 import androidx.camera.extensions.impl.advanced.MultiResolutionImageReaderOutputConfigImpl;
@@ -36,6 +37,7 @@
 /**
  * A builder for building {@link Camera2OutputConfig}.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 class Camera2OutputConfigBuilder {
     private static AtomicInteger sLastId = new AtomicInteger(0);
     private OutputConfig mOutputConfig;
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2SessionConfig.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2SessionConfig.java
index c077ee1..4ba35a5 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2SessionConfig.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2SessionConfig.java
@@ -19,6 +19,7 @@
 import android.hardware.camera2.CaptureRequest;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 
 import java.util.List;
 import java.util.Map;
@@ -26,6 +27,7 @@
 /**
  * A config representing a {@link android.hardware.camera2.params.SessionConfiguration}
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 interface Camera2SessionConfig {
     /**
      * Returns all the {@link Camera2OutputConfig}s that will be used to create
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2SessionConfigBuilder.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2SessionConfigBuilder.java
index c178bee..60e13b7 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2SessionConfigBuilder.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/Camera2SessionConfigBuilder.java
@@ -21,6 +21,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.camera.extensions.impl.advanced.Camera2SessionConfigImpl;
 
 import java.util.ArrayList;
@@ -31,6 +32,7 @@
 /**
  * A builder implementation to build the {@link Camera2SessionConfig} instance.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 class Camera2SessionConfigBuilder {
     private int mSessionTemplateId = CameraDevice.TEMPLATE_PREVIEW;
     private Map<CaptureRequest.Key<?>, Object> mSessionParameters = new HashMap<>();
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/ImageProcessor.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/ImageProcessor.java
index fac650f..4ab0374 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/ImageProcessor.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/ImageProcessor.java
@@ -18,10 +18,12 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 /**
  * An interface to receive and process the upcoming next available Image.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface ImageProcessor {
     /**
      * The reference count will be decremented when this method returns. If an extension wants
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/ImageReaderOutputConfig.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/ImageReaderOutputConfig.java
index 98f4249..79965c9 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/ImageReaderOutputConfig.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/ImageReaderOutputConfig.java
@@ -19,10 +19,12 @@
 import android.util.Size;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 
 /**
  * Surface will be created by constructing an ImageReader.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface ImageReaderOutputConfig extends Camera2OutputConfig {
     /**
      * Returns the size of the surface.
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/ImageReference.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/ImageReference.java
index 43d866f..c3b88c6 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/ImageReference.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/ImageReference.java
@@ -19,6 +19,7 @@
 import android.media.Image;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 /**
  * An Image reference container that enables the Image sharing between Camera2/CameraX and OEM
@@ -27,6 +28,7 @@
  *
  * <p>Implemented by Camera2/CameraX.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface ImageReference {
     /**
      * Increment the reference count. Returns true if the value was incremented.
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/MultiResolutionImageReaderOutputConfig.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/MultiResolutionImageReaderOutputConfig.java
index 21fd271..7a33619 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/MultiResolutionImageReaderOutputConfig.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/MultiResolutionImageReaderOutputConfig.java
@@ -16,9 +16,12 @@
 
 package androidx.camera.extensions.internal.sessionprocessor;
 
+import androidx.annotation.RequiresApi;
+
 /**
  * Surface will be created by constructing a MultiResolutionImageReader.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface MultiResolutionImageReaderOutputConfig extends Camera2OutputConfig {
     /**
      * Gets the image format of the surface.
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/SessionProcessorBase.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/SessionProcessorBase.java
index 1ec8a84..7b61ff4 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/SessionProcessorBase.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/SessionProcessorBase.java
@@ -27,6 +27,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.OptIn;
+import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.impl.Camera2ImplConfig;
 import androidx.camera.camera2.interop.Camera2CameraInfo;
 import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
@@ -49,6 +50,7 @@
  * Base class for SessionProcessor implementation. It is responsible for creating image readers and
  * maintaining the {@link ImageProcessor} associated with the image reader.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 abstract class SessionProcessorBase implements SessionProcessor {
     private static final String TAG = "SessionProcessorBase";
     @NonNull
@@ -190,6 +192,7 @@
 
     protected abstract void deInitSessionInternal();
 
+    @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
     private static class ImageRefHolder implements ImageReference {
         private int mRefCount;
         private Image mImage;
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/SurfaceOutputConfig.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/SurfaceOutputConfig.java
index 15f494b..4881283 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/SurfaceOutputConfig.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/sessionprocessor/SurfaceOutputConfig.java
@@ -19,10 +19,12 @@
 import android.view.Surface;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 
 /**
  * Use Surface directly to create the OutputConfiguration.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface SurfaceOutputConfig extends Camera2OutputConfig {
     /**
      * Get the {@link Surface}. It'll return a valid surface only when type is TYPE_SURFACE.
diff --git a/camera/camera-testlib-extensions/build.gradle b/camera/camera-testlib-extensions/build.gradle
index deb9bbd..077c748 100644
--- a/camera/camera-testlib-extensions/build.gradle
+++ b/camera/camera-testlib-extensions/build.gradle
@@ -29,7 +29,6 @@
 
 android {
     defaultConfig {
-        minSdkVersion 21
         versionCode 1
         multiDexEnabled true
     }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java
index 6154482..e1f6033 100755
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java
@@ -30,6 +30,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
@@ -44,6 +45,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class AutoImageCaptureExtenderImpl implements ImageCaptureExtenderImpl {
     private static final String TAG = "AutoICExtender";
     private static final int DEFAULT_STAGE_ID = 0;
@@ -84,59 +86,11 @@
 
     @Override
     public CaptureProcessorImpl getCaptureProcessor() {
-        CaptureProcessorImpl captureProcessor =
-                new CaptureProcessorImpl() {
-                    private ImageWriter mImageWriter;
-
-                    @Override
-                    public void onOutputSurface(Surface surface, int imageFormat) {
-                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                            mImageWriter = ImageWriter.newInstance(surface, 1);
-                        }
-                    }
-
-                    @Override
-                    public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results) {
-                        Log.d(TAG, "Started auto CaptureProcessor");
-
-                        Pair<Image, TotalCaptureResult> result = results.get(DEFAULT_STAGE_ID);
-
-                        if (result == null) {
-                            Log.w(TAG,
-                                    "Unable to process since images does not contain all stages.");
-                            return;
-                        } else {
-                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                                Image image = mImageWriter.dequeueInputImage();
-
-                                // Do processing here
-                                ByteBuffer yByteBuffer = image.getPlanes()[0].getBuffer();
-                                ByteBuffer uByteBuffer = image.getPlanes()[2].getBuffer();
-                                ByteBuffer vByteBuffer = image.getPlanes()[1].getBuffer();
-
-                                // Sample here just simply copy/paste the capture image result
-                                yByteBuffer.put(result.first.getPlanes()[0].getBuffer());
-                                uByteBuffer.put(result.first.getPlanes()[2].getBuffer());
-                                vByteBuffer.put(result.first.getPlanes()[1].getBuffer());
-
-                                mImageWriter.queueInputImage(image);
-                            }
-                        }
-
-                        Log.d(TAG, "Completed auto CaptureProcessor");
-                    }
-
-                    @Override
-                    public void onResolutionUpdate(Size size) {
-
-                    }
-
-                    @Override
-                    public void onImageFormatUpdate(int imageFormat) {
-
-                    }
-                };
-        return captureProcessor;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            return new AutoImageCaptureExtenderCaptureProcessorImpl();
+        } else {
+            return new NoOpCaptureProcessorImpl();
+        }
     }
 
     @Override
@@ -201,4 +155,54 @@
     public Range<Long> getEstimatedCaptureLatencyRange(@Nullable Size captureOutputSize) {
         return new Range<>(300L, 1000L);
     }
+
+    @RequiresApi(23)
+    static final class AutoImageCaptureExtenderCaptureProcessorImpl implements
+            CaptureProcessorImpl {
+        private ImageWriter mImageWriter;
+
+        @Override
+        public void onOutputSurface(Surface surface, int imageFormat) {
+            mImageWriter = ImageWriter.newInstance(surface, 1);
+        }
+
+        @Override
+        public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results) {
+            Log.d(TAG, "Started auto CaptureProcessor");
+
+            Pair<Image, TotalCaptureResult> result = results.get(DEFAULT_STAGE_ID);
+
+            if (result == null) {
+                Log.w(TAG,
+                        "Unable to process since images does not contain all stages.");
+                return;
+            } else {
+                Image image = mImageWriter.dequeueInputImage();
+
+                // Do processing here
+                ByteBuffer yByteBuffer = image.getPlanes()[0].getBuffer();
+                ByteBuffer uByteBuffer = image.getPlanes()[2].getBuffer();
+                ByteBuffer vByteBuffer = image.getPlanes()[1].getBuffer();
+
+                // Sample here just simply copy/paste the capture image result
+                yByteBuffer.put(result.first.getPlanes()[0].getBuffer());
+                uByteBuffer.put(result.first.getPlanes()[2].getBuffer());
+                vByteBuffer.put(result.first.getPlanes()[1].getBuffer());
+
+                mImageWriter.queueInputImage(image);
+            }
+
+            Log.d(TAG, "Completed auto CaptureProcessor");
+        }
+
+        @Override
+        public void onResolutionUpdate(Size size) {
+
+        }
+
+        @Override
+        public void onImageFormatUpdate(int imageFormat) {
+
+        }
+    }
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/AutoPreviewExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/AutoPreviewExtenderImpl.java
index 0814b3d..e2aabfa 100755
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/AutoPreviewExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/AutoPreviewExtenderImpl.java
@@ -24,6 +24,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import java.util.List;
 
@@ -35,6 +36,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class AutoPreviewExtenderImpl implements PreviewExtenderImpl {
     private static final int DEFAULT_STAGE_ID = 0;
     private static final int SESSION_STAGE_ID = 101;
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java
index 8380a7f..89871c8 100755
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java
@@ -32,6 +32,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
@@ -46,6 +47,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class BeautyImageCaptureExtenderImpl implements ImageCaptureExtenderImpl {
     private static final String TAG = "BeautyICExtender";
     private static final int DEFAULT_STAGE_ID = 0;
@@ -89,59 +91,11 @@
 
     @Override
     public CaptureProcessorImpl getCaptureProcessor() {
-        CaptureProcessorImpl captureProcessor =
-                new CaptureProcessorImpl() {
-                    private ImageWriter mImageWriter;
-
-                    @Override
-                    public void onOutputSurface(Surface surface, int imageFormat) {
-                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                            mImageWriter = ImageWriter.newInstance(surface, 1);
-                        }
-                    }
-
-                    @Override
-                    public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results) {
-                        Log.d(TAG, "Started beauty CaptureProcessor");
-
-                        Pair<Image, TotalCaptureResult> result = results.get(DEFAULT_STAGE_ID);
-
-                        if (result == null) {
-                            Log.w(TAG,
-                                    "Unable to process since images does not contain all stages.");
-                            return;
-                        } else {
-                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                                Image image = mImageWriter.dequeueInputImage();
-
-                                // Do processing here
-                                ByteBuffer yByteBuffer = image.getPlanes()[0].getBuffer();
-                                ByteBuffer uByteBuffer = image.getPlanes()[2].getBuffer();
-                                ByteBuffer vByteBuffer = image.getPlanes()[1].getBuffer();
-
-                                // Sample here just simply copy/paste the capture image result
-                                yByteBuffer.put(result.first.getPlanes()[0].getBuffer());
-                                uByteBuffer.put(result.first.getPlanes()[2].getBuffer());
-                                vByteBuffer.put(result.first.getPlanes()[1].getBuffer());
-
-                                mImageWriter.queueInputImage(image);
-                            }
-                        }
-
-                        Log.d(TAG, "Completed beauty CaptureProcessor");
-                    }
-
-                    @Override
-                    public void onResolutionUpdate(Size size) {
-
-                    }
-
-                    @Override
-                    public void onImageFormatUpdate(int imageFormat) {
-
-                    }
-                };
-        return captureProcessor;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            return new BeautyImageCaptureExtenderCaptureProcessorImpl();
+        } else {
+            return new NoOpCaptureProcessorImpl();
+        }
     }
 
     @Override
@@ -227,4 +181,54 @@
     public Range<Long> getEstimatedCaptureLatencyRange(@Nullable Size captureOutputSize) {
         return new Range<>(300L, 1000L);
     }
+
+    @RequiresApi(23)
+    static final class BeautyImageCaptureExtenderCaptureProcessorImpl implements
+            CaptureProcessorImpl {
+        private ImageWriter mImageWriter;
+
+        @Override
+        public void onOutputSurface(Surface surface, int imageFormat) {
+            mImageWriter = ImageWriter.newInstance(surface, 1);
+        }
+
+        @Override
+        public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results) {
+            Log.d(TAG, "Started beauty CaptureProcessor");
+
+            Pair<Image, TotalCaptureResult> result = results.get(DEFAULT_STAGE_ID);
+
+            if (result == null) {
+                Log.w(TAG,
+                        "Unable to process since images does not contain all stages.");
+                return;
+            } else {
+                Image image = mImageWriter.dequeueInputImage();
+
+                // Do processing here
+                ByteBuffer yByteBuffer = image.getPlanes()[0].getBuffer();
+                ByteBuffer uByteBuffer = image.getPlanes()[2].getBuffer();
+                ByteBuffer vByteBuffer = image.getPlanes()[1].getBuffer();
+
+                // Sample here just simply copy/paste the capture image result
+                yByteBuffer.put(result.first.getPlanes()[0].getBuffer());
+                uByteBuffer.put(result.first.getPlanes()[2].getBuffer());
+                vByteBuffer.put(result.first.getPlanes()[1].getBuffer());
+
+                mImageWriter.queueInputImage(image);
+            }
+
+            Log.d(TAG, "Completed beauty CaptureProcessor");
+        }
+
+        @Override
+        public void onResolutionUpdate(Size size) {
+
+        }
+
+        @Override
+        public void onImageFormatUpdate(int imageFormat) {
+
+        }
+    }
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BeautyPreviewExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BeautyPreviewExtenderImpl.java
index 4801055..a49c0e6 100755
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BeautyPreviewExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BeautyPreviewExtenderImpl.java
@@ -26,6 +26,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -38,6 +39,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class BeautyPreviewExtenderImpl implements PreviewExtenderImpl {
     private static final int DEFAULT_STAGE_ID = 0;
     private static final int SESSION_STAGE_ID = 101;
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java
index f0f7c59..df88d11 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java
@@ -30,6 +30,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
@@ -44,6 +45,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class BokehImageCaptureExtenderImpl implements ImageCaptureExtenderImpl {
     private static final String TAG = "BokehICExtender";
     private static final int DEFAULT_STAGE_ID = 0;
@@ -84,60 +86,11 @@
 
     @Override
     public CaptureProcessorImpl getCaptureProcessor() {
-        CaptureProcessorImpl captureProcessor =
-                new CaptureProcessorImpl() {
-                    private ImageWriter mImageWriter;
-
-                    @Override
-                    public void onOutputSurface(Surface surface, int imageFormat) {
-                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                            mImageWriter = ImageWriter.newInstance(surface, 1);
-                        }
-                    }
-
-                    @Override
-                    public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results) {
-                        Log.d(TAG, "Started bokeh CaptureProcessor");
-
-                        Pair<Image, TotalCaptureResult> result = results.get(DEFAULT_STAGE_ID);
-
-                        if (result == null) {
-                            Log.w(TAG,
-                                    "Unable to process since images does not contain all stages.");
-                            return;
-                        } else {
-                            if (android.os.Build.VERSION.SDK_INT
-                                    >= android.os.Build.VERSION_CODES.M) {
-                                Image image = mImageWriter.dequeueInputImage();
-
-                                // Do processing here
-                                ByteBuffer yByteBuffer = image.getPlanes()[0].getBuffer();
-                                ByteBuffer uByteBuffer = image.getPlanes()[2].getBuffer();
-                                ByteBuffer vByteBuffer = image.getPlanes()[1].getBuffer();
-
-                                // Sample here just simply copy/paste the capture image result
-                                yByteBuffer.put(result.first.getPlanes()[0].getBuffer());
-                                uByteBuffer.put(result.first.getPlanes()[2].getBuffer());
-                                vByteBuffer.put(result.first.getPlanes()[1].getBuffer());
-
-                                mImageWriter.queueInputImage(image);
-                            }
-                        }
-
-                        Log.d(TAG, "Completed bokeh CaptureProcessor");
-                    }
-
-                    @Override
-                    public void onResolutionUpdate(Size size) {
-
-                    }
-
-                    @Override
-                    public void onImageFormatUpdate(int imageFormat) {
-
-                    }
-                };
-        return captureProcessor;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            return new BokehImageCaptureExtenderCaptureProcessorImpl();
+        } else {
+            return new NoOpCaptureProcessorImpl();
+        }
     }
 
     @Override
@@ -202,4 +155,54 @@
     public Range<Long> getEstimatedCaptureLatencyRange(@Nullable Size captureOutputSize) {
         return new Range<>(300L, 1000L);
     }
+
+    @RequiresApi(23)
+    static final class BokehImageCaptureExtenderCaptureProcessorImpl implements
+            CaptureProcessorImpl {
+        private ImageWriter mImageWriter;
+
+        @Override
+        public void onOutputSurface(Surface surface, int imageFormat) {
+            mImageWriter = ImageWriter.newInstance(surface, 1);
+        }
+
+        @Override
+        public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results) {
+            Log.d(TAG, "Started bokeh CaptureProcessor");
+
+            Pair<Image, TotalCaptureResult> result = results.get(DEFAULT_STAGE_ID);
+
+            if (result == null) {
+                Log.w(TAG,
+                        "Unable to process since images does not contain all stages.");
+                return;
+            } else {
+                Image image = mImageWriter.dequeueInputImage();
+
+                // Do processing here
+                ByteBuffer yByteBuffer = image.getPlanes()[0].getBuffer();
+                ByteBuffer uByteBuffer = image.getPlanes()[2].getBuffer();
+                ByteBuffer vByteBuffer = image.getPlanes()[1].getBuffer();
+
+                // Sample here just simply copy/paste the capture image result
+                yByteBuffer.put(result.first.getPlanes()[0].getBuffer());
+                uByteBuffer.put(result.first.getPlanes()[2].getBuffer());
+                vByteBuffer.put(result.first.getPlanes()[1].getBuffer());
+
+                mImageWriter.queueInputImage(image);
+            }
+
+            Log.d(TAG, "Completed bokeh CaptureProcessor");
+        }
+
+        @Override
+        public void onResolutionUpdate(Size size) {
+
+        }
+
+        @Override
+        public void onImageFormatUpdate(int imageFormat) {
+
+        }
+    }
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BokehPreviewExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BokehPreviewExtenderImpl.java
index ca6a8da..7d72e9b 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BokehPreviewExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BokehPreviewExtenderImpl.java
@@ -26,6 +26,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import java.util.List;
 
@@ -37,6 +38,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class BokehPreviewExtenderImpl implements PreviewExtenderImpl {
     private static final int DEFAULT_STAGE_ID = 0;
     private static final int SESSION_STAGE_ID = 101;
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CameraCharacteristicAvailability.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CameraCharacteristicAvailability.java
index f4d6ddd..277cc61 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CameraCharacteristicAvailability.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CameraCharacteristicAvailability.java
@@ -20,12 +20,14 @@
 import android.util.Log;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 
 import java.util.Arrays;
 
 /**
  * A utility class to check the availabilities of camera characteristics.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 final class CameraCharacteristicAvailability {
     private static final String TAG = "CharacteristicAbility";
 
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java
index 564e941..68731c4 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java
@@ -23,6 +23,8 @@
 import android.util.Size;
 import android.view.Surface;
 
+import androidx.annotation.RequiresApi;
+
 import java.util.Map;
 
 /**
@@ -30,6 +32,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface CaptureProcessorImpl {
     /**
      * This gets called to update where the CaptureProcessor should write the output of {@link
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CaptureStageImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CaptureStageImpl.java
index c4796c2..27adb97a 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CaptureStageImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CaptureStageImpl.java
@@ -19,6 +19,8 @@
 import android.hardware.camera2.CaptureRequest;
 import android.util.Pair;
 
+import androidx.annotation.RequiresApi;
+
 import java.util.List;
 
 /**
@@ -26,6 +28,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface CaptureStageImpl {
     /** Returns the identifier for the {@link CaptureStageImpl}. */
     int getId();
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ExtenderStateListener.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ExtenderStateListener.java
index 010ce68..935673b 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ExtenderStateListener.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ExtenderStateListener.java
@@ -22,11 +22,14 @@
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.params.SessionConfiguration;
 
+import androidx.annotation.RequiresApi;
+
 /**
  * Provides interfaces that the OEM needs to implement to handle the state change.
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface ExtenderStateListener {
 
     /**
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ExtensionVersionImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ExtensionVersionImpl.java
index d3618e48..a524aea 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ExtensionVersionImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ExtensionVersionImpl.java
@@ -18,6 +18,8 @@
 
 import android.util.Log;
 
+import androidx.annotation.RequiresApi;
+
 /**
  * Implementation for extension version check.
  *
@@ -26,6 +28,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class ExtensionVersionImpl {
     private static final String TAG = "ExtenderVersionImpl";
     private static final String VERSION = "1.2.0";
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/GLImage2SurfaceRenderer.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/GLImage2SurfaceRenderer.java
index 99a3513..f35a47c 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/GLImage2SurfaceRenderer.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/GLImage2SurfaceRenderer.java
@@ -54,6 +54,8 @@
 import android.util.Size;
 import android.view.Surface;
 
+import androidx.annotation.RequiresApi;
+
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.FloatBuffer;
@@ -68,6 +70,7 @@
  * take as input a {@link Image} and write to a {@link android.graphics.SurfaceTexture}. It has only
  * been tested on a Pixel 2XL.
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 final class GLImage2SurfaceRenderer {
     private static final String TAG = "GLImage2SurfaceRenderer";
 
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java
index e41ad73..8469b34 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java
@@ -32,6 +32,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
@@ -47,6 +48,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class HdrImageCaptureExtenderImpl implements ImageCaptureExtenderImpl {
     private static final String TAG = "HdrImageCaptureExtender";
     private static final int UNDER_STAGE_ID = 0;
@@ -128,126 +130,11 @@
 
     @Override
     public CaptureProcessorImpl getCaptureProcessor() {
-        CaptureProcessorImpl captureProcessor =
-                new CaptureProcessorImpl() {
-                    private ImageWriter mImageWriter;
-
-                    @Override
-                    public void onOutputSurface(Surface surface, int imageFormat) {
-                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                            mImageWriter = ImageWriter.newInstance(surface, 1);
-                        }
-                    }
-
-                    @Override
-                    public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results) {
-                        Log.d(TAG, "Started HDR CaptureProcessor");
-
-                        // Check for availability of all requested images
-                        if (!results.containsKey(UNDER_STAGE_ID)) {
-                            Log.w(TAG,
-                                    "Unable to process since images does not contain "
-                                            + "underexposed image.");
-                            return;
-                        }
-
-                        if (!results.containsKey(NORMAL_STAGE_ID)) {
-                            Log.w(TAG,
-                                    "Unable to process since images does not contain normal "
-                                            + "exposed image.");
-                            return;
-                        }
-
-                        if (!results.containsKey(OVER_STAGE_ID)) {
-                            Log.w(TAG,
-                                    "Unable to process since images does not contain "
-                                            + "overexposed image.");
-                            return;
-                        }
-
-                        // Do processing of images, our placeholder logic just copies the first
-                        // Image into the output buffer.
-                        List<Pair<Image, TotalCaptureResult>> imageDataPairs = new ArrayList<>(
-                                results.values());
-                        if (android.os.Build.VERSION.SDK_INT
-                                >= android.os.Build.VERSION_CODES.M) {
-                            Image outputImage = mImageWriter.dequeueInputImage();
-
-                            // Do processing here
-                            // The sample here simply returns the normal image result
-                            Image normalImage = imageDataPairs.get(NORMAL_STAGE_ID).first;
-
-                            if (outputImage.getWidth() != normalImage.getWidth()
-                                    || outputImage.getHeight() != normalImage.getHeight()) {
-                                throw new IllegalStateException(String.format("input image "
-                                                + "resolution [%d, %d] not the same as the "
-                                                + "output image[%d, %d]", normalImage.getWidth(),
-                                        normalImage.getHeight(), outputImage.getWidth(),
-                                        outputImage.getHeight()));
-                            }
-
-                            try {
-                                // copy y plane
-                                Image.Plane inYPlane = normalImage.getPlanes()[0];
-                                Image.Plane outYPlane = outputImage.getPlanes()[0];
-                                ByteBuffer inYBuffer = inYPlane.getBuffer();
-                                ByteBuffer outYBuffer = outYPlane.getBuffer();
-                                int inYPixelStride = inYPlane.getPixelStride();
-                                int inYRowStride = inYPlane.getRowStride();
-                                int outYPixelStride = outYPlane.getPixelStride();
-                                int outYRowStride = outYPlane.getRowStride();
-                                for (int x = 0; x < outputImage.getHeight(); x++) {
-                                    for (int y = 0; y < outputImage.getWidth(); y++) {
-                                        int inIndex = x * inYRowStride + y * inYPixelStride;
-                                        int outIndex = x * outYRowStride + y * outYPixelStride;
-                                        outYBuffer.put(outIndex, inYBuffer.get(inIndex));
-                                    }
-                                }
-
-                                // Copy UV
-                                for (int i = 1; i < 3; i++) {
-                                    Image.Plane inPlane = normalImage.getPlanes()[i];
-                                    Image.Plane outPlane = outputImage.getPlanes()[i];
-                                    ByteBuffer inBuffer = inPlane.getBuffer();
-                                    ByteBuffer outBuffer = outPlane.getBuffer();
-                                    int inPixelStride = inPlane.getPixelStride();
-                                    int inRowStride = inPlane.getRowStride();
-                                    int outPixelStride = outPlane.getPixelStride();
-                                    int outRowStride = outPlane.getRowStride();
-                                    // UV are half width compared to Y
-                                    for (int x = 0; x < outputImage.getHeight() / 2; x++) {
-                                        for (int y = 0; y < outputImage.getWidth() / 2; y++) {
-                                            int inIndex = x * inRowStride + y * inPixelStride;
-                                            int outIndex = x * outRowStride + y * outPixelStride;
-                                            byte b = inBuffer.get(inIndex);
-                                            outBuffer.put(outIndex, b);
-                                        }
-                                    }
-                                }
-                            } catch (IllegalStateException e) {
-                                Log.e(TAG, "Error accessing the Image: " + e);
-                                // Since something went wrong, don't try to queue up the image.
-                                // Instead let the Image writing get dropped.
-                                return;
-                            }
-
-                            mImageWriter.queueInputImage(outputImage);
-                        }
-
-                        Log.d(TAG, "Completed HDR CaptureProcessor");
-                    }
-
-                    @Override
-                    public void onResolutionUpdate(Size size) {
-
-                    }
-
-                    @Override
-                    public void onImageFormatUpdate(int imageFormat) {
-
-                    }
-                };
-        return captureProcessor;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            return new HdrImageCaptureExtenderCaptureProcessorImpl();
+        } else {
+            return new NoOpCaptureProcessorImpl();
+        }
     }
 
     @Override
@@ -300,4 +187,119 @@
     public Range<Long> getEstimatedCaptureLatencyRange(@Nullable Size captureOutputSize) {
         return new Range<>(300L, 1000L);
     }
+
+    @RequiresApi(23)
+    static final class HdrImageCaptureExtenderCaptureProcessorImpl implements CaptureProcessorImpl {
+        private ImageWriter mImageWriter;
+
+        @Override
+        public void onOutputSurface(Surface surface, int imageFormat) {
+            mImageWriter = ImageWriter.newInstance(surface, 1);
+        }
+
+        @Override
+        public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results) {
+            Log.d(TAG, "Started HDR CaptureProcessor");
+
+            // Check for availability of all requested images
+            if (!results.containsKey(UNDER_STAGE_ID)) {
+                Log.w(TAG,
+                        "Unable to process since images does not contain "
+                                + "underexposed image.");
+                return;
+            }
+
+            if (!results.containsKey(NORMAL_STAGE_ID)) {
+                Log.w(TAG,
+                        "Unable to process since images does not contain normal "
+                                + "exposed image.");
+                return;
+            }
+
+            if (!results.containsKey(OVER_STAGE_ID)) {
+                Log.w(TAG,
+                        "Unable to process since images does not contain "
+                                + "overexposed image.");
+                return;
+            }
+
+            // Do processing of images, our placeholder logic just copies the first
+            // Image into the output buffer.
+            List<Pair<Image, TotalCaptureResult>> imageDataPairs = new ArrayList<>(
+                    results.values());
+            Image outputImage = mImageWriter.dequeueInputImage();
+
+            // Do processing here
+            // The sample here simply returns the normal image result
+            Image normalImage = imageDataPairs.get(NORMAL_STAGE_ID).first;
+
+            if (outputImage.getWidth() != normalImage.getWidth()
+                    || outputImage.getHeight() != normalImage.getHeight()) {
+                throw new IllegalStateException(String.format("input image "
+                                + "resolution [%d, %d] not the same as the "
+                                + "output image[%d, %d]", normalImage.getWidth(),
+                        normalImage.getHeight(), outputImage.getWidth(),
+                        outputImage.getHeight()));
+            }
+
+            try {
+                // copy y plane
+                Image.Plane inYPlane = normalImage.getPlanes()[0];
+                Image.Plane outYPlane = outputImage.getPlanes()[0];
+                ByteBuffer inYBuffer = inYPlane.getBuffer();
+                ByteBuffer outYBuffer = outYPlane.getBuffer();
+                int inYPixelStride = inYPlane.getPixelStride();
+                int inYRowStride = inYPlane.getRowStride();
+                int outYPixelStride = outYPlane.getPixelStride();
+                int outYRowStride = outYPlane.getRowStride();
+                for (int x = 0; x < outputImage.getHeight(); x++) {
+                    for (int y = 0; y < outputImage.getWidth(); y++) {
+                        int inIndex = x * inYRowStride + y * inYPixelStride;
+                        int outIndex = x * outYRowStride + y * outYPixelStride;
+                        outYBuffer.put(outIndex, inYBuffer.get(inIndex));
+                    }
+                }
+
+                // Copy UV
+                for (int i = 1; i < 3; i++) {
+                    Image.Plane inPlane = normalImage.getPlanes()[i];
+                    Image.Plane outPlane = outputImage.getPlanes()[i];
+                    ByteBuffer inBuffer = inPlane.getBuffer();
+                    ByteBuffer outBuffer = outPlane.getBuffer();
+                    int inPixelStride = inPlane.getPixelStride();
+                    int inRowStride = inPlane.getRowStride();
+                    int outPixelStride = outPlane.getPixelStride();
+                    int outRowStride = outPlane.getRowStride();
+                    // UV are half width compared to Y
+                    for (int x = 0; x < outputImage.getHeight() / 2; x++) {
+                        for (int y = 0; y < outputImage.getWidth() / 2; y++) {
+                            int inIndex = x * inRowStride + y * inPixelStride;
+                            int outIndex = x * outRowStride + y * outPixelStride;
+                            byte b = inBuffer.get(inIndex);
+                            outBuffer.put(outIndex, b);
+                        }
+                    }
+                }
+            } catch (IllegalStateException e) {
+                Log.e(TAG, "Error accessing the Image: " + e);
+                // Since something went wrong, don't try to queue up the image.
+                // Instead let the Image writing get dropped.
+                return;
+            }
+
+            mImageWriter.queueInputImage(outputImage);
+
+            Log.d(TAG, "Completed HDR CaptureProcessor");
+        }
+
+        @Override
+        public void onResolutionUpdate(Size size) {
+
+        }
+
+        @Override
+        public void onImageFormatUpdate(int imageFormat) {
+
+        }
+    }
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrPreviewExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrPreviewExtenderImpl.java
index 2e44ba9..264dfd5 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrPreviewExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrPreviewExtenderImpl.java
@@ -26,6 +26,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import java.util.List;
 
@@ -37,6 +38,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class HdrPreviewExtenderImpl implements PreviewExtenderImpl {
     private static final int DEFAULT_STAGE_ID = 0;
 
@@ -79,7 +81,38 @@
         return null;
     }
 
-    private PreviewImageProcessorImpl mProcessor = new PreviewImageProcessorImpl() {
+    private final PreviewImageProcessorImpl mProcessor =
+            new HdrPreviewExtenderPreviewImageProcessorImpl();
+
+    @Override
+    public void onInit(String cameraId, CameraCharacteristics cameraCharacteristics,
+            Context context) {
+        mRenderer = new GLImage2SurfaceRenderer();
+    }
+
+    @Override
+    public void onDeInit() {
+        mRenderer.close();
+        mRenderer = null;
+    }
+
+    @Override
+    public CaptureStageImpl onPresetSession() {
+        return null;
+    }
+
+    @Override
+    public CaptureStageImpl onEnableSession() {
+        return null;
+    }
+
+    @Override
+    public CaptureStageImpl onDisableSession() {
+        return null;
+    }
+
+    @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+    final class HdrPreviewExtenderPreviewImageProcessorImpl implements PreviewImageProcessorImpl {
         Surface mSurface;
         Size mSize;
 
@@ -112,32 +145,5 @@
         public void onImageFormatUpdate(int imageFormat) {
 
         }
-    };
-
-    @Override
-    public void onInit(String cameraId, CameraCharacteristics cameraCharacteristics,
-            Context context) {
-        mRenderer = new GLImage2SurfaceRenderer();
-    }
-
-    @Override
-    public void onDeInit() {
-        mRenderer.close();
-        mRenderer = null;
-    }
-
-    @Override
-    public CaptureStageImpl onPresetSession() {
-        return null;
-    }
-
-    @Override
-    public CaptureStageImpl onEnableSession() {
-        return null;
-    }
-
-    @Override
-    public CaptureStageImpl onDisableSession() {
-        return null;
     }
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java
index 884c0dd..f47a1a0 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java
@@ -23,6 +23,7 @@
 import android.util.Size;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import java.util.List;
 
@@ -31,6 +32,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface ImageCaptureExtenderImpl extends ExtenderStateListener {
     /**
      * Indicates whether the extension is supported on the device.
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/InitializerImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/InitializerImpl.java
index fc245c8..66892da 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/InitializerImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/InitializerImpl.java
@@ -20,6 +20,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
@@ -31,6 +32,7 @@
  *
  * @since 1.1
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class InitializerImpl {
     private InitializerImpl() {
     }
@@ -116,6 +118,7 @@
     /**
      * Callback that gets called when the library has finished initializing and is ready for used.
      */
+    @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
     public interface OnExtensionsInitializedCallback {
         /** Called if the library successfully initializes. */
         void onSuccess();
@@ -135,6 +138,7 @@
      * {@link #init(String, Context, OnExtensionsInitializedCallback, Executor)} can be called
      * again regardless of whether or not the deinitialization has succeeded or failed.
      */
+    @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
     public interface OnExtensionsDeinitializedCallback {
         /** Called if the library successfully deinitializes. */
         void onSuccess();
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java
index 405da8d..6d84fa0 100755
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java
@@ -30,6 +30,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
@@ -44,6 +45,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class NightImageCaptureExtenderImpl implements ImageCaptureExtenderImpl {
     private static final String TAG = "NightICExtender";
     private static final int DEFAULT_STAGE_ID = 0;
@@ -84,59 +86,11 @@
 
     @Override
     public CaptureProcessorImpl getCaptureProcessor() {
-        CaptureProcessorImpl captureProcessor =
-                new CaptureProcessorImpl() {
-                    private ImageWriter mImageWriter;
-
-                    @Override
-                    public void onOutputSurface(Surface surface, int imageFormat) {
-                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                            mImageWriter = ImageWriter.newInstance(surface, 1);
-                        }
-                    }
-
-                    @Override
-                    public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results) {
-                        Log.d(TAG, "Started night CaptureProcessor");
-
-                        Pair<Image, TotalCaptureResult> result = results.get(DEFAULT_STAGE_ID);
-
-                        if (result == null) {
-                            Log.w(TAG,
-                                    "Unable to process since images does not contain all stages.");
-                            return;
-                        } else {
-                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                                Image image = mImageWriter.dequeueInputImage();
-
-                                // Do processing here
-                                ByteBuffer yByteBuffer = image.getPlanes()[0].getBuffer();
-                                ByteBuffer uByteBuffer = image.getPlanes()[2].getBuffer();
-                                ByteBuffer vByteBuffer = image.getPlanes()[1].getBuffer();
-
-                                // Sample here just simply copy/paste the capture image result
-                                yByteBuffer.put(result.first.getPlanes()[0].getBuffer());
-                                uByteBuffer.put(result.first.getPlanes()[2].getBuffer());
-                                vByteBuffer.put(result.first.getPlanes()[1].getBuffer());
-
-                                mImageWriter.queueInputImage(image);
-                            }
-                        }
-
-                        Log.d(TAG, "Completed night CaptureProcessor");
-                    }
-
-                    @Override
-                    public void onResolutionUpdate(Size size) {
-
-                    }
-
-                    @Override
-                    public void onImageFormatUpdate(int imageFormat) {
-
-                    }
-                };
-        return captureProcessor;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            return new NightImageCaptureExtenderCaptureProcessorImpl();
+        } else {
+            return new NoOpCaptureProcessorImpl();
+        }
     }
 
     @Override
@@ -201,4 +155,54 @@
     public Range<Long> getEstimatedCaptureLatencyRange(@Nullable Size captureOutputSize) {
         return new Range<>(300L, 1000L);
     }
+
+    @RequiresApi(23)
+    static final class NightImageCaptureExtenderCaptureProcessorImpl implements
+            CaptureProcessorImpl {
+        private ImageWriter mImageWriter;
+
+        @Override
+        public void onOutputSurface(Surface surface, int imageFormat) {
+            mImageWriter = ImageWriter.newInstance(surface, 1);
+        }
+
+        @Override
+        public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results) {
+            Log.d(TAG, "Started night CaptureProcessor");
+
+            Pair<Image, TotalCaptureResult> result = results.get(DEFAULT_STAGE_ID);
+
+            if (result == null) {
+                Log.w(TAG,
+                        "Unable to process since images does not contain all stages.");
+                return;
+            } else {
+                Image image = mImageWriter.dequeueInputImage();
+
+                // Do processing here
+                ByteBuffer yByteBuffer = image.getPlanes()[0].getBuffer();
+                ByteBuffer uByteBuffer = image.getPlanes()[2].getBuffer();
+                ByteBuffer vByteBuffer = image.getPlanes()[1].getBuffer();
+
+                // Sample here just simply copy/paste the capture image result
+                yByteBuffer.put(result.first.getPlanes()[0].getBuffer());
+                uByteBuffer.put(result.first.getPlanes()[2].getBuffer());
+                vByteBuffer.put(result.first.getPlanes()[1].getBuffer());
+
+                mImageWriter.queueInputImage(image);
+            }
+
+            Log.d(TAG, "Completed night CaptureProcessor");
+        }
+
+        @Override
+        public void onResolutionUpdate(Size size) {
+
+        }
+
+        @Override
+        public void onImageFormatUpdate(int imageFormat) {
+
+        }
+    }
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NightPreviewExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NightPreviewExtenderImpl.java
index 8bb6074..2df3724 100755
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NightPreviewExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NightPreviewExtenderImpl.java
@@ -24,6 +24,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import java.util.List;
 
@@ -35,6 +36,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class NightPreviewExtenderImpl implements PreviewExtenderImpl {
     private static final int DEFAULT_STAGE_ID = 0;
     private static final int SESSION_STAGE_ID = 101;
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NoOpCaptureProcessorImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NoOpCaptureProcessorImpl.java
new file mode 100644
index 0000000..9645c43
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NoOpCaptureProcessorImpl.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 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.impl;
+
+import android.hardware.camera2.TotalCaptureResult;
+import android.media.Image;
+import android.util.Pair;
+import android.util.Size;
+import android.view.Surface;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import java.util.Map;
+
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+final class NoOpCaptureProcessorImpl implements CaptureProcessorImpl {
+    @Override
+    public void onOutputSurface(@NonNull Surface surface, int imageFormat) {
+
+    }
+
+    @Override
+    public void process(@NonNull Map<Integer, Pair<Image, TotalCaptureResult>> results) {
+
+    }
+
+    @Override
+    public void onResolutionUpdate(@NonNull Size size) {
+
+    }
+
+    @Override
+    public void onImageFormatUpdate(int imageFormat) {
+
+    }
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/PreviewExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/PreviewExtenderImpl.java
index 4324987..4613f24 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/PreviewExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/PreviewExtenderImpl.java
@@ -23,6 +23,7 @@
 import android.util.Size;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import java.util.List;
 
@@ -31,6 +32,7 @@
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface PreviewExtenderImpl extends ExtenderStateListener {
     /** The different types of the preview processing. */
     enum ProcessorType {
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/PreviewImageProcessorImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/PreviewImageProcessorImpl.java
index 7caad1a..60d3f77 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/PreviewImageProcessorImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/PreviewImageProcessorImpl.java
@@ -20,12 +20,15 @@
 import android.hardware.camera2.TotalCaptureResult;
 import android.media.Image;
 
+import androidx.annotation.RequiresApi;
+
 /**
  * Processing a single {@link Image} and {@link TotalCaptureResult} to produce an output to a
  * stream.
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface PreviewImageProcessorImpl extends ProcessorImpl {
     /**
      * Processes the requested image capture.
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ProcessorImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ProcessorImpl.java
index 6be328b..663a16a 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ProcessorImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ProcessorImpl.java
@@ -19,11 +19,14 @@
 import android.util.Size;
 import android.view.Surface;
 
+import androidx.annotation.RequiresApi;
+
 /**
  * Processes an input image stream and produces an output image stream.
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface ProcessorImpl {
     /**
      * Updates where the ProcessorImpl should write the output to.
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/RequestUpdateProcessorImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/RequestUpdateProcessorImpl.java
index 14637d7..d42aa2a 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/RequestUpdateProcessorImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/RequestUpdateProcessorImpl.java
@@ -18,11 +18,14 @@
 
 import android.hardware.camera2.TotalCaptureResult;
 
+import androidx.annotation.RequiresApi;
+
 /**
  * Processes a {@link TotalCaptureResult} to update a CaptureStage.
  *
  * @since 1.0
  */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface RequestUpdateProcessorImpl extends ProcessorImpl {
     /**
      * Process the {@link TotalCaptureResult} to update the {@link CaptureStageImpl}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/RequestUpdateProcessorImpls.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/RequestUpdateProcessorImpls.java
index afbad00..45ac4ab 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/RequestUpdateProcessorImpls.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/RequestUpdateProcessorImpls.java
@@ -20,6 +20,9 @@
 import android.util.Size;
 import android.view.Surface;
 
+import androidx.annotation.RequiresApi;
+
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 class RequestUpdateProcessorImpls {
     private static final RequestUpdateProcessorImpl sNoUpdateProcessor =
             new RequestUpdateProcessorImpl() {
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/SettableCaptureStage.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/SettableCaptureStage.java
index 66d75b9..8aecf5d 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/SettableCaptureStage.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/SettableCaptureStage.java
@@ -19,11 +19,14 @@
 import android.hardware.camera2.CaptureRequest;
 import android.util.Pair;
 
+import androidx.annotation.RequiresApi;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 final class SettableCaptureStage implements CaptureStageImpl {
     private final int mId;