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.marshal.Marshaler;
19 import android.hardware.camera2.marshal.MarshalQueryable;
20 import android.hardware.camera2.marshal.MarshalRegistry;
21 import android.hardware.camera2.utils.TypeReference;
22 import android.util.Range;
23 
24 import java.lang.reflect.Constructor;
25 import java.lang.reflect.InvocationTargetException;
26 import java.lang.reflect.ParameterizedType;
27 import java.lang.reflect.Type;
28 import java.nio.ByteBuffer;
29 
30 /**
31  * Marshal {@link Range} to/from any native type
32  */
33 public class MarshalQueryableRange<T extends Comparable<? super T>>
34         implements MarshalQueryable<Range<T>> {
35     private static final int RANGE_COUNT = 2;
36 
37     private class MarshalerRange extends Marshaler<Range<T>> {
38         private final Class<? super Range<T>> mClass;
39         private final Constructor<Range<T>> mConstructor;
40         /** Marshal the {@code T} inside of {@code Range<T>} */
41         private final Marshaler<T> mNestedTypeMarshaler;
42 
43         @SuppressWarnings("unchecked")
MarshalerRange(TypeReference<Range<T>> typeReference, int nativeType)44         protected MarshalerRange(TypeReference<Range<T>> typeReference,
45                 int nativeType) {
46             super(MarshalQueryableRange.this, typeReference, nativeType);
47 
48             mClass = typeReference.getRawType();
49 
50             /*
51              * Lookup the actual type argument, e.g. Range<Integer> --> Integer
52              * and then get the marshaler for that managed type.
53              */
54             ParameterizedType paramType;
55             try {
56                 paramType = (ParameterizedType) typeReference.getType();
57             } catch (ClassCastException e) {
58                 throw new AssertionError("Raw use of Range is not supported", e);
59             }
60             Type actualTypeArgument = paramType.getActualTypeArguments()[0];
61 
62             TypeReference<?> actualTypeArgToken =
63                     TypeReference.createSpecializedTypeReference(actualTypeArgument);
64 
65             mNestedTypeMarshaler = (Marshaler<T>)MarshalRegistry.getMarshaler(
66                     actualTypeArgToken, mNativeType);
67             try {
68                 mConstructor = (Constructor<Range<T>>)mClass.getConstructor(
69                         Comparable.class, Comparable.class);
70             } catch (NoSuchMethodException e) {
71                 throw new AssertionError(e);
72             }
73         }
74 
75         @Override
marshal(Range<T> value, ByteBuffer buffer)76         public void marshal(Range<T> value, ByteBuffer buffer) {
77             mNestedTypeMarshaler.marshal(value.getLower(), buffer);
78             mNestedTypeMarshaler.marshal(value.getUpper(), buffer);
79         }
80 
81         @Override
unmarshal(ByteBuffer buffer)82         public Range<T> unmarshal(ByteBuffer buffer) {
83             T lower = mNestedTypeMarshaler.unmarshal(buffer);
84             T upper = mNestedTypeMarshaler.unmarshal(buffer);
85 
86             try {
87                 return mConstructor.newInstance(lower, upper);
88             } catch (InstantiationException e) {
89                 throw new AssertionError(e);
90             } catch (IllegalAccessException e) {
91                 throw new AssertionError(e);
92             } catch (IllegalArgumentException e) {
93                 throw new AssertionError(e);
94             } catch (InvocationTargetException e) {
95                 throw new AssertionError(e);
96             }
97         }
98 
99         @Override
getNativeSize()100         public int getNativeSize() {
101             int nestedSize = mNestedTypeMarshaler.getNativeSize();
102 
103             if (nestedSize != NATIVE_SIZE_DYNAMIC) {
104                 return nestedSize * RANGE_COUNT;
105             } else {
106                 return NATIVE_SIZE_DYNAMIC;
107             }
108         }
109 
110         @Override
calculateMarshalSize(Range<T> value)111         public int calculateMarshalSize(Range<T> value) {
112             int nativeSize = getNativeSize();
113 
114             if (nativeSize != NATIVE_SIZE_DYNAMIC) {
115                 return nativeSize;
116             } else {
117                 int lowerSize = mNestedTypeMarshaler.calculateMarshalSize(value.getLower());
118                 int upperSize = mNestedTypeMarshaler.calculateMarshalSize(value.getUpper());
119 
120                 return lowerSize + upperSize;
121             }
122         }
123     }
124 
125     @Override
createMarshaler(TypeReference<Range<T>> managedType, int nativeType)126     public Marshaler<Range<T>> createMarshaler(TypeReference<Range<T>> managedType,
127             int nativeType) {
128         return new MarshalerRange(managedType, nativeType);
129     }
130 
131     @Override
isTypeMappingSupported(TypeReference<Range<T>> managedType, int nativeType)132     public boolean isTypeMappingSupported(TypeReference<Range<T>> managedType, int nativeType) {
133         return (Range.class.equals(managedType.getRawType()));
134     }
135 
136 }
137