[go: nahoru, domu]

Expose postview and captureProcessProgressed APIs

1. Add ImageCapture#getImageCaptureCapabilities(CameraInfo)
  to query the capabilities of postview and capture process progress.

2. Add setPostviewEnabled and setPostviewResolutionSelector
  to ImageCapture.Builder for app to configure the postview

3. Add onPostviewBitmapAvailable and onCaptureProcessProgressed
  to OnImageSavedCallback and OnImageCapturedCallback.

Relnote: "Added ImageCapture#getImageCaptureCapabilities() APIs
for apps to query the capabilities of the postview and capture
process progress callback. Apps can enable the postview using
the ImageCapture.Builder#setPostviewEnabled(). The postview size
can be selected using
ImageCapture.Builder#setPostviewResolutionSelector(). When invoking
takePicture(), OnPostviewBitmapAvailable and
onCaptureProcessProgressed can be implemented in
OnImageSavedCallback or OnImageCapturedCallback to get the postview
andd process progress notification if supported."

Bug: 308422192
Test: NA
Change-Id: I5cd88131d689950ee0d50fa63f9b3e2d2e7b06cb
diff --git a/camera/camera-core/api/current.txt b/camera/camera-core/api/current.txt
index 92f0b23..4a977b9 100644
--- a/camera/camera-core/api/current.txt
+++ b/camera/camera-core/api/current.txt
@@ -288,11 +288,14 @@
   @RequiresApi(21) public final class ImageCapture extends androidx.camera.core.UseCase {
     method public int getCaptureMode();
     method public int getFlashMode();
+    method public static androidx.camera.core.ImageCaptureCapabilities getImageCaptureCapabilities(androidx.camera.core.CameraInfo);
     method @IntRange(from=1, to=100) public int getJpegQuality();
+    method public androidx.camera.core.resolutionselector.ResolutionSelector? getPostviewResolutionSelector();
     method public androidx.camera.core.ResolutionInfo? getResolutionInfo();
     method public androidx.camera.core.resolutionselector.ResolutionSelector? getResolutionSelector();
     method public androidx.camera.core.ImageCapture.ScreenFlashUiControl? getScreenFlashUiControl();
     method public int getTargetRotation();
+    method public boolean isPostviewEnabled();
     method public void setCropAspectRatio(android.util.Rational);
     method public void setFlashMode(int);
     method public void setScreenFlashUiControl(androidx.camera.core.ImageCapture.ScreenFlashUiControl?);
@@ -321,6 +324,8 @@
     method public androidx.camera.core.ImageCapture.Builder setFlashMode(int);
     method public androidx.camera.core.ImageCapture.Builder setIoExecutor(java.util.concurrent.Executor);
     method public androidx.camera.core.ImageCapture.Builder setJpegQuality(@IntRange(from=1, to=100) int);
+    method public androidx.camera.core.ImageCapture.Builder setPostviewEnabled(boolean);
+    method public androidx.camera.core.ImageCapture.Builder setPostviewResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector);
     method public androidx.camera.core.ImageCapture.Builder setResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector);
     method public androidx.camera.core.ImageCapture.Builder setScreenFlashUiControl(androidx.camera.core.ImageCapture.ScreenFlashUiControl);
     method @Deprecated public androidx.camera.core.ImageCapture.Builder setTargetAspectRatio(int);
@@ -341,15 +346,19 @@
 
   public abstract static class ImageCapture.OnImageCapturedCallback {
     ctor public ImageCapture.OnImageCapturedCallback();
+    method public void onCaptureProcessProgressed(int);
     method public void onCaptureStarted();
     method public void onCaptureSuccess(androidx.camera.core.ImageProxy);
     method public void onError(androidx.camera.core.ImageCaptureException);
+    method public void onPostviewBitmapAvailable(android.graphics.Bitmap);
   }
 
   public static interface ImageCapture.OnImageSavedCallback {
+    method public default void onCaptureProcessProgressed(int);
     method public default void onCaptureStarted();
     method public void onError(androidx.camera.core.ImageCaptureException);
     method public void onImageSaved(androidx.camera.core.ImageCapture.OutputFileResults);
+    method public default void onPostviewBitmapAvailable(android.graphics.Bitmap);
   }
 
   public static final class ImageCapture.OutputFileOptions {
@@ -376,6 +385,11 @@
     method @UiThread public void clearScreenFlashUi();
   }
 
