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