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.impl; 17 18 import android.hardware.camera2.impl.CameraMetadataNative; 19 import android.hardware.camera2.marshal.Marshaler; 20 import android.hardware.camera2.marshal.MarshalQueryable; 21 import android.hardware.camera2.utils.TypeReference; 22 import android.util.Rational; 23 24 import static android.hardware.camera2.impl.CameraMetadataNative.*; 25 import static android.hardware.camera2.marshal.MarshalHelpers.*; 26 import java.nio.ByteBuffer; 27 28 /** 29 * Marshal/unmarshal built-in primitive types to and from a {@link ByteBuffer}. 30 * 31 * <p>The following list of type marshaling is supported: 32 * <ul> 33 * <li>byte <-> TYPE_BYTE 34 * <li>int <-> TYPE_INT32 35 * <li>long <-> TYPE_INT64 36 * <li>float <-> TYPE_FLOAT 37 * <li>double <-> TYPE_DOUBLE 38 * <li>Rational <-> TYPE_RATIONAL 39 * </ul> 40 * </p> 41 * 42 * <p>Due to the nature of generics, values are always boxed; this also means that both 43 * the boxed and unboxed types are supported (i.e. both {@code int} and {@code Integer}).</p> 44 * 45 * <p>Each managed type <!--(other than boolean)--> must correspond 1:1 to the native type 46 * (e.g. a byte will not map to a {@link CameraMetadataNative#TYPE_INT32 TYPE_INT32} or vice versa) 47 * for marshaling.</p> 48 */ 49 public final class MarshalQueryablePrimitive<T> implements MarshalQueryable<T> { 50 51 private class MarshalerPrimitive extends Marshaler<T> { 52 /** Always the wrapped class variant of the primitive class for {@code T} */ 53 private final Class<T> mClass; 54 55 @SuppressWarnings("unchecked") MarshalerPrimitive(TypeReference<T> typeReference, int nativeType)56 protected MarshalerPrimitive(TypeReference<T> typeReference, int nativeType) { 57 super(MarshalQueryablePrimitive.this, typeReference, nativeType); 58 59 // Turn primitives into wrappers, otherwise int.class.cast(Integer) will fail 60 mClass = wrapClassIfPrimitive((Class<T>)typeReference.getRawType()); 61 } 62 63 @Override unmarshal(ByteBuffer buffer)64 public T unmarshal(ByteBuffer buffer) { 65 return mClass.cast(unmarshalObject(buffer)); 66 } 67 68 @Override calculateMarshalSize(T value)69 public int calculateMarshalSize(T value) { 70 return getPrimitiveTypeSize(mNativeType); 71 } 72 73 @Override marshal(T value, ByteBuffer buffer)74 public void marshal(T value, ByteBuffer buffer) { 75 if (value instanceof Integer) { 76 checkNativeTypeEquals(TYPE_INT32, mNativeType); 77 final int val = (Integer) value; 78 marshalPrimitive(val, buffer); 79 } else if (value instanceof Float) { 80 checkNativeTypeEquals(TYPE_FLOAT, mNativeType); 81 final float val = (Float) value; 82 marshalPrimitive(val, buffer); 83 } else if (value instanceof Long) { 84 checkNativeTypeEquals(TYPE_INT64, mNativeType); 85 final long val = (Long) value; 86 marshalPrimitive(val, buffer); 87 } else if (value instanceof Rational) { 88 checkNativeTypeEquals(TYPE_RATIONAL, mNativeType); 89 marshalPrimitive((Rational) value, buffer); 90 } else if (value instanceof Double) { 91 checkNativeTypeEquals(TYPE_DOUBLE, mNativeType); 92 final double val = (Double) value; 93 marshalPrimitive(val, buffer); 94 } else if (value instanceof Byte) { 95 checkNativeTypeEquals(TYPE_BYTE, mNativeType); 96 final byte val = (Byte) value; 97 marshalPrimitive(val, buffer); 98 } else { 99 throw new UnsupportedOperationException( 100 "Can't marshal managed type " + mTypeReference); 101 } 102 } 103 marshalPrimitive(int value, ByteBuffer buffer)104 private void marshalPrimitive(int value, ByteBuffer buffer) { 105 buffer.putInt(value); 106 } 107 marshalPrimitive(float value, ByteBuffer buffer)108 private void marshalPrimitive(float value, ByteBuffer buffer) { 109 buffer.putFloat(value); 110 } 111 marshalPrimitive(double value, ByteBuffer buffer)112 private void marshalPrimitive(double value, ByteBuffer buffer) { 113 buffer.putDouble(value); 114 } 115 marshalPrimitive(long value, ByteBuffer buffer)116 private void marshalPrimitive(long value, ByteBuffer buffer) { 117 buffer.putLong(value); 118 } 119 marshalPrimitive(Rational value, ByteBuffer buffer)120 private void marshalPrimitive(Rational value, ByteBuffer buffer) { 121 buffer.putInt(value.getNumerator()); 122 buffer.putInt(value.getDenominator()); 123 } 124 marshalPrimitive(byte value, ByteBuffer buffer)125 private void marshalPrimitive(byte value, ByteBuffer buffer) { 126 buffer.put(value); 127 } 128 unmarshalObject(ByteBuffer buffer)129 private Object unmarshalObject(ByteBuffer buffer) { 130 switch (mNativeType) { 131 case TYPE_INT32: 132 return buffer.getInt(); 133 case TYPE_FLOAT: 134 return buffer.getFloat(); 135 case TYPE_INT64: 136 return buffer.getLong(); 137 case TYPE_RATIONAL: 138 int numerator = buffer.getInt(); 139 int denominator = buffer.getInt(); 140 return new Rational(numerator, denominator); 141 case TYPE_DOUBLE: 142 return buffer.getDouble(); 143 case TYPE_BYTE: 144 return buffer.get(); // getByte 145 default: 146 throw new UnsupportedOperationException( 147 "Can't unmarshal native type " + mNativeType); 148 } 149 } 150 151 @Override getNativeSize()152 public int getNativeSize() { 153 return getPrimitiveTypeSize(mNativeType); 154 } 155 } 156 157 @Override createMarshaler(TypeReference<T> managedType, int nativeType)158 public Marshaler<T> createMarshaler(TypeReference<T> managedType, int nativeType) { 159 return new MarshalerPrimitive(managedType, nativeType); 160 } 161 162 @Override isTypeMappingSupported(TypeReference<T> managedType, int nativeType)163 public boolean isTypeMappingSupported(TypeReference<T> managedType, int nativeType) { 164 if (managedType.getType() instanceof Class<?>) { 165 Class<?> klass = (Class<?>)managedType.getType(); 166 167 if (klass == byte.class || klass == Byte.class) { 168 return nativeType == TYPE_BYTE; 169 } else if (klass == int.class || klass == Integer.class) { 170 return nativeType == TYPE_INT32; 171 } else if (klass == float.class || klass == Float.class) { 172 return nativeType == TYPE_FLOAT; 173 } else if (klass == long.class || klass == Long.class) { 174 return nativeType == TYPE_INT64; 175 } else if (klass == double.class || klass == Double.class) { 176 return nativeType == TYPE_DOUBLE; 177 } else if (klass == Rational.class) { 178 return nativeType == TYPE_RATIONAL; 179 } 180 } 181 return false; 182 } 183 } 184