diff options
| -rw-r--r-- | core/api/current.txt | 2 | ||||
| -rw-r--r-- | core/java/android/hardware/camera2/params/OutputConfiguration.java | 121 | 
2 files changed, 118 insertions, 5 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index a8b9e331de2a..48a5d41aa802 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -20270,6 +20270,7 @@ package android.hardware.camera2.params {      method public long getDynamicRangeProfile();      method public int getMaxSharedSurfaceCount();      method public int getMirrorMode(); +    method @FlaggedApi("com.android.internal.camera.flags.mirror_mode_shared_surfaces") public int getMirrorMode(@NonNull android.view.Surface);      method public long getStreamUseCase();      method @Nullable public android.view.Surface getSurface();      method public int getSurfaceGroupId(); @@ -20280,6 +20281,7 @@ package android.hardware.camera2.params {      method public void removeSurface(@NonNull android.view.Surface);      method public void setDynamicRangeProfile(long);      method public void setMirrorMode(int); +    method @FlaggedApi("com.android.internal.camera.flags.mirror_mode_shared_surfaces") public void setMirrorMode(@NonNull android.view.Surface, int);      method public void setPhysicalCameraId(@Nullable String);      method public void setReadoutTimestampEnabled(boolean);      method public void setStreamUseCase(long); diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java index ebcc37113d1a..22dbf5bdde37 100644 --- a/core/java/android/hardware/camera2/params/OutputConfiguration.java +++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java @@ -43,6 +43,7 @@ import android.hardware.camera2.utils.SurfaceUtils;  import android.media.ImageReader;  import android.os.Parcel;  import android.os.Parcelable; +import android.util.IntArray;  import android.util.Log;  import android.util.Size;  import android.view.Surface; @@ -596,6 +597,10 @@ public final class OutputConfiguration implements Parcelable {          mStreamUseCase = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;          mTimestampBase = TIMESTAMP_BASE_DEFAULT;          mMirrorMode = MIRROR_MODE_AUTO; +        mMirrorModeForSurfaces = new IntArray(); +        if (Flags.mirrorModeSharedSurfaces()) { +            mMirrorModeForSurfaces.add(mMirrorMode); +        }          mReadoutTimestampEnabled = false;          mIsReadoutSensorTimestampBase = false;          mUsage = 0; @@ -827,6 +832,7 @@ public final class OutputConfiguration implements Parcelable {          mSurfaceGroupId = SURFACE_GROUP_ID_NONE;          mSurfaces = new ArrayList<Surface>(); +        mMirrorModeForSurfaces = new IntArray();          mRotation = ROTATION_0;          mConfiguredSize = surfaceSize;          mConfiguredFormat = StreamConfigurationMap.imageFormatToInternal(ImageFormat.PRIVATE); @@ -971,6 +977,9 @@ public final class OutputConfiguration implements Parcelable {          mDynamicRangeProfile = DynamicRangeProfiles.STANDARD;          mColorSpace = ColorSpaceProfiles.UNSPECIFIED;          mStreamUseCase = CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT; +        mTimestampBase = TIMESTAMP_BASE_DEFAULT; +        mMirrorMode = MIRROR_MODE_AUTO; +        mMirrorModeForSurfaces = new IntArray();          mReadoutTimestampEnabled = false;          mIsReadoutSensorTimestampBase = false;          mUsage = usage; @@ -1239,6 +1248,9 @@ public final class OutputConfiguration implements Parcelable {          }          mSurfaces.add(surface); +        if (Flags.mirrorModeSharedSurfaces()) { +            mMirrorModeForSurfaces.add(mMirrorMode); +        }      }      /** @@ -1266,9 +1278,16 @@ public final class OutputConfiguration implements Parcelable {              throw new IllegalArgumentException(                      "Cannot remove surface associated with this output configuration");          } -        if (!mSurfaces.remove(surface)) { + +        int surfaceIndex = mSurfaces.indexOf(surface); +        if (surfaceIndex == -1) {              throw new IllegalArgumentException("Surface is not part of this output configuration");          } + +        mSurfaces.remove(surfaceIndex); +        if (Flags.mirrorModeSharedSurfaces()) { +            mMirrorModeForSurfaces.remove(surfaceIndex); +        }      }      /** @@ -1405,6 +1424,11 @@ public final class OutputConfiguration implements Parcelable {       * ImageReader, MediaRecorder, or MediaCodec, the mirror mode has no effect. If mirroring is       * needed for such outputs, the application needs to mirror the image buffers itself before       * passing them onward.</p> +     * +     * <p>Starting from Android 16, this function sets the mirror modes for all of the output +     * surfaces contained within this OutputConfiguration. To set the mirror mode for a particular +     * output surface, the application can call {@link #setMirrorMode(Surface, int)}. Prior to +     * Android 16, this function is only applicable if surface sharing is not enabled.</p>       */      public void setMirrorMode(@MirrorMode int mirrorMode) {          // Verify that the value is in range @@ -1413,6 +1437,9 @@ public final class OutputConfiguration implements Parcelable {              throw new IllegalArgumentException("Not a valid mirror mode " + mirrorMode);          }          mMirrorMode = mirrorMode; +        for (int j = 0; j < mMirrorModeForSurfaces.size(); j++) { +            mMirrorModeForSurfaces.set(j, mirrorMode); +        }      }      /** @@ -1428,6 +1455,72 @@ public final class OutputConfiguration implements Parcelable {      }      /** +     * Set the mirroring mode for a surface belonging to this OutputConfiguration +     * +     * <p>This function is identical to {@link #setMirroMode(int)} if {@code surface} is +     * the only surface belonging to this OutputConfiguration.</p> +     * +     * <p>If this OutputConfiguration contains a deferred surface, the application can either +     * call {@link #setMirrorMode(int)}, or call this function after calling {@link #addSurface}. +     * </p> +     * +     * <p>If this OutputConfiguration contains shared surfaces, the application can set +     * different mirroring modes for different surfaces.</p> +     * +     * <p>For efficiency, the mirror effect is applied as a transform flag, so it is only effective +     * in some outputs. It works automatically for SurfaceView and TextureView outputs. For manual +     * use of SurfaceTexture, it is reflected in the value of +     * {@link android.graphics.SurfaceTexture#getTransformMatrix}. For other end points, such as +     * ImageReader, MediaRecorder, or MediaCodec, the mirror mode has no effect. If mirroring is +     * needed for such outputs, the application needs to mirror the image buffers itself before +     * passing them onward.</p> +     * +     * @throws IllegalArgumentException If the {@code surface} doesn't belong to this +     *                                  OutputConfiguration, or the {@code mirrorMode} value is +     *                                  not valid. +     */ +    @FlaggedApi(Flags.FLAG_MIRROR_MODE_SHARED_SURFACES) +    public void setMirrorMode(@NonNull Surface surface, @MirrorMode int mirrorMode) { +        checkNotNull(surface, "Surface must not be null"); +        // Verify that the value is in range +        if (mirrorMode < MIRROR_MODE_AUTO || mirrorMode > MIRROR_MODE_V) { +            throw new IllegalArgumentException("Not a valid mirror mode " + mirrorMode); +        } +        int surfaceIndex = mSurfaces.indexOf(surface); +        if (surfaceIndex == -1) { +            throw new IllegalArgumentException("Surface not part of the OutputConfiguration"); +        } + +        mMirrorModeForSurfaces.set(surfaceIndex, mirrorMode); +    } + +    /** +     * Get the current mirroring mode for an output surface +     * +     * <p>If no {@link #setMirrorMode} is called first, this function returns +     * {@link #MIRROR_MODE_AUTO}.</p> +     * +     * <p>If only {@link #setMirrorMode(int)} is called, the mirroring mode set by that +     * function will be returned here as long as the {@code surface} belongs to this +     * output configuration.</p> +     * +     * @throws IllegalArgumentException If the {@code surface} doesn't belong to this +     *                                  OutputConfiguration. +     * +     * @return The mirroring mode for the specified output surface +     */ +    @FlaggedApi(Flags.FLAG_MIRROR_MODE_SHARED_SURFACES) +    public @MirrorMode int getMirrorMode(@NonNull Surface surface) { +        checkNotNull(surface, "Surface must not be null"); + +        int surfaceIndex = mSurfaces.indexOf(surface); +        if (surfaceIndex == -1) { +            throw new IllegalArgumentException("Surface not part of the OutputConfiguration"); +        } +        return mMirrorModeForSurfaces.get(surfaceIndex); +    } + +    /**       * Use the camera sensor's readout time for the image timestamp.       *       * <p>The start of the camera sensor readout after exposure. For a rolling shutter camera @@ -1491,6 +1584,7 @@ public final class OutputConfiguration implements Parcelable {          this.mStreamUseCase = other.mStreamUseCase;          this.mTimestampBase = other.mTimestampBase;          this.mMirrorMode = other.mMirrorMode; +        this.mMirrorModeForSurfaces = other.mMirrorModeForSurfaces.clone();          this.mReadoutTimestampEnabled = other.mReadoutTimestampEnabled;          this.mUsage = other.mUsage;      } @@ -1520,6 +1614,7 @@ public final class OutputConfiguration implements Parcelable {          int timestampBase = source.readInt();          int mirrorMode = source.readInt(); +        int[] mirrorModeForSurfaces = source.createIntArray();          boolean readoutTimestampEnabled = source.readInt() == 1;          int format = source.readInt();          int dataSpace = source.readInt(); @@ -1531,7 +1626,6 @@ public final class OutputConfiguration implements Parcelable {          mConfiguredSize = new Size(width, height);          mIsDeferredConfig = isDeferred;          mIsShared = isShared; -        mSurfaces = surfaces;          mUsage = 0;          if (mSurfaces.size() > 0) {              mSurfaceType = SURFACE_TYPE_UNKNOWN; @@ -1560,6 +1654,7 @@ public final class OutputConfiguration implements Parcelable {          mStreamUseCase = streamUseCase;          mTimestampBase = timestampBase;          mMirrorMode = mirrorMode; +        mMirrorModeForSurfaces = IntArray.wrap(mirrorModeForSurfaces);          mReadoutTimestampEnabled = readoutTimestampEnabled;      } @@ -1706,6 +1801,7 @@ public final class OutputConfiguration implements Parcelable {          dest.writeLong(mStreamUseCase);          dest.writeInt(mTimestampBase);          dest.writeInt(mMirrorMode); +        dest.writeIntArray(mMirrorModeForSurfaces.toArray());          dest.writeInt(mReadoutTimestampEnabled ? 1 : 0);          dest.writeInt(mConfiguredFormat);          dest.writeInt(mConfiguredDataspace); @@ -1756,6 +1852,16 @@ public final class OutputConfiguration implements Parcelable {                      return false;                  }              } +            if (Flags.mirrorModeSharedSurfaces()) { +                if (mMirrorModeForSurfaces.size() != other.mMirrorModeForSurfaces.size()) { +                    return false; +                } +                for (int j = 0; j < mMirrorModeForSurfaces.size(); j++) { +                    if (mMirrorModeForSurfaces.get(j) != other.mMirrorModeForSurfaces.get(j)) { +                        return false; +                    } +                } +            }              int minLen = Math.min(mSurfaces.size(), other.mSurfaces.size());              for (int i = 0;  i < minLen; i++) {                  if (mSurfaces.get(i) != other.mSurfaces.get(i)) @@ -1799,8 +1905,9 @@ public final class OutputConfiguration implements Parcelable {                      mPhysicalCameraId == null ? 0 : mPhysicalCameraId.hashCode(),                      mIsMultiResolution ? 1 : 0, mSensorPixelModesUsed.hashCode(),                      mDynamicRangeProfile, mColorSpace, mStreamUseCase, -                    mTimestampBase, mMirrorMode, mReadoutTimestampEnabled ? 1 : 0, -                    Long.hashCode(mUsage)); +                    mTimestampBase, mMirrorMode, +                    HashCodeHelpers.hashCode(mMirrorModeForSurfaces.toArray()), +                    mReadoutTimestampEnabled ? 1 : 0, Long.hashCode(mUsage));          }          return HashCodeHelpers.hashCode( @@ -1810,7 +1917,9 @@ public final class OutputConfiguration implements Parcelable {                  mPhysicalCameraId == null ? 0 : mPhysicalCameraId.hashCode(),                  mIsMultiResolution ? 1 : 0, mSensorPixelModesUsed.hashCode(),                  mDynamicRangeProfile, mColorSpace, mStreamUseCase, mTimestampBase, -                mMirrorMode, mReadoutTimestampEnabled ? 1 : 0, Long.hashCode(mUsage)); +                mMirrorMode, HashCodeHelpers.hashCode(mMirrorModeForSurfaces.toArray()), +                mReadoutTimestampEnabled ? 1 : 0, +                Long.hashCode(mUsage));      }      private static final String TAG = "OutputConfiguration"; @@ -1852,6 +1961,8 @@ public final class OutputConfiguration implements Parcelable {      private int mTimestampBase;      // Mirroring mode      private int mMirrorMode; +    // Per-surface mirror modes +    private IntArray mMirrorModeForSurfaces;      // readout timestamp      private boolean mReadoutTimestampEnabled;      // Whether the timestamp base is set to READOUT_SENSOR  |