Use new image capture pipeline for software JPEG path / remove unused classes and methods.

1.  use new image capture pipeline for software JPEG path
2.  add test in coretestapp/ImageCaptureTest for saving file with software JPEG capture
3.  remove isRGBA8888Required
4.  remove unused classes and methods.

Test: all auto tests
Bug: 260184815
Change-Id: I0dd21967c4bf12617bc6938c6778f998c2004dec
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/compat/workaround/ExtraSupportedSurfaceCombinationsContainerDeviceTest.kt b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/compat/workaround/ExtraSupportedSurfaceCombinationsContainerDeviceTest.kt
index c7ef572..053529d 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/compat/workaround/ExtraSupportedSurfaceCombinationsContainerDeviceTest.kt
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/compat/workaround/ExtraSupportedSurfaceCombinationsContainerDeviceTest.kt
@@ -21,8 +21,6 @@
 import android.hardware.camera2.CameraCharacteristics
 import android.os.Handler
 import android.os.Looper
-import android.util.Size
-import android.view.Surface
 import androidx.camera.camera2.Camera2Config
 import androidx.camera.camera2.internal.Camera2CameraFactory
 import androidx.camera.camera2.internal.compat.quirk.DeviceQuirks
@@ -38,10 +36,8 @@
 import androidx.camera.core.impl.CameraConfig
 import androidx.camera.core.impl.CameraInfoInternal
 import androidx.camera.core.impl.CameraThreadConfig
-import androidx.camera.core.impl.CaptureProcessor
 import androidx.camera.core.impl.Config
 import androidx.camera.core.impl.Identifier
-import androidx.camera.core.impl.ImageProxyBundle
 import androidx.camera.core.impl.MutableOptionsBundle
 import androidx.camera.core.impl.SessionProcessor
 import androidx.camera.core.impl.SurfaceCombination
@@ -372,21 +368,4 @@
             assertThat(latch.await(timeout, TimeUnit.MILLISECONDS)).isTrue()
         }
     }
-
-    private class FakePreviewCaptureProcessor : CaptureProcessor {
-        override fun onOutputSurface(surface: Surface, imageFormat: Int) {
-            // No-op
-        }
-
-        override fun process(bundle: ImageProxyBundle) {
-            bundle.captureIds.forEach {
-                val image = bundle.getImageProxy(it).get()
-                image.close()
-            }
-        }
-
-        override fun onResolutionUpdate(size: Size) {
-            // No-op
-        }
-    }
 }
\ No newline at end of file
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/ProcessingImageReaderDeviceTest.kt b/camera/camera-core/src/androidTest/java/androidx/camera/core/ProcessingImageReaderDeviceTest.kt
deleted file mode 100644
index 7d1c8fd..0000000
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/ProcessingImageReaderDeviceTest.kt
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2020 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.core
-
-import android.graphics.ImageFormat
-import android.media.ImageWriter
-import android.util.Pair
-import android.util.Size
-import android.view.Surface
-import androidx.camera.core.impl.CameraCaptureCallback
-import androidx.camera.core.impl.CaptureBundle
-import androidx.camera.core.impl.CaptureProcessor
-import androidx.camera.core.impl.ImageProxyBundle
-import androidx.camera.core.impl.ImageReaderProxy
-import androidx.camera.core.impl.TagBundle
-import androidx.camera.core.impl.utils.executor.CameraXExecutors
-import androidx.camera.testing.fakes.FakeCameraCaptureResult
-import androidx.camera.testing.fakes.FakeCaptureStage
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import androidx.test.filters.SmallTest
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.async
-import kotlinx.coroutines.runBlocking
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import kotlin.coroutines.resume
-import kotlin.coroutines.suspendCoroutine
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = 23) // This test uses ImageWriter which is supported from api 23.
-class ProcessingImageReaderDeviceTest {
-    private companion object Bundle {
-        private const val CAPTURE_ID_0 = 0
-        private const val CAPTURE_ID_1 = 1
-        private const val TIMESTAMP_0 = 0L
-        private const val TIMESTAMP_1 = 1000L
-    }
-
-    // A processor that will generate a garbage image but has the timestamp of the first image in
-    // the bundle
-    private val mProcessor = object : CaptureProcessor {
-        private lateinit var mImageWriter: ImageWriter
-
-        override fun onOutputSurface(surface: Surface, imageFormat: Int) {
-            mImageWriter = ImageWriter.newInstance(surface, 2)
-        }
-
-        override fun process(bundle: ImageProxyBundle) {
-            val image = mImageWriter.dequeueInputImage()
-            image.timestamp = bundle.getImageProxy(bundle.captureIds[0]).get().imageInfo.timestamp
-            mImageWriter.queueInputImage(image)
-        }
-
-        override fun onResolutionUpdate(size: Size) = Unit
-    }
-
-    private val mCaptureStage0 = FakeCaptureStage(CAPTURE_ID_0, null)
-    private val mCaptureStage1 = FakeCaptureStage(CAPTURE_ID_1, null)
-
-    private lateinit var mCaptureBundle: CaptureBundle
-
-    @Before
-    fun setUp() {
-        mCaptureBundle = CaptureBundles.createCaptureBundle(mCaptureStage0, mCaptureStage1)
-    }
-
-    @Test
-    fun processesImage_whenImageInBundleEnqueued() = runBlocking {
-        val processingImageReader = ProcessingImageReader.Builder(
-            640,
-            480,
-            ImageFormat.YUV_420_888,
-            2,
-            mCaptureBundle,
-            mProcessor
-        ).build()
-
-        val job = async {
-            suspendCoroutine<ImageProxy?> { cont ->
-                // Waiting on the ProcessingImageReader to produce an ImageProxy
-                processingImageReader.setOnImageAvailableListener(
-                    ImageReaderProxy.OnImageAvailableListener { imageReader ->
-                        cont.resume(imageReader.acquireNextImage())
-                    },
-                    CameraXExecutors.directExecutor()
-                )
-
-                processingImageReader.setCaptureBundle(mCaptureBundle)
-                val imageWriter = ImageWriter.newInstance(processingImageReader.surface!!, 2)
-                val callback = processingImageReader.cameraCaptureCallback!!
-
-                // Trigger the bundle of images required for processing to occur
-                triggerImage(imageWriter, callback, TIMESTAMP_0, CAPTURE_ID_0)
-                triggerImage(imageWriter, callback, TIMESTAMP_1, CAPTURE_ID_1)
-            }
-        }
-        val image = job.await()
-
-        // Check the values of the images that are captured
-        assertThat(image).isNotNull()
-        assertThat(image!!.imageInfo.timestamp).isEqualTo(TIMESTAMP_0)
-    }
-
-    private fun triggerImage(
-        imageWriter: ImageWriter,
-        callback: CameraCaptureCallback,
-        timestamp: Long,
-        captureId: Int
-    ) {
-        val image = imageWriter.dequeueInputImage()
-        image.timestamp = timestamp
-        imageWriter.queueInputImage(image)
-        val fakeCameraCaptureResult = FakeCameraCaptureResult()
-        fakeCameraCaptureResult.timestamp = timestamp
-        val tagBundle = TagBundle.create(
-            Pair(
-                mCaptureBundle.hashCode().toString(),
-                captureId
-            )
-        )
-        fakeCameraCaptureResult.setTag(tagBundle)
-        callback.onCaptureCompleted(fakeCameraCaptureResult)
-    }
-}
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/SurfaceRequestTest.kt b/camera/camera-core/src/androidTest/java/androidx/camera/core/SurfaceRequestTest.kt
index d5b344c..ebe18d2 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/SurfaceRequestTest.kt
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/SurfaceRequestTest.kt
@@ -351,7 +351,7 @@
         autoCleanup: Boolean = true,
         onInvalidated: () -> Unit = {},
     ): SurfaceRequest {
-        val request = SurfaceRequest(size, FakeCamera(), false, expectedFrameRate, onInvalidated)
+        val request = SurfaceRequest(size, FakeCamera(), expectedFrameRate, onInvalidated)
         if (autoCleanup) {
             surfaceRequests.add(request)
         }
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/DefaultSurfaceProcessorTest.kt b/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/DefaultSurfaceProcessorTest.kt
index 884de88..a16b6f3 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/DefaultSurfaceProcessorTest.kt
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/processing/DefaultSurfaceProcessorTest.kt
@@ -303,7 +303,7 @@
     }
 
     private fun createInputSurfaceRequest(): SurfaceRequest {
-        return SurfaceRequest(Size(WIDTH, HEIGHT), fakeCamera, false) {}.apply {
+        return SurfaceRequest(Size(WIDTH, HEIGHT), fakeCamera) {}.apply {
             inputSurfaceRequestsToClose.add(this)
         }
     }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
index 17254cc..45076b8 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
@@ -17,7 +17,6 @@
 package androidx.camera.core;
 
 import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_BUFFER_FORMAT;
-import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_CAPTURE_BUNDLE;
 import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_CAPTURE_CONFIG_UNPACKER;
 import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_DEFAULT_CAPTURE_CONFIG;
 import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_DEFAULT_SESSION_CONFIG;
@@ -92,10 +91,7 @@
 import androidx.camera.core.impl.CameraConfig;
 import androidx.camera.core.impl.CameraInfoInternal;
 import androidx.camera.core.impl.CameraInternal;
-import androidx.camera.core.impl.CaptureBundle;
 import androidx.camera.core.impl.CaptureConfig;
-import androidx.camera.core.impl.CaptureProcessor;
-import androidx.camera.core.impl.CaptureStage;
 import androidx.camera.core.impl.Config;
 import androidx.camera.core.impl.ConfigProvider;
 import androidx.camera.core.impl.DeferrableSurface;
@@ -117,7 +113,6 @@
 import androidx.camera.core.impl.utils.futures.Futures;
 import androidx.camera.core.internal.IoConfig;
 import androidx.camera.core.internal.TargetConfig;
-import androidx.camera.core.internal.YuvToJpegProcessor;
 import androidx.camera.core.internal.compat.quirk.SoftwareJpegEncodingPreferredQuirk;
 import androidx.camera.core.internal.compat.workaround.ExifRotationAvailability;
 import androidx.camera.core.internal.utils.ImageUtil;
@@ -136,6 +131,7 @@
 import java.nio.ByteBuffer;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Deque;
 import java.util.List;
@@ -143,12 +139,8 @@
 import java.util.UUID;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
 import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
 /**
@@ -318,9 +310,6 @@
     ////////////////////////////////////////////////////////////////////////////////////////////
     // [UseCase attached constant] - Is only valid when the UseCase is attached to a camera.
     ////////////////////////////////////////////////////////////////////////////////////////////
-
-    private ExecutorService mExecutor;
-
     private CaptureConfig mCaptureConfig;
 
     /**
@@ -339,11 +328,6 @@
     @SuppressWarnings("WeakerAccess")
     SafeCloseImageReaderProxy mImageReader;
 
-    @SuppressWarnings("WeakerAccess")
-    ProcessingImageReader mProcessingImageReader;
-
-    private ListenableFuture<Void> mImageReaderCloseFuture = Futures.immediateFuture(null);
-
     /** Callback used to match the {@link ImageProxy} with the {@link ImageInfo}. */
     private CameraCaptureCallback mMetadataMatchingCaptureCallback;
 
@@ -391,7 +375,6 @@
             return createPipelineWithNode(cameraId, config, resolution);
         }
         SessionConfig.Builder sessionConfigBuilder = SessionConfig.Builder.createFrom(config);
-        YuvToJpegProcessor softwareJpegProcessor = null;
 
         if (Build.VERSION.SDK_INT >= 23 && getCaptureMode() == CAPTURE_MODE_ZERO_SHUTTER_LAG) {
             getCameraControl().addZslConfig(sessionConfigBuilder);
@@ -419,32 +402,6 @@
                 throw new IllegalArgumentException("Unsupported image format:" + getImageFormat());
             }
             mImageReader = new SafeCloseImageReaderProxy(imageReader);
-        } else if (mUseSoftwareJpeg) {
-            CaptureProcessor captureProcessor;
-            int inputFormat = getImageFormat();
-            // API check to satisfy linter
-            if (Build.VERSION.SDK_INT >= 26) {
-                Logger.i(TAG, "Using software JPEG encoder.");
-                captureProcessor = softwareJpegProcessor =
-                        new YuvToJpegProcessor(getJpegQualityInternal(), MAX_IMAGES);
-            } else {
-                // Note: This should never be hit due to SDK_INT check before setting
-                // useSoftwareJpeg.
-                throw new IllegalStateException("Software JPEG only supported on API 26+");
-            }
-
-            // TODO: To allow user to use an Executor for the image processing.
-            mProcessingImageReader = new ProcessingImageReader.Builder(
-                    resolution.getWidth(),
-                    resolution.getHeight(),
-                    inputFormat,
-                    MAX_IMAGES,
-                    CaptureBundles.singleDefaultCaptureBundle(),
-                    captureProcessor
-            ).setPostProcessExecutor(mExecutor).setOutputFormat(ImageFormat.JPEG).build();
-
-            mMetadataMatchingCaptureCallback = mProcessingImageReader.getCameraCaptureCallback();
-            mImageReader = new SafeCloseImageReaderProxy(mProcessingImageReader);
         } else {
             MetadataImageReader metadataImageReader = new MetadataImageReader(resolution.getWidth(),
                     resolution.getHeight(), getImageFormat(), MAX_IMAGES);
@@ -457,27 +414,8 @@
                     new CancellationException("Request is canceled."));
         }
 
-        final YuvToJpegProcessor finalSoftwareJpegProcessor = softwareJpegProcessor;
-
         mImageCaptureRequestProcessor = new ImageCaptureRequestProcessor(MAX_IMAGES,
-                this::takePictureInternal, finalSoftwareJpegProcessor == null ? null :
-                (ImageCaptureRequestProcessor.RequestProcessCallback) imageCaptureRequest -> {
-                    //noinspection ConstantConditions
-                    if (Build.VERSION.SDK_INT >= 26) {
-                        // Updates output JPEG compression quality of YuvToJpegProcessor
-                        // according to current request. This was determined by whether the
-                        // final output image needs to be cropped (uncompress and recompress)
-                        // again when the capture request was created.
-                        finalSoftwareJpegProcessor.setJpegQuality(
-                                imageCaptureRequest.mJpegQuality);
-
-                        // Updates output rotation degrees value to the YuvToJpegProcessor so
-                        // that it can write the correct value to the ExifData in the output
-                        // JPEG image file.
-                        finalSoftwareJpegProcessor.setRotationDegrees(
-                                imageCaptureRequest.mRotationDegrees);
-                    }
-                });
+                this::takePictureInternal);
 
         // By default close images that come from the listener.
         mImageReader.setOnImageAvailableListener(mClosingListener,
@@ -494,9 +432,6 @@
                 /* get the surface image format using getImageFormat */
                 getImageFormat());
 
-        mImageReaderCloseFuture =
-                mProcessingImageReader != null ? mProcessingImageReader.getCloseFuture()
-                        : Futures.immediateFuture(null);
         mDeferrableSurface.getTerminationFuture().addListener(mImageReader::safeClose,
                 CameraXExecutors.mainThreadExecutor());
 
@@ -559,8 +494,6 @@
         DeferrableSurface deferrableSurface = mDeferrableSurface;
         mDeferrableSurface = null;
         mImageReader = null;
-        mProcessingImageReader = null;
-        mImageReaderCloseFuture = Futures.immediateFuture(null);
 
         if (deferrableSurface != null) {
             deferrableSurface.close();
@@ -611,9 +544,8 @@
     @Override
     protected UseCaseConfig<?> onMergeConfig(@NonNull CameraInfoInternal cameraInfo,
             @NonNull UseCaseConfig.Builder<?, ?, ?> builder) {
-        if (cameraInfo.getCameraQuirks().contains(
-                SoftwareJpegEncodingPreferredQuirk.class)) {
-            // Request software JPEG encoder if quirk exists on this device and the software JPEG
+        if (cameraInfo.getCameraQuirks().contains(SoftwareJpegEncodingPreferredQuirk.class)) {
+            // Request software JPEG encoder if quirk exists on this device, and the software JPEG
             // option has not already been explicitly set.
             if (Boolean.FALSE.equals(builder.getMutableConfig().retrieveOption(
                     OPTION_USE_SOFTWARE_JPEG_ENCODER, true))) {
@@ -625,7 +557,7 @@
             }
         }
 
-        // If software JPEG is requested, disable if it can't be supported on current API level.
+        // If software JPEG is requested, disable if it is incompatible.
         boolean useSoftwareJpeg = enforceSoftwareJpegConstraints(builder.getMutableConfig());
 
         // Update the input format base on the other options set (mainly whether processing
@@ -1293,11 +1225,10 @@
                                     completer.setException(throwable);
                                 }
                             },
-                            mExecutor);
+                            CameraXExecutors.mainThreadExecutor());
 
                     completer.addCancellationListener(() -> future.cancel(true),
                             CameraXExecutors.directExecutor());
-
                     return "takePictureInternal";
                 });
     }
@@ -1328,24 +1259,13 @@
 
         @GuardedBy("mLock")
         private final ImageCaptor mImageCaptor;
-
         private final int mMaxImages;
