| /* |
| * 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}. |
| * |
| * <p>The following list of type marshaling is supported: |
| * <ul> |
| * <li>byte <-> TYPE_BYTE |
| * <li>int <-> TYPE_INT32 |
| * <li>long <-> TYPE_INT64 |
| * <li>float <-> TYPE_FLOAT |
| * <li>double <-> TYPE_DOUBLE |
| * <li>Rational <-> TYPE_RATIONAL |
| * </ul> |
| * </p> |
| * |
| * <p>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}).</p> |
| * |
| * <p>Each managed type <!--(other than boolean)--> 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.</p> |
| */ |
| public final class MarshalQueryablePrimitive<T> implements MarshalQueryable<T> { |
| |
| private class MarshalerPrimitive extends Marshaler<T> { |
| /** Always the wrapped class variant of the primitive class for {@code T} */ |
| private final Class<T> mClass; |
| |
| @SuppressWarnings("unchecked") |
| protected MarshalerPrimitive(TypeReference<T> typeReference, int nativeType) { |
| super(MarshalQueryablePrimitive.this, typeReference, nativeType); |
| |
| // Turn primitives into wrappers, otherwise int.class.cast(Integer) will fail |
| mClass = wrapClassIfPrimitive((Class<T>)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<T> createMarshaler(TypeReference<T> managedType, int nativeType) { |
| return new MarshalerPrimitive(managedType, nativeType); |
| } |
| |
| @Override |
| public boolean isTypeMappingSupported(TypeReference<T> 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; |
| } |
| } |