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 */ getPrimitiveTypeSize(int nativeType)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 */ checkPrimitiveClass(Class<T> klass)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 unboxed 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 * </ul> 107 * </p> 108 * 109 * @param klass a {@link Class} instance; using {@code null} will return {@code false} 110 * @return {@code true} if primitive, {@code false} otherwise 111 */ isUnwrappedPrimitiveClass(Class<?> klass)112 public static boolean isUnwrappedPrimitiveClass(Class<?> klass) { 113 if (klass == null) { 114 return false; 115 } 116 117 if (klass == byte.class) { 118 return true; 119 } else if (klass == int.class) { 120 return true; 121 } else if (klass == float.class) { 122 return true; 123 } else if (klass == long.class) { 124 return true; 125 } else if (klass == double.class) { 126 return true; 127 } 128 return false; 129 } 130 131 /** 132 * Checks whether or not {@code klass} is one of the metadata-primitive classes. 133 * 134 * <p>The following types (whether boxed or unboxed) are considered primitive: 135 * <ul> 136 * <li>byte 137 * <li>int 138 * <li>float 139 * <li>double 140 * <li>Rational 141 * </ul> 142 * </p> 143 * 144 * <p>This doesn't strictly follow the java understanding of primitive since 145 * boxed objects are included, Rational is included, and other types such as char and 146 * short are not included.</p> 147 * 148 * @param klass a {@link Class} instance; using {@code null} will return {@code false} 149 * @return {@code true} if primitive, {@code false} otherwise 150 */ isPrimitiveClass(Class<T> klass)151 public static <T> boolean isPrimitiveClass(Class<T> klass) { 152 if (klass == null) { 153 return false; 154 } 155 156 if (klass == byte.class || klass == Byte.class) { 157 return true; 158 } else if (klass == int.class || klass == Integer.class) { 159 return true; 160 } else if (klass == float.class || klass == Float.class) { 161 return true; 162 } else if (klass == long.class || klass == Long.class) { 163 return true; 164 } else if (klass == double.class || klass == Double.class) { 165 return true; 166 } else if (klass == Rational.class) { 167 return true; 168 } 169 170 return false; 171 } 172 173 /** 174 * Wrap {@code klass} with its wrapper variant if it was a {@code Class} corresponding 175 * to a Java primitive. 176 * 177 * <p>Non-primitive classes are passed through as-is.</p> 178 * 179 * <p>For example, for a primitive {@code int.class => Integer.class}, 180 * but for a non-primitive {@code Rational.class => Rational.class}.</p> 181 * 182 * @param klass a {@code Class} reference 183 * 184 * @return wrapped class object, or same class object if non-primitive 185 */ 186 @SuppressWarnings("unchecked") wrapClassIfPrimitive(Class<T> klass)187 public static <T> Class<T> wrapClassIfPrimitive(Class<T> klass) { 188 if (klass == byte.class) { 189 return (Class<T>)Byte.class; 190 } else if (klass == int.class) { 191 return (Class<T>)Integer.class; 192 } else if (klass == float.class) { 193 return (Class<T>)Float.class; 194 } else if (klass == long.class) { 195 return (Class<T>)Long.class; 196 } else if (klass == double.class) { 197 return (Class<T>)Double.class; 198 } 199 200 return klass; 201 } 202 203 /** 204 * Return a human-readable representation of the {@code nativeType}, e.g. "TYPE_INT32" 205 * 206 * <p>Out-of-range values return a string with "UNKNOWN" as the prefix.</p> 207 * 208 * @param nativeType the native type 209 * 210 * @return human readable type name 211 */ toStringNativeType(int nativeType)212 public static String toStringNativeType(int nativeType) { 213 switch (nativeType) { 214 case TYPE_BYTE: 215 return "TYPE_BYTE"; 216 case TYPE_INT32: 217 return "TYPE_INT32"; 218 case TYPE_FLOAT: 219 return "TYPE_FLOAT"; 220 case TYPE_INT64: 221 return "TYPE_INT64"; 222 case TYPE_DOUBLE: 223 return "TYPE_DOUBLE"; 224 case TYPE_RATIONAL: 225 return "TYPE_RATIONAL"; 226 } 227 228 return "UNKNOWN(" + nativeType + ")"; 229 } 230 231 /** 232 * Ensure that the {@code nativeType} is one of the native types supported 233 * by {@link CameraMetadataNative}. 234 * 235 * @param nativeType the native type 236 * 237 * @return the native type 238 * 239 * @throws UnsupportedOperationException if the native type was invalid 240 */ checkNativeType(int nativeType)241 public static int checkNativeType(int nativeType) { 242 switch (nativeType) { 243 case TYPE_BYTE: 244 case TYPE_INT32: 245 case TYPE_FLOAT: 246 case TYPE_INT64: 247 case TYPE_DOUBLE: 248 case TYPE_RATIONAL: 249 return nativeType; 250 } 251 252 throw new UnsupportedOperationException("Unknown nativeType " + nativeType); 253 } 254 255 /** 256 * Get the unboxed primitive type corresponding to nativeType 257 * 258 * @param nativeType the native type (RATIONAL not included) 259 * 260 * @return the native type class 261 * 262 * @throws UnsupportedOperationException if the native type was invalid 263 */ getPrimitiveTypeClass(int nativeType)264 public static Class<?> getPrimitiveTypeClass(int nativeType) { 265 switch (nativeType) { 266 case TYPE_BYTE: 267 return byte.class; 268 case TYPE_INT32: 269 return int.class; 270 case TYPE_FLOAT: 271 return float.class; 272 case TYPE_INT64: 273 return long.class; 274 case TYPE_DOUBLE: 275 return double.class; 276 } 277 278 throw new UnsupportedOperationException("Unknown nativeType " + nativeType); 279 } 280 281 /** 282 * Ensure that the expected and actual native types are equal. 283 * 284 * @param expectedNativeType the expected native type 285 * @param actualNativeType the actual native type 286 * @return the actual native type 287 * 288 * @throws UnsupportedOperationException if the types are not equal 289 */ checkNativeTypeEquals(int expectedNativeType, int actualNativeType)290 public static int checkNativeTypeEquals(int expectedNativeType, int actualNativeType) { 291 if (expectedNativeType != actualNativeType) { 292 throw new UnsupportedOperationException( 293 String.format("Expected native type %d, but got %d", 294 expectedNativeType, actualNativeType)); 295 } 296 297 return actualNativeType; 298 } 299 MarshalHelpers()300 private MarshalHelpers() { 301 throw new AssertionError(); 302 } 303 } 304