/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.hardware.camera2.marshal.impl; import android.hardware.camera2.marshal.Marshaler; import android.hardware.camera2.marshal.MarshalQueryable; import android.hardware.camera2.marshal.MarshalRegistry; import android.hardware.camera2.utils.TypeReference; import android.util.Range; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.nio.ByteBuffer; /** * Marshal {@link Range} to/from any native type */ public class MarshalQueryableRange> implements MarshalQueryable> { private static final int RANGE_COUNT = 2; private class MarshalerRange extends Marshaler> { private final Class> mClass; private final Constructor> mConstructor; /** Marshal the {@code T} inside of {@code Range} */ private final Marshaler mNestedTypeMarshaler; @SuppressWarnings("unchecked") protected MarshalerRange(TypeReference> typeReference, int nativeType) { super(MarshalQueryableRange.this, typeReference, nativeType); mClass = typeReference.getRawType(); /* * Lookup the actual type argument, e.g. Range --> Integer * and then get the marshaler for that managed type. */ ParameterizedType paramType; try { paramType = (ParameterizedType) typeReference.getType(); } catch (ClassCastException e) { throw new AssertionError("Raw use of Range is not supported", e); } Type actualTypeArgument = paramType.getActualTypeArguments()[0]; TypeReference actualTypeArgToken = TypeReference.createSpecializedTypeReference(actualTypeArgument); mNestedTypeMarshaler = (Marshaler)MarshalRegistry.getMarshaler( actualTypeArgToken, mNativeType); try { mConstructor = (Constructor>)mClass.getConstructor( Comparable.class, Comparable.class); } catch (NoSuchMethodException e) { throw new AssertionError(e); } } @Override public void marshal(Range value, ByteBuffer buffer) { mNestedTypeMarshaler.marshal(value.getLower(), buffer); mNestedTypeMarshaler.marshal(value.getUpper(), buffer); } @Override public Range unmarshal(ByteBuffer buffer) { T lower = mNestedTypeMarshaler.unmarshal(buffer); T upper = mNestedTypeMarshaler.unmarshal(buffer); try { return mConstructor.newInstance(lower, upper); } catch (InstantiationException e) { throw new AssertionError(e); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (IllegalArgumentException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw new AssertionError(e); } } @Override public int getNativeSize() { int nestedSize = mNestedTypeMarshaler.getNativeSize(); if (nestedSize != NATIVE_SIZE_DYNAMIC) { return nestedSize * RANGE_COUNT; } else { return NATIVE_SIZE_DYNAMIC; } } @Override public int calculateMarshalSize(Range value) { int nativeSize = getNativeSize(); if (nativeSize != NATIVE_SIZE_DYNAMIC) { return nativeSize; } else { int lowerSize = mNestedTypeMarshaler.calculateMarshalSize(value.getLower()); int upperSize = mNestedTypeMarshaler.calculateMarshalSize(value.getUpper()); return lowerSize + upperSize; } } } @Override public Marshaler> createMarshaler(TypeReference> managedType, int nativeType) { return new MarshalerRange(managedType, nativeType); } @Override public boolean isTypeMappingSupported(TypeReference> managedType, int nativeType) { return (Range.class.equals(managedType.getRawType())); } }