-
-        @Nullable
-        private final RequestProcessCallback mRequestProcessCallback;
-
         @SuppressWarnings("WeakerAccess") /* synthetic accessor */
         final Object mLock = new Object();
 
         ImageCaptureRequestProcessor(int maxImages, @NonNull ImageCaptor imageCaptor) {
-            this(maxImages, imageCaptor, null);
-        }
-
-        ImageCaptureRequestProcessor(int maxImages, @NonNull ImageCaptor imageCaptor,
-                @Nullable RequestProcessCallback requestProcessCallback) {
             mMaxImages = maxImages;
             mImageCaptor = imageCaptor;
-            mRequestProcessCallback = requestProcessCallback;
         }
 
         /**
@@ -1448,9 +1368,6 @@
                 }
 
                 mCurrentRequest = imageCaptureRequest;
-                if (mRequestProcessCallback != null) {
-                    mRequestProcessCallback.onPreProcessRequest(mCurrentRequest);
-                }
                 mCurrentRequestFuture = mImageCaptor.capture(imageCaptureRequest);
                 Futures.addCallback(mCurrentRequestFuture, new FutureCallback<ImageProxy>() {
                     @Override
@@ -1539,17 +1456,16 @@
      *
      * @return {@code true} if software JPEG will be used after applying constraints.
      */
