Merge "Fix ImageReader#newInstace with usage"

This commit is contained in:
John Reck
2019-01-28 20:17:25 +00:00
committed by Android (Google) Code Review
5 changed files with 70 additions and 46 deletions

View File

@@ -16171,6 +16171,7 @@ package android.hardware {
method public long getUsage();
method public int getWidth();
method public boolean isClosed();
method public static boolean isSupported(int, int, int, int, long);
method public void writeToParcel(android.os.Parcel, int);
field public static final int BLOB = 33; // 0x21
field public static final android.os.Parcelable.Creator<android.hardware.HardwareBuffer> CREATOR;

View File

@@ -181,6 +181,38 @@ public final class HardwareBuffer implements Parcelable, AutoCloseable {
return new HardwareBuffer(nativeObject);
}
/**
* Queries whether the given buffer description is supported by the system. If this returns
* true, then the allocation may succeed until resource exhaustion occurs. If this returns
* false then this combination will never succeed.
*
* @param width The width in pixels of the buffer
* @param height The height in pixels of the buffer
* @param format The @Format of each pixel
* @param layers The number of layers in the buffer
* @param usage The @Usage flags describing how the buffer will be used
* @return True if the combination is supported, false otherwise.
*/
public static boolean isSupported(int width, int height, @Format int format, int layers,
@Usage long usage) {
if (!HardwareBuffer.isSupportedFormat(format)) {
throw new IllegalArgumentException("Invalid pixel format " + format);
}
if (width <= 0) {
throw new IllegalArgumentException("Invalid width " + width);
}
if (height <= 0) {
throw new IllegalArgumentException("Invalid height " + height);
}
if (layers <= 0) {
throw new IllegalArgumentException("Invalid layer count " + layers);
}
if (format == BLOB && height != 1) {
throw new IllegalArgumentException("Height must be 1 when using the BLOB format");
}
return nIsSupported(width, height, format, layers, usage);
}
/**
* Private use only. See {@link #create(int, int, int, int, long)}. May also be
* called from JNI using an already allocated native <code>HardwareBuffer</code>.
@@ -386,4 +418,6 @@ public final class HardwareBuffer implements Parcelable, AutoCloseable {
private static native int nGetLayers(long nativeObject);
@FastNative
private static native long nGetUsage(long nativeObject);
private static native boolean nIsSupported(int width, int height, int format, int layers,
long usage);
}

View File

@@ -104,6 +104,21 @@ static jlong android_hardware_HardwareBuffer_getNativeFinalizer(JNIEnv* env, job
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyWrapper));
}
static jboolean android_hardware_HardwareBuffer_isSupported(JNIEnv* env, jobject clazz,
jint width, jint height, jint format, jint layers, jlong usage) {
AHardwareBuffer_Desc desc;
desc.width = width;
desc.height = height;
desc.format = format;
desc.layers = layers;
desc.usage = usage;
desc.stride = 0;
desc.rfu0 = 0;
desc.rfu1 = 0;
return AHardwareBuffer_isSupported(&desc);
}
//----------------------------------------------------------------------------
// Accessors
// ----------------------------------------------------------------------------
@@ -234,6 +249,8 @@ static const JNINativeMethod gMethods[] = {
(void*) android_hardware_HardwareBuffer_write },
{ "nReadHardwareBufferFromParcel", "(Landroid/os/Parcel;)J",
(void*) android_hardware_HardwareBuffer_read },
{ "nIsSupported", "(IIIIJ)Z",
(void*) android_hardware_HardwareBuffer_isSupported },
// --------------- @FastNative ----------------------
{ "nGetWidth", "(J)I", (void*) android_hardware_HardwareBuffer_getWidth },

View File

@@ -17,12 +17,10 @@
package android.media;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.hardware.HardwareBuffer;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Surface;
import dalvik.system.VMRuntime;
@@ -73,12 +71,6 @@ public class ImageReader implements AutoCloseable {
*/
private static final int ACQUIRE_MAX_IMAGES = 2;
/**
* Invalid consumer buffer usage flag. This usage flag will be ignored
* by the {@code ImageReader} instance is constructed with this value.
*/
private static final long BUFFER_USAGE_UNKNOWN = 0;
/**
* <p>
* Create a new reader for images of the desired size and format.
@@ -129,7 +121,10 @@ public class ImageReader implements AutoCloseable {
* @see Image
*/
public static ImageReader newInstance(int width, int height, int format, int maxImages) {
return new ImageReader(width, height, format, maxImages, BUFFER_USAGE_UNKNOWN);
// If the format is private don't default to USAGE_CPU_READ_OFTEN since it may not
// work, and is inscrutable anyway
return new ImageReader(width, height, format, maxImages,
format == ImageFormat.PRIVATE ? 0 : HardwareBuffer.USAGE_CPU_READ_OFTEN);
}
/**
@@ -207,18 +202,23 @@ public class ImageReader implements AutoCloseable {
* obtained by the user, one of them has to be released before a new Image will
* become available for access through {@link #acquireLatestImage()} or
* {@link #acquireNextImage()}. Must be greater than 0.
* @param usage The intended usage of the images produced by this ImageReader. It needs
* to be one of the Usage defined by {@link HardwareBuffer}, or an
* {@link IllegalArgumentException} will be thrown.
* @param usage The intended usage of the images produced by this ImageReader. See the usages
* on {@link HardwareBuffer} for a list of valid usage bits. See also
* {@link HardwareBuffer#isSupported(int, int, int, int, long)} for checking
* if a combination is supported. If it's not supported this will throw
* an {@link IllegalArgumentException}.
* @see Image
* @see HardwareBuffer
*/
public static ImageReader newInstance(int width, int height, int format, int maxImages,
long usage) {
if (!isFormatUsageCombinationAllowed(format, usage)) {
throw new IllegalArgumentException("Format usage combination is not supported:"
+ " format = " + format + ", usage = " + usage);
}
// TODO: Check this - can't do it just yet because format support is different
// Unify formats! The only reliable way to validate usage is to just try it and see.
// if (!HardwareBuffer.isSupported(width, height, format, 1, usage)) {
// throw new IllegalArgumentException("The given format=" + Integer.toHexString(format)
// + " & usage=" + Long.toHexString(usage) + " is not supported");
// }
return new ImageReader(width, height, format, maxImages, usage);
}
@@ -716,19 +716,6 @@ public class ImageReader implements AutoCloseable {
return si.getReader() == this;
}
private static boolean isFormatUsageCombinationAllowed(int format, long usage) {
if (!ImageFormat.isPublicFormat(format) && !PixelFormat.isPublicFormat(format)) {
return false;
}
// Valid usage needs to be provided.
if (usage == BUFFER_USAGE_UNKNOWN) {
return false;
}
return true;
}
/**
* Called from Native code when an Event happens.
*

View File

@@ -379,24 +379,9 @@ static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint w
String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d-%d",
width, height, format, maxImages, getpid(),
createProcessUniqueId());
uint32_t consumerUsage = GRALLOC_USAGE_SW_READ_OFTEN;
bool needUsageOverride = ndkUsage != CONSUMER_BUFFER_USAGE_UNKNOWN;
uint64_t outProducerUsage = 0;
uint64_t outConsumerUsage = 0;
android_hardware_HardwareBuffer_convertToGrallocUsageBits(&outProducerUsage, &outConsumerUsage,
ndkUsage, 0);
uint64_t consumerUsage =
android_hardware_HardwareBuffer_convertToGrallocUsageBits(ndkUsage);
if (isFormatOpaque(nativeFormat)) {
// Use the SW_READ_NEVER usage to tell producer that this format is not for preview or video
// encoding. The only possibility will be ZSL output.
consumerUsage = GRALLOC_USAGE_SW_READ_NEVER;
if (needUsageOverride) {
consumerUsage = android_convertGralloc1To0Usage(0, outConsumerUsage);
}
} else if (needUsageOverride) {
ALOGW("Consumer usage override for non-opaque format is not implemented yet, "
"ignore the provided usage from the application");
}
bufferConsumer = new BufferItemConsumer(gbConsumer, consumerUsage, maxImages,
/*controlledByApp*/true);
if (bufferConsumer == nullptr) {