| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package android.hardware.camera2.marshal; |
| |
| import static android.hardware.camera2.impl.CameraMetadataNative.*; |
| import static com.android.internal.util.Preconditions.*; |
| |
| import android.hardware.camera2.impl.CameraMetadataNative; |
| import android.util.Rational; |
| |
| /** |
| * Static functions in order to help implementing various marshaler functionality. |
| * |
| * <p>The intention is to statically import everything from this file into another file when |
| * implementing a new marshaler (or marshal queryable).</p> |
| * |
| * <p>The helpers are centered around providing primitive knowledge of the native types, |
| * such as the native size, the managed class wrappers, and various precondition checks.</p> |
| */ |
| public final class MarshalHelpers { |
| |
| public static final int SIZEOF_BYTE = 1; |
| public static final int SIZEOF_INT32 = Integer.SIZE / Byte.SIZE; |
| public static final int SIZEOF_INT64 = Long.SIZE / Byte.SIZE; |
| public static final int SIZEOF_FLOAT = Float.SIZE / Byte.SIZE; |
| public static final int SIZEOF_DOUBLE = Double.SIZE / Byte.SIZE; |
| public static final int SIZEOF_RATIONAL = SIZEOF_INT32 * 2; |
| |
| /** |
| * Get the size in bytes for the native camera metadata type. |
| * |
| * <p>This used to determine how many bytes it would take to encode/decode a single value |
| * of that {@link nativeType}.</p> |
| * |
| * @param nativeType the native type, e.g. |
| * {@link android.hardware.camera2.impl.CameraMetadataNative#TYPE_BYTE TYPE_BYTE}. |
| * @return size in bytes >= 1 |
| * |
| * @throws UnsupportedOperationException if nativeType was not one of the built-in types |
| */ |
| public static int getPrimitiveTypeSize(int nativeType) { |
| switch (nativeType) { |
| case TYPE_BYTE: |
| return SIZEOF_BYTE; |
| case TYPE_INT32: |
| return SIZEOF_INT32; |
| case TYPE_FLOAT: |
| return SIZEOF_FLOAT; |
| case TYPE_INT64: |
| return SIZEOF_INT64; |
| case TYPE_DOUBLE: |
| return SIZEOF_DOUBLE; |
| case TYPE_RATIONAL: |
| return SIZEOF_RATIONAL; |
| } |
| |
| throw new UnsupportedOperationException("Unknown type, can't get size for " |
| + nativeType); |
| } |
| |
| |
| /** |
| * Ensure that the {@code klass} is one of the metadata-primitive classes. |
| * |
| * @param klass a non-{@code null} reference |
| * @return {@code klass} instance |
| * |
| * @throws UnsupportedOperationException if klass was not one of the built-in classes |
| * @throws NullPointerException if klass was null |
| * |
| * @see #isPrimitiveClass |
| */ |
| public static <T> Class<T> checkPrimitiveClass(Class<T> klass) { |
| checkNotNull(klass, "klass must not be null"); |
| |
| if (isPrimitiveClass(klass)) { |
| return klass; |
| } |
| |
| throw new UnsupportedOperationException("Unsupported class '" + klass + |
| "'; expected a metadata primitive class"); |
| } |
| |
| /** |
| * Checks whether or not {@code klass} is one of the metadata-primitive classes. |
| * |
| * <p>The following types (whether boxed or unboxed) are considered primitive: |
| * <ul> |
| * <li>byte |
| * <li>int |
| * <li>float |
| * <li>double |
| * <li>Rational |
| * </ul> |
| * </p> |
| * |
| * <p>This doesn't strictly follow the java understanding of primitive since |
| * boxed objects are included, Rational is included, and other types such as char and |
| * short are not included.</p> |
| * |
| * @param klass a {@link Class} instance; using {@code null} will return {@code false} |
| * @return {@code true} if primitive, {@code false} otherwise |
| */ |
| public static <T> boolean isPrimitiveClass(Class<T> klass) { |
| if (klass == null) { |
| return false; |
| } |
| |
| if (klass == byte.class || klass == Byte.class) { |
| return true; |
| } else if (klass == int.class || klass == Integer.class) { |
| return true; |
| } else if (klass == float.class || klass == Float.class) { |
| return true; |
| } else if (klass == long.class || klass == Long.class) { |
| return true; |
| } else if (klass == double.class || klass == Double.class) { |
| return true; |
| } else if (klass == Rational.class) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Wrap {@code klass} with its wrapper variant if it was a {@code Class} corresponding |
| * to a Java primitive. |
| * |
| * <p>Non-primitive classes are passed through as-is.</p> |
| * |
| * <p>For example, for a primitive {@code int.class => Integer.class}, |
| * but for a non-primitive {@code Rational.class => Rational.class}.</p> |
| * |
| * @param klass a {@code Class} reference |
| * |
| * @return wrapped class object, or same class object if non-primitive |
| */ |
| @SuppressWarnings("unchecked") |
| public static <T> Class<T> wrapClassIfPrimitive(Class<T> klass) { |
| if (klass == byte.class) { |
| return (Class<T>)Byte.class; |
| } else if (klass == int.class) { |
| return (Class<T>)Integer.class; |
| } else if (klass == float.class) { |
| return (Class<T>)Float.class; |
| } else if (klass == long.class) { |
| return (Class<T>)Long.class; |
| } else if (klass == double.class) { |
| return (Class<T>)Double.class; |
| } |
| |
| return klass; |
| } |
| |
| /** |
| * Return a human-readable representation of the {@code nativeType}, e.g. "TYPE_INT32" |
| * |
| * <p>Out-of-range values return a string with "UNKNOWN" as the prefix.</p> |
| * |
| * @param nativeType the native type |
| * |
| * @return human readable type name |
| */ |
| public static String toStringNativeType(int nativeType) { |
| switch (nativeType) { |
| case TYPE_BYTE: |
| return "TYPE_BYTE"; |
| case TYPE_INT32: |
| return "TYPE_INT32"; |
| case TYPE_FLOAT: |
| return "TYPE_FLOAT"; |
| case TYPE_INT64: |
| return "TYPE_INT64"; |
| case TYPE_DOUBLE: |
| return "TYPE_DOUBLE"; |
| case TYPE_RATIONAL: |
| return "TYPE_RATIONAL"; |
| } |
| |
| return "UNKNOWN(" + nativeType + ")"; |
| } |
| |
| /** |
| * Ensure that the {@code nativeType} is one of the native types supported |
| * by {@link CameraMetadataNative}. |
| * |
| * @param nativeType the native type |
| * |
| * @return the native type |
| * |
| * @throws UnsupportedOperationException if the native type was invalid |
| */ |
| public static int checkNativeType(int nativeType) { |
| switch (nativeType) { |
| case TYPE_BYTE: |
| case TYPE_INT32: |
| case TYPE_FLOAT: |
| case TYPE_INT64: |
| case TYPE_DOUBLE: |
| case TYPE_RATIONAL: |
| return nativeType; |
| } |
| |
| throw new UnsupportedOperationException("Unknown nativeType " + nativeType); |
| } |
| |
| /** |
| * Ensure that the expected and actual native types are equal. |
| * |
| * @param expectedNativeType the expected native type |
| * @param actualNativeType the actual native type |
| * @return the actual native type |
| * |
| * @throws UnsupportedOperationException if the types are not equal |
| */ |
| public static int checkNativeTypeEquals(int expectedNativeType, int actualNativeType) { |
| if (expectedNativeType != actualNativeType) { |
| throw new UnsupportedOperationException( |
| String.format("Expected native type %d, but got %d", |
| expectedNativeType, actualNativeType)); |
| } |
| |
| return actualNativeType; |
| } |
| |
| private MarshalHelpers() { |
| throw new AssertionError(); |
| } |
| } |