-    static boolean enforceSoftwareJpegConstraints(@NonNull MutableConfig mutableConfig) {
+    boolean enforceSoftwareJpegConstraints(@NonNull MutableConfig mutableConfig) {
         // Software encoder currently only supports API 26+.
         if (Boolean.TRUE.equals(
                 mutableConfig.retrieveOption(OPTION_USE_SOFTWARE_JPEG_ENCODER, false))) {
             boolean supported = true;
-            if (Build.VERSION.SDK_INT < 26) {
-                Logger.w(TAG, "Software JPEG only supported on API 26+, but current API level is "
-                        + Build.VERSION.SDK_INT);
+            if (isSessionProcessorEnabledInCurrentCamera()) {
+                // SessionProcessor requires JPEG input format so it is incompatible with SW Jpeg.
+                Logger.w(TAG, "Software JPEG cannot be used with Extensions.");
                 supported = false;
             }
-
             Integer bufferFormat = mutableConfig.retrieveOption(OPTION_BUFFER_FORMAT, null);
             if (bufferFormat != null && bufferFormat != ImageFormat.JPEG) {
                 Logger.w(TAG, "Software JPEG cannot be used with non-JPEG output buffer format.");
@@ -1574,20 +1490,9 @@
     @RestrictTo(Scope.LIBRARY_GROUP)
     @Override
     public void onDetached() {
-        ListenableFuture<Void> imageReaderCloseFuture = mImageReaderCloseFuture;
-
         abortImageCaptureRequests();
         clearPipeline();
         mUseSoftwareJpeg = false;
-
-        // Shutdowns the executor after mImageReader is closed. This can avoid
-        // RejectedExecutionException if a ProcessingImageReader is used to processing the
-        // captured images.
-        ExecutorService executorService = mExecutor;
-        if (executorService != null) {
-            imageReaderCloseFuture.addListener(executorService::shutdown,
-                    CameraXExecutors.directExecutor());
-        }
     }
 
     /**
@@ -1609,21 +1514,6 @@
 
         CameraInternal camera = getCamera();
         checkNotNull(camera, "Attached camera cannot be null");
-
-        mExecutor =
-                Executors.newFixedThreadPool(
-                        1,
-                        new ThreadFactory() {
-                            private final AtomicInteger mId = new AtomicInteger(0);
-
-                            @Override
-                            public Thread newThread(@NonNull Runnable r) {
-                                return new Thread(
-                                        r,
-                                        CameraXThreads.TAG + "image_capture_"
-                                                + mId.getAndIncrement());
-                            }
-                        });
     }
 
     /**
@@ -1658,80 +1548,33 @@
     ListenableFuture<Void> issueTakePicture(@NonNull ImageCaptureRequest imageCaptureRequest) {
         Logger.d(TAG, "issueTakePicture");
 
-        final List<CaptureConfig> captureConfigs = new ArrayList<>();
-        String tagBundleKey = null;
+        final CaptureConfig.Builder builder = new CaptureConfig.Builder();
+        builder.setTemplateType(mCaptureConfig.getTemplateType());
 
-        CaptureBundle captureBundle;
-        if (mProcessingImageReader != null) {
-            // If the Processor is provided, check if we have valid CaptureBundle and update
-            // ProcessingImageReader before actually issuing a take picture request.
-            captureBundle = CaptureBundles.singleDefaultCaptureBundle();
-            mProcessingImageReader.setCaptureBundle(captureBundle);
-            mProcessingImageReader.setOnProcessingErrorCallback(
-                    CameraXExecutors.directExecutor(),
-                    (message, cause) -> {
-                        Logger.e(TAG, "Processing image failed! " + message);
-                        imageCaptureRequest.notifyCallbackError(ERROR_CAPTURE_FAILED, message,
-                                cause);
-                    });
-            tagBundleKey = mProcessingImageReader.getTagBundleKey();
-        } else {
-            captureBundle = CaptureBundles.singleDefaultCaptureBundle();
-            if (captureBundle == null) {
-                return Futures.immediateFailedFuture(new IllegalArgumentException(
-                        "ImageCapture cannot set empty CaptureBundle."));
-            }
+        // Add the default implementation options of ImageCapture
+        builder.addImplementationOptions(mCaptureConfig.getImplementationOptions());
+        builder.addAllCameraCaptureCallbacks(
+                mSessionConfigBuilder.getSingleCameraCaptureCallbacks());
 
-            List<CaptureStage> captureStages = captureBundle.getCaptureStages();
-            if (captureStages == null) {
-                return Futures.immediateFailedFuture(new IllegalArgumentException(
-                        "ImageCapture has CaptureBundle with null capture stages"));
-            }
+        builder.addSurface(mDeferrableSurface);
 
-            if (captureStages.size() > 1) {
-                return Futures.immediateFailedFuture(new IllegalArgumentException(
-                        "ImageCapture have no CaptureProcess set with CaptureBundle size > 1."));
+        // Only sets the JPEG rotation and quality capture request options when capturing
+        // images in JPEG format. Some devices do not handle these CaptureRequest key values
+        // when capturing a non-JPEG image. Setting these capture requests and checking the
+        // returned capture results for specific purpose might cause problems. See b/204375890.
+        if (getImageFormat() == ImageFormat.JPEG) {
+            // Add the dynamic implementation options of ImageCapture
+            if (EXIF_ROTATION_AVAILABILITY.isRotationOptionSupported()) {
+                builder.addImplementationOption(CaptureConfig.OPTION_ROTATION,
+                        imageCaptureRequest.mRotationDegrees);
             }
+            builder.addImplementationOption(CaptureConfig.OPTION_JPEG_QUALITY,
+                    imageCaptureRequest.mJpegQuality);
         }
 
-        for (final CaptureStage captureStage : captureBundle.getCaptureStages()) {
-            final CaptureConfig.Builder builder = new CaptureConfig.Builder();
-            builder.setTemplateType(mCaptureConfig.getTemplateType());
+        builder.addCameraCaptureCallback(mMetadataMatchingCaptureCallback);
 
-            // Add the default implementation options of ImageCapture
-            builder.addImplementationOptions(mCaptureConfig.getImplementationOptions());
-            builder.addAllCameraCaptureCallbacks(
-                    mSessionConfigBuilder.getSingleCameraCaptureCallbacks());
-
-            builder.addSurface(mDeferrableSurface);
-
-            // Only sets the JPEG rotation and quality capture request options when capturing
-            // images in JPEG format. Some devices do not handle these CaptureRequest key values
-            // when capturing a non-JPEG image. Setting these capture requests and checking the
-            // returned capture results for specific purpose might cause problems. See b/204375890.
-            if (getImageFormat() == ImageFormat.JPEG) {
-                // Add the dynamic implementation options of ImageCapture
-                if (EXIF_ROTATION_AVAILABILITY.isRotationOptionSupported()) {
-                    builder.addImplementationOption(CaptureConfig.OPTION_ROTATION,
-                            imageCaptureRequest.mRotationDegrees);
-                }
-                builder.addImplementationOption(CaptureConfig.OPTION_JPEG_QUALITY,
-                        imageCaptureRequest.mJpegQuality);
-            }
-
-            // Add the implementation options required by the CaptureStage
-            builder.addImplementationOptions(
-                    captureStage.getCaptureConfig().getImplementationOptions());
-
-            // Use CaptureBundle object as the key for TagBundle
-            if (tagBundleKey != null) {
-                builder.addTag(tagBundleKey, captureStage.getId());
-            }
-            builder.addCameraCaptureCallback(mMetadataMatchingCaptureCallback);
-            captureConfigs.add(builder.build());
-        }
-
-        return submitStillCaptureRequest(captureConfigs);
+        return submitStillCaptureRequest(Arrays.asList(builder.build()));
     }
 
     /**
@@ -1790,33 +1633,17 @@
             return false;
         }
         if (isSessionProcessorEnabledInCurrentCamera()) {
-            // Use old pipeline for advanced Extensions.
+            // Use old pipeline when extension is enabled.
             return false;
         }
-        if (getCaptureStageSize(config) > 1) {
-            // Use old pipeline for multiple stages capture.
-            return false;
-        }
-        if (requireNonNull(config.retrieveOption(OPTION_INPUT_FORMAT, ImageFormat.JPEG))
-                != ImageFormat.JPEG) {
+
+        if (config.getBufferFormat(ImageFormat.JPEG) != ImageFormat.JPEG) {
             // Use old pipeline for non-JPEG output format.
             return false;
         }
         return mUseProcessingPipeline;
     }
 
-    private int getCaptureStageSize(@NonNull ImageCaptureConfig config) {
-        CaptureBundle captureBundle = config.getCaptureBundle(null);
-        if (captureBundle == null) {
-            return 1;
-        }
-        List<CaptureStage> captureStages = captureBundle.getCaptureStages();
-        if (captureStages == null) {
-            return 1;
-        }
-        return captureStages.size();
-    }
-
     /**
      * Creates the pipeline for both capture request configuration and image post-processing.
      *
@@ -2770,20 +2597,6 @@
         }
 
         /**
-         * Sets the {@link CaptureBundle}.
-         *
-         * @param captureBundle The requested capture bundle for extension.
-         * @return The current Builder.
-         * @hide
-         */
-        @RestrictTo(Scope.LIBRARY_GROUP)
-        @NonNull
-        public Builder setCaptureBundle(@NonNull CaptureBundle captureBundle) {
-            getMutableConfig().insertOption(OPTION_CAPTURE_BUNDLE, captureBundle);
-            return this;
-        }
-
-        /**
          * Sets the {@link ImageFormat} of the {@link ImageProxy} returned by the
          * {@link ImageCapture.OnImageCapturedCallback}.
          *
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
index 36096c8..8f0865500 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
@@ -219,7 +219,7 @@
         //  CaptureProcessor. e.g. only update the output Surface (between Processor/App), and
         //  still use the same input Surface (between Camera/Processor). It's just simpler for now.
         final SurfaceRequest surfaceRequest = new SurfaceRequest(resolution, getCamera(),
-                /* isRGBA8888Required */ false, this::notifyReset);
+                this::notifyReset);
         mCurrentSurfaceRequest = surfaceRequest;
 
         if (mSurfaceProvider != null) {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ProcessingImageReader.java b/camera/camera-core/src/main/java/androidx/camera/core/ProcessingImageReader.java
deleted file mode 100644
index 97fb3ec..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/ProcessingImageReader.java
+++ /dev/null
@@ -1,598 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core;
-
-import android.graphics.ImageFormat;
-import android.media.ImageReader;
-import android.util.Size;
-import android.view.Surface;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.camera.core.impl.CameraCaptureCallback;
-import androidx.camera.core.impl.CaptureBundle;
-import androidx.camera.core.impl.CaptureProcessor;
-import androidx.camera.core.impl.CaptureStage;
-import androidx.camera.core.impl.ImageReaderProxy;
-import androidx.camera.core.impl.utils.executor.CameraXExecutors;
-import androidx.camera.core.impl.utils.futures.FutureCallback;
-import androidx.camera.core.impl.utils.futures.Futures;
-import androidx.concurrent.futures.CallbackToFutureAdapter;
-import androidx.core.util.Preconditions;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-
-/**
- * An {@link ImageReaderProxy} which takes one or more {@link android.media.Image}, processes it,
- * then output the final result {@link ImageProxy} to
- * {@link ImageReaderProxy.OnImageAvailableListener}.
- *
- * <p>ProcessingImageReader takes {@link CaptureBundle} as the expected set of
- * {@link CaptureStage}. Once all the ImageProxy from the captures are ready. It invokes
- * the {@link CaptureProcessor} set, then returns a single output ImageProxy to
- * OnImageAvailableListener.
- */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-class ProcessingImageReader implements ImageReaderProxy {
-    private static final String TAG = "ProcessingImageReader";
-
-    // Exif metadata are restricted in size to 64 kB in JPEG images because according to
-    // the specification this information must be contained within a single JPEG APP1
-    // segment. (See: https://en.wikipedia.org/wiki/Exif)
-    private static final int EXIF_MAX_SIZE_BYTES = 64000;
-
-    final Object mLock = new Object();
-
-    // Callback when Image is ready from InputImageReader.
-    private ImageReaderProxy.OnImageAvailableListener mTransformedListener =
-            new ImageReaderProxy.OnImageAvailableListener() {
-                @Override
-                public void onImageAvailable(@NonNull ImageReaderProxy reader) {
-                    imageIncoming(reader);
-                }
-            };
-
-    // Callback when Image is ready from OutputImageReader.
-    private ImageReaderProxy.OnImageAvailableListener mImageProcessedListener =
-            new ImageReaderProxy.OnImageAvailableListener() {
-                @Override
-                public void onImageAvailable(@NonNull ImageReaderProxy reader) {
-                    // Callback the output OnImageAvailableListener.
-                    ImageReaderProxy.OnImageAvailableListener listener;
-                    Executor executor;
-                    synchronized (mLock) {
-                        listener = mListener;
-                        executor = mExecutor;
-
-                        // Resets SettableImageProxyBundle after the processor finishes processing.
-                        mSettableImageProxyBundle.reset();
-                        setupSettableImageProxyBundleCallbacks();
-                    }
-                    if (listener != null) {
-                        if (executor != null) {
-                            executor.execute(
-                                    () -> listener.onImageAvailable(ProcessingImageReader.this));
-                        } else {
-                            listener.onImageAvailable(ProcessingImageReader.this);
-                        }
-                    }
-                }
-            };
-
-    // Callback when all the ImageProxies in SettableImageProxyBundle are ready.
-    private FutureCallback<List<ImageProxy>> mCaptureStageReadyCallback =
-            new FutureCallback<List<ImageProxy>>() {
-                @Override
-                public void onSuccess(@Nullable List<ImageProxy> imageProxyList) {
-                    SettableImageProxyBundle settableImageProxyBundle;
-                    OnProcessingErrorCallback errorCallback;
-                    Executor errorCallbackExecutor;
-                    synchronized (mLock) {
-                        if (mClosed) {
-                            return;
-                        }
-                        mProcessing = true;
-                        settableImageProxyBundle = mSettableImageProxyBundle;
-                        errorCallback = mOnProcessingErrorCallback;
-                        errorCallbackExecutor = mErrorCallbackExecutor;
-                    }
-                    try {
-                        mCaptureProcessor.process(settableImageProxyBundle);
-                    } catch (Exception e) {
-                        synchronized (mLock) {
-                            // Resets mSettableImageProxyBundle to close the held images.
-                            mSettableImageProxyBundle.reset();
-
-                            if (errorCallback != null && errorCallbackExecutor != null) {
-                                errorCallbackExecutor.execute(
-                                        () -> errorCallback.notifyProcessingError(
-                                                e.getMessage(), e.getCause()));
-                            }
-                        }
-                    }
-
-                    synchronized (mLock) {
-                        mProcessing = false;
-                    }
-
-                    closeAndCompleteFutureIfNecessary();
-                }
-
-                @Override
-                public void onFailure(@NonNull Throwable throwable) {
-
-                }
-            };
-
-    @GuardedBy("mLock")
-    boolean mClosed = false;
-
-    @GuardedBy("mLock")
-    boolean mProcessing = false;
-
-    @GuardedBy("mLock")
-    final ImageReaderProxy mInputImageReader;
-
-    @GuardedBy("mLock")
-    final ImageReaderProxy mOutputImageReader;
-
-    @GuardedBy("mLock")
-    @Nullable
-    ImageReaderProxy.OnImageAvailableListener mListener;
-
-    @GuardedBy("mLock")
-    @Nullable
-    Executor mExecutor;
-
-    @GuardedBy("mLock")
-    CallbackToFutureAdapter.Completer<Void> mCloseCompleter;
-    @GuardedBy("mLock")
-    private ListenableFuture<Void> mCloseFuture;
-
-    /** The Executor to execute the image post processing task. */
-    @NonNull
-    final Executor mPostProcessExecutor;
-
-    @NonNull
-    final CaptureProcessor mCaptureProcessor;
-
-    @NonNull
-    private final ListenableFuture<Void> mUnderlyingCaptureProcessorCloseFuture;
-
-    private String mTagBundleKey = new String();
-
-    @GuardedBy("mLock")
-    @NonNull
-    SettableImageProxyBundle mSettableImageProxyBundle =
-            new SettableImageProxyBundle(Collections.emptyList(), mTagBundleKey);
-
-    private final List<Integer> mCaptureIdList = new ArrayList<>();
-
-    private ListenableFuture<List<ImageProxy>> mSettableImageProxyFutureList =
-            Futures.immediateFuture(new ArrayList<>());
-
-    @GuardedBy("mLock")
-    OnProcessingErrorCallback mOnProcessingErrorCallback;
-
-    @GuardedBy("mLock")
-    Executor mErrorCallbackExecutor;
-
-    ProcessingImageReader(@NonNull Builder builder) {
-        if (builder.mInputImageReader.getMaxImages()
-                < builder.mCaptureBundle.getCaptureStages().size()) {
-            throw new IllegalArgumentException(
-                    "MetadataImageReader is smaller than CaptureBundle.");
-        }
-
-        mInputImageReader = builder.mInputImageReader;
-
-        // For JPEG ImageReaders, the Surface that is created will have format BLOB which can
-        // only be allocated with a height of 1. The output Image from the image reader will read
-        // its dimensions from the JPEG data's EXIF in order to set the final dimensions.
-        int outputWidth = mInputImageReader.getWidth();
-        int outputHeight = mInputImageReader.getHeight();
-
-        if (builder.mOutputFormat == ImageFormat.JPEG) {
-            // The output JPEG compression quality is 100 when taking a picture in MAX_QUALITY
-            // mode. It might cause the compressed data size exceeds image's width * height.
-            // YUV_420_888 should be 1.5 times of image's width * height. The compressed data
-            // size shouldn't exceed it. Therefore, scales the output image reader byte buffer to
-            // 1.5 times when the JPEG compression quality setting is 100.
-            outputWidth = (int) (outputWidth * outputHeight * 1.5f) + EXIF_MAX_SIZE_BYTES;
-            outputHeight = 1;
-        }
-        mOutputImageReader = new AndroidImageReaderProxy(
-                ImageReader.newInstance(outputWidth, outputHeight, builder.mOutputFormat,
-                        mInputImageReader.getMaxImages()));
-
-        mPostProcessExecutor = builder.mPostProcessExecutor;
-        mCaptureProcessor = builder.mCaptureProcessor;
-        mCaptureProcessor.onOutputSurface(mOutputImageReader.getSurface(), builder.mOutputFormat);
-        mCaptureProcessor.onResolutionUpdate(
-                new Size(mInputImageReader.getWidth(), mInputImageReader.getHeight()));
-
-        mUnderlyingCaptureProcessorCloseFuture = mCaptureProcessor.getCloseFuture();
-
-        setCaptureBundle(builder.mCaptureBundle);
-    }
-
-    @Override
-    @Nullable
-    public ImageProxy acquireLatestImage() {
-        synchronized (mLock) {
-            return mOutputImageReader.acquireLatestImage();
-        }
-    }
-
-    @Override
-    @Nullable
-    public ImageProxy acquireNextImage() {
-        synchronized (mLock) {
-            return mOutputImageReader.acquireNextImage();
-        }
-    }
-
-    @Override
-    public void close() {
-        synchronized (mLock) {
-            if (mClosed) {
-                return;
-            }
-
-            // Prevent the ImageAvailableListener from being triggered after the close function
-            // is called.
-            mInputImageReader.clearOnImageAvailableListener();
-            mOutputImageReader.clearOnImageAvailableListener();
-
-            mClosed = true;
-        }
-
-        mCaptureProcessor.close();
-        closeAndCompleteFutureIfNecessary();
-    }
-
-    void closeAndCompleteFutureIfNecessary() {
-        boolean closed;
-        boolean processing;
-        CallbackToFutureAdapter.Completer<Void> closeCompleter;
-
-        synchronized (mLock) {
-            closed = mClosed;
-            processing = mProcessing;
-            closeCompleter = mCloseCompleter;
-
-            // If the CaptureProcessor is in the middle of processing then don't close the
-            // ImageReaderProxys and associated ImageProxy. Let the processing complete before
-            // closing them.
-            if (closed && !processing) {
-                mInputImageReader.close();
-                mSettableImageProxyBundle.close();
-                mOutputImageReader.close();
-            }
-        }
-
-        if (closed && !processing) {
-            // Complete the capture process pipeline's close future after the underlying capture
-            // processor is closed.
-            mUnderlyingCaptureProcessorCloseFuture.addListener(() -> {
-                cancelSettableImageProxyBundleFutureList();
-                if (closeCompleter != null) {
-                    closeCompleter.set(null);
-                }
-            }, CameraXExecutors.directExecutor());
-        }
-    }
-
-    /**
-     * Returns a future that will complete when the ProcessingImageReader is actually closed.
-     *
-     * @return A future that signals when the ProcessingImageReader is actually closed
-     * (after all processing). Cancelling this future has no effect.
-     */
-    @NonNull
-    ListenableFuture<Void> getCloseFuture() {
-        ListenableFuture<Void> closeFuture;
-        synchronized (mLock) {
-            if (mClosed && !mProcessing) {
-                // Everything should be closed but still need to wait for underlying capture
-                // processors being closed.
-                closeFuture = Futures.transform(mUnderlyingCaptureProcessorCloseFuture,
-                        nullVoid -> null, CameraXExecutors.directExecutor());
-            } else {
-                if (mCloseFuture == null) {
-                    mCloseFuture = CallbackToFutureAdapter.getFuture(completer -> {
-                        // Should already be locked, but lock again to satisfy linter.
-                        synchronized (mLock) {
-                            mCloseCompleter = completer;
-                        }
-                        return "ProcessingImageReader-close";
-                    });
-                }
-                closeFuture = Futures.nonCancellationPropagating(mCloseFuture);
-            }
-        }
-        return closeFuture;
-    }
-
-    @Override
-    public int getHeight() {
-        synchronized (mLock) {
-            return mInputImageReader.getHeight();
-        }
-    }
-
-    @Override
-    public int getWidth() {
-        synchronized (mLock) {
-            return mInputImageReader.getWidth();
-        }
-    }
-
-    @Override
-    public int getImageFormat() {
-        synchronized (mLock) {
-            return mOutputImageReader.getImageFormat();
-        }
-    }
-
-    @Override
-    public int getMaxImages() {
-        synchronized (mLock) {
-            return mInputImageReader.getMaxImages();
-        }
-    }
-
-    @Nullable
-    @Override
-    public Surface getSurface() {
-        synchronized (mLock) {
-            return mInputImageReader.getSurface();
-        }
-    }
-
-    @Override
-    public void setOnImageAvailableListener(@NonNull OnImageAvailableListener listener,
-            @NonNull Executor executor) {
-        synchronized (mLock) {
-            mListener = Preconditions.checkNotNull(listener);
-            mExecutor = Preconditions.checkNotNull(executor);
-            mInputImageReader.setOnImageAvailableListener(mTransformedListener, executor);
-            mOutputImageReader.setOnImageAvailableListener(mImageProcessedListener, executor);
-        }
-    }
-
-    @Override
-    public void clearOnImageAvailableListener() {
-        synchronized (mLock) {
-            mListener = null;
-            mExecutor = null;
-            mInputImageReader.clearOnImageAvailableListener();
-            mOutputImageReader.clearOnImageAvailableListener();
-
-            if (!mProcessing) {
-                mSettableImageProxyBundle.close();
-            }
-        }
-    }
-
-    /** Sets a CaptureBundle */
-    public void setCaptureBundle(@NonNull CaptureBundle captureBundle) {
-        synchronized (mLock) {
-            if (mClosed) {
-                return;
-            }
-
-            cancelSettableImageProxyBundleFutureList();
-
-            if (captureBundle.getCaptureStages() != null) {
-                if (mInputImageReader.getMaxImages() < captureBundle.getCaptureStages().size()) {
-                    throw new IllegalArgumentException(
-                            "CaptureBundle is larger than InputImageReader.");
-                }
-
-                mCaptureIdList.clear();
-
-                for (CaptureStage captureStage : captureBundle.getCaptureStages()) {
-                    if (captureStage != null) {
-                        mCaptureIdList.add(captureStage.getId());
-                    }
-                }
-            }
-
-            // Use the mCaptureBundle as the key for TagBundle
-            mTagBundleKey = Integer.toString(captureBundle.hashCode());
-            mSettableImageProxyBundle = new SettableImageProxyBundle(mCaptureIdList, mTagBundleKey);
-            setupSettableImageProxyBundleCallbacks();
-        }
-    }
-
-    private void cancelSettableImageProxyBundleFutureList() {
-        synchronized (mLock) {
-            if (!mSettableImageProxyFutureList.isDone()) {
-                mSettableImageProxyFutureList.cancel(true);
-            }
-
-            mSettableImageProxyBundle.reset();
-        }
-    }
-
-    /** Returns a TagBundleKey which is used in this processing image reader.*/
-    @NonNull
-    public String getTagBundleKey() {
-        return mTagBundleKey;
-    }
-
-    /** Returns necessary camera callbacks to retrieve metadata from camera result. */
-    @Nullable
-    CameraCaptureCallback getCameraCaptureCallback() {
-        synchronized (mLock) {
-            if (mInputImageReader instanceof MetadataImageReader) {
-                return ((MetadataImageReader) mInputImageReader).getCameraCaptureCallback();
-            } else {
-                return new CameraCaptureCallback() {};
-            }
-        }
-    }
-
-    /**
-     * Sets {@link OnProcessingErrorCallback} to receive error notifications.
-     *
-     * @param executor The executor in which the callback methods will be run.
-     * @param callback Callback to be invoked if an error occurs when processing the images.
-     */
-    public void setOnProcessingErrorCallback(@NonNull Executor executor,
-            @NonNull OnProcessingErrorCallback callback) {
-        synchronized (mLock) {
-            mErrorCallbackExecutor = executor;
-            mOnProcessingErrorCallback = callback;
-        }
-    }
-
-    @GuardedBy("mLock")
-    void setupSettableImageProxyBundleCallbacks() {
-        List<ListenableFuture<ImageProxy>> futureList = new ArrayList<>();
-        for (Integer id : mCaptureIdList) {
-            futureList.add(mSettableImageProxyBundle.getImageProxy(id));
-        }
-
-        mSettableImageProxyFutureList = Futures.allAsList(futureList);
-
-        Futures.addCallback(Futures.allAsList(futureList), mCaptureStageReadyCallback,
-                mPostProcessExecutor);
-    }
-
-    // Incoming Image from InputImageReader. Acquires it and add to SettableImageProxyBundle.
-    void imageIncoming(ImageReaderProxy imageReader) {
-        synchronized (mLock) {
-            if (mClosed) {
-                return;
-            }
-
-            ImageProxy image = null;
-            try {
-                image = imageReader.acquireNextImage();
-            } catch (IllegalStateException e) {
-                Logger.e(TAG, "Failed to acquire latest image.", e);
-            } finally {
-                if (image != null) {
-                    // Currently use the same key which intends to get a captureStage id value.
-                    Integer tagValue =
-                            (Integer) image.getImageInfo().getTagBundle().getTag(mTagBundleKey);
-
-                    if (!mCaptureIdList.contains(tagValue)) {
-                        Logger.w(TAG, "ImageProxyBundle does not contain this id: " + tagValue);
-                        image.close();
-                    } else {
-                        mSettableImageProxyBundle.addImageProxy(image);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * The builder to create a {@link ProcessingImageReader} object.
-     */
-    static final class Builder {
-        @NonNull
-        protected final ImageReaderProxy mInputImageReader;
-        @NonNull
-        protected final CaptureBundle mCaptureBundle;
-        @NonNull
-        protected final CaptureProcessor mCaptureProcessor;
-
-        protected int mOutputFormat;
-
-        @NonNull
-        protected Executor mPostProcessExecutor = Executors.newSingleThreadExecutor();
-
-        /**
-         * Create a {@link Builder} with specific configurations.
-         *
-         * @param imageReader      The input image reader.
-         * @param captureBundle    The {@link CaptureBundle} includes the processing information
-         * @param captureProcessor The {@link CaptureProcessor} to be invoked when the Images are
-         *                         ready
-         */
-        Builder(@NonNull ImageReaderProxy imageReader, @NonNull CaptureBundle captureBundle,
-                @NonNull CaptureProcessor captureProcessor) {
-            mInputImageReader = imageReader;
-            mCaptureBundle = captureBundle;
-            mCaptureProcessor = captureProcessor;
-            mOutputFormat = imageReader.getImageFormat();
-        }
-
-        /**
-         * Create a {@link Builder} with specific configurations.
-         *
-         * @param width            Width of the ImageReader
-         * @param height           Height of the ImageReader
-         * @param inputFormat      Input image format
-         * @param maxImages        Maximum Image number the ImageReader can hold. The capacity
-         *                         should be greater than the captureBundle size in order to hold
-         *                         all the Images needed with this processing.
-         * @param captureBundle    The {@link CaptureBundle} includes the processing information
-         * @param captureProcessor The {@link CaptureProcessor} to be invoked when the Images are
-         *                         ready
-         */
-        Builder(int width, int height, int inputFormat, int maxImages,
-                @NonNull CaptureBundle captureBundle, @NonNull CaptureProcessor captureProcessor) {
-            this(new MetadataImageReader(width, height, inputFormat, maxImages), captureBundle,
-                    captureProcessor);
-        }
-
-        /**
-         * Sets an Executor to execute the post-process of the image result.
-         */
-        @NonNull
-        Builder setPostProcessExecutor(@NonNull Executor postProcessExecutor) {
-            mPostProcessExecutor = postProcessExecutor;
-            return this;
-        }
-
-        /**
-         * Sets the output image format.
-         */
-        @NonNull
-        Builder setOutputFormat(int outputFormat) {
-            mOutputFormat = outputFormat;
-            return this;
-        }
-
-        /**
-         * Builds an {@link ProcessingImageReader} from current configurations.
-         */
-        ProcessingImageReader build() {
-            return new ProcessingImageReader(this);
-        }
-    }
-
-    /**
-     * Callback for notifying processing errors.
-     */
-    interface OnProcessingErrorCallback {
-        void notifyProcessingError(@Nullable String message, @Nullable Throwable cause);
-    }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/SettableImageProxyBundle.java b/camera/camera-core/src/main/java/androidx/camera/core/SettableImageProxyBundle.java
deleted file mode 100644
index 8bf8a73..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/SettableImageProxyBundle.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core;
-
-import android.util.SparseArray;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.camera.core.impl.ImageProxyBundle;
-import androidx.concurrent.futures.CallbackToFutureAdapter;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * A {@link ImageProxyBundle} with a predefined set of captured ids. The {@link ListenableFuture}
- * for the capture id becomes valid when the corresponding {@link ImageProxy} has been set.
- */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-final class SettableImageProxyBundle implements ImageProxyBundle {
-    @SuppressWarnings("WeakerAccess") /* synthetic accessor */
-    final Object mLock = new Object();
-    @SuppressWarnings("WeakerAccess") /* synthetic accessor */
-    @GuardedBy("mLock")
-    final SparseArray<CallbackToFutureAdapter.Completer<ImageProxy>> mCompleters =
-            new SparseArray<>();
-    /** Map of id to {@link ImageProxy} Future. */
-    @GuardedBy("mLock")
-    private final SparseArray<ListenableFuture<ImageProxy>> mFutureResults = new SparseArray<>();
-
-    @GuardedBy("mLock")
-    private final List<ImageProxy> mOwnedImageProxies = new ArrayList<>();
-
-    private final List<Integer> mCaptureIdList;
-    private String mTagBundleKey = null;
-
-    // Whether or not the bundle has been closed or not
-    @GuardedBy("mLock")
-    private boolean mClosed = false;
-
-    /**
-     * Create a {@link ImageProxyBundle} for captures with the given ids.
-     *
-     * @param captureIds    The set of captureIds contained by the ImageProxyBundle
-     * @param tagBundleKey `The key for checking desired image from TagBundle
-     */
-    SettableImageProxyBundle(List<Integer> captureIds, String tagBundleKey) {
-        mCaptureIdList = captureIds;
-        mTagBundleKey = tagBundleKey;
-        setup();
-    }
-
-    @Override
-    @NonNull
-    public ListenableFuture<ImageProxy> getImageProxy(int captureId) {
-        synchronized (mLock) {
-            if (mClosed) {
-                throw new IllegalStateException("ImageProxyBundle already closed.");
-            }
-
-            // Returns the future that has been set if it exists
-            ListenableFuture<ImageProxy> result = mFutureResults.get(captureId);
-            if (result == null) {
-                throw new IllegalArgumentException(
-                        "ImageProxyBundle does not contain this id: " + captureId);
-            }
-
-            return result;
-        }
-    }
-
-    @Override
-    @NonNull
-    public List<Integer> getCaptureIds() {
-        return Collections.unmodifiableList(mCaptureIdList);
-    }
-
-    /**
-     * Add an {@link ImageProxy} to synchronize.
-     */
-    void addImageProxy(ImageProxy imageProxy) {
-        synchronized (mLock) {
-            if (mClosed) {
-                return;
-            }
-
-            Integer captureId =
-                    (Integer) imageProxy.getImageInfo().getTagBundle().getTag(mTagBundleKey);
-            if (captureId == null) {
-                throw new IllegalArgumentException("CaptureId is null.");
-            }
-
-            // If the CaptureId is associated with this SettableImageProxyBundle, set the
-            // corresponding Future. Otherwise, throws exception.
-            CallbackToFutureAdapter.Completer<ImageProxy> completer = mCompleters.get(captureId);
-            if (completer != null) {
-                mOwnedImageProxies.add(imageProxy);
-                completer.set(imageProxy);
-            } else {
-                throw new IllegalArgumentException(
-                        "ImageProxyBundle does not contain this id: " + captureId);
-            }
-        }
-    }
-
-    /**
-     * Flush all {@link ImageProxy} that have been added.
-     */
-    void close() {
-        synchronized (mLock) {
-            if (mClosed) {
-                return;
-            }
-            for (ImageProxy imageProxy : mOwnedImageProxies) {
-                imageProxy.close();
-            }
-            mOwnedImageProxies.clear();
-            mFutureResults.clear();
-            mCompleters.clear();
-            mClosed = true;
-        }
-    }
-
-    /**
-     * Clear all {@link ImageProxy} that have been added and recreate the entries from the bundle.
-     */
-    void reset() {
-        synchronized (mLock) {
-            if (mClosed) {
-                return;
-            }
-            for (ImageProxy imageProxy : mOwnedImageProxies) {
-                imageProxy.close();
-            }
-            mOwnedImageProxies.clear();
-            mFutureResults.clear();
-            mCompleters.clear();
-            setup();
-        }
-    }
-
-    private void setup() {
-        synchronized (mLock) {
-            for (final int captureId : mCaptureIdList) {
-                ListenableFuture<ImageProxy> futureResult = CallbackToFutureAdapter.getFuture(
-                        new CallbackToFutureAdapter.Resolver<ImageProxy>() {
-                            @Override
-                            public Object attachCompleter(
-                                    @NonNull CallbackToFutureAdapter.Completer<ImageProxy>
-                                            completer) {
-                                synchronized (mLock) { // Not technically needed since
-                                    // attachCompleter is called inline, but mLock is re-entrant
-                                    // so there's no harm.
-                                    mCompleters.put(captureId, completer);
-                                }
-                                return "getImageProxy(id: " + captureId + ")";
-                            }
-                        });
-                mFutureResults.put(captureId, futureResult);
-            }
-        }
-    }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java b/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java
index 88986d5..3137f24 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/SurfaceRequest.java
@@ -71,8 +71,6 @@
 
     @Nullable
     private final Range<Integer> mExpectedFrameRate;
-    private final boolean mRGBA8888Required;
-
     private final CameraInternal mCamera;
 
     // For the camera to retrieve the surface from the user
@@ -114,9 +112,8 @@
     public SurfaceRequest(
             @NonNull Size resolution,
             @NonNull CameraInternal camera,
-            boolean isRGBA8888Required,
             @NonNull Runnable onInvalidated) {
-        this(resolution, camera, isRGBA8888Required, /*expectedFrameRate=*/null, onInvalidated);
+        this(resolution, camera, /*expectedFrameRate=*/null, onInvalidated);
     }
 
     /**
@@ -129,13 +126,11 @@
     public SurfaceRequest(
             @NonNull Size resolution,
             @NonNull CameraInternal camera,
-            boolean isRGBA8888Required,
             @Nullable Range<Integer> expectedFrameRate,
             @NonNull Runnable onInvalidated) {
         super();
         mResolution = resolution;
         mCamera = camera;
-        mRGBA8888Required = isRGBA8888Required;
         mExpectedFrameRate = expectedFrameRate;
 
         // To ensure concurrency and ordering, operations are chained. Completion can only be
@@ -324,17 +319,6 @@
     }
 
     /**
-     * Returns whether a surface of RGBA_8888 pixel format is required.
-     *
-     * @return true if a surface of RGBA_8888 pixel format is required.
-     * @hide
-     */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-    public boolean isRGBA8888Required() {
-        return mRGBA8888Required;
-    }
-
-    /**
      * Completes the request for a {@link Surface} if it has not already been
      * completed or cancelled.
      *
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CaptureProcessor.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CaptureProcessor.java
deleted file mode 100644
index 38b82cf..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CaptureProcessor.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core.impl;
-
-import android.util.Size;
-import android.view.Surface;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.camera.core.ImageCapture;
-import androidx.camera.core.ImageProxy;
-import androidx.camera.core.Preview;
-import androidx.camera.core.impl.utils.futures.Futures;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * A processing step of the image capture pipeline.
- */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-public interface CaptureProcessor {
-    /**
-     * This gets called to update where the CaptureProcessor should write the output of {@link
-     * #process(ImageProxyBundle)}.
-     *
-     * @param surface The {@link Surface} that the CaptureProcessor should write data into.
-     * @param imageFormat The format of that the surface expects.
-     */
-    void onOutputSurface(@NonNull Surface surface, int imageFormat);
-
-    /**
-     * Process a {@link ImageProxyBundle} for the set of captures that were
-     * requested.
-     *
-     * <p> A result of the processing step must be written to the {@link Surface} that was
-     * received by {@link #onOutputSurface(Surface, int)}. Otherwise, it might cause the
-     * {@link ImageCapture#takePicture} can't be complete or frame lost in {@link Preview}.
-     * @param bundle The set of images to process. The ImageProxyBundle and the {@link ImageProxy}
-     *               that are retrieved from it will become invalid after this method completes, so
-     *               no references to them should be kept.
-     */
-    void process(@NonNull ImageProxyBundle bundle);
-
-    /**
-     * This will be invoked when the input surface resolution is updated.
-     *
-     * @param size for the surface.
-     */
-    void onResolutionUpdate(@NonNull Size size);
-
-    /**
-     * Triggers to close the capture processor.
-     *
-     * <p>The capture processor might stop the in-progress task or have a flag to stop handling
-     * new tasks after this function is called. When the capture processor is closed completely,
-     * the {@link ListenableFuture} returned by {@link #getCloseFuture()} needs to be completed.
-     */
-    default void close() {
-        // No-op by default.
-    }
-
-    /**
-     * Returns the {@link ListenableFuture} which allows to know when the capture processor has
-     * been closed completely.
-     */
-    @NonNull
-    default ListenableFuture<Void> getCloseFuture() {
-        // Returns immediate future by default.
-        return Futures.immediateFuture(null);
-    }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/YuvToJpegProcessor.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/YuvToJpegProcessor.java
deleted file mode 100644
index 12c9144..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/internal/YuvToJpegProcessor.java
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright 2020 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.core.internal;
-
-import android.graphics.ImageFormat;
-import android.graphics.Rect;
-import android.graphics.YuvImage;
-import android.media.Image;
-import android.media.ImageWriter;
-import android.util.Size;
-import android.view.Surface;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.IntRange;
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.camera.core.ImageProxy;
-import androidx.camera.core.Logger;
-import androidx.camera.core.impl.CaptureProcessor;
-import androidx.camera.core.impl.ImageOutputConfig;
-import androidx.camera.core.impl.ImageProxyBundle;
-import androidx.camera.core.impl.utils.ExifData;
-import androidx.camera.core.impl.utils.ExifOutputStream;
-import androidx.camera.core.impl.utils.futures.Futures;
-import androidx.camera.core.internal.compat.ImageWriterCompat;
-import androidx.camera.core.internal.utils.ImageUtil;
-import androidx.concurrent.futures.CallbackToFutureAdapter;
-import androidx.core.util.Preconditions;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.util.List;
-
-/**
- * A CaptureProcessor which produces JPEGs from input YUV images.
- */
-@RequiresApi(26)
-public class YuvToJpegProcessor implements CaptureProcessor {
-    private static final String TAG = "YuvToJpegProcessor";
-
-    private static final Rect UNINITIALIZED_RECT = new Rect(0, 0, 0, 0);
-
-    private final int mMaxImages;
-
-    private final Object mLock = new Object();
-
-    @GuardedBy("mLock")
-    @IntRange(from = 0, to = 100)
-    private int mQuality;
-    @GuardedBy("mLock")
-    @ImageOutputConfig.RotationDegreesValue
-    private int mRotationDegrees = 0;
-
-    @GuardedBy("mLock")
-    private boolean mClosed = false;
-    @GuardedBy("mLock")
-    private int mProcessingImages = 0;
-    @GuardedBy("mLock")
-    private ImageWriter mImageWriter;
-    @GuardedBy("mLock")
-    private Rect mImageRect = UNINITIALIZED_RECT;
-
-    @GuardedBy("mLock")
-    CallbackToFutureAdapter.Completer<Void> mCloseCompleter;
-    @GuardedBy("mLock")
-    private ListenableFuture<Void> mCloseFuture;
-
-    public YuvToJpegProcessor(@IntRange(from = 0, to = 100) int quality, int maxImages) {
-        mQuality = quality;
-        mMaxImages = maxImages;
-    }
-
-    /**
-     * Sets the compression quality for the output JPEG image.
-     */
-    public void setJpegQuality(@IntRange(from = 0, to = 100) int quality) {
-        synchronized (mLock) {
-            mQuality = quality;
-        }
-    }
-
-    /**
-     * Sets the rotation degrees value of the output images.
-     *
-     * @param rotationDegrees The rotation in degrees which will be a value in {0, 90, 180, 270}.
-     */
-    public void setRotationDegrees(@ImageOutputConfig.RotationDegreesValue int rotationDegrees) {
-        synchronized (mLock) {
-            mRotationDegrees = rotationDegrees;
-        }
-    }
-
-    @Override
-    public void onOutputSurface(@NonNull Surface surface, int imageFormat) {
-        Preconditions.checkState(imageFormat == ImageFormat.JPEG, "YuvToJpegProcessor only "
-                + "supports JPEG output format.");
-        synchronized (mLock) {
-            if (!mClosed) {
-                if (mImageWriter != null) {
-                    throw new IllegalStateException("Output surface already set.");
-                }
-                mImageWriter = ImageWriterCompat.newInstance(surface, mMaxImages, imageFormat);
-            } else {
-                Logger.w(TAG, "Cannot set output surface. Processor is closed.");
-            }
-        }
-    }
-
-    @Override
-    public void process(@NonNull ImageProxyBundle bundle) {
-        List<Integer> ids = bundle.getCaptureIds();
-        Preconditions.checkArgument(ids.size() == 1,
-                "Processing image bundle have single capture id, but found " + ids.size());
-
-        ListenableFuture<ImageProxy> imageProxyListenableFuture = bundle.getImageProxy(ids.get(0));
-        Preconditions.checkArgument(imageProxyListenableFuture.isDone());
-
-        ImageWriter imageWriter;
-        Rect imageRect;
-        boolean processing;
-        int quality;
-        int rotationDegrees;
-        synchronized (mLock) {
-            imageWriter = mImageWriter;
-            processing = !mClosed;
-            imageRect = mImageRect;
-            if (processing) {
-                mProcessingImages++;
-            }
-            quality = mQuality;
-            rotationDegrees = mRotationDegrees;
-        }
-
-        ImageProxy imageProxy = null;
-        Image jpegImage = null;
-        try {
-            imageProxy = imageProxyListenableFuture.get();
-            if (!processing) {
-                Logger.w(TAG, "Image enqueued for processing on closed processor.");
-                imageProxy.close();
-                imageProxy = null;
-                return;
-            }
-
-            jpegImage = imageWriter.dequeueInputImage();
-
-            imageProxy = imageProxyListenableFuture.get();
-            Preconditions.checkState(imageProxy.getFormat() == ImageFormat.YUV_420_888,
-                    "Input image is not expected YUV_420_888 image format");
-            byte[] yuvBytes = ImageUtil.yuv_420_888toNv21(imageProxy);
-
-            YuvImage yuvImage = new YuvImage(yuvBytes, ImageFormat.NV21, imageProxy.getWidth(),
-                    imageProxy.getHeight(), null);
-
-            ByteBuffer jpegBuf = jpegImage.getPlanes()[0].getBuffer();
-            int initialPos = jpegBuf.position();
-            OutputStream os = new ExifOutputStream(new ByteBufferOutputStream(jpegBuf),
-                    ExifData.create(imageProxy, rotationDegrees));
-            yuvImage.compressToJpeg(imageRect, quality, os);
-
-            // Input can now be closed.
-            imageProxy.close();
-            imageProxy = null;
-
-            // Set limits on jpeg buffer and rewind
-            jpegBuf.limit(jpegBuf.position());
-            jpegBuf.position(initialPos);
-
-            // Enqueue the completed jpeg image
-            imageWriter.queueInputImage(jpegImage);
-            jpegImage = null;
-        } catch (Exception e) {
-            // InterruptedException, ExecutionException and EOFException might be caught here.
-            //
-            // InterruptedException should not be possible here since
-            // imageProxyListenableFuture.isDone() returned true, but we have to handle the
-            // exception case so bundle it with ExecutionException.
-            //
-            // EOFException might happen if the compressed JPEG data size exceeds the byte buffer
-            // size of the output image reader.
-            if (processing) {
-                Logger.e(TAG, "Failed to process YUV -> JPEG", e);
-                // Something went wrong attempting to retrieve ImageProxy. Enqueue an invalid buffer
-                // to make sure the downstream isn't blocked.
-                jpegImage = imageWriter.dequeueInputImage();
-                ByteBuffer jpegBuf = jpegImage.getPlanes()[0].getBuffer();
-                jpegBuf.rewind();
-                jpegBuf.limit(0);
-                imageWriter.queueInputImage(jpegImage);
-            }
-        } finally {
-            boolean shouldCloseImageWriter;
-            CallbackToFutureAdapter.Completer<Void> closeCompleter;
-
-            synchronized (mLock) {
-                // Note: order of condition is important here due to short circuit of &&
-                shouldCloseImageWriter = processing && (mProcessingImages-- == 0) && mClosed;
-                closeCompleter = mCloseCompleter;
-            }
-
-            // Fallback in case something went wrong during processing.
-            if (jpegImage != null) {
-                jpegImage.close();
-            }
-            if (imageProxy != null) {
-                imageProxy.close();
-            }
-
-            if (shouldCloseImageWriter) {
-                imageWriter.close();
-                Logger.d(TAG, "Closed after completion of last image processed.");
-
-                if (closeCompleter != null) {
-                    // Notify listeners of close
-                    closeCompleter.set(null);
-                }
-            }
-        }
-    }
-
-    /**
-     * Closes the YuvToJpegProcessor so that no more processing will occur.
-     *
-     * This should only be called once no more images will be produced for processing. Otherwise
-     * the images may not be propagated to the output surface and the pipeline could stall.
-     */
-    @Override
-    public void close() {
-        CallbackToFutureAdapter.Completer<Void> closeCompleter = null;
-
-        synchronized (mLock) {
-            if (mClosed) {
-                return;
-            }
-
-            mClosed = true;
-            // Close the ImageWriter if no images are currently processing. Otherwise the
-            // ImageWriter will be closed once the last image is closed.
-            if (mProcessingImages == 0 && mImageWriter != null) {
-                Logger.d(TAG, "No processing in progress. Closing immediately.");
-                mImageWriter.close();
-                closeCompleter = mCloseCompleter;
-            } else {
-                Logger.d(TAG, "close() called while processing. Will close after completion.");
-            }
-        }
-
-        if (closeCompleter != null) {
-            closeCompleter.set(null);
-        }
-    }
-
-    /**
-     * Returns a future that will complete when the YuvToJpegProcessor is actually closed.
-     *
-     * @return A future that signals when the YuvToJpegProcessor is actually closed
-     * (after all processing). Cancelling this future has no effect.
-     */
-    @NonNull
-    @Override
-    public ListenableFuture<Void> getCloseFuture() {
-        ListenableFuture<Void> closeFuture;
-        synchronized (mLock) {
-            if (mClosed && mProcessingImages == 0) {
-                // Everything should be closed. Return immediate future.
-                closeFuture = Futures.immediateFuture(null);
-            } else {
-                if (mCloseFuture == null) {
-                    mCloseFuture = CallbackToFutureAdapter.getFuture(completer -> {
-                        // Should already be locked, but lock again to satisfy linter.
-                        synchronized (mLock) {
-                            mCloseCompleter = completer;
-                        }
-                        return "YuvToJpegProcessor-close";
-                    });
-                }
-                closeFuture = Futures.nonCancellationPropagating(mCloseFuture);
-            }
-        }
-        return closeFuture;
-    }
-
-    @Override
-    public void onResolutionUpdate(@NonNull Size size) {
-        synchronized (mLock) {
-            mImageRect = new Rect(0, 0, size.getWidth(), size.getHeight());
-        }
-    }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/processing/SettableSurface.java b/camera/camera-core/src/main/java/androidx/camera/core/processing/SettableSurface.java
index 8584670..ef86985 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/processing/SettableSurface.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/processing/SettableSurface.java
@@ -227,7 +227,7 @@
             @Nullable Range<Integer> expectedFpsRange) {
         checkMainThread();
         // TODO(b/238230154) figure out how to support HDR.
-        SurfaceRequest surfaceRequest = new SurfaceRequest(getSize(), cameraInternal, false,
+        SurfaceRequest surfaceRequest = new SurfaceRequest(getSize(), cameraInternal,
                 expectedFpsRange, this::invalidate);
         try {
             setProvider(surfaceRequest.getDeferrableSurface());
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/ProcessingImageReaderTest.java b/camera/camera-core/src/test/java/androidx/camera/core/ProcessingImageReaderTest.java
deleted file mode 100644
index 386b37c..0000000
--- a/camera/camera-core/src/test/java/androidx/camera/core/ProcessingImageReaderTest.java
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core;
-
-import static android.os.Looper.getMainLooper;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.robolectric.Shadows.shadowOf;
-
-import android.graphics.ImageFormat;
-import android.os.Build;
-import android.util.Pair;
-import android.util.Size;
-import android.view.Surface;
-
-import androidx.annotation.NonNull;
-import androidx.camera.core.impl.CaptureBundle;
-import androidx.camera.core.impl.CaptureProcessor;
-import androidx.camera.core.impl.CaptureStage;
-import androidx.camera.core.impl.ImageProxyBundle;
-import androidx.camera.core.impl.ImageReaderProxy;
-import androidx.camera.core.impl.TagBundle;
-import androidx.camera.core.impl.utils.executor.CameraXExecutors;
-import androidx.camera.testing.fakes.FakeCameraCaptureResult;
-import androidx.camera.testing.fakes.FakeCaptureStage;
-import androidx.camera.testing.fakes.FakeImageReaderProxy;
-import androidx.concurrent.futures.CallbackToFutureAdapter;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mockito;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.android.util.concurrent.PausedExecutorService;
-import org.robolectric.annotation.Config;
-import org.robolectric.annotation.internal.DoNotInstrument;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicReference;
-
-// UnstableApiUsage is needed because PausedExecutorService is marked @Beta
-@SuppressWarnings({"UnstableApiUsage", "deprecation"})
-@RunWith(RobolectricTestRunner.class)
-@DoNotInstrument
-@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
-public final class ProcessingImageReaderTest {
-    private static final int CAPTURE_ID_0 = 0;
-    private static final int CAPTURE_ID_1 = 1;
-    private static final int CAPTURE_ID_2 = 2;
-    private static final int CAPTURE_ID_3 = 3;
-    private static final long TIMESTAMP_0 = 0L;
-    private static final long TIMESTAMP_1 = 1000L;
-    private static final long TIMESTAMP_2 = 2000L;
-    private static final long TIMESTAMP_3 = 4000L;
-    private static final CaptureProcessor NOOP_PROCESSOR = new CaptureProcessor() {
-        @Override
-        public void onOutputSurface(@NonNull Surface surface, int imageFormat) {
-
-        }
-
-        @Override
-        public void process(@NonNull ImageProxyBundle bundle) {
-
-        }
-
-        @Override
-        public void onResolutionUpdate(@NonNull Size size) {
-
-        }
-    };
-    private static PausedExecutorService sPausedExecutor;
-    private final CaptureStage mCaptureStage0 = new FakeCaptureStage(CAPTURE_ID_0, null);
-    private final CaptureStage mCaptureStage1 = new FakeCaptureStage(CAPTURE_ID_1, null);
-    private final CaptureStage mCaptureStage2 = new FakeCaptureStage(CAPTURE_ID_2, null);
-    private final CaptureStage mCaptureStage3 = new FakeCaptureStage(CAPTURE_ID_3, null);
-    private final FakeImageReaderProxy mImageReaderProxy = new FakeImageReaderProxy(8);
-    private MetadataImageReader mMetadataImageReader;
-    private CaptureBundle mCaptureBundle;
-    private String mTagBundleKey;
-
-    @BeforeClass
-    public static void setUpClass() {
-        sPausedExecutor = new PausedExecutorService();
-    }
-
-    @AfterClass
-    public static void tearDownClass() {
-        sPausedExecutor.shutdown();
-    }
-
-    @Before
-    public void setUp() {
-        mCaptureBundle = CaptureBundles.createCaptureBundle(mCaptureStage0, mCaptureStage1);
-        mTagBundleKey = Integer.toString(mCaptureBundle.hashCode());
-        mMetadataImageReader = new MetadataImageReader(mImageReaderProxy);
-    }
-
-    @After
-    public void cleanUp() {
-        // Ensure the PausedExecutorService is drained
-        sPausedExecutor.runAll();
-    }
-
-    @Test
-    public void canSetFuturesInSettableImageProxyBundle()
-            throws InterruptedException, TimeoutException, ExecutionException {
-        // Sets the callback from ProcessingImageReader to start processing
-        CaptureProcessor captureProcessor = mock(CaptureProcessor.class);
-        ProcessingImageReader processingImageReader = new ProcessingImageReader.Builder(
-                mMetadataImageReader, mCaptureBundle, captureProcessor).setPostProcessExecutor(
-                sPausedExecutor).build();
-        processingImageReader.setOnImageAvailableListener(mock(
-                ImageReaderProxy.OnImageAvailableListener.class),
-                CameraXExecutors.mainThreadExecutor());
-        Map<Integer, Long> resultMap = new HashMap<>();
-        resultMap.put(CAPTURE_ID_0, TIMESTAMP_0);
-        resultMap.put(CAPTURE_ID_1, TIMESTAMP_1);
-
-        // Cache current CaptureBundle as the TagBundle key for generate the fake image
-        mTagBundleKey = processingImageReader.getTagBundleKey();
-        triggerAndVerify(captureProcessor, resultMap);
-        Mockito.reset(captureProcessor);
-
-        CaptureBundle captureBundle = CaptureBundles.createCaptureBundle(mCaptureStage2,
-                mCaptureStage3);
-        processingImageReader.setCaptureBundle(captureBundle);
-
-        // Reset the key for TagBundle because the CaptureBundle is renewed
-        mTagBundleKey = processingImageReader.getTagBundleKey();
-
-        Map<Integer, Long> resultMap1 = new HashMap<>();
-        resultMap1.put(CAPTURE_ID_2, TIMESTAMP_2);
-        resultMap1.put(CAPTURE_ID_3, TIMESTAMP_3);
-        triggerAndVerify(captureProcessor, resultMap1);
-    }
-
-    private void triggerAndVerify(CaptureProcessor captureProcessor,
-            Map<Integer, Long> captureIdToTime)
-            throws InterruptedException, ExecutionException, TimeoutException {
-        // Feeds ImageProxy with all capture id on the initial list.
-        for (Integer id : captureIdToTime.keySet()) {
-            triggerImageAvailable(id, captureIdToTime.get(id));
-        }
-
-        // Ensure tasks are posted to the processing executor
-        shadowOf(getMainLooper()).idle();
-
-        // Run processing
-        sPausedExecutor.runAll();
-
-        ArgumentCaptor<ImageProxyBundle> imageProxyBundleCaptor =
-                ArgumentCaptor.forClass(ImageProxyBundle.class);
-        verify(captureProcessor, times(1)).process(imageProxyBundleCaptor.capture());
-        assertThat(imageProxyBundleCaptor.getValue()).isNotNull();
-
-        // CaptureProcessor.process should be called once all ImageProxies on the
-        // initial lists are ready. Then checks if the output has matched timestamp.
-        for (Integer id : captureIdToTime.keySet()) {
-            assertThat(imageProxyBundleCaptor.getValue().getImageProxy(id).get(0,
-                    TimeUnit.SECONDS).getImageInfo().getTimestamp()).isEqualTo(
-                    captureIdToTime.get(id));
-        }
-    }
-
-    // Make sure that closing the ProcessingImageReader while the CaptureProcessor is processing
-    // the image is safely done so that the CaptureProcessor will not be accessing closed images
-    @Test
-    public void canCloseWhileProcessingIsOccurring()
-            throws InterruptedException {
-        // Sets the callback from ProcessingImageReader to start processing
-        WaitingCaptureProcessor waitingCaptureProcessor = new WaitingCaptureProcessor();
-        ProcessingImageReader processingImageReader = new ProcessingImageReader.Builder(
-                mMetadataImageReader, mCaptureBundle, waitingCaptureProcessor).build();
-        processingImageReader.setOnImageAvailableListener(mock(
-                ImageReaderProxy.OnImageAvailableListener.class),
-                CameraXExecutors.mainThreadExecutor());
-        Map<Integer, Long> resultMap = new HashMap<>();
-        resultMap.put(CAPTURE_ID_0, TIMESTAMP_0);
-        resultMap.put(CAPTURE_ID_1, TIMESTAMP_1);
-
-        // Cache current CaptureBundle as the TagBundle key for generate the fake image
-        mTagBundleKey = processingImageReader.getTagBundleKey();
-
-        // Trigger the Images so that the CaptureProcessor starts
-        for (Map.Entry<Integer, Long> idTimestamp : resultMap.entrySet()) {
-            triggerImageAvailable(idTimestamp.getKey(), idTimestamp.getValue());
-        }
-
-        // Ensure tasks are posted to the processing executor
-        shadowOf(getMainLooper()).idle();
-
-        // Wait for CaptureProcessor.process() to start so that it is in the middle of processing
-        assertThat(waitingCaptureProcessor.waitForProcessingToStart(3000)).isTrue();
-
-        processingImageReader.close();
-
-        // Allow the CaptureProcessor to continue processing. Calling finishProcessing() will
-        // cause the CaptureProcessor to start accessing the ImageProxy. If the ImageProxy has
-        // already been closed then we will time out at waitForProcessingToComplete().
-        waitingCaptureProcessor.finishProcessing();
-
-        // The processing will only complete if no exception was thrown during the processing
-        // which causes it to return prematurely.
-        assertThat(waitingCaptureProcessor.waitForProcessingToComplete(3000)).isTrue();
-    }
-
-    // Tests that a ProcessingImageReader can be closed while in the process of receiving
-    // ImageProxies for an ImageProxyBundle.
-    @Test
-    public void closeImageHalfway() throws InterruptedException {
-        // Sets the callback from ProcessingImageReader to start processing
-        ProcessingImageReader processingImageReader = new ProcessingImageReader.Builder(
-                mMetadataImageReader, mCaptureBundle, NOOP_PROCESSOR).setPostProcessExecutor(
-                sPausedExecutor).build();
-        processingImageReader.setOnImageAvailableListener(mock(
-                ImageReaderProxy.OnImageAvailableListener.class),
-                CameraXExecutors.mainThreadExecutor());
-
-        // Cache current CaptureBundle as the TagBundle key for generate the fake image
-        mTagBundleKey = processingImageReader.getTagBundleKey();
-        triggerImageAvailable(CAPTURE_ID_0, TIMESTAMP_0);
-
-        // Ensure the first image is received by the ProcessingImageReader
-        shadowOf(getMainLooper()).idle();
-
-        // The ProcessingImageReader is closed after receiving the first image, but before
-        // receiving enough images for the entire ImageProxyBundle.
-        processingImageReader.close();
-
-        assertThat(mImageReaderProxy.isClosed()).isTrue();
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void imageReaderSizeIsSmallerThanCaptureBundle() {
-        // Creates a ProcessingImageReader with maximum Image number smaller than CaptureBundle
-        // size.
-        ImageReaderProxy imageReaderProxy = new FakeImageReaderProxy(1);
-        MetadataImageReader metadataImageReader = new MetadataImageReader(imageReaderProxy);
-
-        // Expects to throw exception when creating ProcessingImageReader.
-        new ProcessingImageReader.Builder(metadataImageReader, mCaptureBundle,
-                NOOP_PROCESSOR).build();
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void captureStageExceedMaxCaptureStage_setCaptureBundleThrowsException() {
-        // Creates a ProcessingImageReader with maximum Image number.
-        ProcessingImageReader processingImageReader = new ProcessingImageReader.Builder(100, 100,
-                ImageFormat.YUV_420_888, 2, mCaptureBundle, mock(CaptureProcessor.class)).build();
-
-        // Expects to throw exception when invoke the setCaptureBundle method with a
-        // CaptureBundle size greater than maximum image number.
-        processingImageReader.setCaptureBundle(
-                CaptureBundles.createCaptureBundle(mCaptureStage1, mCaptureStage2, mCaptureStage3));
-    }
-
-    @Test
-    public void imageReaderFormatIsOutputFormat() {
-        // Creates a ProcessingImageReader with input format YUV_420_888 and output JPEG
-        ProcessingImageReader processingImageReader = new ProcessingImageReader.Builder(100, 100,
-                ImageFormat.YUV_420_888, 2, mCaptureBundle,
-                mock(CaptureProcessor.class)).setOutputFormat(ImageFormat.JPEG).build();
-
-        assertThat(processingImageReader.getImageFormat()).isEqualTo(ImageFormat.JPEG);
-    }
-
-    @Test
-    public void canCloseUnderlyingCaptureProcessor() throws InterruptedException {
-        // Sets up the underlying capture processor
-        CaptureProcessor captureProcessor = mock(CaptureProcessor.class);
-        AtomicReference<CallbackToFutureAdapter.Completer<Void>> underlyingCompleterReference =
-                new AtomicReference<>();
-        ListenableFuture<Void> underlyingCloseFuture =
-                CallbackToFutureAdapter.getFuture(completer -> {
-                    underlyingCompleterReference.set(completer);
-                    return "underlyingCloseFuture";
-                });
-        when(captureProcessor.getCloseFuture()).thenReturn(underlyingCloseFuture);
-        ProcessingImageReader processingImageReader = new ProcessingImageReader.Builder(
-                mMetadataImageReader, mCaptureBundle, captureProcessor).build();
-
-        // Calls the close() function of the ProcessingImageReader
-        processingImageReader.close();
-
-        // Verifies whether close() function of the underlying capture processor is called
-        verify(captureProcessor, times(1)).close();
-
-        // Sets up the listener to monitor whether the close future is closed or not.
-        CountDownLatch closedLatch = new CountDownLatch(1);
-        processingImageReader.getCloseFuture().addListener(() -> closedLatch.countDown(),
-                CameraXExecutors.directExecutor());
-
-        // Checks that the close future is not completed before the underlying capture processor
-        // complete their close futures
-        assertThat(closedLatch.await(1000, TimeUnit.MILLISECONDS)).isFalse();
-
-        // Completes the completer of the underlying capture processor to complete their close
-        // future
-        underlyingCompleterReference.get().set(null);
-
-        // Checks whether the close future of ProcessingImageReader is completed after the
-        // underlying capture processor complete their close futures
-        assertThat(closedLatch.await(1000, TimeUnit.MILLISECONDS)).isTrue();
-    }
-
-    private void triggerImageAvailable(int captureId, long timestamp) throws InterruptedException {
-        TagBundle tagBundle = TagBundle.create(new Pair<>(mTagBundleKey, captureId));
-        mImageReaderProxy.triggerImageAvailable(tagBundle, timestamp);
-        FakeCameraCaptureResult.Builder builder = new FakeCameraCaptureResult.Builder();
-        builder.setTimestamp(timestamp);
-        builder.setTag(tagBundle);
-
-        mMetadataImageReader.getCameraCaptureCallback().onCaptureCompleted(builder.build());
-    }
-
-    // Only allows for processing once.
-    private static class WaitingCaptureProcessor implements CaptureProcessor {
-        // Block processing so that the ProcessingImageReader can be closed before the
-        // CaptureProcessor has finished accessing the ImageProxy and ImageProxyBundle
-        private final CountDownLatch mProcessingLatch = new CountDownLatch(1);
-
-        // To wait for processing to start. This makes sure that the ProcessingImageReader can be
-        // closed after processing has started
-        private final CountDownLatch mProcessingStartLatch = new CountDownLatch(1);
-
-        // Block processing from completing. This ensures that the CaptureProcessor has finished
-        // accessing the ImageProxy and ImageProxyBundle successfully.
-        private final CountDownLatch mProcessingComplete = new CountDownLatch(1);
-
-        WaitingCaptureProcessor() {
-        }
-
-        @Override
-        public void onOutputSurface(@NonNull Surface surface, int imageFormat) {
-        }
-
-        @Override
-        public void process(@NonNull ImageProxyBundle bundle) {
-            mProcessingStartLatch.countDown();
-            try {
-                mProcessingLatch.await();
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-                return;
-            }
-
-            ImageProxy imageProxy;
-            try {
-                imageProxy = bundle.getImageProxy(CAPTURE_ID_0).get();
-            } catch (ExecutionException | InterruptedException e) {
-                e.printStackTrace();
-                return;
-            }
-
-            // Try to get the crop rect. If the image has already been closed it will thrown an
-            // IllegalStateException
-            try {
-                imageProxy.getFormat();
-            } catch (IllegalStateException e) {
-                e.printStackTrace();
-                return;
-            }
-
-            mProcessingComplete.countDown();
-        }
-
-        @Override
-        public void onResolutionUpdate(@NonNull Size size) {
-        }
-
-        void finishProcessing() {
-            mProcessingLatch.countDown();
-        }
-
-        /** Returns false if it fails to start processing. */
-        boolean waitForProcessingToStart(long timeout) {
-            try {
-                return mProcessingStartLatch.await(timeout, TimeUnit.MILLISECONDS);
-            } catch (InterruptedException e) {
-                return false;
-            }
-        }
-
-        /** Returns false if processing does not complete. */
-        boolean waitForProcessingToComplete(long timeout) {
-            try {
-                return mProcessingComplete.await(timeout, TimeUnit.MILLISECONDS);
-            } catch (InterruptedException e) {
-                return false;
-            }
-        }
-    }
-}
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/SettableImageProxyBundleTest.java b/camera/camera-core/src/test/java/androidx/camera/core/SettableImageProxyBundleTest.java
deleted file mode 100644
index 37fe524..0000000
--- a/camera/camera-core/src/test/java/androidx/camera/core/SettableImageProxyBundleTest.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Build;
-
-import androidx.camera.testing.fakes.FakeImageInfo;
-import androidx.camera.testing.fakes.FakeImageProxy;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-import org.robolectric.annotation.internal.DoNotInstrument;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-@RunWith(RobolectricTestRunner.class)
-@DoNotInstrument
-@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
-public class SettableImageProxyBundleTest {
-    private static final int CAPTURE_ID_0 = 0;
-    private static final int CAPTURE_ID_1 = 1;
-    private static final int CAPTURE_ID_NONEXISTANT = 5;
-    private static final long TIMESTAMP_0 = 10L;
-    private static final long TIMESTAMP_1 = 20L;
-    private final ImageInfo mImageInfo0 = new FakeImageInfo();
-    private final ImageInfo mImageInfo1 = new FakeImageInfo();
-    private ImageProxy mImageProxy0;
-    private ImageProxy mImageProxy1;
-    private List<Integer> mCaptureIdList;
-    private SettableImageProxyBundle mImageProxyBundle;
-    private String mTagBundleKey = "fakeTagBundleKey";
-    @Before
-    public void setup() {
-        ((FakeImageInfo) mImageInfo0).setTimestamp(TIMESTAMP_0);
-        ((FakeImageInfo) mImageInfo1).setTimestamp(TIMESTAMP_1);
-        ((FakeImageInfo) mImageInfo0).setTag(mTagBundleKey, CAPTURE_ID_0);
-        ((FakeImageInfo) mImageInfo1).setTag(mTagBundleKey, CAPTURE_ID_1);
-        mImageProxy0 = new FakeImageProxy(mImageInfo0);
-        mImageProxy1 = new FakeImageProxy(mImageInfo1);
-
-        mCaptureIdList = new ArrayList<>();
-        mCaptureIdList.add(CAPTURE_ID_0);
-        mCaptureIdList.add(CAPTURE_ID_1);
-
-        mImageProxyBundle = new SettableImageProxyBundle(mCaptureIdList, mTagBundleKey);
-    }
-
-    @Test
-    public void canInvokeMatchedImageProxyFuture() throws InterruptedException,
-            ExecutionException, TimeoutException {
-
-        // Inputs two ImageProxy to SettableImageProxyBundle.
-        mImageProxyBundle.addImageProxy(mImageProxy0);
-        mImageProxyBundle.addImageProxy(mImageProxy1);
-
-        // Tries to get the Images for the ListenableFutures got from SettableImageProxyBundle.
-        ImageProxy result0 = mImageProxyBundle.getImageProxy(CAPTURE_ID_0).get(0, TimeUnit.SECONDS);
-        ImageProxy result1 = mImageProxyBundle.getImageProxy(CAPTURE_ID_1).get(0, TimeUnit.SECONDS);
-
-        // Checks if the results match what was input.
-        assertThat(result0.getImageInfo()).isSameInstanceAs(mImageInfo0);
-        assertThat(result0).isSameInstanceAs(mImageProxy0);
-        assertThat(result1.getImageInfo()).isSameInstanceAs(mImageInfo1);
-        assertThat(result1).isSameInstanceAs(mImageProxy1);
-    }
-
-    @Test
-    public void canInvokeMatchedImageProxyFutureWithMultiTag() throws InterruptedException,
-            ExecutionException, TimeoutException {
-        FakeImageInfo imageInfo0 = new FakeImageInfo();
-        imageInfo0.setTimestamp(TIMESTAMP_0);
-        FakeImageInfo imageInfo1 = new FakeImageInfo();
-        imageInfo1.setTimestamp(TIMESTAMP_1);
-
-        imageInfo0.setTag(mTagBundleKey, CAPTURE_ID_0);
-        imageInfo1.setTag(mTagBundleKey, CAPTURE_ID_1);
-
-        ImageProxy imageProxy0;
-        imageProxy0 = new FakeImageProxy(imageInfo0);
-        ImageProxy imageProxy1;
-        imageProxy1 = new FakeImageProxy(imageInfo1);
-
-        mImageProxyBundle.addImageProxy(imageProxy0);
-        mImageProxyBundle.addImageProxy(imageProxy1);
-
-        // Tries to get the Images for the ListenableFutures got from SettableImageProxyBundle.
-        ImageProxy result0 = mImageProxyBundle.getImageProxy(CAPTURE_ID_0).get(0, TimeUnit.SECONDS);
-        ImageProxy result1 = mImageProxyBundle.getImageProxy(CAPTURE_ID_1).get(0, TimeUnit.SECONDS);
-
-        // Checks if the results match what was input.
-        assertThat(result0.getImageInfo()).isSameInstanceAs(imageInfo0);
-        assertThat(result0).isSameInstanceAs(imageProxy0);
-        assertThat(result1.getImageInfo()).isSameInstanceAs(imageInfo1);
-        assertThat(result1).isSameInstanceAs(imageProxy1);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void exceptionWhenAddingImageWithInvalidCaptureId() {
-        ImageInfo imageInfo = new FakeImageInfo();
-        ImageProxy imageProxy = new FakeImageProxy(imageInfo);
-
-        // Adds an ImageProxy with a capture id which doesn't exist in the initial list.
-        ((FakeImageInfo) imageInfo).setTag(mTagBundleKey, CAPTURE_ID_NONEXISTANT);
-        ((FakeImageProxy) imageProxy).setImageInfo(imageInfo);
-
-        // Expects to throw exception while adding ImageProxy.
-        mImageProxyBundle.addImageProxy(imageProxy);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void exceptionWhenRetrievingImageWithInvalidCaptureId() throws InterruptedException,
-            ExecutionException, TimeoutException {
-        // Tries to get a ImageProxy with non-existed capture id. Expects to throw exception
-        // while getting ImageProxy.
-        mImageProxyBundle.getImageProxy(CAPTURE_ID_NONEXISTANT).get(0, TimeUnit.SECONDS);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void exceptionWhenAddingImageWithInvalidCaptureIdInMultiTagCase() {
-        ImageInfo imageInfo = new FakeImageInfo();
-        ImageProxy imageProxy = new FakeImageProxy(imageInfo);
-
-        // Adds an ImageProxy with a capture id which doesn't exist in the initial list.
-        ((FakeImageInfo) imageInfo).setTag(mTagBundleKey,
-                CAPTURE_ID_NONEXISTANT);
-        ((FakeImageProxy) imageProxy).setImageInfo(imageInfo);
-
-        // Expects to throw exception while adding ImageProxy.
-        mImageProxyBundle.addImageProxy(imageProxy);
-    }
-}
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/processing/SurfaceProcessorWithExecutorTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/processing/SurfaceProcessorWithExecutorTest.kt
index 9047555..80aadbac 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/processing/SurfaceProcessorWithExecutorTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/processing/SurfaceProcessorWithExecutorTest.kt
@@ -93,7 +93,7 @@
                 }
             }, executor)
         // Act: invoke methods.
-        processorWithExecutor.onInputSurface(SurfaceRequest(SIZE, FakeCamera(), false) {})
+        processorWithExecutor.onInputSurface(SurfaceRequest(SIZE, FakeCamera()) {})
         processorWithExecutor.onOutputSurface(mock(SurfaceOutput::class.java))
         shadowOf(getMainLooper()).idle()
         shadowOf(executorThread.looper).idle()
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
deleted file mode 100644
index dd46bbc..0000000
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingCaptureProcessor.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 2020 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.internal;
-
-import android.content.Context;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CaptureResult;
-import android.hardware.camera2.TotalCaptureResult;
-import android.media.Image;
-import android.util.Pair;
-import android.util.Size;
-import android.view.Surface;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.camera.camera2.impl.Camera2CameraCaptureResultConverter;
-import androidx.camera.core.ExperimentalGetImage;
-import androidx.camera.core.ImageInfo;
-import androidx.camera.core.ImageProxy;
-import androidx.camera.core.impl.CameraCaptureResult;
-import androidx.camera.core.impl.CameraCaptureResults;
-import androidx.camera.core.impl.CaptureProcessor;
-import androidx.camera.core.impl.ImageProxyBundle;
-import androidx.camera.extensions.impl.CaptureProcessorImpl;
-import androidx.camera.extensions.impl.ExtenderStateListener;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-/**
- * 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, VendorProcessor {
-    @NonNull
-    private final CaptureProcessorImpl mImpl;
-    @Nullable
-    private volatile Surface mSurface;
-    private volatile int mImageFormat;
-    private volatile Size mResolution;
-
-    private final Object mLock = new Object();
-
-    @GuardedBy("mLock")
-    private boolean mActive = false;
-
-    private BlockingCloseAccessCounter mAccessCounter = new BlockingCloseAccessCounter();
-
-    public AdaptingCaptureProcessor(@NonNull CaptureProcessorImpl impl) {
-        mImpl = impl;
-    }
-
-    /**
-     * Invoked after
-     * {@link ExtenderStateListener#onInit(String, CameraCharacteristics, Context)}()} to
-     * initialize the processor.
-     */
-    @Override
-    public void onInit() {
-        if (!mAccessCounter.tryIncrement()) {
-            return;
-        }
-
-        // Delay the onOutputSurface / onImageFormatUpdate/ onResolutionUpdate calls because on
-        // some OEM devices, these CaptureProcessImpl configuration should be performed only after
-        // onInit. Otherwise it will cause black preview issue.
-        try {
-            mImpl.onOutputSurface(mSurface, mImageFormat);
-            mImpl.onImageFormatUpdate(mImageFormat);
-            mImpl.onResolutionUpdate(mResolution);
-        } finally {
-            mAccessCounter.decrement();
-        }
-
-        synchronized (mLock) {
-            mActive = true;
-        }
-    }
-
-    @Override
-    public void onDeInit() {
-        synchronized (mLock) {
-            mActive = false;
-        }
-    }
-
-    @Override
-    public void close() {
-        mAccessCounter.destroyAndWaitForZeroAccess();
-        mSurface = null;
-        mResolution = null;
-    }
-
-    @Override
-    public void onOutputSurface(@NonNull Surface surface, int imageFormat) {
-        mSurface = surface;
-        mImageFormat = imageFormat;
-    }
-
-    @Override
-    public void onResolutionUpdate(@NonNull Size size) {
-        mResolution = size;
-    }
-
-    @Override
-    @ExperimentalGetImage
-    public void process(@NonNull ImageProxyBundle bundle) {
-        synchronized (mLock) {
-            if (!mActive) {
-                return;
-            }
-
-            List<Integer> ids = bundle.getCaptureIds();
-
-            Map<Integer, Pair<Image, TotalCaptureResult>> bundleMap = new HashMap<>();
-
-            for (Integer id : ids) {
-                ListenableFuture<ImageProxy> imageProxyListenableFuture = bundle.getImageProxy(id);
-                try {
-                    ImageProxy imageProxy = imageProxyListenableFuture.get(5, TimeUnit.SECONDS);
-                    Image image = imageProxy.getImage();
-                    if (image == null) {
-                        return;
-                    }
-
-                    ImageInfo imageInfo = imageProxy.getImageInfo();
-
-                    CameraCaptureResult result =
-                            CameraCaptureResults.retrieveCameraCaptureResult(imageInfo);
-                    if (result == null) {
-                        return;
-                    }
-
-                    CaptureResult captureResult =
-                            Camera2CameraCaptureResultConverter.getCaptureResult(result);
-                    if (captureResult == null) {
-                        return;
-                    }
-
-                    TotalCaptureResult totalCaptureResult = (TotalCaptureResult) captureResult;
-                    if (totalCaptureResult == null) {
-                        return;
-                    }
-
-                    Pair<Image, TotalCaptureResult> imageCapturePair = new Pair<>(
-                            imageProxy.getImage(), totalCaptureResult);
-                    bundleMap.put(id, imageCapturePair);
-                } catch (TimeoutException | ExecutionException | InterruptedException e) {
-                    return;
-                }
-            }
-
-            if (!mAccessCounter.tryIncrement()) {
-                return;
-            }
-
-            try {
-                mImpl.process(bundleMap);
-            } finally {
-                mAccessCounter.decrement();
-            }
-        }
-    }
-}
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
deleted file mode 100644
index f9bc984..0000000
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingCaptureStage.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2020 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.internal;
-
-import android.hardware.camera2.CaptureRequest;
-import android.util.Pair;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.OptIn;
-import androidx.annotation.RequiresApi;
-import androidx.camera.camera2.impl.Camera2ImplConfig;
-import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
-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;
-    private final int mId;
-
-    @SuppressWarnings("unchecked")
-    @OptIn(markerClass = ExperimentalCamera2Interop.class)
-    public AdaptingCaptureStage(@NonNull CaptureStageImpl impl) {
-        mId = impl.getId();
-        Camera2ImplConfig.Builder camera2ConfigurationBuilder = new Camera2ImplConfig.Builder();
-
-        for (Pair<CaptureRequest.Key, Object> captureParameter : impl.getParameters()) {
-            camera2ConfigurationBuilder.setCaptureRequestOption(captureParameter.first,
-                    captureParameter.second);
-        }
-
-        CaptureConfig.Builder captureConfigBuilder = new CaptureConfig.Builder();
-        captureConfigBuilder.addImplementationOptions(camera2ConfigurationBuilder.build());
-        mCaptureRequestConfiguration = captureConfigBuilder.build();
-    }
-
-    @Override
-    public int getId() {
-        return mId;
-    }
-
-    @Override
-    @NonNull
-    public CaptureConfig getCaptureConfig() {
-        return 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
deleted file mode 100644
index e3fda54..0000000
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingPreviewProcessor.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright 2020 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.internal;
-
-import android.content.Context;
-import android.graphics.ImageFormat;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CaptureResult;
-import android.hardware.camera2.TotalCaptureResult;
-import android.media.Image;
-import android.util.Size;
-import android.view.Surface;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.camera.camera2.impl.Camera2CameraCaptureResultConverter;
-import androidx.camera.core.ExperimentalGetImage;
-import androidx.camera.core.ImageInfo;
-import androidx.camera.core.ImageProxy;
-import androidx.camera.core.Logger;
-import androidx.camera.core.impl.CameraCaptureResult;
-import androidx.camera.core.impl.CameraCaptureResults;
-import androidx.camera.core.impl.CaptureProcessor;
-import androidx.camera.core.impl.ImageProxyBundle;
-import androidx.camera.extensions.impl.ExtenderStateListener;
-import androidx.camera.extensions.impl.PreviewImageProcessorImpl;
-import androidx.core.util.Preconditions;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
-/**
- * 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, VendorProcessor {
-    private static final String TAG = "AdaptingPreviewProcesso";
-    private final PreviewImageProcessorImpl mImpl;
-    private volatile Surface mSurface;
-    private volatile int mImageFormat;
-    private volatile Size mResolution;
-
-    private final Object mLock = new Object();
-
-    @GuardedBy("mLock")
-    private boolean mActive = false;
-
-    /**
-     * Invoked after
-     * {@link ExtenderStateListener#onInit(String, CameraCharacteristics, Context)}()} to
-     * initialize the processor.
-     */
-    @Override
-    public void onInit() {
-        // Delay the onOutputSurface / onImageFormatUpdate/ onResolutionUpdate calls because on
-        // some OEM devices, these CaptureProcessImpl configuration should be performed only after
-        // onInit. Otherwise it will cause black preview issue.
-        if (!mAccessCounter.tryIncrement()) {
-            return;
-        }
-
-        try {
-            mImpl.onResolutionUpdate(mResolution);
-            mImpl.onOutputSurface(mSurface, mImageFormat);
-            // No input formats other than YUV_420_888 are allowed.
-            mImpl.onImageFormatUpdate(ImageFormat.YUV_420_888);
-        } finally {
-            mAccessCounter.decrement();
-        }
-
-        synchronized (mLock) {
-            mActive = true;
-        }
-    }
-
-    private BlockingCloseAccessCounter mAccessCounter = new BlockingCloseAccessCounter();
-
-    public AdaptingPreviewProcessor(@NonNull PreviewImageProcessorImpl impl) {
-        mImpl = impl;
-    }
-
-    @Override
-    public void onOutputSurface(@NonNull Surface surface, int imageFormat) {
-        if (!mAccessCounter.tryIncrement()) {
-            return;
-        }
-
-        try {
-            mSurface = surface;
-            mImageFormat = imageFormat;
-        } finally {
-            mAccessCounter.decrement();
-        }
-    }
-
-    @ExperimentalGetImage
-    @Override
-    public void process(@NonNull ImageProxyBundle bundle) {
-        synchronized (mLock) {
-            if (!mActive) {
-                return;
-            }
-
-            List<Integer> ids = bundle.getCaptureIds();
-            Preconditions.checkArgument(ids.size() == 1,
-                    "Processing preview bundle must be 1, but found " + ids.size());
-
-            ListenableFuture<ImageProxy> imageProxyListenableFuture = bundle.getImageProxy(
-                    ids.get(0));
-            Preconditions.checkArgument(imageProxyListenableFuture.isDone());
-
-            ImageProxy imageProxy;
-            try {
-                imageProxy = imageProxyListenableFuture.get();
-            } catch (ExecutionException | InterruptedException e) {
-                Logger.e(TAG, "Unable to retrieve ImageProxy from bundle");
-                return;
-            }
-
-            Image image = imageProxy.getImage();
-
-            ImageInfo imageInfo = imageProxy.getImageInfo();
-            CameraCaptureResult result =
-                    CameraCaptureResults.retrieveCameraCaptureResult(imageInfo);
-            CaptureResult captureResult =
-                    Camera2CameraCaptureResultConverter.getCaptureResult(result);
-
-            TotalCaptureResult totalCaptureResult = null;
-            if (captureResult instanceof TotalCaptureResult) {
-                totalCaptureResult = (TotalCaptureResult) captureResult;
-            }
-
-            if (image == null) {
-                return;
-            }
-
-            if (!mAccessCounter.tryIncrement()) {
-                return;
-            }
-
-            try {
-                mImpl.process(image, totalCaptureResult);
-            } finally {
-                mAccessCounter.decrement();
-            }
-        }
-    }
-
-    @Override
-    public void onResolutionUpdate(@NonNull Size size) {
-        if (!mAccessCounter.tryIncrement()) {
-            return;
-        }
-
-        try {
-            mResolution = size;
-        } finally {
-            mAccessCounter.decrement();
-        }
-    }
-
-    @Override
-    public void onDeInit() {
-        synchronized (mLock) {
-            mActive = false;
-        }
-    }
-
-    @Override
-    public void close() {
-        mAccessCounter.destroyAndWaitForZeroAccess();
-        mSurface = null;
-        mResolution = null;
-    }
-}
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
deleted file mode 100644
index f10a4aa..0000000
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/AdaptingRequestUpdateProcessor.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2020 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.internal;
-
-import android.hardware.camera2.CaptureResult;
-import android.hardware.camera2.TotalCaptureResult;
-
-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;
-import androidx.camera.core.impl.CameraCaptureResults;
-import androidx.camera.core.impl.CaptureStage;
-import androidx.camera.core.impl.ImageInfoProcessor;
-import androidx.camera.extensions.impl.CaptureStageImpl;
-import androidx.camera.extensions.impl.PreviewExtenderImpl;
-import androidx.camera.extensions.impl.RequestUpdateProcessorImpl;
-import androidx.core.util.Preconditions;
-
-/**
- * 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, VendorProcessor {
-    private final PreviewExtenderImpl mPreviewExtenderImpl;
-    private final RequestUpdateProcessorImpl mProcessorImpl;
-    private BlockingCloseAccessCounter mAccessCounter = new BlockingCloseAccessCounter();
-
-    public AdaptingRequestUpdateProcessor(@NonNull PreviewExtenderImpl previewExtenderImpl) {
-        Preconditions.checkArgument(previewExtenderImpl.getProcessorType()
-                        == PreviewExtenderImpl.ProcessorType.PROCESSOR_TYPE_REQUEST_UPDATE_ONLY,
-                "AdaptingRequestUpdateProcess can only adapt extender with "
-                        + "PROCESSOR_TYPE_REQUEST_UPDATE_ONLY ProcessorType.");
-        mPreviewExtenderImpl = previewExtenderImpl;
-        mProcessorImpl = (RequestUpdateProcessorImpl) mPreviewExtenderImpl.getProcessor();
-    }
-
-    @Override
-    @Nullable
-    public CaptureStage getCaptureStage() {
-        if (!mAccessCounter.tryIncrement()) {
-            return null;
-        }
-
-        try {
-            return new AdaptingCaptureStage(mPreviewExtenderImpl.getCaptureStage());
-        } finally {
-            mAccessCounter.decrement();
-        }
-
-    }
-
-    @Override
-    public boolean process(@NonNull ImageInfo imageInfo) {
-        if (!mAccessCounter.tryIncrement()) {
-            return false;
-        }
-
-        try {
-            boolean processResult = false;
-
-            CameraCaptureResult result = CameraCaptureResults.retrieveCameraCaptureResult(
-                    imageInfo);
-            CaptureResult captureResult = Camera2CameraCaptureResultConverter.getCaptureResult(
-                    result);
-
-            if (captureResult instanceof TotalCaptureResult) {
-
-                CaptureStageImpl captureStageImpl =
-                        mProcessorImpl.process((TotalCaptureResult) captureResult);
-                processResult = captureStageImpl != null;
-            }
-            return processResult;
-        } finally {
-            mAccessCounter.decrement();
-        }
-    }
-
-    @Override
-    public void close() {
-        mAccessCounter.destroyAndWaitForZeroAccess();
-    }
-}
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
deleted file mode 100644
index b41659e..0000000
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/BlockingCloseAccessCounter.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2020 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.internal;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.RequiresApi;
-
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * A counter for blocking closing until all access to the counter has been completed.
- *
- * <pre>{@code
- * public void callingMethod() {
- *     if (!mAtomicAccessCounter.tryIncrement()) {
- *         return;
- *     }
- *
- *     try {
- *         // Some work that needs to be done
- *     } finally {
- *         mAtomicAccessCounter.decrement();
- *     }
- * }
- *
- * // Method that can only be called after all callingMethods are done with access
- * public void blockingMethod() {
- *     destroyAndWaitForZeroAccess();
- * }
- * }</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);
-    private final Lock mLock = new ReentrantLock();
-    private final Condition mDoneCondition = mLock.newCondition();
-
-    private static final int COUNTER_DESTROYED_FLAG = -1;
-
-    /**
-     * Attempt to increment the access counter.
-     *
-     * <p>Once {@link #destroyAndWaitForZeroAccess()} has returned this will always fail to
-     * increment, meaning access is not safe.
-     *
-     * @return true if the counter was incremented, false otherwise
-     */
-    boolean tryIncrement() {
-        mLock.lock();
-        try {
-            if (mAccessCount.get() == COUNTER_DESTROYED_FLAG) {
-                return false;
-            }
-            mAccessCount.getAndIncrement();
-        } finally {
-            mLock.unlock();
-        }
-        return true;
-    }
-
-    /**
-     * Decrement the access counter.
-     **/
-    void decrement() {
-        mLock.lock();
-        try {
-            switch (mAccessCount.getAndDecrement()) {
-                case COUNTER_DESTROYED_FLAG:
-                    throw new IllegalStateException("Unable to decrement. Counter already "
-                            + "destroyed");
-                case 0:
-                    throw new IllegalStateException("Unable to decrement. No corresponding "
-                            + "counter increment");
-                default:
-                    //
-            }
-            mDoneCondition.signal();
-        } finally {
-            mLock.unlock();
-        }
-    }
-
-    /**
-     * Blocks until there are zero accesses in the counter.
-     *
-     * <p>Once this call completes, the counter is destroyed and can not be incremented and
-     * decremented.
-     */
-    void destroyAndWaitForZeroAccess() {
-        mLock.lock();
-
-        try {
-            while (!mAccessCount.compareAndSet(0, COUNTER_DESTROYED_FLAG)) {
-                try {
-                    mDoneCondition.await();
-                } catch (InterruptedException e) {
-                    // Continue to check
-                }
-            }
-        } finally {
-            mLock.unlock();
-        }
-    }
-}
diff --git a/camera/camera-extensions/src/test/java/androidx/camera/extensions/internal/AdaptingCaptureProcessorTest.kt b/camera/camera-extensions/src/test/java/androidx/camera/extensions/internal/AdaptingCaptureProcessorTest.kt
deleted file mode 100644
index 54cb68d..0000000
--- a/camera/camera-extensions/src/test/java/androidx/camera/extensions/internal/AdaptingCaptureProcessorTest.kt
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright 2022 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.internal
-
-import android.hardware.camera2.TotalCaptureResult
-import android.media.Image
-import android.os.Build
-import android.util.Pair
-import android.util.Size
-import android.view.Surface
-import androidx.camera.camera2.internal.Camera2CameraCaptureResult
-import androidx.camera.core.impl.ImageProxyBundle
-import androidx.camera.core.impl.SingleImageProxyBundle
-import androidx.camera.core.impl.TagBundle
-import androidx.camera.core.internal.CameraCaptureResultImageInfo
-import androidx.camera.extensions.impl.CaptureProcessorImpl
-import androidx.camera.testing.fakes.FakeImageProxy
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mockito
-import org.mockito.Mockito.inOrder
-import org.robolectric.RobolectricTestRunner
-import org.robolectric.annotation.Config
-import org.robolectric.annotation.internal.DoNotInstrument
-
-private const val TAG_BUNDLE_KEY = "FakeTagBundleKey"
-private const val CAPTURE_ID = 0
-
-@RunWith(RobolectricTestRunner::class)
-@DoNotInstrument
-@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
-class AdaptingCaptureProcessorTest {
-    private val captureProcessorImpl = Mockito.mock(CaptureProcessorImpl::class.java)
-    private var adaptingCaptureProcessor = AdaptingCaptureProcessor(captureProcessorImpl)
-    private val imageProxyBundle = createFakeImageProxyBundle()
-
-    @Test
-    fun processDoesNotCallImplAfterClose() {
-        callOnInitAndVerify()
-        adaptingCaptureProcessor.close()
-        adaptingCaptureProcessor.process(imageProxyBundle)
-        Mockito.verifyNoMoreInteractions(captureProcessorImpl)
-    }
-
-    @Test
-    fun onImageFormatUpdateDoesNotCallImplAfterClose() {
-        adaptingCaptureProcessor.close()
-        adaptingCaptureProcessor.onOutputSurface(Mockito.mock(Surface::class.java), 0)
-        adaptingCaptureProcessor.onInit()
-        Mockito.verifyNoMoreInteractions(captureProcessorImpl)
-    }
-
-    @Test
-    fun onResolutionUpdateDoesNotCallImplAfterClose() {
-        adaptingCaptureProcessor.close()
-        adaptingCaptureProcessor.onResolutionUpdate(Size(640, 480))
-        adaptingCaptureProcessor.onInit()
-        Mockito.verifyNoMoreInteractions(captureProcessorImpl)
-    }
-
-    @Test
-    fun processCanCallImplBeforeDeInit() {
-        callOnInitAndVerify()
-        adaptingCaptureProcessor.process(imageProxyBundle)
-        Mockito.verify(captureProcessorImpl, Mockito.times(1)).process(any())
-    }
-
-    @Test
-    fun processDoesNotCallImplAfterDeInit() {
-        callOnInitAndVerify()
-        adaptingCaptureProcessor.onDeInit()
-        adaptingCaptureProcessor.process(imageProxyBundle)
-        Mockito.verifyNoMoreInteractions(captureProcessorImpl)
-    }
-
-    private fun createFakeImageProxyBundle(
-        bundleKey: String = TAG_BUNDLE_KEY,
-        captureId: Int = CAPTURE_ID
-    ): ImageProxyBundle {
-        val fakeCameraCaptureResult = Mockito.mock(Camera2CameraCaptureResult::class.java)
-        Mockito.`when`(fakeCameraCaptureResult.tagBundle)
-            .thenReturn(TagBundle.create(Pair.create(bundleKey, captureId)))
-        Mockito.`when`(fakeCameraCaptureResult.captureResult)
-            .thenReturn(Mockito.mock(TotalCaptureResult::class.java))
-        val fakeImageInfo = CameraCaptureResultImageInfo(fakeCameraCaptureResult)
-        val fakeImageProxy = FakeImageProxy(fakeImageInfo)
-        fakeImageProxy.image = Mockito.mock(Image::class.java)
-        return SingleImageProxyBundle(fakeImageProxy, bundleKey)
-    }
-
-    private fun callOnInitAndVerify() {
-        adaptingCaptureProcessor.onInit()
-
-        inOrder(captureProcessorImpl).apply {
-            verify(captureProcessorImpl).onOutputSurface(any(), anyInt())
-            verify(captureProcessorImpl).onImageFormatUpdate(anyInt())
-            verify(captureProcessorImpl).onResolutionUpdate(any())
-        }
-    }
-}
\ No newline at end of file
diff --git a/camera/camera-extensions/src/test/java/androidx/camera/extensions/internal/AdaptingPreviewProcessorTest.java b/camera/camera-extensions/src/test/java/androidx/camera/extensions/internal/AdaptingPreviewProcessorTest.java
deleted file mode 100644
index ba9d15b..0000000
--- a/camera/camera-extensions/src/test/java/androidx/camera/extensions/internal/AdaptingPreviewProcessorTest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright 2020 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.internal;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
-import android.media.Image;
-import android.os.Build;
-import android.util.Size;
-import android.view.Surface;
-
-import androidx.camera.core.impl.ImageProxyBundle;
-import androidx.camera.core.impl.SingleImageProxyBundle;
-import androidx.camera.extensions.impl.PreviewImageProcessorImpl;
-import androidx.camera.testing.fakes.FakeImageInfo;
-import androidx.camera.testing.fakes.FakeImageProxy;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InOrder;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-import org.robolectric.annotation.internal.DoNotInstrument;
-
-@RunWith(RobolectricTestRunner.class)
-@DoNotInstrument
-@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
-public class AdaptingPreviewProcessorTest {
-    private AdaptingPreviewProcessor mAdaptingPreviewProcessor;
-    private PreviewImageProcessorImpl mImpl;
-    private ImageProxyBundle mImageProxyBundle;
-    private String mTagBundleKey = "FakeTagBundleKey";
-
-    @Before
-    public void setup() {
-        mImpl = mock(PreviewImageProcessorImpl.class);
-
-        FakeImageInfo fakeImageInfo = new FakeImageInfo();
-        // Use the key which SingleImageProxyBundle is used to get tag.
-        fakeImageInfo.setTag(mTagBundleKey, 1);
-
-        FakeImageProxy fakeImageProxy = new FakeImageProxy(fakeImageInfo);
-        fakeImageProxy.setImage(mock(Image.class));
-
-        mImageProxyBundle = new SingleImageProxyBundle(fakeImageProxy, mTagBundleKey);
-        mAdaptingPreviewProcessor = new AdaptingPreviewProcessor(mImpl);
-    }
-
-    @Test
-    public void processDoesNotCallImplAfterClose() {
-        mAdaptingPreviewProcessor.close();
-        mAdaptingPreviewProcessor.process(mImageProxyBundle);
-        mAdaptingPreviewProcessor.onInit();
-
-        verifyNoMoreInteractions(mImpl);
-    }
-
-    @Test
-    public void onImageFormatUpdateDoesNotCallImplAfterClose() {
-        mAdaptingPreviewProcessor.close();
-        mAdaptingPreviewProcessor.onOutputSurface(mock(Surface.class), 0);
-        mAdaptingPreviewProcessor.onInit();
-
-        verifyNoMoreInteractions(mImpl);
-    }
-
-    @Test
-    public void onResolutionUpdateDoesNotCallImplAfterClose() {
-        mAdaptingPreviewProcessor.close();
-        mAdaptingPreviewProcessor.onResolutionUpdate(new Size(640, 480));
-        mAdaptingPreviewProcessor.onInit();
-
-        verifyNoMoreInteractions(mImpl);
-    }
-
-    @Test
-    public void processCanCallImplBeforeDeInit() {
-        callOnInitAndVerify();
-        mAdaptingPreviewProcessor.process(mImageProxyBundle);
-        verify(mImpl, times(1)).process(any(), any());
-    }
-
-    @Test
-    public void processDoesNotCallImplAfterDeInit() {
-        callOnInitAndVerify();
-        mAdaptingPreviewProcessor.onDeInit();
-        mAdaptingPreviewProcessor.process(mImageProxyBundle);
-
-        verifyNoMoreInteractions(mImpl);
-    }
-
-    private void callOnInitAndVerify() {
-        mAdaptingPreviewProcessor.onInit();
-
-        InOrder inOrderImpl = inOrder(mImpl);
-        inOrderImpl.verify(mImpl).onResolutionUpdate(any());
-        inOrderImpl.verify(mImpl).onOutputSurface(any(), anyInt());
-        inOrderImpl.verify(mImpl).onImageFormatUpdate(anyInt());
-    }
-}
diff --git a/camera/camera-extensions/src/test/java/androidx/camera/extensions/internal/AdaptingRequestUpdateProcessorTest.java b/camera/camera-extensions/src/test/java/androidx/camera/extensions/internal/AdaptingRequestUpdateProcessorTest.java
deleted file mode 100644
index ff8b784..0000000
--- a/camera/camera-extensions/src/test/java/androidx/camera/extensions/internal/AdaptingRequestUpdateProcessorTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright 2020 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.internal;
-
-import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import android.hardware.camera2.CaptureResult;
-import android.hardware.camera2.TotalCaptureResult;
-import android.os.Build;
-
-import androidx.camera.camera2.impl.Camera2CameraCaptureResultConverter;
-import androidx.camera.core.ImageInfo;
-import androidx.camera.core.impl.CameraCaptureResult;
-import androidx.camera.core.impl.CameraCaptureResults;
-import androidx.camera.extensions.impl.PreviewExtenderImpl;
-import androidx.camera.extensions.impl.RequestUpdateProcessorImpl;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.annotation.internal.DoNotInstrument;
-
-@RunWith(RobolectricTestRunner.class)
-@DoNotInstrument
-@Config(minSdk = Build.VERSION_CODES.LOLLIPOP,
-        shadows = {
-                AdaptingRequestUpdateProcessorTest.ShadowCameraCaptureResults.class,
-                AdaptingRequestUpdateProcessorTest.ShadowCamera2CameraCaptureResultConverter.class})
-public class AdaptingRequestUpdateProcessorTest {
-    private AdaptingRequestUpdateProcessor mAdaptingRequestUpdateProcessor;
-    private PreviewExtenderImpl mPreviewExtenderImpl;
-    private RequestUpdateProcessorImpl mImpl;
-    private ImageInfo mImageInfo;
-
-    @Before
-    public void setup() {
-        mImpl = mock(RequestUpdateProcessorImpl.class);
-        mPreviewExtenderImpl = mock(PreviewExtenderImpl.class);
-        when(mPreviewExtenderImpl.getProcessor()).thenReturn(mImpl);
-        when(mPreviewExtenderImpl.getProcessorType()).thenReturn(
-                PreviewExtenderImpl.ProcessorType.PROCESSOR_TYPE_REQUEST_UPDATE_ONLY);
-
-        mImageInfo = mock(ImageInfo.class);
-
-        mAdaptingRequestUpdateProcessor = new AdaptingRequestUpdateProcessor(mPreviewExtenderImpl);
-    }
-
-    @Test
-    public void getCaptureStageDoesNotCallImplAfterClose() {
-        clearInvocations(mPreviewExtenderImpl);
-        mAdaptingRequestUpdateProcessor.close();
-
-        mAdaptingRequestUpdateProcessor.getCaptureStage();
-
-        verifyNoMoreInteractions(mPreviewExtenderImpl);
-    }
-
-    @Test
-    public void processDoesNotCallImplAfterClose() {
-        mAdaptingRequestUpdateProcessor.close();
-
-        mAdaptingRequestUpdateProcessor.process(mImageInfo);
-
-        verifyNoMoreInteractions(mImpl);
-    }
-
-    /**
-     * Shadow of {@link Camera2CameraCaptureResultConverter} to control return of
-     * {@link #getCaptureResult(CameraCaptureResult)}.
-     */
-    @Implements(
-            value = Camera2CameraCaptureResultConverter.class,
-            minSdk = 21
-    )
-    static final class ShadowCamera2CameraCaptureResultConverter {
-        /** Returns {@link TotalCaptureResult} regardless of input. */
-        @Implementation
-        public static CaptureResult getCaptureResult(CameraCaptureResult cameraCaptureResult) {
-            return mock(TotalCaptureResult.class);
-        }
-    }
-
-    /**
-     * Shadow of {@link CameraCaptureResults} to control return of
-     * {@link #retrieveCameraCaptureResult(ImageInfo)}.
-     */
-    @Implements(
-            value = CameraCaptureResults.class,
-            minSdk = 21
-    )
-    static final class ShadowCameraCaptureResults {
-        /** Returns {@link CameraCaptureResult} regardless of input. */
-        @Implementation
-        public static CameraCaptureResult retrieveCameraCaptureResult(ImageInfo imageInfo) {
-            return mock(CameraCaptureResult.class);
-        }
-    }
-
-}
diff --git a/camera/camera-extensions/src/test/java/androidx/camera/extensions/internal/BlockingCloseAccessCounterTest.java b/camera/camera-extensions/src/test/java/androidx/camera/extensions/internal/BlockingCloseAccessCounterTest.java
deleted file mode 100644
index ececd6d..0000000
--- a/camera/camera-extensions/src/test/java/androidx/camera/extensions/internal/BlockingCloseAccessCounterTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2020 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.internal;
-
-import static org.junit.Assert.assertFalse;
-
-import android.os.Build;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-import org.robolectric.annotation.internal.DoNotInstrument;
-
-@RunWith(RobolectricTestRunner.class)
-@DoNotInstrument
-@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
-public class BlockingCloseAccessCounterTest {
-    @Test(expected = IllegalStateException.class)
-    public void decrementWithoutIncrementThrowsException() {
-        BlockingCloseAccessCounter counter = new BlockingCloseAccessCounter();
-
-        // Expect a IllegalStateException to be thrown
-        counter.decrement();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void decrementAfterDestroy() {
-        BlockingCloseAccessCounter counter = new BlockingCloseAccessCounter();
-        counter.destroyAndWaitForZeroAccess();
-
-        // Expect a IllegalStateException to be thrown
-        counter.decrement();
-    }
-
-    @Test
-    public void incrementAfterDestroyDoesNotIncrement() {
-        BlockingCloseAccessCounter counter = new BlockingCloseAccessCounter();
-        counter.destroyAndWaitForZeroAccess();
-
-        assertFalse(counter.tryIncrement());
-    }
-}
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/TimestampCaptureProcessor.java b/camera/camera-testing/src/main/java/androidx/camera/testing/TimestampCaptureProcessor.java
deleted file mode 100644
index 72c18fa..0000000
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/TimestampCaptureProcessor.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.testing;
-
-import android.media.Image;
-import android.util.Size;
-import android.view.Surface;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.annotation.RestrictTo;
-import androidx.camera.core.ExperimentalGetImage;
-import androidx.camera.core.ImageProxy;
-import androidx.camera.core.impl.CaptureProcessor;
-import androidx.camera.core.impl.ImageProxyBundle;
-import androidx.core.util.Preconditions;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
-/**
- * A {@link CaptureProcessor} that wraps another CaptureProcessor and captures the timestamps of all
- * the {@link ImageProxy} that are processed by it.
- *
- * <p>This class is used for testing of preview processing only. The expectation is that each
- * {@link ImageProxyBundle} will only have a single {@link ImageProxy}.
- *
- * @hide
- */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-@RestrictTo(RestrictTo.Scope.TESTS)
-public class TimestampCaptureProcessor implements CaptureProcessor {
-    private CaptureProcessor mCaptureProcessor;
-    private TimestampListener mTimestampListener;
-
-    /**
-     * @param captureProcessor  The {@link CaptureProcessor} that is wrapped.
-     * @param timestampListener The listener which receives the timestamp of all
-     *                          {@link ImageProxy} which are processed.
-     */
-    public TimestampCaptureProcessor(@NonNull CaptureProcessor captureProcessor,
-            @NonNull TimestampListener timestampListener) {
-        mCaptureProcessor = captureProcessor;
-        mTimestampListener = timestampListener;
-    }
-
-    /**
-     * Interface for receiving the timestamps of all {@link ImageProxy} which are processed by the
-     * wrapped {@link CaptureProcessor}.
-     */
-    @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-    public interface TimestampListener {
-        /**
-         * Called whenever an {@link ImageProxy} is processed.
-         *
-         * @param timestamp The timestamp of the {@link ImageProxy} that is processed.
-         */
-        void onTimestampAvailable(long timestamp);
-    }
-
-    @Override
-    public void onOutputSurface(@NonNull Surface surface, int imageFormat) {
-        mCaptureProcessor.onOutputSurface(surface, imageFormat);
-    }
-
-    @Override
-    @ExperimentalGetImage
-    public void process(@NonNull ImageProxyBundle bundle) {
-        List<Integer> ids = bundle.getCaptureIds();
-        Preconditions.checkArgument(ids.size() == 1,
-                "Processing preview bundle must be 1, but found " + ids.size());
-
-        ListenableFuture<ImageProxy> imageProxyListenableFuture = bundle.getImageProxy(ids.get(0));
-        Preconditions.checkArgument(imageProxyListenableFuture.isDone());
-
-        try {
-            ImageProxy imageProxy = imageProxyListenableFuture.get();
-            Image image = imageProxy.getImage();
-            if (image == null) {
-                return;
-            }
-
-            // Send timestamp
-            mTimestampListener.onTimestampAvailable(image.getTimestamp());
-            mCaptureProcessor.process(bundle);
-        } catch (ExecutionException | InterruptedException e) {
-            // Intentionally empty. Only the ImageProxy which can be retrieved need to have its
-            // timestamp captured.
-        }
-    }
-
-    @Override
-    public void onResolutionUpdate(@NonNull Size size) {
-        mCaptureProcessor.onResolutionUpdate(size);
-    }
-}
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java b/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
index 3b47dfb..91b870c 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
@@ -544,7 +544,7 @@
                 }
             }, CameraXExecutors.mainThreadExecutor());
         } else {
-            mSurfaceRequest = new SurfaceRequest(resolution, camera, false, targetFpsRange,
+            mSurfaceRequest = new SurfaceRequest(resolution, camera, targetFpsRange,
                     onSurfaceInvalidated);
             mDeferrableSurface = mSurfaceRequest.getDeferrableSurface();
             // When camera buffers from a REALTIME device are passed directly to a video encoder
diff --git a/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewDeviceTest.kt b/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewDeviceTest.kt
index 5df9f75..bccd2e9 100644
--- a/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewDeviceTest.kt
+++ b/camera/camera-view/src/androidTest/java/androidx/camera/view/PreviewViewDeviceTest.kt
@@ -17,7 +17,6 @@
 
 import android.content.Context
 import android.graphics.Bitmap
-import android.graphics.PixelFormat
 import android.graphics.Rect
 import android.graphics.drawable.ColorDrawable
 import android.os.Build
@@ -44,15 +43,12 @@
 import androidx.camera.core.SurfaceRequest
 import androidx.camera.core.ViewPort
 import androidx.camera.core.impl.CameraInfoInternal
-import androidx.camera.core.impl.utils.executor.CameraXExecutors
-import androidx.camera.core.impl.utils.futures.FutureCallback
 import androidx.camera.core.impl.utils.futures.Futures
 import androidx.camera.lifecycle.ProcessCameraProvider
 import androidx.camera.testing.CameraPipeConfigTestRule
 import androidx.camera.testing.CameraUtil
 import androidx.camera.testing.CameraUtil.PreTestCameraIdList
 import androidx.camera.testing.CoreAppTestUtil
-import androidx.camera.testing.SurfaceFormatUtil
 import androidx.camera.testing.fakes.FakeActivity
 import androidx.camera.testing.fakes.FakeCamera
 import androidx.camera.testing.fakes.FakeCameraInfoInternal
@@ -578,33 +574,6 @@
     }
 
     @Test
-    fun correctSurfacePixelFormat_whenRGBA8888IsRequired() {
-        val cameraInfo = createCameraInfo(CameraInfo.IMPLEMENTATION_TYPE_CAMERA2)
-        val surfaceRequest = createRgb8888SurfaceRequest(cameraInfo)
-        val future = surfaceRequest.deferrableSurface.surface
-        activityScenario!!.onActivity {
-            val previewView = PreviewView(context)
-            setContentView(previewView)
-            previewView.implementationMode = ImplementationMode.PERFORMANCE
-            val surfaceProvider = previewView.surfaceProvider
-            surfaceProvider.onSurfaceRequested(surfaceRequest)
-        }
-        val surface = arrayOfNulls<Surface>(1)
-        val countDownLatch = CountDownLatch(1)
-        Futures.addCallback(future, object : FutureCallback<Surface?> {
-            override fun onSuccess(result: Surface?) {
-                surface[0] = result
-                countDownLatch.countDown()
-            }
-
-            override fun onFailure(t: Throwable) {}
-        }, CameraXExecutors.directExecutor())
-        Truth.assertThat(countDownLatch.await(TIMEOUT_SECONDS.toLong(), TimeUnit.SECONDS)).isTrue()
-        Truth.assertThat(SurfaceFormatUtil.getSurfaceFormat(surface[0]))
-            .isEqualTo(PixelFormat.RGBA_8888)
-    }
-
-    @Test
     fun canCreateValidMeteringPoint() {
         val cameraInfo = createCameraInfo(
             90,
@@ -1060,18 +1029,12 @@
         activityScenario!!.onActivity { activity: FakeActivity -> activity.setContentView(view) }
     }
 
-    private fun createRgb8888SurfaceRequest(cameraInfo: CameraInfoInternal): SurfaceRequest {
-        return createSurfaceRequest(cameraInfo, true)
-    }
-
     private fun createSurfaceRequest(
         cameraInfo: CameraInfoInternal,
-        isRGBA8888Required: Boolean = false
     ): SurfaceRequest {
         val fakeCamera = FakeCamera( /*cameraControl=*/null, cameraInfo)
         val surfaceRequest = SurfaceRequest(
-            DEFAULT_SURFACE_SIZE, fakeCamera,
-            isRGBA8888Required
+            DEFAULT_SURFACE_SIZE, fakeCamera
         ) {}
         surfaceRequestList.add(surfaceRequest)
         return surfaceRequest
diff --git a/camera/camera-view/src/androidTest/java/androidx/camera/view/SurfaceViewImplementationTest.kt b/camera/camera-view/src/androidTest/java/androidx/camera/view/SurfaceViewImplementationTest.kt
index 3e0fede..a3f1971 100644
--- a/camera/camera-view/src/androidTest/java/androidx/camera/view/SurfaceViewImplementationTest.kt
+++ b/camera/camera-view/src/androidTest/java/androidx/camera/view/SurfaceViewImplementationTest.kt
@@ -68,7 +68,7 @@
         mParent = FrameLayout(mContext)
         setContentView(mParent)
 
-        mSurfaceRequest = SurfaceRequest(ANY_SIZE, FakeCamera(), false) {}
+        mSurfaceRequest = SurfaceRequest(ANY_SIZE, FakeCamera()) {}
         mImplementation = SurfaceViewImplementation(mParent, PreviewTransformation())
     }
 
@@ -92,7 +92,7 @@
         val previousSurfaceView = mImplementation.mSurfaceView
 
         // Act.
-        val sameResolutionSurfaceRequest = SurfaceRequest(ANY_SIZE, FakeCamera(), false) {}
+        val sameResolutionSurfaceRequest = SurfaceRequest(ANY_SIZE, FakeCamera()) {}
         mImplementation.testSurfaceRequest(sameResolutionSurfaceRequest)
         val newSurfaceView = mImplementation.mSurfaceView
 
@@ -110,7 +110,7 @@
         // Act.
         val differentSize: Size by lazy { Size(720, 480) }
         val differentResolutionSurfaceRequest =
-            SurfaceRequest(differentSize, FakeCamera(), false) {}
+            SurfaceRequest(differentSize, FakeCamera()) {}
         mImplementation.testSurfaceRequest(differentResolutionSurfaceRequest)
         val newSurfaceView = mImplementation.mSurfaceView
 
diff --git a/camera/camera-view/src/androidTest/java/androidx/camera/view/TextureViewImplementationTest.kt b/camera/camera-view/src/androidTest/java/androidx/camera/view/TextureViewImplementationTest.kt
index c6998bd..20d9291 100644
--- a/camera/camera-view/src/androidTest/java/androidx/camera/view/TextureViewImplementationTest.kt
+++ b/camera/camera-view/src/androidTest/java/androidx/camera/view/TextureViewImplementationTest.kt
@@ -50,7 +50,7 @@
     private val surfaceRequest: SurfaceRequest
         get() {
             if (_surfaceRequest == null) {
-                _surfaceRequest = SurfaceRequest(ANY_SIZE, FakeCamera(), false) {}
+                _surfaceRequest = SurfaceRequest(ANY_SIZE, FakeCamera()) {}
             }
             return _surfaceRequest!!
         }
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java b/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
index 1d141c6..1f3921e 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
@@ -681,10 +681,9 @@
                 .getImplementationType().equals(CameraInfo.IMPLEMENTATION_TYPE_CAMERA2_LEGACY);
         boolean hasSurfaceViewQuirk = DeviceQuirks.get(SurfaceViewStretchedQuirk.class) != null
                 ||  DeviceQuirks.get(SurfaceViewNotCroppedByParentQuirk.class) != null;
-        if (surfaceRequest.isRGBA8888Required() || Build.VERSION.SDK_INT <= 24 || isLegacyDevice
-                || hasSurfaceViewQuirk) {
+        if (Build.VERSION.SDK_INT <= 24 || isLegacyDevice || hasSurfaceViewQuirk) {
             // Force to use TextureView when the device is running android 7.0 and below, legacy
-            // level, RGBA8888 is required or SurfaceView has quirks.
+            // level or SurfaceView has quirks.
             return true;
         }
         switch (implementationMode) {
diff --git a/camera/camera-view/src/test/java/androidx/camera/view/PreviewViewTest.java b/camera/camera-view/src/test/java/androidx/camera/view/PreviewViewTest.java
index 804de8a..fb1c45d 100644
--- a/camera/camera-view/src/test/java/androidx/camera/view/PreviewViewTest.java
+++ b/camera/camera-view/src/test/java/androidx/camera/view/PreviewViewTest.java
@@ -139,7 +139,6 @@
         FakeCameraInfoInternal cameraInfoInternal = new FakeCameraInfoInternal();
         cameraInfoInternal.setImplementationType(CameraInfo.IMPLEMENTATION_TYPE_CAMERA2);
         return new SurfaceRequest(new Size(800, 600),
-                new FakeCamera(null, cameraInfoInternal),
-                /*isRGB8888Required*/ false, () -> {});
+                new FakeCamera(null, cameraInfoInternal), () -> {});
     }
 }
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
index 1d83c85..e812cab 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
@@ -1197,10 +1197,7 @@
         assertThat(imageCapture.flashMode).isEqualTo(ImageCapture.FLASH_MODE_ON)
     }
 
-    // Output JPEG format image when setting a CaptureProcessor is only enabled for devices whose
-    // API level is at least 29.
     @Test
-    @SdkSuppress(minSdkVersion = 29)
     fun returnJpegImage_whenSoftwareJpegIsEnabled() = runBlocking {
         val builder = ImageCapture.Builder()
 
@@ -1234,7 +1231,61 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 26)
+    fun canSaveJpegFileWithRotation_whenSoftwareJpegIsEnabled() = runBlocking {
+        val builder = ImageCapture.Builder()
+
+        // Enables software Jpeg
+        builder.mutableConfig.insertOption(
+            ImageCaptureConfig.OPTION_USE_SOFTWARE_JPEG_ENCODER,
+            true
+        )
+        val useCase = builder.build()
+        var camera: Camera
+        withContext(Dispatchers.Main) {
+            camera = cameraProvider.bindToLifecycle(fakeLifecycleOwner, BACK_SELECTOR, useCase)
+        }
+
+        val saveLocation = File.createTempFile("test", ".jpg")
+        saveLocation.deleteOnExit()
+        val callback = FakeImageSavedCallback(capturesCount = 1)
+        useCase.takePicture(
+            ImageCapture.OutputFileOptions.Builder(saveLocation).build(),
+            mainExecutor, callback)
+
+        // Wait for the signal that the image has been captured and saved.
+        callback.awaitCapturesAndAssert(savedImagesCount = 1)
+
+        // For YUV to JPEG case, the rotation will only be in Exif.
+        val exif = Exif.createFromFile(saveLocation)
+        assertThat(exif.rotation).isEqualTo(
+            camera.cameraInfo.getSensorRotationDegrees(useCase.targetRotation))
+    }
+
+    @Test
+    fun returnYuvImage_withYuvBufferFormat() = runBlocking {
+        val builder = ImageCapture.Builder().setBufferFormat(ImageFormat.YUV_420_888)
+        val useCase = builder.build()
+        var camera: Camera
+        withContext(Dispatchers.Main) {
+            camera = cameraProvider.bindToLifecycle(fakeLifecycleOwner, BACK_SELECTOR, useCase)
+        }
+
+        val callback = FakeImageCaptureCallback(capturesCount = 1)
+        useCase.takePicture(mainExecutor, callback)
+
+        // Wait for the signal that the image has been captured.
+        callback.awaitCapturesAndAssert(capturedImagesCount = 1)
+
+        val imageProperties = callback.results.first()
+        // Check the output image rotation degrees value is correct.
+        assertThat(imageProperties.rotationDegrees).isEqualTo(
+            camera.cameraInfo.getSensorRotationDegrees(useCase.targetRotation)
+        )
+        // Check the output format is correct.
+        assertThat(imageProperties.format).isEqualTo(ImageFormat.YUV_420_888)
+    }
+
+    @Test
     fun returnYuvImage_whenSoftwareJpegIsEnabledWithYuvBufferFormat() = runBlocking {
         val builder = ImageCapture.Builder().setBufferFormat(ImageFormat.YUV_420_888)
 
@@ -1268,7 +1319,7 @@
 
     @Test
     @SdkSuppress(minSdkVersion = 28)
-    fun returnJpegImage_whenSessionProcessorIsSet_outputFormantYuv() = runBlocking {
+    fun returnJpegImage_whenSessionProcessorIsSet() = runBlocking {
         val builder = ImageCapture.Builder()
         val sessionProcessor = FakeSessionProcessor(
             inputFormatPreview = null, // null means using the same output surface
@@ -1306,7 +1357,7 @@
 
     @Test
     @SdkSuppress(minSdkVersion = 28)
-    fun returnJpegImage_whenSessionProcessorIsSet_outputFormantJpeg() = runBlocking {
+    fun returnJpegImage_whenSessionProcessorIsSet_outputFormatJpeg() = runBlocking {
         assumeFalse(
             "Cuttlefish does not correctly handle Jpeg exif. Unable to test.",
             Build.MODEL.contains("Cuttlefish")