Merge "camera2: Avoid boxing primitives while unmarshalling primitive arrays."

This commit is contained in:
Jayant Chowdhary
2020-12-29 22:22:54 +00:00
committed by Android (Google) Code Review
2 changed files with 128 additions and 3 deletions

View File

@@ -94,6 +94,40 @@ public final class MarshalHelpers {
"'; expected a metadata primitive class");
}
/**
* Checks whether or not {@code klass} is one of the unboxed primitive classes.
*
* <p>The following types (whether boxed or unboxed) are considered primitive:
* <ul>
* <li>byte
* <li>int
* <li>float
* <li>double
* </ul>
* </p>
*
* @param klass a {@link Class} instance; using {@code null} will return {@code false}
* @return {@code true} if primitive, {@code false} otherwise
*/
public static boolean isUnwrappedPrimitiveClass(Class<?> klass) {
if (klass == null) {
return false;
}
if (klass == byte.class) {
return true;
} else if (klass == int.class) {
return true;
} else if (klass == float.class) {
return true;
} else if (klass == long.class) {
return true;
} else if (klass == double.class) {
return true;
}
return false;
}
/**
* Checks whether or not {@code klass} is one of the metadata-primitive classes.
*
@@ -218,6 +252,32 @@ public final class MarshalHelpers {
throw new UnsupportedOperationException("Unknown nativeType " + nativeType);
}
/**
* Get the unboxed primitive type corresponding to nativeType
*
* @param nativeType the native type (RATIONAL not included)
*
* @return the native type class
*
* @throws UnsupportedOperationException if the native type was invalid
*/
public static Class<?> getPrimitiveTypeClass(int nativeType) {
switch (nativeType) {
case TYPE_BYTE:
return byte.class;
case TYPE_INT32:
return int.class;
case TYPE_FLOAT:
return float.class;
case TYPE_INT64:
return long.class;
case TYPE_DOUBLE:
return double.class;
}
throw new UnsupportedOperationException("Unknown nativeType " + nativeType);
}
/**
* Ensure that the expected and actual native types are equal.
*

View File

@@ -21,6 +21,9 @@ import android.hardware.camera2.marshal.MarshalRegistry;
import android.hardware.camera2.utils.TypeReference;
import android.util.Log;
import static android.hardware.camera2.marshal.MarshalHelpers.isUnwrappedPrimitiveClass;
import static android.hardware.camera2.marshal.MarshalHelpers.getPrimitiveTypeClass;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -41,6 +44,62 @@ public class MarshalQueryableArray<T> implements MarshalQueryable<T> {
private static final String TAG = MarshalQueryableArray.class.getSimpleName();
private static final boolean DEBUG = false;
private static interface PrimitiveArrayFiller {
public void fillPosition(Object arr, int index, ByteBuffer buffer);
static PrimitiveArrayFiller getPrimitiveArrayFiller(Class<?> componentType) {
if (componentType == int.class) {
return new PrimitiveArrayFiller() {
@Override
public void fillPosition(Object arr, int index, ByteBuffer buffer) {
int i = buffer.getInt();
Array.setInt(arr, index, i);
}
};
} else if (componentType == float.class) {
return new PrimitiveArrayFiller() {
@Override
public void fillPosition(Object arr, int index, ByteBuffer buffer) {
float i = buffer.getFloat();
Array.setFloat(arr, index, i);
}
};
} else if (componentType == long.class) {
return new PrimitiveArrayFiller() {
@Override
public void fillPosition(Object arr, int index, ByteBuffer buffer) {
long i = buffer.getLong();
Array.setLong(arr, index, i);
}
};
} else if (componentType == double.class) {
return new PrimitiveArrayFiller() {
@Override
public void fillPosition(Object arr, int index, ByteBuffer buffer) {
double i = buffer.getDouble();
Array.setDouble(arr, index, i);
}
};
} else if (componentType == byte.class) {
return new PrimitiveArrayFiller() {
@Override
public void fillPosition(Object arr, int index, ByteBuffer buffer) {
byte i = buffer.get();
Array.setByte(arr, index, i);
}
};
}
throw new UnsupportedOperationException("PrimitiveArrayFiller of type "
+ componentType.getName() + " not supported");
}
};
static void unmarshalPrimitiveArray(Object arr, int size, ByteBuffer buffer,
PrimitiveArrayFiller filler) {
for (int i = 0; i < size; i++) {
filler.fillPosition(arr, i, buffer);
}
}
private class MarshalerArray extends Marshaler<T> {
private final Class<T> mClass;
private final Marshaler<?> mComponentMarshaler;
@@ -89,9 +148,15 @@ public class MarshalQueryableArray<T> implements MarshalQueryable<T> {
}
array = Array.newInstance(mComponentClass, arraySize);
for (int i = 0; i < arraySize; ++i) {
Object elem = mComponentMarshaler.unmarshal(buffer);
Array.set(array, i, elem);
if (isUnwrappedPrimitiveClass(mComponentClass) &&
mComponentClass == getPrimitiveTypeClass(mNativeType)) {
unmarshalPrimitiveArray(array, arraySize, buffer,
PrimitiveArrayFiller.getPrimitiveArrayFiller(mComponentClass));
} else {
for (int i = 0; i < arraySize; ++i) {
Object elem = mComponentMarshaler.unmarshal(buffer);
Array.set(array, i, elem);
}
}
} else {
// Dynamic size, use an array list.