Home | History | Annotate | Download | only in marshal
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package android.hardware.camera2.marshal;
     17 
     18 import static android.hardware.camera2.impl.CameraMetadataNative.*;
     19 import static com.android.internal.util.Preconditions.*;
     20 
     21 import android.hardware.camera2.impl.CameraMetadataNative;
     22 import android.util.Rational;
     23 
     24 /**
     25  * Static functions in order to help implementing various marshaler functionality.
     26  *
     27  * <p>The intention is to statically import everything from this file into another file when
     28  * implementing a new marshaler (or marshal queryable).</p>
     29  *
     30  * <p>The helpers are centered around providing primitive knowledge of the native types,
     31  * such as the native size, the managed class wrappers, and various precondition checks.</p>
     32  */
     33 public final class MarshalHelpers {
     34 
     35     public static final int SIZEOF_BYTE = 1;
     36     public static final int SIZEOF_INT32 = Integer.SIZE / Byte.SIZE;
     37     public static final int SIZEOF_INT64 = Long.SIZE / Byte.SIZE;
     38     public static final int SIZEOF_FLOAT = Float.SIZE / Byte.SIZE;
     39     public static final int SIZEOF_DOUBLE = Double.SIZE / Byte.SIZE;
     40     public static final int SIZEOF_RATIONAL = SIZEOF_INT32 * 2;
     41 
     42     /**
     43      * Get the size in bytes for the native camera metadata type.
     44      *
     45      * <p>This used to determine how many bytes it would take to encode/decode a single value
     46      * of that {@link nativeType}.</p>
     47      *
     48      * @param nativeType the native type, e.g.
     49      *        {@link android.hardware.camera2.impl.CameraMetadataNative#TYPE_BYTE TYPE_BYTE}.
     50      * @return size in bytes >= 1
     51      *
     52      * @throws UnsupportedOperationException if nativeType was not one of the built-in types
     53      */
     54     public static int getPrimitiveTypeSize(int nativeType) {
     55         switch (nativeType) {
     56             case TYPE_BYTE:
     57                 return SIZEOF_BYTE;
     58             case TYPE_INT32:
     59                 return SIZEOF_INT32;
     60             case TYPE_FLOAT:
     61                 return SIZEOF_FLOAT;
     62             case TYPE_INT64:
     63                 return SIZEOF_INT64;
     64             case TYPE_DOUBLE:
     65                 return SIZEOF_DOUBLE;
     66             case TYPE_RATIONAL:
     67                 return SIZEOF_RATIONAL;
     68         }
     69 
     70         throw new UnsupportedOperationException("Unknown type, can't get size for "
     71                 + nativeType);
     72     }
     73 
     74 
     75     /**
     76      * Ensure that the {@code klass} is one of the metadata-primitive classes.
     77      *
     78      * @param klass a non-{@code null} reference
     79      * @return {@code klass} instance
     80      *
     81      * @throws UnsupportedOperationException if klass was not one of the built-in classes
     82      * @throws NullPointerException if klass was null
     83      *
     84      * @see #isPrimitiveClass
     85      */
     86     public static <T> Class<T> checkPrimitiveClass(Class<T> klass) {
     87         checkNotNull(klass, "klass must not be null");
     88 
     89         if (isPrimitiveClass(klass)) {
     90             return klass;
     91         }
     92 
     93         throw new UnsupportedOperationException("Unsupported class '" + klass +
     94                 "'; expected a metadata primitive class");
     95     }
     96 
     97     /**
     98      * Checks whether or not {@code klass} is one of the metadata-primitive classes.
     99      *
    100      * <p>The following types (whether boxed or unboxed) are considered primitive:
    101      * <ul>
    102      * <li>byte
    103      * <li>int
    104      * <li>float
    105      * <li>double
    106      * <li>Rational
    107      * </ul>
    108      * </p>
    109      *
    110      * <p>This doesn't strictly follow the java understanding of primitive since
    111      * boxed objects are included, Rational is included, and other types such as char and
    112      * short are not included.</p>
    113      *
    114      * @param klass a {@link Class} instance; using {@code null} will return {@code false}
    115      * @return {@code true} if primitive, {@code false} otherwise
    116      */
    117     public static <T> boolean isPrimitiveClass(Class<T> klass) {
    118         if (klass == null) {
    119             return false;
    120         }
    121 
    122         if (klass == byte.class || klass == Byte.class) {
    123             return true;
    124         } else if (klass == int.class || klass == Integer.class) {
    125             return true;
    126         } else if (klass == float.class || klass == Float.class) {
    127             return true;
    128         } else if (klass == long.class || klass == Long.class) {
    129             return true;
    130         } else if (klass == double.class || klass == Double.class) {
    131             return true;
    132         } else if (klass == Rational.class) {
    133             return true;
    134         }
    135 
    136         return false;
    137     }
    138 
    139     /**
    140      * Wrap {@code klass} with its wrapper variant if it was a {@code Class} corresponding
    141      * to a Java primitive.
    142      *
    143      * <p>Non-primitive classes are passed through as-is.</p>
    144      *
    145      * <p>For example, for a primitive {@code int.class => Integer.class},
    146      * but for a non-primitive {@code Rational.class => Rational.class}.</p>
    147      *
    148      * @param klass a {@code Class} reference
    149      *
    150      * @return wrapped class object, or same class object if non-primitive
    151      */
    152     @SuppressWarnings("unchecked")
    153     public static <T> Class<T> wrapClassIfPrimitive(Class<T> klass) {
    154         if (klass == byte.class) {
    155             return (Class<T>)Byte.class;
    156         } else if (klass == int.class) {
    157             return (Class<T>)Integer.class;
    158         } else if (klass == float.class) {
    159             return (Class<T>)Float.class;
    160         } else if (klass == long.class) {
    161             return (Class<T>)Long.class;
    162         } else if (klass == double.class) {
    163             return (Class<T>)Double.class;
    164         }
    165 
    166         return klass;
    167     }
    168 
    169     /**
    170      * Return a human-readable representation of the {@code nativeType}, e.g. "TYPE_INT32"
    171      *
    172      * <p>Out-of-range values return a string with "UNKNOWN" as the prefix.</p>
    173      *
    174      * @param nativeType the native type
    175      *
    176      * @return human readable type name
    177      */
    178     public static String toStringNativeType(int nativeType) {
    179         switch (nativeType) {
    180             case TYPE_BYTE:
    181                 return "TYPE_BYTE";
    182             case TYPE_INT32:
    183                 return "TYPE_INT32";
    184             case TYPE_FLOAT:
    185                 return "TYPE_FLOAT";
    186             case TYPE_INT64:
    187                 return "TYPE_INT64";
    188             case TYPE_DOUBLE:
    189                 return "TYPE_DOUBLE";
    190             case TYPE_RATIONAL:
    191                 return "TYPE_RATIONAL";
    192         }
    193 
    194         return "UNKNOWN(" + nativeType + ")";
    195     }
    196 
    197     /**
    198      * Ensure that the {@code nativeType} is one of the native types supported
    199      * by {@link CameraMetadataNative}.
    200      *
    201      * @param nativeType the native type
    202      *
    203      * @return the native type
    204      *
    205      * @throws UnsupportedOperationException if the native type was invalid
    206      */
    207     public static int checkNativeType(int nativeType) {
    208         switch (nativeType) {
    209             case TYPE_BYTE:
    210             case TYPE_INT32:
    211             case TYPE_FLOAT:
    212             case TYPE_INT64:
    213             case TYPE_DOUBLE:
    214             case TYPE_RATIONAL:
    215                 return nativeType;
    216         }
    217 
    218         throw new UnsupportedOperationException("Unknown nativeType " + nativeType);
    219     }
    220 
    221     /**
    222      * Ensure that the expected and actual native types are equal.
    223      *
    224      * @param expectedNativeType the expected native type
    225      * @param actualNativeType the actual native type
    226      * @return the actual native type
    227      *
    228      * @throws UnsupportedOperationException if the types are not equal
    229      */
    230     public static int checkNativeTypeEquals(int expectedNativeType, int actualNativeType) {
    231         if (expectedNativeType != actualNativeType) {
    232             throw new UnsupportedOperationException(
    233                     String.format("Expected native type %d, but got %d",
    234                             expectedNativeType, actualNativeType));
    235         }
    236 
    237         return actualNativeType;
    238     }
    239 
    240     private MarshalHelpers() {
    241         throw new AssertionError();
    242     }
    243 }
    244