Sync the latest extensions interface to the testlib

camera-extensions androidTest will depend on the testlib dependencies
to test therefore it needs to be in sync with extensions-stub

Test: NA
Bug: NA
Change-Id: Ia7ad4a6ad90437150ee9f9bee22e05151b2a8a7a
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java
index e1f6033..ceef8d19 100755
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java
@@ -15,9 +15,11 @@
  */
 package androidx.camera.extensions.impl;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.TotalCaptureResult;
 import android.media.Image;
 import android.media.ImageWriter;
@@ -36,6 +38,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Executor;
 
 /**
  * Implementation for auto image capture use case.
@@ -46,6 +49,7 @@
  * @since 1.0
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+@SuppressLint("UnknownNullness")
 public final class AutoImageCaptureExtenderImpl implements ImageCaptureExtenderImpl {
     private static final String TAG = "AutoICExtender";
     private static final int DEFAULT_STAGE_ID = 0;
@@ -204,5 +208,21 @@
         public void onImageFormatUpdate(int imageFormat) {
 
         }
+
+        @Override
+        public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
+                ProcessResultImpl resultCallback, Executor executor) {
+
+        }
+    }
+
+    @Override
+    public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureResult.Key> getAvailableCaptureResultKeys() {
+        return null;
     }
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java
index 89871c8..6d44ebe 100755
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java
@@ -15,10 +15,12 @@
  */
 package androidx.camera.extensions.impl;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.graphics.ImageFormat;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.TotalCaptureResult;
 import android.hardware.camera2.params.StreamConfigurationMap;
 import android.media.Image;
@@ -38,6 +40,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Executor;
 
 /**
  * Implementation for beauty image capture use case.
@@ -48,6 +51,7 @@
  * @since 1.0
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+@SuppressLint("UnknownNullness")
 public final class BeautyImageCaptureExtenderImpl implements ImageCaptureExtenderImpl {
     private static final String TAG = "BeautyICExtender";
     private static final int DEFAULT_STAGE_ID = 0;
@@ -222,6 +226,11 @@
         }
 
         @Override
+        public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
+                ProcessResultImpl resultCallback, Executor executor) {
+        }
+
+        @Override
         public void onResolutionUpdate(Size size) {
 
         }
@@ -231,4 +240,14 @@
 
         }
     }
+
+    @Override
+    public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureResult.Key> getAvailableCaptureResultKeys() {
+        return null;
+    }
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java
index df88d11..5bfb538 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java
@@ -15,9 +15,11 @@
  */
 package androidx.camera.extensions.impl;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.TotalCaptureResult;
 import android.media.Image;
 import android.media.ImageWriter;
@@ -36,6 +38,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Executor;
 
 /**
  * Implementation for bokeh image capture use case.
@@ -46,6 +49,7 @@
  * @since 1.0
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+@SuppressLint("UnknownNullness")
 public final class BokehImageCaptureExtenderImpl implements ImageCaptureExtenderImpl {
     private static final String TAG = "BokehICExtender";
     private static final int DEFAULT_STAGE_ID = 0;
@@ -196,6 +200,12 @@
         }
 
         @Override
+        public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
+                ProcessResultImpl resultCallback, Executor executor) {
+
+        }
+
+        @Override
         public void onResolutionUpdate(Size size) {
 
         }
@@ -205,4 +215,14 @@
 
         }
     }
+
+    @Override
+    public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureResult.Key> getAvailableCaptureResultKeys() {
+        return null;
+    }
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java
index 68731c4..8518283 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java
@@ -16,33 +16,26 @@
 
 package androidx.camera.extensions.impl;
 
+import android.annotation.SuppressLint;
 import android.graphics.ImageFormat;
 import android.hardware.camera2.TotalCaptureResult;
 import android.media.Image;
 import android.util.Pair;
-import android.util.Size;
 import android.view.Surface;
 
 import androidx.annotation.RequiresApi;
 
 import java.util.Map;
+import java.util.concurrent.Executor;
 
 /**
  * The interface for processing a set of {@link Image}s that have captured.
  *
  * @since 1.0
  */
+@SuppressLint("UnknownNullness")
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-public interface CaptureProcessorImpl {
-    /**
-     * This gets called to update where the CaptureProcessor should write the output of {@link
-     * #process(Map)}.
-     *
-     * @param surface The {@link Surface} that the CaptureProcessor should write data into.
-     * @param imageFormat The format of that the surface expects.
-     */
-    void onOutputSurface(Surface surface, int imageFormat);
-
+public interface CaptureProcessorImpl extends ProcessorImpl {
     /**
      * Process a set images captured that were requested.
      *
@@ -56,20 +49,21 @@
     void process(Map<Integer, Pair<Image, TotalCaptureResult>> results);
 
     /**
-     * This callback will be invoked when CameraX changes the configured input resolution. After
-     * this call, {@link CaptureProcessorImpl} should expect any {@link Image} received as input
-     * to be at the specified resolution.
+     * Process a set images captured that were requested.
      *
-     * @param size for the surface.
-     */
-    void onResolutionUpdate(Size size);
-
-    /**
-     * This callback will be invoked when CameraX changes the configured input image format.
-     * After this call, {@link CaptureProcessorImpl} should expect any {@link Image} received as
-     * input to have the specified image format.
+     * <p> The result of the processing step should be written to the {@link Surface} that was
+     * received by {@link #onOutputSurface(Surface, int)}.
      *
-     * @param imageFormat for the surface.
+     * @param results        The map of {@link ImageFormat#YUV_420_888} format images and metadata
+     *                       to process. The {@link Image} that are contained within the map will
+     *                       become invalid after this method completes, so no references to them
+     *                       should be kept.
+     * @param resultCallback Capture result callback to be called once the capture result
+     *                       values of the processed image are ready.
+     * @param executor       The executor to run the callback on. If null then the callback will
+     *                       run on any arbitrary executor.
+     * @since 1.3
      */
-    void onImageFormatUpdate(int imageFormat);
+    void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
+            ProcessResultImpl resultCallback, Executor executor);
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ExtensionVersionImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ExtensionVersionImpl.java
index a524aea..a438fdc 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ExtensionVersionImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ExtensionVersionImpl.java
@@ -63,4 +63,27 @@
         Log.d(TAG, "Extension device library version " + VERSION);
         return VERSION;
     }
+
+    /**
+     * Specify whether or not CameraX should invoke the AdvancedExtenderImpl instead of
+     * PreviewExtenderImpl/ImageCaptureExtenderImpl.
+     *
+     * <p>Starting from version 1.2, a set of alternative interfaces called advanced extender for
+     * implementing extensions are provided to OEMs as another option. OEMs can continue using
+     * previous interfaces (PreviewExtenderImpl/ImageCaptureExtenderImpl, also called basic
+     * extender).
+     *
+     * <p>OEMs should return false here if only basic extender is implemented. When returning true,
+     * CameraX will invoke the AdvancedExtenderImpl implementation in advanced package for all
+     * types of extension modes.
+     *
+     * <p>ExtensionVersionImpl, InitializerImpl will still be called for both basic and advanced
+     * extender implementation paths.
+     *
+     * @return true if AdvancedExtenderImpl is implemented
+     * @since 1.2
+     */
+    public boolean isAdvancedExtenderImplemented() {
+        return false;
+    }
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java
index 8469b34..fe09802 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java
@@ -17,9 +17,11 @@
 
 import static android.hardware.camera2.CameraMetadata.CONTROL_AE_MODE_OFF;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.TotalCaptureResult;
 import android.media.Image;
 import android.media.ImageWriter;
@@ -38,6 +40,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -49,6 +52,7 @@
  * @since 1.0
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+@SuppressLint("UnknownNullness")
 public final class HdrImageCaptureExtenderImpl implements ImageCaptureExtenderImpl {
     private static final String TAG = "HdrImageCaptureExtender";
     private static final int UNDER_STAGE_ID = 0;
@@ -293,6 +297,12 @@
         }
 
         @Override
+        public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
+                ProcessResultImpl resultCallback, Executor executor) {
+
+        }
+
+        @Override
         public void onResolutionUpdate(Size size) {
 
         }
@@ -302,4 +312,14 @@
 
         }
     }
