Fix throw exception when using HardwareBuffer.BLOB format to create

ImageReader/ImageWriter object.

- Internally, we should deal with HardwareBuffer.BLOB format according
  to surface's dataSpace. Directly passing BLOB format to
  getEstimatedNativeAllocBytes function will throw exception because
  BLOB format is not handled inside. Instead, use their corresponding
  imageFormat to avoid such failure in this case.

Bug: 244268240
Test: atest android.hardware.camera2.cts.ImageReaderTest, atest
android.hardware.camera2.cts.ImageWriterTest, atest
android.hardware.cts.DataSpaceTest

Change-Id: I3f18b9d3550f88be82cde75372637a3ae528b5ec
This commit is contained in:
Sally Qi
2022-08-30 22:46:57 -07:00
parent 6b86e2cbbf
commit 49afba7d80
4 changed files with 65 additions and 37 deletions

View File

@@ -16892,6 +16892,7 @@ package android.hardware {
field public static final int DATASPACE_DEPTH = 4096; // 0x1000 field public static final int DATASPACE_DEPTH = 4096; // 0x1000
field public static final int DATASPACE_DISPLAY_P3 = 143261696; // 0x88a0000 field public static final int DATASPACE_DISPLAY_P3 = 143261696; // 0x88a0000
field public static final int DATASPACE_DYNAMIC_DEPTH = 4098; // 0x1002 field public static final int DATASPACE_DYNAMIC_DEPTH = 4098; // 0x1002
field public static final int DATASPACE_HEIF = 4100; // 0x1004
field public static final int DATASPACE_JFIF = 146931712; // 0x8c20000 field public static final int DATASPACE_JFIF = 146931712; // 0x8c20000
field public static final int DATASPACE_SCRGB = 411107328; // 0x18810000 field public static final int DATASPACE_SCRGB = 411107328; // 0x18810000
field public static final int DATASPACE_SCRGB_LINEAR = 406913024; // 0x18410000 field public static final int DATASPACE_SCRGB_LINEAR = 406913024; // 0x18410000

View File

@@ -407,6 +407,22 @@ public final class DataSpace {
*/ */
public static final int DATASPACE_DYNAMIC_DEPTH = 4098; public static final int DATASPACE_DYNAMIC_DEPTH = 4098;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = true, value = {
DATASPACE_HEIF,
})
public @interface DataSpaceFileFormat {};
/**
* High Efficiency Image File Format (HEIF).
*
* <p>This value is valid with {@link android.hardware.HardwareBuffer#BLOB HardwareBuffer.BLOB}
* format. The combination is an HEIC image encoded by HEIC or HEVC encoder according to
* ISO/IEC 23008-12.</p>
*/
public static final int DATASPACE_HEIF = 4100;
/** @hide */ /** @hide */
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef(flag = true, value = { @IntDef(flag = true, value = {

View File

@@ -342,9 +342,14 @@ public class ImageReader implements AutoCloseable {
// Only include memory for 1 buffer, since actually accounting for the memory used is // Only include memory for 1 buffer, since actually accounting for the memory used is
// complex, and 1 buffer is enough for the VM to treat the ImageReader as being of some // complex, and 1 buffer is enough for the VM to treat the ImageReader as being of some
// size. // size.
if (hardwareBufferFormat == HardwareBuffer.BLOB) {
mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(
width, height, imageFormat, /*buffer count*/ 1);
} else {
mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes( mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(
width, height, useLegacyImageFormat ? imageFormat : hardwareBufferFormat, width, height, useLegacyImageFormat ? imageFormat : hardwareBufferFormat,
/*buffer count*/ 1); /*buffer count*/ 1);
}
VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes); VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes);
} }
@@ -370,7 +375,6 @@ public class ImageReader implements AutoCloseable {
MultiResolutionImageReader parent, int hardwareBufferFormat, int dataSpace) { MultiResolutionImageReader parent, int hardwareBufferFormat, int dataSpace) {
mWidth = width; mWidth = width;
mHeight = height; mHeight = height;
mFormat = ImageFormat.UNKNOWN; // set default image format value as UNKNOWN
mUsage = usage; mUsage = usage;
mMaxImages = maxImages; mMaxImages = maxImages;
mParent = parent; mParent = parent;
@@ -378,6 +382,7 @@ public class ImageReader implements AutoCloseable {
mDataSpace = dataSpace; mDataSpace = dataSpace;
mUseLegacyImageFormat = false; mUseLegacyImageFormat = false;
mNumPlanes = ImageUtils.getNumPlanesForHardwareBufferFormat(mHardwareBufferFormat); mNumPlanes = ImageUtils.getNumPlanesForHardwareBufferFormat(mHardwareBufferFormat);
mFormat = PublicFormatUtils.getPublicFormat(hardwareBufferFormat, dataSpace);
initializeImageReader(width, height, mFormat, maxImages, usage, hardwareBufferFormat, initializeImageReader(width, height, mFormat, maxImages, usage, hardwareBufferFormat,
dataSpace, mUseLegacyImageFormat); dataSpace, mUseLegacyImageFormat);

View File

@@ -29,7 +29,6 @@ import android.hardware.DataSpace.NamedDataSpace;
import android.hardware.HardwareBuffer; import android.hardware.HardwareBuffer;
import android.hardware.HardwareBuffer.Usage; import android.hardware.HardwareBuffer.Usage;
import android.hardware.SyncFence; import android.hardware.SyncFence;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.utils.SurfaceUtils; import android.hardware.camera2.utils.SurfaceUtils;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
@@ -266,31 +265,11 @@ public class ImageWriter implements AutoCloseable {
// nativeInit internally overrides UNKNOWN format. So does surface format query after // nativeInit internally overrides UNKNOWN format. So does surface format query after
// nativeInit and before getEstimatedNativeAllocBytes(). // nativeInit and before getEstimatedNativeAllocBytes().
imageFormat = SurfaceUtils.getSurfaceFormat(surface); imageFormat = SurfaceUtils.getSurfaceFormat(surface);
mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat); mDataSpace = dataSpace = PublicFormatUtils.getHalDataspace(dataSpace);
mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat); mHardwareBufferFormat =
hardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
} }
// Several public formats use the same native HAL_PIXEL_FORMAT_BLOB. The native
// allocation estimation sequence depends on the public formats values. To avoid
// possible errors, convert where necessary.
if (imageFormat == StreamConfigurationMap.HAL_PIXEL_FORMAT_BLOB) {
int surfaceDataspace = SurfaceUtils.getSurfaceDataspace(surface);
switch (surfaceDataspace) {
case StreamConfigurationMap.HAL_DATASPACE_DEPTH:
imageFormat = ImageFormat.DEPTH_POINT_CLOUD;
break;
case StreamConfigurationMap.HAL_DATASPACE_DYNAMIC_DEPTH:
imageFormat = ImageFormat.DEPTH_JPEG;
break;
case StreamConfigurationMap.HAL_DATASPACE_HEIF:
imageFormat = ImageFormat.HEIC;
break;
default:
imageFormat = ImageFormat.JPEG;
}
mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
}
// Estimate the native buffer allocation size and register it so it gets accounted for // Estimate the native buffer allocation size and register it so it gets accounted for
// during GC. Note that this doesn't include the buffers required by the buffer queue // during GC. Note that this doesn't include the buffers required by the buffer queue
// itself and the buffers requested by the producer. // itself and the buffers requested by the producer.
@@ -301,17 +280,44 @@ public class ImageWriter implements AutoCloseable {
mWidth = width == -1 ? surfSize.getWidth() : width; mWidth = width == -1 ? surfSize.getWidth() : width;
mHeight = height == -1 ? surfSize.getHeight() : height; mHeight = height == -1 ? surfSize.getHeight() : height;
if (hardwareBufferFormat == HardwareBuffer.BLOB) {
// TODO(b/246344817): remove mWriterFormat and mDataSpace re-set here after fixing.
mWriterFormat = imageFormat = getImageFormatByBLOB(dataSpace);
mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(mWidth, mHeight,
imageFormat, /*buffer count*/ 1);
} else {
mEstimatedNativeAllocBytes = mEstimatedNativeAllocBytes =
ImageUtils.getEstimatedNativeAllocBytes(mWidth, mHeight, ImageUtils.getEstimatedNativeAllocBytes(mWidth, mHeight,
useLegacyImageFormat ? imageFormat : hardwareBufferFormat, /*buffer count*/ 1); useLegacyImageFormat ? imageFormat : hardwareBufferFormat, /*buffer count*/ 1);
}
VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes); VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes);
} }
// Several public formats use the same native HAL_PIXEL_FORMAT_BLOB. The native
// allocation estimation sequence depends on the public formats values. To avoid
// possible errors, convert where necessary.
private int getImageFormatByBLOB(int dataspace) {
switch (dataspace) {
case DataSpace.DATASPACE_DEPTH:
return ImageFormat.DEPTH_POINT_CLOUD;
case DataSpace.DATASPACE_DYNAMIC_DEPTH:
return ImageFormat.DEPTH_JPEG;
case DataSpace.DATASPACE_HEIF:
return ImageFormat.HEIC;
default:
return ImageFormat.JPEG;
}
}
private ImageWriter(Surface surface, int maxImages, boolean useSurfaceImageFormatInfo, private ImageWriter(Surface surface, int maxImages, boolean useSurfaceImageFormatInfo,
int imageFormat, int width, int height) { int imageFormat, int width, int height) {
mMaxImages = maxImages; mMaxImages = maxImages;
if (!useSurfaceImageFormatInfo) {
mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat); mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat); mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
}
initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, true, initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, true,
imageFormat, mHardwareBufferFormat, mDataSpace, width, height, mUsage); imageFormat, mHardwareBufferFormat, mDataSpace, width, height, mUsage);
@@ -321,8 +327,10 @@ public class ImageWriter implements AutoCloseable {
int imageFormat, int width, int height, long usage) { int imageFormat, int width, int height, long usage) {
mMaxImages = maxImages; mMaxImages = maxImages;
mUsage = usage; mUsage = usage;
if (!useSurfaceImageFormatInfo) {
mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat); mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat); mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
}
initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, true, initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, true,
imageFormat, mHardwareBufferFormat, mDataSpace, width, height, usage); imageFormat, mHardwareBufferFormat, mDataSpace, width, height, usage);
@@ -337,8 +345,6 @@ public class ImageWriter implements AutoCloseable {
// and retrieve corresponding hardwareBufferFormat and dataSpace here. // and retrieve corresponding hardwareBufferFormat and dataSpace here.
if (useSurfaceImageFormatInfo) { if (useSurfaceImageFormatInfo) {
imageFormat = ImageFormat.UNKNOWN; imageFormat = ImageFormat.UNKNOWN;
mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
} else { } else {
imageFormat = PublicFormatUtils.getPublicFormat(hardwareBufferFormat, dataSpace); imageFormat = PublicFormatUtils.getPublicFormat(hardwareBufferFormat, dataSpace);
mHardwareBufferFormat = hardwareBufferFormat; mHardwareBufferFormat = hardwareBufferFormat;