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