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