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