+
+    @Override
+    public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureResult.Key> getAvailableCaptureResultKeys() {
+        return null;
+    }
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrPreviewExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrPreviewExtenderImpl.java
index eb02fe9..5af32e2 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrPreviewExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/HdrPreviewExtenderImpl.java
@@ -32,6 +32,7 @@
 
 import java.util.List;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.RunnableFuture;
 
@@ -160,6 +161,12 @@
         }
 
         @Override
+        public void process(Image image, TotalCaptureResult result,
+                ProcessResultImpl resultCallback, Executor executor) {
+
+        }
+
+        @Override
         public void onResolutionUpdate(Size size) {
             mSize = size;
             setWindowSurface();
@@ -206,6 +213,5 @@
                 // handle exception
             }
         }
-
     }
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java
index f47a1a0..6d0b4f4 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java
@@ -16,13 +16,15 @@
 
 package androidx.camera.extensions.impl;
 
+import android.annotation.SuppressLint;
 import android.graphics.ImageFormat;
 import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
 import android.util.Pair;
 import android.util.Range;
 import android.util.Size;
 
-import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 
 import java.util.List;
@@ -33,6 +35,7 @@
  * @since 1.0
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+@SuppressLint("UnknownNullness")
 public interface ImageCaptureExtenderImpl extends ExtenderStateListener {
     /**
      * Indicates whether the extension is supported on the device.
@@ -78,27 +81,85 @@
      * returned list is not null, it will be used to find the best resolutions combination for
      * the bound use cases.
      *
-     * @return the customized supported resolutions.
+     * @return the customized supported resolutions, or null to support all sizes retrieved from
+     *         {@link android.hardware.camera2.params.StreamConfigurationMap}.
      * @since 1.1
      */
-    @Nullable
     List<Pair<Integer, Size[]>> getSupportedResolutions();
 
     /**
      * Returns the estimated capture latency range in milliseconds for the target capture
      * resolution.
      *
-     * <p> This includes the time spent processing the multi-frame capture request along with any
-     * additional time for encoding of the processed buffer in the framework if necessary.
+     * <p>This includes the time spent processing the multi-frame capture request along with any
+     * additional time for encoding of the processed buffer in the framework if necessary.</p>
      *
      * @param captureOutputSize size of the capture output surface. If it is null or not in the
      *                          supported output sizes, maximum capture output size is used for
      *                          the estimation.
-     * @return the range of estimated minimal and maximal capture latency in milliseconds.
-     * Returns null if no capture latency info can be provided.
+     * @return the range of estimated minimal and maximal capture latency in milliseconds, or
+     * null if no capture latency info can be provided.
      * @since 1.2
      */
-    @Nullable
-    Range<Long> getEstimatedCaptureLatencyRange(@Nullable Size captureOutputSize);
-}
+    Range<Long> getEstimatedCaptureLatencyRange(Size captureOutputSize);
 
+    /**
+     * Return a list of orthogonal capture request keys.
+     *
+     * <p>Any keys included in the list will be configurable by clients of the extension and will
+     * affect the extension functionality.</p>
+     *
+     * <p>Do note that the list of keys applies to {@link PreviewExtenderImpl} as well.</p>
+     *
+     * <p>Also note that the keys {@link CaptureRequest#JPEG_QUALITY} and
+     * {@link CaptureRequest#JPEG_ORIENTATION} are always supported regardless being added in the
+     * list or not. To support common camera operations like zoom, tap-to-focus, flash and
+     * exposure compensation, we recommend supporting the following keys if possible.
+     * <pre>
+     *  zoom:  {@link CaptureRequest#CONTROL_ZOOM_RATIO}
+     *         {@link CaptureRequest#SCALER_CROP_REGION}
+     *  tap-to-focus:
+     *         {@link CaptureRequest#CONTROL_AF_MODE}
+     *         {@link CaptureRequest#CONTROL_AF_TRIGGER}
+     *         {@link CaptureRequest#CONTROL_AF_REGIONS}
+     *         {@link CaptureRequest#CONTROL_AE_REGIONS}
+     *         {@link CaptureRequest#CONTROL_AWB_REGIONS}
+     *  flash:
+     *         {@link CaptureRequest#CONTROL_AE_MODE}
+     *         {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER}
+     *         {@link CaptureRequest#FLASH_MODE}
+     *  exposure compensation:
+     *         {@link CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION}
+     * </pre>
+     * On basic extensions that implement 1.2 or prior version, the above keys are all supported
+     * explicitly. When migrating from 1.2 or prior to 1.3, please note that both CameraX and
+     * Camera2 will honor the returned list and support only the keys contained in it. For
+     * example, if OEM decides to return only {@link CaptureRequest#CONTROL_ZOOM_RATIO} and
+     * {@link CaptureRequest#SCALER_CROP_REGION} in the 1.3 implementation, it means only zoom is
+     * supported for the app while tap-to-focus , flash and exposure compensation are not allowed.
+     *
+     * @return List of supported orthogonal capture keys, or an empty list if no capture settings
+     * are not supported.
+     * @since 1.3
+     */
+    List<CaptureRequest.Key> getAvailableCaptureRequestKeys();
+
+    /**
+     * Return a list of supported capture result keys.
+     *
+     * <p>Any keys included in this list must be available as part of the registered
+     * {@link ProcessResultImpl} callback. In case frame processing is not supported,
+     * then the Camera2/CameraX framework will use the list to filter and notify camera clients
+     * using the respective camera results.</p>
+     *
+     * <p>At the very minimum, it is expected that the result key list is a superset of the
+     * capture request keys.</p>
+     *
+     * <p>Do note that the list of keys applies to {@link PreviewExtenderImpl} as well.</p>
+     *
+     * @return List of supported capture result keys, or an empty list if capture results are not
+     * supported.
+     * @since 1.3
+     */
+    List<CaptureResult.Key> getAvailableCaptureResultKeys();
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java
index 6d84fa0..c106921 100755
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java
@@ -15,9 +15,11 @@
  */
 package androidx.camera.extensions.impl;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.TotalCaptureResult;
 import android.media.Image;
 import android.media.ImageWriter;
@@ -36,6 +38,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Executor;
 
 /**
  * Implementation for night image capture use case.
@@ -46,6 +49,7 @@
  * @since 1.0
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+@SuppressLint("UnknownNullness")
 public final class NightImageCaptureExtenderImpl implements ImageCaptureExtenderImpl {
     private static final String TAG = "NightICExtender";
     private static final int DEFAULT_STAGE_ID = 0;
@@ -157,8 +161,8 @@
     }
 
     @RequiresApi(23)
-    static final class NightImageCaptureExtenderCaptureProcessorImpl implements
-            CaptureProcessorImpl {
+    static final class NightImageCaptureExtenderCaptureProcessorImpl
+            implements CaptureProcessorImpl {
         private ImageWriter mImageWriter;
 
         @Override
@@ -196,13 +200,26 @@
         }
 
         @Override
-        public void onResolutionUpdate(Size size) {
+        public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
+                ProcessResultImpl resultCallback, Executor executor) {
+        }
 
+        @Override
+        public void onResolutionUpdate(Size size) {
         }
 
         @Override
         public void onImageFormatUpdate(int imageFormat) {
-
         }
     }
+
+    @Override
+    public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureResult.Key> getAvailableCaptureResultKeys() {
+        return null;
+    }
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NoOpCaptureProcessorImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NoOpCaptureProcessorImpl.java
index 9645c43..a84fed7 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NoOpCaptureProcessorImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/NoOpCaptureProcessorImpl.java
@@ -26,6 +26,7 @@
 import androidx.annotation.RequiresApi;
 
 import java.util.Map;
+import java.util.concurrent.Executor;
 
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 final class NoOpCaptureProcessorImpl implements CaptureProcessorImpl {
@@ -48,4 +49,10 @@
     public void onImageFormatUpdate(int imageFormat) {
 
     }
+
+    @Override
+    public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
+            ProcessResultImpl resultCallback, Executor executor) {
+
+    }
 }
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/PreviewImageProcessorImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/PreviewImageProcessorImpl.java
index 60d3f77..ff6ed88 100644
--- a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/PreviewImageProcessorImpl.java
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/PreviewImageProcessorImpl.java
@@ -16,19 +16,23 @@
 
 package androidx.camera.extensions.impl;
 
+import android.annotation.SuppressLint;
 import android.graphics.ImageFormat;
 import android.hardware.camera2.TotalCaptureResult;
 import android.media.Image;
 
 import androidx.annotation.RequiresApi;
 
+import java.util.concurrent.Executor;
+
 /**
- * Processing a single {@link Image} and {@link TotalCaptureResult} to produce an output to a
+ * Processes a single {@link Image} and {@link TotalCaptureResult} to produce an output to a
  * stream.
  *
  * @since 1.0
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+@SuppressLint("UnknownNullness")
 public interface PreviewImageProcessorImpl extends ProcessorImpl {
     /**
      * Processes the requested image capture.
@@ -41,5 +45,23 @@
      * @param result The metadata associated with the image to process.
      */
     void process(Image image, TotalCaptureResult result);