+  public interface ImageCaptureCapabilities {
+    method public boolean isCaptureProcessProgressSupported();
+    method public boolean isPostviewSupported();
+  }
+
   @RequiresApi(21) public class ImageCaptureException extends java.lang.Exception {
     ctor public ImageCaptureException(int, String, Throwable?);
     method public int getImageCaptureError();
diff --git a/camera/camera-core/api/restricted_current.txt b/camera/camera-core/api/restricted_current.txt
index 92f0b23..4a977b9 100644
--- a/camera/camera-core/api/restricted_current.txt
+++ b/camera/camera-core/api/restricted_current.txt
@@ -288,11 +288,14 @@
   @RequiresApi(21) public final class ImageCapture extends androidx.camera.core.UseCase {
     method public int getCaptureMode();
     method public int getFlashMode();
+    method public static androidx.camera.core.ImageCaptureCapabilities getImageCaptureCapabilities(androidx.camera.core.CameraInfo);
     method @IntRange(from=1, to=100) public int getJpegQuality();
+    method public androidx.camera.core.resolutionselector.ResolutionSelector? getPostviewResolutionSelector();
     method public androidx.camera.core.ResolutionInfo? getResolutionInfo();
     method public androidx.camera.core.resolutionselector.ResolutionSelector? getResolutionSelector();
     method public androidx.camera.core.ImageCapture.ScreenFlashUiControl? getScreenFlashUiControl();
     method public int getTargetRotation();
+    method public boolean isPostviewEnabled();
     method public void setCropAspectRatio(android.util.Rational);
     method public void setFlashMode(int);
     method public void setScreenFlashUiControl(androidx.camera.core.ImageCapture.ScreenFlashUiControl?);
@@ -321,6 +324,8 @@
     method public androidx.camera.core.ImageCapture.Builder setFlashMode(int);
     method public androidx.camera.core.ImageCapture.Builder setIoExecutor(java.util.concurrent.Executor);
     method public androidx.camera.core.ImageCapture.Builder setJpegQuality(@IntRange(from=1, to=100) int);
+    method public androidx.camera.core.ImageCapture.Builder setPostviewEnabled(boolean);
+    method public androidx.camera.core.ImageCapture.Builder setPostviewResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector);
     method public androidx.camera.core.ImageCapture.Builder setResolutionSelector(androidx.camera.core.resolutionselector.ResolutionSelector);
     method public androidx.camera.core.ImageCapture.Builder setScreenFlashUiControl(androidx.camera.core.ImageCapture.ScreenFlashUiControl);
     method @Deprecated public androidx.camera.core.ImageCapture.Builder setTargetAspectRatio(int);
@@ -341,15 +346,19 @@
 
   public abstract static class ImageCapture.OnImageCapturedCallback {
     ctor public ImageCapture.OnImageCapturedCallback();
+    method public void onCaptureProcessProgressed(int);
     method public void onCaptureStarted();
     method public void onCaptureSuccess(androidx.camera.core.ImageProxy);
     method public void onError(androidx.camera.core.ImageCaptureException);
+    method public void onPostviewBitmapAvailable(android.graphics.Bitmap);
   }
 
   public static interface ImageCapture.OnImageSavedCallback {
+    method public default void onCaptureProcessProgressed(int);
     method public default void onCaptureStarted();
     method public void onError(androidx.camera.core.ImageCaptureException);
     method public void onImageSaved(androidx.camera.core.ImageCapture.OutputFileResults);
+    method public default void onPostviewBitmapAvailable(android.graphics.Bitmap);
   }
 
   public static final class ImageCapture.OutputFileOptions {
@@ -376,6 +385,11 @@
     method @UiThread public void clearScreenFlashUi();
   }
 
+  public interface ImageCaptureCapabilities {
+    method public boolean isCaptureProcessProgressSupported();
+    method public boolean isPostviewSupported();
+  }
+
   @RequiresApi(21) public class ImageCaptureException extends java.lang.Exception {
     ctor public ImageCaptureException(int, String, Throwable?);
     method public int getImageCaptureError();
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
index 93fbb12..58a3170 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
@@ -884,7 +884,6 @@
      *
      * @return {@link ImageCaptureCapabilities}
      */
-    @RestrictTo(Scope.LIBRARY_GROUP)
     @NonNull
     public static ImageCaptureCapabilities getImageCaptureCapabilities(
             @NonNull CameraInfo cameraInfo) {
@@ -1427,6 +1426,26 @@
     }
 
     /**
+     * Returns if postview is enabled or not.
+     *
+     * @see Builder#setPostviewEnabled(boolean)
+     */
+    public boolean isPostviewEnabled() {
+        return getCurrentConfig().retrieveOption(OPTION_POSTVIEW_ENABLED, false);
+    }
+
+    /**
+     * Returns the {@link ResolutionSelector} used to select the postview size.
+     *
+     * @see Builder#setPostviewResolutionSelector(ResolutionSelector)
+     */
+    @Nullable
+    public ResolutionSelector getPostviewResolutionSelector() {
+        return getCurrentConfig().retrieveOption(OPTION_POSTVIEW_RESOLUTION_SELECTOR,
+                null);
+    }
+
+    /**
      * Describes the error that occurred during an image capture operation (such as {@link
      * ImageCapture#takePicture(Executor, OnImageCapturedCallback)}).
      *
@@ -1510,44 +1529,37 @@
          *
          * <p>To know in advanced if this callback will be invoked or not, check the
          * capabilities by {@link #getImageCaptureCapabilities(CameraInfo)} and
-         * {@link ImageCaptureCapabilities#isCaptureProcessProgressSupported()}.
+         * {@link ImageCaptureCapabilities#isCaptureProcessProgressSupported()}. If supported,
+         * this callback will be called multiple times with monotonically increasing
+         * values. At the minimum the callback will be called once with value 100 to
+         * indicate the processing is finished. This callback will always be called before
+         * {@link #onImageSaved(OutputFileResults)}.
          *
          * @param progress the progress ranging from 0 to 100.
          */
-        @RestrictTo(Scope.LIBRARY_GROUP)
         default void onCaptureProcessProgressed(int progress) {
         }
 
         /**
-         * Callback to notify that the postview image is available. The postview is intended to be
+         * Callback to notify that the postview bitmap is available. The postview is intended to be
          * shown on UI before the long-processing capture is completed in order to provide a
-         * better UX. The image format is {@link ImageFormat#JPEG}.
+         * better UX.
          *
          * <p>The postview is only available when the
          * {@link ImageCaptureCapabilities#isPostviewSupported()} returns true for the specified
          * {@link CameraInfo} and applications must explicitly enable the postview using the
-         * {@link Builder#setPostviewEnabled(boolean)}. Please note that if something goes wrong
-         * when processing the postview, this callback method won't be invoked.
+         * {@link Builder#setPostviewEnabled(boolean)}. This callback will be called before
+         * {@link #onImageSaved(OutputFileResults)}. But if something goes wrong when processing
+         * the postview, this callback method could be skipped.
          *
-         * <p>Please close the {@link ImageProxy} once you no longer need it. The default
-         * implementation of this method will close it in case apps don't implement the method.
-         *
-         * <p>The image is provided as captured by the underlying {@link ImageReader} without
-         * rotation applied. The value in {@code image.getImageInfo().getRotationDegrees()}
-         * describes the magnitude of clockwise rotation, which if applied to the image will make
-         * it match the currently configured target rotation.
-         *
-         * <p>For example, if the current target rotation is set to the display rotation,
-         * rotationDegrees is the rotation to apply to the image to match the display orientation.
-         * A rotation of 90 degrees would mean rotating the image 90 degrees clockwise produces an
-         * image that will match the display orientation.
+         * <p>The bitmap is rotated according to the target rotation set to the {@link ImageCapture}
+         * to make it upright. If target rotation is not set, the display rotation is used.
          *
          * <p>See also {@link ImageCapture.Builder#setTargetRotation(int)} and
          * {@link #setTargetRotation(int)}.
          *
-         * @param image the postview {@link ImageProxy}
+         * @param bitmap the postview bitmap.
          */
-        @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
         default void onPostviewBitmapAvailable(@NonNull Bitmap bitmap) {
         }
     }
@@ -1616,44 +1628,38 @@
          *
          * <p>To know in advanced if this callback will be invoked or not, check the
          * capabilities by {@link #getImageCaptureCapabilities(CameraInfo)} and
-         * {@link ImageCaptureCapabilities#isCaptureProcessProgressSupported()}.
+         * {@link ImageCaptureCapabilities#isCaptureProcessProgressSupported()}. If supported,
+         * this callback will be called multiple times with monotonically increasing
+         * values. At the minimum the callback will be called once with value 100 to
+         * indicate the processing is finished. This callback will always be called before
+         * {@link #onCaptureSuccess(ImageProxy)}.
          *
          * @param progress the progress ranging from 0 to 100.
          */
-        @RestrictTo(Scope.LIBRARY_GROUP)
         public void onCaptureProcessProgressed(int progress) {
         }
 
         /**
-         * Callback to notify that the postview image is available. The postview is intended to be
+         * Callback to notify that the postview bitmap is available. The postview is intended to be
          * shown on UI before the long-processing capture is completed in order to provide a
-         * better UX. The image format is {@link ImageFormat#JPEG}.
+         * better UX.
          *
          * <p>The postview is only available when the
          * {@link ImageCaptureCapabilities#isPostviewSupported()} returns true for the specified
          * {@link CameraInfo} and applications must explicitly enable the postview using the
-         * {@link Builder#setPostviewEnabled(boolean)}. Please note that if something goes wrong
-         * when processing the postview, this callback method won't be invoked.
+         * {@link Builder#setPostviewEnabled(boolean)}. This callback will be called before
+         * {@link #onCaptureSuccess(ImageProxy)}. But if something goes wrong when processing the
+         * postview, this callback method could be skipped.
          *
-         * <p>Please close the {@link ImageProxy} once you no longer need it. The default
-         * implementation of this method will close it in case apps don't implement the method.
-         *
-         * <p>The image is provided as captured by the underlying {@link ImageReader} without
-         * rotation applied. The value in {@code image.getImageInfo().getRotationDegrees()}
-         * describes the magnitude of clockwise rotation, which if applied to the image will make
-         * it match the currently configured target rotation.
-         *
-         * <p>For example, if the current target rotation is set to the display rotation,
-         * rotationDegrees is the rotation to apply to the image to match the display orientation.
-         * A rotation of 90 degrees would mean rotating the image 90 degrees clockwise produces an
-         * image that will match the display orientation.
+         * <p>The bitmap is rotated according to the target rotation set to the {@link ImageCapture}
+         * to make it upright. If target rotation is not set, the display rotation is used.
          *
          * <p>See also {@link ImageCapture.Builder#setTargetRotation(int)} and
          * {@link #setTargetRotation(int)}.
          *
-         * @param image the postview {@link ImageProxy}
+         * @param bitmap the postview bitmap.
+
          */
-        @RestrictTo(Scope.LIBRARY_GROUP)
         public void onPostviewBitmapAvailable(@NonNull Bitmap bitmap) {
         }
     }
@@ -2538,22 +2544,27 @@
         }
 
         /**
-         * Enables the postview which allows you to get the unprocessed image before the processing
-         * is done during the <code>takePicture</code> call.
+         * Enables postview image generation. A postview image is a low-quality image
+         * that's produced earlier during image capture than the final high-quality image,
+         * and can be used as a thumbnail or placeholder until the final image is ready.
          *
-         * <p>By default the largest available postview size that are smaller or equal to the
+         * <p>When the postview is available,
+         * {@link OnImageCapturedCallback#onPostviewBitmapAvailable(Bitmap)} or
+         * {@link OnImageSavedCallback#onPostviewBitmapAvailable(Bitmap)} will be called.
+         *
+         * <p>By default the largest available postview size that is smaller or equal to the
          * ImagaeCapture size will be used to configure the postview. The {@link ResolutionSelector}
          * can also be used to select a specific size via
          * {@link #setPostviewResolutionSelector(ResolutionSelector)}.
          *
-         * <p>It is recommended to query the capture capability via
-         * {@link #getImageCaptureCapabilities(CameraInfo)} before enabling this feature to avoid
-         * unnecessary initializations.
+         * <p>You can query the postview capability by invoking
+         * {@link #getImageCaptureCapabilities(CameraInfo)}. If
+         * {@link ImageCaptureCapabilities#isPostviewSupported()} returns false and you still
+         * enable the postview, the postview image won't be generated.
          *
          * @param postviewEnabled whether postview is enabled or not
          * @return the current Builder.
          */
-        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
         public Builder setPostviewEnabled(boolean postviewEnabled) {
             getMutableConfig().insertOption(OPTION_POSTVIEW_ENABLED,
@@ -2563,15 +2574,17 @@
 
         /**
          * Set the {@link ResolutionSelector} to select the postview size from the available
-         * postview sizes. Please note the selected size will be smaller or equal to the
-         * ImageCapture size.
+         * postview sizes. These available postview sizes are smaller or equal to the
+         * ImageCapture size. You can implement the
+         * {@link androidx.camera.core.resolutionselector.ResolutionFilter} and set it to the
+         * {@link ResolutionSelector} to get the list of available sizes and determine which size
+         * to use.
          *
          * <p>If no sizes can be selected using the given {@link ResolutionSelector}, it will throw
          * an {@link IllegalArgumentException} when {@code bindToLifecycle()} is invoked.
          *
          * @return the current Builder.
          */
-        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
         public Builder setPostviewResolutionSelector(
                 @NonNull ResolutionSelector resolutionSelector) {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureCapabilities.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureCapabilities.java
index 1c81d44..9c05020 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureCapabilities.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureCapabilities.java
@@ -16,24 +16,29 @@
 
 package androidx.camera.core;
 
-import androidx.annotation.RestrictTo;
-
 /**
  * ImageCaptureCapabilities is used to query {@link ImageCapture} use case capabilities on the
  * device.
  */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 public interface ImageCaptureCapabilities {
     /**
-     * Returns if the takePicture() call in {@link ImageCapture} is capable of outputting post
-     * view images ahead of final images. If supported, apps can enable the postview using
+     * Returns if the takePicture() call in {@link ImageCapture} is capable of outputting
+     * postview images.
+     *
+     * <p>A postview image is a low-quality image that's produced earlier during image capture
+     * than the final high-quality image, and can be used as a thumbnail or placeholder until the
+     * final image is ready.
+     *
+     * If supported, apps can enable the postview using
      * {@link ImageCapture.Builder#setPostviewEnabled(boolean)}.
      */
     boolean isPostviewSupported();
 
     /**
      * Returns if the takePicture() call in {@link ImageCapture} is capable of notifying the
-     * onCaptureProcessProgressed callback to the apps.
+     * {@link ImageCapture.OnImageSavedCallback#onCaptureProcessProgressed(int)} or
+     * {@link ImageCapture.OnImageCapturedCallback#onCaptureProcessProgressed(int)} callback to
+     * the apps.
      */
     boolean isCaptureProcessProgressSupported();
 }