/* * 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.impl.CameraMetadataNative; import android.hardware.camera2.marshal.Marshaler; import android.hardware.camera2.marshal.MarshalQueryable; import android.hardware.camera2.utils.TypeReference; import android.util.Rational; import static android.hardware.camera2.impl.CameraMetadataNative.*; import static android.hardware.camera2.marshal.MarshalHelpers.*; import java.nio.ByteBuffer; /** * Marshal/unmarshal built-in primitive types to and from a {@link ByteBuffer}. * *

The following list of type marshaling is supported: *

*

* *

Due to the nature of generics, values are always boxed; this also means that both * the boxed and unboxed types are supported (i.e. both {@code int} and {@code Integer}).

* *

Each managed type must correspond 1:1 to the native type * (e.g. a byte will not map to a {@link CameraMetadataNative#TYPE_INT32 TYPE_INT32} or vice versa) * for marshaling.

*/ public final class MarshalQueryablePrimitive implements MarshalQueryable { private class MarshalerPrimitive extends Marshaler { /** Always the wrapped class variant of the primitive class for {@code T} */ private final Class mClass; @SuppressWarnings("unchecked") protected MarshalerPrimitive(TypeReference typeReference, int nativeType) { super(MarshalQueryablePrimitive.this, typeReference, nativeType); // Turn primitives into wrappers, otherwise int.class.cast(Integer) will fail mClass = wrapClassIfPrimitive((Class)typeReference.getRawType()); } @Override public T unmarshal(ByteBuffer buffer) { return mClass.cast(unmarshalObject(buffer)); } @Override public int calculateMarshalSize(T value) { return getPrimitiveTypeSize(mNativeType); } @Override public void marshal(T value, ByteBuffer buffer) { if (value instanceof Integer) { checkNativeTypeEquals(TYPE_INT32, mNativeType); final int val = (Integer) value; marshalPrimitive(val, buffer); } else if (value instanceof Float) { checkNativeTypeEquals(TYPE_FLOAT, mNativeType); final float val = (Float) value; marshalPrimitive(val, buffer); } else if (value instanceof Long) { checkNativeTypeEquals(TYPE_INT64, mNativeType); final long val = (Long) value; marshalPrimitive(val, buffer); } else if (value instanceof Rational) { checkNativeTypeEquals(TYPE_RATIONAL, mNativeType); marshalPrimitive((Rational) value, buffer); } else if (value instanceof Double) { checkNativeTypeEquals(TYPE_DOUBLE, mNativeType); final double val = (Double) value; marshalPrimitive(val, buffer); } else if (value instanceof Byte) { checkNativeTypeEquals(TYPE_BYTE, mNativeType); final byte val = (Byte) value; marshalPrimitive(val, buffer); } else { throw new UnsupportedOperationException( "Can't marshal managed type " + mTypeReference); } } private void marshalPrimitive(int value, ByteBuffer buffer) { buffer.putInt(value); } private void marshalPrimitive(float value, ByteBuffer buffer) { buffer.putFloat(value); } private void marshalPrimitive(double value, ByteBuffer buffer) { buffer.putDouble(value); } private void marshalPrimitive(long value, ByteBuffer buffer) { buffer.putLong(value); } private void marshalPrimitive(Rational value, ByteBuffer buffer) { buffer.putInt(value.getNumerator()); buffer.putInt(value.getDenominator()); } private void marshalPrimitive(byte value, ByteBuffer buffer) { buffer.put(value); } private Object unmarshalObject(ByteBuffer buffer) { switch (mNativeType) { case TYPE_INT32: return buffer.getInt(); case TYPE_FLOAT: return buffer.getFloat(); case TYPE_INT64: return buffer.getLong(); case TYPE_RATIONAL: int numerator = buffer.getInt(); int denominator = buffer.getInt(); return new Rational(numerator, denominator); case TYPE_DOUBLE: return buffer.getDouble(); case TYPE_BYTE: return buffer.get(); // getByte default: throw new UnsupportedOperationException( "Can't unmarshal native type " + mNativeType); } } @Override public int getNativeSize() { return getPrimitiveTypeSize(mNativeType); } } @Override public Marshaler createMarshaler(TypeReference managedType, int nativeType) { return new MarshalerPrimitive(managedType, nativeType); } @Override public boolean isTypeMappingSupported(TypeReference managedType, int nativeType) { if (managedType.getType() instanceof Class) { Class klass = (Class)managedType.getType(); if (klass == byte.class || klass == Byte.class) { return nativeType == TYPE_BYTE; } else if (klass == int.class || klass == Integer.class) { return nativeType == TYPE_INT32; } else if (klass == float.class || klass == Float.class) { return nativeType == TYPE_FLOAT; } else if (klass == long.class || klass == Long.class) { return nativeType == TYPE_INT64; } else if (klass == double.class || klass == Double.class) { return nativeType == TYPE_DOUBLE; } else if (klass == Rational.class) { return nativeType == TYPE_RATIONAL; } } return false; } }