-}
 
+    /**
+     * Processes the requested image capture.
+     *
+     * <p> The result of the processing step should be written to the {@link android.view.Surface}
+     * that was received by {@link ProcessorImpl#onOutputSurface(android.view.Surface, int)}.
+     *
+     * @param image          The {@link ImageFormat#YUV_420_888} format image to process. This will
+     *                       be invalid after the method completes so no reference to it should be
+     *                       kept.
+     * @param result         The metadata associated with the image to process.
+     * @param resultCallback Capture result callback to be called once the capture result
+     *                       values of the processed image are ready.
+     * @param executor       The executor to run the callback on. If null then the callback will
+     *                       run on any arbitrary executor.
+     * @since 1.3
+     */
+    void process(Image image, TotalCaptureResult result, ProcessResultImpl resultCallback,
+            Executor executor);
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ProcessResultImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ProcessResultImpl.java
new file mode 100644
index 0000000..d0e3605
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/ProcessResultImpl.java
@@ -0,0 +1,45 @@
+/*
+ * 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.impl;
+
+import android.annotation.SuppressLint;
+import android.hardware.camera2.CaptureResult;
+import android.util.Pair;
+
+import java.util.List;
+
+/**
+ * Allows clients to receive information about the capture result values of processed frames.
+ *
+ * @since 1.3
+ */
+@SuppressLint("UnknownNullness")
+public interface ProcessResultImpl {
+    /**
+     * Capture result callback that needs to be called when the process capture results are
+     * ready as part of frame post-processing.
+     *
+     * @param shutterTimestamp     The shutter time stamp of the processed frame.
+     * @param result               Key value pairs for all supported capture results. Do note that
+     *                             if results 'android.jpeg.quality' and 'android.jpeg.orientation'
+     *                             are present in the process capture input results, then the values
+     *                             must also be passed as part of this callback. Both Camera2 and
+     *                             CameraX guarantee that those two settings and results are always
+     *                             supported and applied by the corresponding framework.
+     */
+    void onCaptureCompleted(long shutterTimestamp, List<Pair<CaptureResult.Key, Object>> result);
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
new file mode 100644
index 0000000..465bfe8
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.util.Range;
+import android.util.Size;
+
+import androidx.camera.extensions.impl.ExtensionVersionImpl;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Advanced OEM contract for implementing Extensions. ImageCapture/Preview Extensions are both
+ * implemented on this interface.
+ *
+ * <p>This advanced OEM contract empowers OEM to gain access to more Camera2 capability. This
+ * includes: (1) Add custom surfaces with specific formats like YUV, RAW, RAW_DEPTH. (2) Access to
+ * the capture request callbacks as well as all the images retrieved of various image formats. (3)
+ * Able to triggers single or repeating request with the capabilities to specify target surfaces,
+ * template id and parameters.
+ *
+ * <p>OEM needs to implement it with class name HdrAdvancedExtenderImpl for HDR,
+ * NightAdvancedExtenderImpl for night mode, BeautyAdvancedExtenderImpl for beauty mode,
+ * BokehAdvancedExtenderImpl for bokeh mode and AutoAdvancedExtenderImpl for auto mode.
+ *
+ * <p>OEMs are required to return true in
+ * {@link ExtensionVersionImpl#isAdvancedExtenderImplemented()} in order to request CameraX to
+ * use advanced extender over basic extender. OEM is okay to implement advanced
+ * extender only Or basic extender only. However the caveat of advanced-only implementation is,
+ * extensions will be unavailable on the apps using interfaces prior to 1.2.
+ *
+ * @since 1.2
+ */
+@SuppressLint("UnknownNullness")
+public interface AdvancedExtenderImpl {
+
+    /**
+     * Indicates whether the extension is supported on the device.
+     *
+     * @param cameraId           The camera2 id string of the camera.
+     * @param characteristicsMap A map consisting of the camera ids and the
+     *                           {@link CameraCharacteristics}s. For every camera, the map
+     *                           contains at least the CameraCharacteristics for the camera id.
+     *                           If the camera is logical camera, it will also contain associated
+     *                           physical camera ids and their CameraCharacteristics.
+     * @return true if the extension is supported, otherwise false
+     */
+    boolean isExtensionAvailable(String cameraId,
+            Map<String, CameraCharacteristics> characteristicsMap);
+
+    /**
+     * Initializes the extender to be used with the specified camera.
+     *
+     * <p>This should be called before any other method on the extender. The exception is {@link
+     * #isExtensionAvailable}.
+     *
+     * @param cameraId           The camera2 id string of the camera.
+     * @param characteristicsMap A map consisting of the camera ids and the
+     *                           {@link CameraCharacteristics}s. For every camera, the map
+     *                           contains at least the CameraCharacteristics for the camera id.
+     *                           If the camera is logical camera, it will also contain associated
+     *                           physical camera ids and their CameraCharacteristics.
+     */
+    void init(String cameraId, Map<String, CameraCharacteristics> characteristicsMap);
+
+    /**
+     * Returns the estimated capture latency range in milliseconds for the
+     * target capture resolution during the calls to
+     * {@link SessionProcessorImpl#startCapture}. This
+     * includes the time spent processing the multi-frame capture request along with any additional
+     * time for encoding of the processed buffer in the framework if necessary.
+     *
+     * @param cameraId          the camera id
+     * @param captureOutputSize size of the capture output surface. If it is null or not in the
+     *                          supported output sizes, maximum capture output size is used for
+     *                          the estimation.
+     * @param imageFormat the image format of the capture output surface.
+     * @return the range of estimated minimal and maximal capture latency in milliseconds.
+     * Returns null if no capture latency info can be provided.
+     */
+    Range<Long> getEstimatedCaptureLatencyRange(String cameraId,
+            Size captureOutputSize, int imageFormat);
+
+    /**
+     * Returns supported output format/size map for preview. The format could be PRIVATE or
+     * YUV_420_888. OEM must support PRIVATE format at least. CameraX will only use resolutions
+     * for preview from the list.
+     *
+     * <p>The preview surface format in the CameraCaptureSession may not be identical to the
+     * supported preview output format returned here. Like in the basic extender interface, the
+     * preview PRIVATE surface could be added to the CameraCaptureSession and OEM processes it in
+     * the HAL. Alternatively OEM can configure a intermediate YUV surface of the same size and
+     * writes the output to the preview output surface.
+     */
+    Map<Integer, List<Size>> getSupportedPreviewOutputResolutions(String cameraId);
+
+    /**
+     * Returns supported output format/size map for image capture. OEM is required to support
+     * both JPEG and YUV_420_888 format output.
+     *
+     * <p>Like in the basic extender interface, the surface created with this supported
+     * format/size could be either added in CameraCaptureSession with HAL processing OR it
+     * configures intermediate surfaces(YUV/RAW..) and writes the output to the output surface.
+     */
+    Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(String cameraId);
+
+    /**
+     * Returns supported output sizes for Image Analysis (YUV_420_888 format).
+     *
+     * <p>OEM can optionally support a YUV surface for ImageAnalysis along with Preview/ImageCapture
+     * output surfaces. If imageAnalysis YUV surface is not supported, OEM should return null or
+     * empty list.
+     */
+    List<Size> getSupportedYuvAnalysisResolutions(String cameraId);
+
+    /**
+     * Returns a processor for activating extension sessions. It implements all the interactions
+     * required for starting a extension and cleanup.
+     */
+    SessionProcessorImpl createSessionProcessor();
+
+    /**
+     * Returns a list of orthogonal capture request keys.
+     *
+     * <p>Any keys included in the list will be configurable by clients of the extension and will
+     * affect the extension functionality.</p>
+     *
+     * <p>Please note that the keys {@link CaptureRequest#JPEG_QUALITY} and
+     * {@link CaptureRequest#JPEG_ORIENTATION} are always supported regardless being added in the
+     * list or not. To support common camera operations like zoom, tap-to-focus, flash and
+     * exposure compensation, we recommend supporting the following keys if possible.
+     * <pre>
+     *  zoom:  {@link CaptureRequest#CONTROL_ZOOM_RATIO}
+     *         {@link CaptureRequest#SCALER_CROP_REGION}
+     *  tap-to-focus:
+     *         {@link CaptureRequest#CONTROL_AF_MODE}
+     *         {@link CaptureRequest#CONTROL_AF_TRIGGER}
+     *         {@link CaptureRequest#CONTROL_AF_REGIONS}
+     *         {@link CaptureRequest#CONTROL_AE_REGIONS}
+     *         {@link CaptureRequest#CONTROL_AWB_REGIONS}
+     *  flash:
+     *         {@link CaptureRequest#CONTROL_AE_MODE}
+     *         {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER}
+     *         {@link CaptureRequest#FLASH_MODE}
+     *  exposure compensation:
+     *         {@link CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION}
+     * </pre>
+     *
+     * @return List of supported orthogonal capture keys, or an empty list if no capture settings
+     * are not supported.
+     * @since 1.3
+     */
+    List<CaptureRequest.Key> getAvailableCaptureRequestKeys();
+
+    /**
+     * Returns a list of supported capture result keys.
+     *
+     * <p>Any keys included in this list must be available as part of the registered
+     * {@link SessionProcessorImpl.CaptureCallback#onCaptureCompleted} callback.</p>
+     *
+     * <p>At the very minimum, it is expected that the result key list is a superset of the
+     * capture request keys.</p>
+     *
+     * @return List of supported capture result keys, or
+     * an empty list if capture results are not supported.
+     * @since 1.3
+     */
+    List<CaptureResult.Key> getAvailableCaptureResultKeys();
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/AutoAdvancedExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/AutoAdvancedExtenderImpl.java
new file mode 100644
index 0000000..7065a8f
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/AutoAdvancedExtenderImpl.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.util.Range;
+import android.util.Size;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Stub advanced extender implementation for auto.
+ *
+ * <p>This class should be implemented by OEM and deployed to the target devices.
+ *
+ * @since 1.2
+ */
+@SuppressLint("UnknownNullness")
+public class AutoAdvancedExtenderImpl implements AdvancedExtenderImpl {
+    public AutoAdvancedExtenderImpl() {
+    }
+
+    @Override
+    public boolean isExtensionAvailable(String cameraId,
+            Map<String, CameraCharacteristics> characteristicsMap) {
+        return false;
+    }
+
+    @Override
+    public void init(String cameraId,
+            Map<String, CameraCharacteristics> characteristicsMap) {
+    }
+
+    @Override
+    public Range<Long> getEstimatedCaptureLatencyRange(
+            String cameraId, Size size, int imageFormat) {
+        return null;
+    }
+
+    @Override
+    public Map<Integer, List<Size>> getSupportedPreviewOutputResolutions(
+            String cameraId) {
+        return null;
+    }
+
+    @Override
+    public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(
+            String cameraId) {
+        return null;
+    }
+
+    @Override
+    public List<Size> getSupportedYuvAnalysisResolutions(
+            String cameraId) {
+        return null;
+    }
+
+    @Override
+    public SessionProcessorImpl createSessionProcessor() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureResult.Key> getAvailableCaptureResultKeys() {
+        return null;
+    }
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/BeautyAdvancedExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/BeautyAdvancedExtenderImpl.java
new file mode 100644
index 0000000..b553ed6
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/BeautyAdvancedExtenderImpl.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.util.Range;
+import android.util.Size;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Stub advanced extender implementation for beauty.
+ *
+ * <p>This class should be implemented by OEM and deployed to the target devices.
+ *
+ * @since 1.2
+ */
+@SuppressLint("UnknownNullness")
+public class BeautyAdvancedExtenderImpl implements AdvancedExtenderImpl {
+    public BeautyAdvancedExtenderImpl() {
+    }
+
+    @Override
+    public boolean isExtensionAvailable(String cameraId,
+            Map<String, CameraCharacteristics> characteristicsMap) {
+        return false;
+    }
+
+    @Override
+    public void init(String cameraId,
+            Map<String, CameraCharacteristics> characteristicsMap) {
+    }
+
+    @Override
+    public Range<Long> getEstimatedCaptureLatencyRange(
+            String cameraId, Size size, int imageFormat) {
+        return null;
+    }
+
+    @Override
+    public Map<Integer, List<Size>> getSupportedPreviewOutputResolutions(
+            String cameraId) {
+        return null;
+    }
+
+    @Override
+    public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(
+            String cameraId) {
+        return null;
+    }
+
+    @Override
+    public List<Size> getSupportedYuvAnalysisResolutions(
+            String cameraId) {
+        return null;
+    }
+
+    @Override
+    public SessionProcessorImpl createSessionProcessor() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureResult.Key> getAvailableCaptureResultKeys() {
+        return null;
+    }
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/BokehAdvancedExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/BokehAdvancedExtenderImpl.java
new file mode 100644
index 0000000..c1df4f4
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/BokehAdvancedExtenderImpl.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.util.Range;
+import android.util.Size;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Stub advanced extender implementation for bokeh.
+ *
+ * <p>This class should be implemented by OEM and deployed to the target devices.
+ *
+ * @since 1.2
+ */
+@SuppressLint("UnknownNullness")
+public class BokehAdvancedExtenderImpl implements AdvancedExtenderImpl {
+    public BokehAdvancedExtenderImpl() {
+    }
+
+    @Override
+    public boolean isExtensionAvailable(String cameraId,
+            Map<String, CameraCharacteristics> characteristicsMap) {
+        return false;
+    }
+
+    @Override
+    public void init(String cameraId,
+            Map<String, CameraCharacteristics> characteristicsMap) {
+    }
+
+    @Override
+    public Range<Long> getEstimatedCaptureLatencyRange(
+            String cameraId, Size size, int imageFormat) {
+        return null;
+    }
+
+    @Override
+    public Map<Integer, List<Size>> getSupportedPreviewOutputResolutions(
+            String cameraId) {
+        return null;
+    }
+
+    @Override
+    public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(
+            String cameraId) {
+        return null;
+    }
+
+    @Override
+    public List<Size> getSupportedYuvAnalysisResolutions(
+            String cameraId) {
+        return null;
+    }
+
+    @Override
+    public SessionProcessorImpl createSessionProcessor() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureResult.Key> getAvailableCaptureResultKeys() {
+        return null;
+    }
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImpl.java
new file mode 100644
index 0000000..68de01b
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImpl.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+
+import java.util.List;
+
+/**
+ * A config representing a {@link android.hardware.camera2.params.OutputConfiguration} where
+ * Surface will be created by the information in this config.
+ */
+@SuppressLint("UnknownNullness")
+public interface Camera2OutputConfigImpl {
+    /**
+     * Gets thd id of this output config. The id can be used to identify the stream in vendor
+     * implementations.
+     */
+    int getId();
+
+    /**
+     * Gets the surface group id. Vendor can use the surface group id to share memory between
+     * Surfaces.
+     */
+    int getSurfaceGroupId();
+
+    /**
+     * Gets the physical camera id. Returns null if not specified.
+     */
+    String getPhysicalCameraId();
+
+    /**
+     * If non-null, enable surface sharing and add the surface constructed by the return
+     * Camera2OutputConfig.
+     */
+    List<Camera2OutputConfigImpl> getSurfaceSharingOutputConfigs();
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java
new file mode 100644
index 0000000..5c2a4aa
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.util.Size;
+import android.view.Surface;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A builder implementation to help OEM build the {@link Camera2OutputConfigImpl} instance.
+ */
+@SuppressLint("UnknownNullness")
+public class Camera2OutputConfigImplBuilder {
+    static AtomicInteger sLastId = new AtomicInteger(0);
+    private OutputConfigImplImpl mOutputConfig;
+    private int mSurfaceGroupId;
+    private String mPhysicalCameraId;
+    private List<Camera2OutputConfigImpl> mSurfaceSharingConfigs;
+
+    private Camera2OutputConfigImplBuilder(OutputConfigImplImpl outputConfig) {
+        mOutputConfig = outputConfig;
+    }
+
+    private int getNextId() {
+        return sLastId.getAndIncrement();
+    }
+
+    /**
+     * Creates a {@link Camera2OutputConfigImpl} that represents a {@link android.media.ImageReader}
+     * with the given parameters.
+     */
+    public static Camera2OutputConfigImplBuilder newImageReaderConfig(
+            Size size, int imageFormat, int maxImages) {
+        return new Camera2OutputConfigImplBuilder(
+                new ImageReaderOutputConfigImplImpl(size, imageFormat, maxImages));
+    }
+
+    /**
+     * Creates a {@link Camera2OutputConfigImpl} that represents a MultiResolutionImageReader with
+     * the given parameters.
+     */
+    public static Camera2OutputConfigImplBuilder newMultiResolutionImageReaderConfig(
+            int imageFormat, int maxImages) {
+        return new Camera2OutputConfigImplBuilder(
+                new MultiResolutionImageReaderOutputConfigImplImpl(imageFormat, maxImages));
+    }
+
+    /**
+     * Creates a {@link Camera2OutputConfigImpl} that contains the Surface directly.
+     */
+    public static Camera2OutputConfigImplBuilder newSurfaceConfig(Surface surface) {
+        return new Camera2OutputConfigImplBuilder(new SurfaceOutputConfigImplImpl(surface));
+    }
+
+    /**
+     * Adds a {@link Camera2SessionConfigImpl} to be shared with current config.
+     */
+    public Camera2OutputConfigImplBuilder addSurfaceSharingOutputConfig(
+            Camera2OutputConfigImpl camera2OutputConfig) {
+        if (mSurfaceSharingConfigs == null) {
+            mSurfaceSharingConfigs = new ArrayList<>();
+        }
+
+        mSurfaceSharingConfigs.add(camera2OutputConfig);
+        return this;
+    }
+
+    /**
+     * Sets a physical camera id.
+     */
+    public Camera2OutputConfigImplBuilder setPhysicalCameraId(String physicalCameraId) {
+        mPhysicalCameraId = physicalCameraId;
+        return this;
+    }
+
+    /**
+     * Sets surface group id.
+     */
+    public Camera2OutputConfigImplBuilder setSurfaceGroupId(int surfaceGroupId) {
+        mSurfaceGroupId = surfaceGroupId;
+        return this;
+    }
+
+    /**
+     * Build a {@link Camera2OutputConfigImpl} instance.
+     */
+    public Camera2OutputConfigImpl build() {
+        mOutputConfig.setId(getNextId());
+        mOutputConfig.setPhysicalCameraId(mPhysicalCameraId);
+        mOutputConfig.setSurfaceGroup(mSurfaceGroupId);
+        mOutputConfig.setSurfaceSharingConfigs(mSurfaceSharingConfigs);
+        return mOutputConfig;
+    }
+
+    private static class OutputConfigImplImpl implements Camera2OutputConfigImpl {
+        private int mId;
+        private int mSurfaceGroup;
+        private String mPhysicalCameraId;
+        private List<Camera2OutputConfigImpl> mSurfaceSharingConfigs;
+
+        OutputConfigImplImpl() {
+            mId = -1;
+            mSurfaceGroup = 0;
+            mPhysicalCameraId = null;
+            mSurfaceSharingConfigs = null;
+        }
+
+        @Override
+        public int getId() {
+            return mId;
+        }
+
+        @Override
+        public int getSurfaceGroupId() {
+            return mSurfaceGroup;
+        }
+
+        @Override
+        public String getPhysicalCameraId() {
+            return mPhysicalCameraId;
+        }
+
+        @Override
+        public List<Camera2OutputConfigImpl> getSurfaceSharingOutputConfigs() {
+            return mSurfaceSharingConfigs;
+        }
+
+        public void setId(int id) {
+            mId = id;
+        }
+
+        public void setSurfaceGroup(int surfaceGroup) {
+            mSurfaceGroup = surfaceGroup;
+        }
+
+        public void setPhysicalCameraId(String physicalCameraId) {
+            mPhysicalCameraId = physicalCameraId;
+        }
+
+        public void setSurfaceSharingConfigs(
+                List<Camera2OutputConfigImpl> surfaceSharingConfigs) {
+            mSurfaceSharingConfigs = surfaceSharingConfigs;
+        }
+    }
+
+    private static class SurfaceOutputConfigImplImpl extends OutputConfigImplImpl
+            implements SurfaceOutputConfigImpl {
+        private Surface mSurface;
+
+        SurfaceOutputConfigImplImpl(Surface surface) {
+            mSurface = surface;
+        }
+
+        @Override
+        public Surface getSurface() {
+            return mSurface;
+        }
+    }
+
+    private static class ImageReaderOutputConfigImplImpl extends OutputConfigImplImpl
+            implements ImageReaderOutputConfigImpl {
+        private Size mSize;
+        private int mImageFormat;
+        private int mMaxImages;
+
+        ImageReaderOutputConfigImplImpl(Size size, int imageFormat, int maxImages) {
+            mSize = size;
+            mImageFormat = imageFormat;
+            mMaxImages = maxImages;
+        }
+
+        @Override
+        public Size getSize() {
+            return mSize;
+        }
+
+        @Override
+        public int getImageFormat() {
+            return mImageFormat;
+        }
+
+        @Override
+        public int getMaxImages() {
+            return mMaxImages;
+        }
+    }
+
+    private static class MultiResolutionImageReaderOutputConfigImplImpl extends OutputConfigImplImpl
+            implements MultiResolutionImageReaderOutputConfigImpl {
+        private int mImageFormat;
+        private int mMaxImages;
+
+        MultiResolutionImageReaderOutputConfigImplImpl(int imageFormat, int maxImages) {
+            mImageFormat = imageFormat;
+            mMaxImages = maxImages;
+        }
+
+        @Override
+        public int getImageFormat() {
+            return mImageFormat;
+        }
+
+        @Override
+        public int getMaxImages() {
+            return mMaxImages;
+        }
+    }
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImpl.java
new file mode 100644
index 0000000..d121717
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImpl.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.hardware.camera2.CaptureRequest;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A config representing a {@link android.hardware.camera2.params.SessionConfiguration}
+ */
+@SuppressLint("UnknownNullness")
+public interface Camera2SessionConfigImpl {
+    /**
+     * Returns all the {@link Camera2OutputConfigImpl}s that will be used to create
+     * {@link android.hardware.camera2.params.OutputConfiguration}.
+     */
+    List<Camera2OutputConfigImpl> getOutputConfigs();
+
+    /**
+     * Gets all the parameters to create the session parameters with.
+     */
+    Map<CaptureRequest.Key<?>, Object> getSessionParameters();
+
+    /**
+     * Gets the template id used for creating {@link CaptureRequest}s to be passed in
+     * {@link android.hardware.camera2.params.SessionConfiguration#setSessionParameters}.
+     */
+    int getSessionTemplateId();
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImplBuilder.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImplBuilder.java
new file mode 100644
index 0000000..a301166
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImplBuilder.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+
+import android.annotation.SuppressLint;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureRequest;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A builder implementation to help OEM build the {@link Camera2SessionConfigImpl} instance.
+ */
+@SuppressLint("UnknownNullness")
+public class Camera2SessionConfigImplBuilder {
+    private int mSessionTemplateId = CameraDevice.TEMPLATE_PREVIEW;
+    Map<CaptureRequest.Key<?>, Object> mSessionParameters = new HashMap<>();
+    List<Camera2OutputConfigImpl> mCamera2OutputConfigs = new ArrayList<>();
+
+    public Camera2SessionConfigImplBuilder() {
+    }
+
+    /**
+     * Adds a output config.
+     */
+    public Camera2SessionConfigImplBuilder addOutputConfig(
+            Camera2OutputConfigImpl outputConfig) {
+        mCamera2OutputConfigs.add(outputConfig);
+        return this;
+    }
+
+    /**
+     * Sets session parameters.
+     */
+    public <T> Camera2SessionConfigImplBuilder addSessionParameter(
+            CaptureRequest.Key<T> key, T value) {
+        mSessionParameters.put(key, value);
+        return this;
+    }
+
+    /**
+     * Sets the template id for session parameters request.
+     */
+    public Camera2SessionConfigImplBuilder setSessionTemplateId(int templateId) {
+        mSessionTemplateId = templateId;
+        return this;
+    }
+
+    /**
+     * Gets the session template id.
+     */
+    public int getSessionTemplateId() {
+        return mSessionTemplateId;
+    }
+
+    /**
+     * Gets the session parameters.
+     */
+    public Map<CaptureRequest.Key<?>, Object> getSessionParameters() {
+        return mSessionParameters;
+    }
+
+    /**
+     * Gets all the output configs.
+     */
+    public List<Camera2OutputConfigImpl> getCamera2OutputConfigs() {
+        return mCamera2OutputConfigs;
+    }
+
+    /**
+     * Builds a {@link Camera2SessionConfigImpl} instance.
+     */
+    public Camera2SessionConfigImpl build() {
+        return new Camera2SessionConfigImplImpl(this);
+    }
+
+    private static class Camera2SessionConfigImplImpl implements
+            Camera2SessionConfigImpl {
+        int mSessionTemplateId;
+        Map<CaptureRequest.Key<?>, Object> mSessionParameters;
+        List<Camera2OutputConfigImpl> mCamera2OutputConfigs;
+
+        Camera2SessionConfigImplImpl(Camera2SessionConfigImplBuilder builder) {
+            mSessionTemplateId = builder.getSessionTemplateId();
+            mSessionParameters = builder.getSessionParameters();
+            mCamera2OutputConfigs = builder.getCamera2OutputConfigs();
+        }
+
+        @Override
+        public List<Camera2OutputConfigImpl> getOutputConfigs() {
+            return mCamera2OutputConfigs;
+        }
+
+        @Override
+        public Map<CaptureRequest.Key<?>, Object> getSessionParameters() {
+            return mSessionParameters;
+        }
+
+        @Override
+        public int getSessionTemplateId() {
+            return mSessionTemplateId;
+        }
+    }
+}
+
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java
new file mode 100644
index 0000000..1621f3e
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.util.Range;
+import android.util.Size;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Stub advanced extender implementation for hdr.
+ *
+ * <p>This class should be implemented by OEM and deployed to the target devices.
+ *
+ * @since 1.2
+ */
+@SuppressLint("UnknownNullness")
+public class HdrAdvancedExtenderImpl implements AdvancedExtenderImpl {
+    public HdrAdvancedExtenderImpl() {
+    }
+
+    @Override
+    public boolean isExtensionAvailable(String cameraId,
+            Map<String, CameraCharacteristics> characteristicsMap) {
+        return false;
+    }
+
+    @Override
+    public void init(String cameraId,
+            Map<String, CameraCharacteristics> characteristicsMap) {
+    }
+
+    @Override
+    public Range<Long> getEstimatedCaptureLatencyRange(
+            String cameraId, Size size, int imageFormat) {
+        return null;
+    }
+
+    @Override
+    public Map<Integer, List<Size>> getSupportedPreviewOutputResolutions(
+            String cameraId) {
+        return null;
+    }
+
+
+    @Override
+    public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(
+            String cameraId) {
+        return null;
+    }
+
+    @Override
+    public List<Size> getSupportedYuvAnalysisResolutions(
+            String cameraId) {
+        return null;
+    }
+
+    @Override
+    public SessionProcessorImpl createSessionProcessor() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureResult.Key> getAvailableCaptureResultKeys() {
+        return null;
+    }
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/ImageProcessorImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/ImageProcessorImpl.java
new file mode 100644
index 0000000..ce17c4f
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/ImageProcessorImpl.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+
+/**
+ * A interface to receive and process the upcoming next available Image.
+ *
+ * <p>Implemented by OEM.
+ */
+@SuppressLint("UnknownNullness")
+public interface ImageProcessorImpl {
+    /**
+     * The reference count will be decremented when this method returns. If an extension wants
+     * to hold onto the image it should increment the reference count in this method and
+     * decrement it when the image is no longer needed.
+     *
+     * <p>If OEM is not closing(decrement) the image fast enough, the imageReference passed
+     * in this method might contain null image meaning that the Image was closed to prevent
+     * preview from stalling.
+     *
+     * @param outputConfigId the id of {@link Camera2OutputConfigImpl} which identifies
+     *                       corresponding Surface
+     * @param timestampNs    the timestamp in nanoseconds associated with this image
+     * @param imageReference A reference to the {@link android.media.Image} which might contain
+     *                       null if OEM close(decrement) the image too slowly
+     * @param physicalCameraId used to distinguish which physical camera id the image comes from
+     *                         when the output configuration is
+     *                         MultiResolutionImageReaderOutputConfigImpl. It is also set if
+     *                         physicalCameraId is set in other Camera2OutputConfigImpl types.
+     *
+     */
+    void onNextImageAvailable(
+            int outputConfigId,
+            long timestampNs,
+            ImageReferenceImpl imageReference,
+            String physicalCameraId
+            );
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/ImageReaderOutputConfigImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/ImageReaderOutputConfigImpl.java
new file mode 100644
index 0000000..ca4dcaf
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/ImageReaderOutputConfigImpl.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.util.Size;
+
+/**
+ * Surface will be created by constructing a ImageReader.
+ */
+@SuppressLint("UnknownNullness")
+public interface ImageReaderOutputConfigImpl extends Camera2OutputConfigImpl {
+    /**
+     * Returns the size of the surface.
+     */
+    Size getSize();
+
+    /**
+     * Gets the image format of the surface.
+     */
+    int getImageFormat();
+
+    /**
+     * Gets the capacity for TYPE_IMAGEREADER.
+     */
+    int getMaxImages();
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/ImageReferenceImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/ImageReferenceImpl.java
new file mode 100644
index 0000000..95f2c3b
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/ImageReferenceImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.media.Image;
+
+/**
+ * A Image reference container that enables the Image sharing between Camera2/CameraX and OEM
+ * using reference counting. The wrapped Image will be closed once the reference count
+ * reaches 0.
+ *
+ * <p>Implemented by Camera2/CameraX.
+ */
+@SuppressLint("UnknownNullness")
+public interface ImageReferenceImpl {
+
+    /**
+     * Increment the reference count. Returns true if the value was incremented.
+     * (returns false if the reference count has already reached zero.)
+     */
+    boolean increment();
+
+    /**
+     * Decrement the reference count. Image will be closed if reference count reaches 0.
+     * Returns true if the value was decremented (returns false if the reference count has
+     * already reached zero)
+     */
+    boolean decrement();
+
+    /**
+     * Return the Android image. This object MUST not be closed directly.
+     * Returns null when the reference count is zero.
+     */
+    Image get();
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/MultiResolutionImageReaderOutputConfigImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/MultiResolutionImageReaderOutputConfigImpl.java
new file mode 100644
index 0000000..c3ad61b
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/MultiResolutionImageReaderOutputConfigImpl.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+/**
+ * Surface will be created by constructing a MultiResolutionImageReader.
+ */
+public interface MultiResolutionImageReaderOutputConfigImpl extends Camera2OutputConfigImpl {
+    /**
+     * Gets the image format of the surface.
+     */
+    int getImageFormat();
+
+    /**
+     * Gets the max images of the ImageReader.
+     */
+    int getMaxImages();
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java
new file mode 100644
index 0000000..a5e0775
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.util.Range;
+import android.util.Size;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Stub advanced extender implementation for night.
+ *
+ * <p>This class should be implemented by OEM and deployed to the target devices.
+ *
+ * @since 1.2
+ */
+@SuppressLint("UnknownNullness")
+public class NightAdvancedExtenderImpl implements AdvancedExtenderImpl {
+    public NightAdvancedExtenderImpl() {
+    }
+
+    @Override
+    public boolean isExtensionAvailable(String cameraId,
+            Map<String, CameraCharacteristics> characteristicsMap) {
+        return false;
+    }
+
+    @Override
+    public void init(String cameraId,
+            Map<String, CameraCharacteristics> characteristicsMap) {
+    }
+
+    @Override
+    public Range<Long> getEstimatedCaptureLatencyRange(
+            String cameraId, Size size, int imageFormat) {
+        return null;
+    }
+
+    @Override
+    public Map<Integer, List<Size>> getSupportedPreviewOutputResolutions(
+            String cameraId) {
+        return null;
+    }
+
+    @Override
+    public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(
+            String cameraId) {
+        return null;
+    }
+
+    @Override
+    public List<Size> getSupportedYuvAnalysisResolutions(
+            String cameraId) {
+        return null;
+    }
+
+    @Override
+    public SessionProcessorImpl createSessionProcessor() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() {
+        return null;
+    }
+
+    @Override
+    public List<CaptureResult.Key> getAvailableCaptureResultKeys() {
+        return null;
+    }
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java
new file mode 100644
index 0000000..f692029
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.util.Size;
+import android.view.Surface;
+
+/**
+ * For specifying output surface of the extension.
+ */
+@SuppressLint("UnknownNullness")
+public interface OutputSurfaceImpl {
+    /**
+     * Gets the surface.
+     */
+    Surface getSurface();
+
+    /**
+     * Gets the size.
+     */
+    Size getSize();
+
+    /**
+     * Gets the image format.
+     */
+    int getImageFormat();
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/RequestProcessorImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/RequestProcessorImpl.java
new file mode 100644
index 0000000..5185333
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/RequestProcessorImpl.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.hardware.camera2.CaptureFailure;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.TotalCaptureResult;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An Interface to execute Camera2 capture requests.
+ */
+@SuppressLint("UnknownNullness")
+public interface RequestProcessorImpl {
+    /**
+     * Sets a {@link ImageProcessorImpl} to receive {@link ImageReferenceImpl} to process.
+     */
+    void setImageProcessor(int outputconfigId, ImageProcessorImpl imageProcessor);
+
+    /**
+     * Submits a request.
+     * @return the id of the capture sequence or -1 in case the processor encounters a fatal error
+     *         or receives an invalid argument.
+     */
+    int submit(Request request, Callback callback);
+
+    /**
+     * Submits a list of requests.
+     * @return the id of the capture sequence or -1 in case the processor encounters a fatal error
+     *         or receives an invalid argument.
+     */
+    int submit(List<Request> requests, Callback callback);
+
+    /**
+     * Set repeating requests.
+     * @return the id of the capture sequence or -1 in case the processor encounters a fatal error
+     *         or receives an invalid argument.
+     */
+    int setRepeating(Request request, Callback callback);
+
+
+    /**
+     * Abort captures.
+     */
+    void abortCaptures();
+
+    /**
+     * Stop Repeating.
+     */
+    void stopRepeating();
+
+    /**
+     * A interface representing a capture request configuration used for submitting requests in
+     * {@link RequestProcessorImpl}.
+     */
+    interface Request {
+        /**
+         * Gets the target ids of {@link Camera2OutputConfigImpl} which identifies corresponding
+         * Surface to be the targeted for the request.
+         */
+        List<Integer> getTargetOutputConfigIds();
+
+        /**
+         * Gets all the parameters.
+         */
+        Map<CaptureRequest.Key<?>, Object> getParameters();
+
+        /**
+         * Gets the template id.
+         */
+        Integer getTemplateId();
+    }
+
+    /**
+     * Callback to be invoked during the capture.
+     */
+    interface Callback {
+        void onCaptureStarted(
+                Request request,
+                long frameNumber,
+                long timestamp);
+
+        void onCaptureProgressed(
+                Request request,
+                CaptureResult partialResult);
+
+        void onCaptureCompleted(
+                Request request,
+                TotalCaptureResult totalCaptureResult);
+
+        void onCaptureFailed(
+                Request request,
+                CaptureFailure captureFailure);
+
+        void onCaptureBufferLost(
+                Request request,
+                long frameNumber,
+                int outputStreamId);
+
+        void onCaptureSequenceCompleted(int sequenceId, long frameNumber);
+
+        void onCaptureSequenceAborted(int sequenceId);
+
+    }
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java
new file mode 100644
index 0000000..fabfc2b
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.view.Surface;
+
+import java.util.Map;
+
+/**
+ * Interface for creating Camera2 CameraCaptureSessions with extension enabled based on
+ * advanced vendor implementation.
+ *
+ * <p><pre>
+ * The flow of a extension session is shown below:
+ * (1) {@link #initSession}: CameraX prepares streams configuration for creating
+ *     CameraCaptureSession. Output surfaces for Preview, ImageCapture and ImageAnalysis are passed
+ *     in and vendor is responsible for outputting the results to these surfaces.
+ *
+ * (2) {@link #onCaptureSessionStart}: It is called after CameraCaptureSession is configured.
+ *     A {@link RequestProcessorImpl} is passed for vendor to send repeating requests and
+ *     single requests.
+ *
+ * (3) {@link #startRepeating}:  CameraX will call this method to start the repeating request
+ *     after CameraCaptureSession is called. Vendor should start the repeating request by
+ *     {@link RequestProcessorImpl}. Vendor can also update the repeating request if needed later.
+ *
+ * (4) {@link #setParameters(Map)}: The passed parameters will be attached to the repeating request
+ *     and single requests but vendor can choose to apply some of them only.
+ *
+ * (5) {@link #startCapture(CaptureCallback)}: It is called when apps want to
+ *     start a multi-frame image capture.  {@link CaptureCallback} will be called
+ *     to report the status and the output image will be written to the capture output surface
+ *     specified in {@link #initSession}.
+ *
+ * (5) {@link #onCaptureSessionEnd}: It is called right BEFORE CameraCaptureSession.close() is
+ *     called.
+ *
+ * (6) {@link #deInitSession}: called when CameraCaptureSession is closed.
+ * </pre>
+ */
+@SuppressLint("UnknownNullness")
+public interface SessionProcessorImpl {
+    /**
+     * Initializes the session for the extension. This is where the OEMs allocate resources for
+     * preparing a CameraCaptureSession. After initSession() is called, the camera ID,
+     * cameraCharacteristics and context will not change until deInitSession() has been called.
+     *
+     * <p>CameraX specifies the output surface configurations for preview, image capture and image
+     * analysis[optional]. And OEM returns a {@link Camera2SessionConfigImpl} which consists of a
+     * list of {@link Camera2OutputConfigImpl} and session parameters. The
+     * {@link Camera2SessionConfigImpl} will be used to configure the CameraCaptureSession.
+     *
+     * <p>OEM is responsible for outputting correct camera images output to these output surfaces.
+     * OEM can have the following options to enable the output:
+     * <pre>
+     * (1) Add these output surfaces in CameraCaptureSession directly using
+     * {@link Camera2OutputConfigImplBuilder#newSurfaceConfig(Surface)} }. Processing is done in
+     * HAL.
+     *
+     * (2) Use surface sharing with other surface by calling
+     * {@link Camera2OutputConfigImplBuilder#addSurfaceSharingOutputConfig(Camera2OutputConfigImpl)}
+     * to add the output surface to the other {@link Camera2OutputConfigImpl}.
+     *
+     * (3) Process output from other surfaces (RAW, YUV..) and write the result to the output
+     * surface. The output surface won't be contained in the returned
+     * {@link Camera2SessionConfigImpl}.
+     * </pre>
+     *
+     * <p>{@link Camera2OutputConfigImplBuilder} and {@link Camera2SessionConfigImplBuilder}
+     * implementations are provided in the stub for OEM to construct the
+     * {@link Camera2OutputConfigImpl} and {@link Camera2SessionConfigImpl} instances.
+     *
+     * @param previewSurfaceConfig       output surface for preview
+     * @param imageCaptureSurfaceConfig  output surface for image capture.
+     * @param imageAnalysisSurfaceConfig an optional output config for image analysis
+     *                                   (YUV_420_888).
+     * @return a {@link Camera2SessionConfigImpl} consisting of a list of
+     * {@link Camera2OutputConfigImpl} and session parameters which will decide the
+     * {@link android.hardware.camera2.params.SessionConfiguration} for configuring the
+     * CameraCaptureSession. Please note that the OutputConfiguration list may not be part of any
+     * supported or mandatory stream combination BUT OEM must ensure this list will always
+     * produce a valid camera capture session.
+     */
+    Camera2SessionConfigImpl initSession(
+            String cameraId,
+            Map<String, CameraCharacteristics> cameraCharacteristicsMap,
+            Context context,
+            OutputSurfaceImpl previewSurfaceConfig,
+            OutputSurfaceImpl imageCaptureSurfaceConfig,
+            OutputSurfaceImpl imageAnalysisSurfaceConfig);
+
+    /**
+     * Notify to de-initialize the extension. This callback will be invoked after
+     * CameraCaptureSession is closed. After onDeInit() was called, it is expected that the
+     * camera ID, cameraCharacteristics will no longer hold and tear down any resources allocated
+     * for this extension. Aborts all pending captures.
+     */
+    void deInitSession();
+
+    /**
+     * CameraX / Camera2 would call these API’s to pass parameters from the app to the OEM. It’s
+     * expected that the OEM would (eventually) update the repeating request if the keys are
+     * supported. Setting a value to null explicitly un-sets the value.
+     */
+    void setParameters(Map<CaptureRequest.Key<?>, Object> parameters);
+
+    /**
+     * CameraX / Camera2 will call this interface in response to client requests involving
+     * the output preview surface. Typical examples include requests that include AF/AE triggers.
+     * Extensions can disregard any capture request keys that were not advertised in
+     * {@link AdvancedExtenderImpl#getAvailableCaptureRequestKeys}.
+     *
+     * @param triggers Capture request key value map.
+     * @param callback a callback to report the status.
+     * @return the id of the capture sequence.
+     *
+     * @throws IllegalArgumentException If there are no valid settings that can be applied
+     *
+     * @since 1.3
+     */
+    int startTrigger(Map<CaptureRequest.Key<?>, Object> triggers, CaptureCallback callback);
+
+    /**
+     * This will be invoked once after the {@link android.hardware.camera2.CameraCaptureSession}
+     * has been created. {@link RequestProcessorImpl} is passed for OEM to submit single
+     * requests or set repeating requests. This ExtensionRequestProcessor will be valid to use
+     * until onCaptureSessionEnd is called.
+     */
+    void onCaptureSessionStart(RequestProcessorImpl requestProcessor);
+
+    /**
+     * This will be invoked before the {@link android.hardware.camera2.CameraCaptureSession} is
+     * closed. {@link RequestProcessorImpl} passed in onCaptureSessionStart will no longer
+     * accept any requests after onCaptureSessionEnd() returns.
+     */
+    void onCaptureSessionEnd();
+
+    /**
+     * Starts the repeating request after CameraCaptureSession is called. Vendor should start the
+     * repeating request by {@link RequestProcessorImpl}. Vendor can also update the
+     * repeating request when needed later.
+     *
+     * @param callback a callback to report the status.
+     * @return the id of the capture sequence.
+     */
+    int startRepeating(CaptureCallback callback);
+
+    /**
+     * Stop the repeating request. To prevent OEM from not calling stopRepeating, CameraX will
+     * first stop the repeating request of current CameraCaptureSession and call this API to signal
+     * OEM that the repeating request was stopped and going forward calling
+     * {@link RequestProcessorImpl#setRepeating} will simply do nothing.
+     */
+    void stopRepeating();
+
+    /**
+     * Start a multi-frame capture.
+     *
+     * When the capture is completed, {@link CaptureCallback#onCaptureSequenceCompleted}
+     * is called and {@code OnImageAvailableListener#onImageAvailable}
+     * will also be called on the ImageReader that creates the image capture output surface.
+     *
+     * <p>Only one capture can perform at a time. Starting a capture when another capture is running
+     * will cause onCaptureFailed to be called immediately.
+     *
+     * @param callback a callback to report the status.
+     * @return the id of the capture sequence.
+     */
+    int startCapture(CaptureCallback callback);
+
+    /**
+     * Abort all capture tasks.
+     */
+    void abortCapture(int captureSequenceId);
+
+    /**
+     * Callback for notifying the status of {@link #startCapture(CaptureCallback)} and
+     * {@link #startRepeating(CaptureCallback)}.
+     */
+    interface CaptureCallback {
+        /**
+         * This method is called when the camera device has started capturing the initial input
+         * image.
+         *
+         * For a multi-frame capture, the method is called when the
+         * CameraCaptureSession.CaptureCallback onCaptureStarted of first frame is called and its
+         * timestamp is directly forwarded to timestamp parameter of
+         * this method.
+         *
+         * @param captureSequenceId id of the current capture sequence
+         * @param timestamp         the timestamp at start of capture for repeating
+         *                          request or the timestamp at start of capture of the
+         *                          first frame in a multi-frame capture, in nanoseconds.
+         */
+        void onCaptureStarted(int captureSequenceId, long timestamp);
+
+        /**
+         * This method is called when an image (or images in case of multi-frame
+         * capture) is captured and device-specific extension processing is triggered.
+         *
+         * @param captureSequenceId id of the current capture sequence
+         */
+        void onCaptureProcessStarted(int captureSequenceId);
+
+        /**
+         * This method is called instead of
+         * {@link #onCaptureProcessStarted} when the camera device failed
+         * to produce the required input for the device-specific extension. The
+         * cause could be a failed camera capture request, a failed
+         * capture result or dropped camera frame.
+         *
+         * @param captureSequenceId id of the current capture sequence
+         */
+        void onCaptureFailed(int captureSequenceId);
+
+        /**
+         * This method is called independently of the others in the CaptureCallback, when a capture
+         * sequence finishes.
+         *
+         * <p>In total, there will be at least one
+         * {@link #onCaptureProcessStarted}/{@link #onCaptureFailed}
+         * invocation before this callback is triggered. If the capture
+         * sequence is aborted before any requests have begun processing,
+         * {@link #onCaptureSequenceAborted} is invoked instead.</p>
+         *
+         * @param captureSequenceId id of the current capture sequence
+         */
+        void onCaptureSequenceCompleted(int captureSequenceId);
+
+        /**
+         * This method is called when a capture sequence aborts.
+         *
+         * @param captureSequenceId id of the current capture sequence
+         */
+        void onCaptureSequenceAborted(int captureSequenceId);
+
+        /**
+         * Capture result callback that needs to be called when the process capture results are
+         * ready as part of frame post-processing.
+         *
+         * This callback will fire after {@link #onCaptureStarted}, {@link #onCaptureProcessStarted}
+         * and before {@link #onCaptureSequenceCompleted}. The callback is not expected to fire
+         * in case of capture failure  {@link #onCaptureFailed} or capture abort
+         * {@link #onCaptureSequenceAborted}.
+         *
+         * @param timestamp            The timestamp at start of capture. The same timestamp value
+         *                             passed to {@link #onCaptureStarted}.
+         * @param captureSequenceId    the capture id of the request that generated the capture
+         *                             results. This is the return value of either
+         *                             {@link #startRepeating} or {@link #startCapture}.
+         * @param result               Map containing the supported capture results. Do note
+         *                             that if results 'android.jpeg.quality' and
+         *                             'android.jpeg.orientation' are present in the process
+         *                             capture input results, then the values must also be passed
+         *                             as part of this callback. Both Camera2 and CameraX guarantee
+         *                             that those two settings and results are always supported and
+         *                             applied by the corresponding framework.
+         */
+        void onCaptureCompleted(long timestamp, int captureSequenceId,
+                Map<CaptureResult.Key, Object> result);
+    }
+}
diff --git a/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/SurfaceOutputConfigImpl.java b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/SurfaceOutputConfigImpl.java
new file mode 100644
index 0000000..7b8d83c
--- /dev/null
+++ b/camera/camera-testlib-extensions/src/main/java/androidx/camera/extensions/impl/advanced/SurfaceOutputConfigImpl.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.extensions.impl.advanced;
+
+import android.annotation.SuppressLint;
+import android.view.Surface;
+
+/**
+ * Use Surface directly to create the OutputConfiguration.
+ */
+@SuppressLint("UnknownNullness")
+public interface SurfaceOutputConfigImpl extends Camera2OutputConfigImpl {
+    /**
+     * Get the {@link Surface}. It'll return valid surface only when type is TYPE_SURFACE.
+     */
+    Surface getSurface();
+}