Home | History | Annotate | Download | only in impl
      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 static com.android.internal.util.Preconditions.*;
     27 
     28 import java.nio.ByteBuffer;
     29 
     30 /**
     31  * Marshal/unmarshal built-in primitive types to and from a {@link ByteBuffer}.
     32  *
     33  * <p>The following list of type marshaling is supported:
     34  * <ul>
     35  * <li>byte <-> TYPE_BYTE
     36  * <li>int <-> TYPE_INT32
     37  * <li>long <-> TYPE_INT64
     38  * <li>float <-> TYPE_FLOAT
     39  * <li>double <-> TYPE_DOUBLE
     40  * <li>Rational <-> TYPE_RATIONAL
     41  * </ul>
     42  * </p>
     43  *
     44  * <p>Due to the nature of generics, values are always boxed; this also means that both
     45  * the boxed and unboxed types are supported (i.e. both {@code int} and {@code Integer}).</p>
     46  *
     47  * <p>Each managed type <!--(other than boolean)--> must correspond 1:1 to the native type
     48  * (e.g. a byte will not map to a {@link CameraMetadataNative#TYPE_INT32 TYPE_INT32} or vice versa)
     49  * for marshaling.</p>
     50  */
     51 public final class MarshalQueryablePrimitive<T> implements MarshalQueryable<T> {
     52 
     53     private class MarshalerPrimitive extends Marshaler<T> {
     54         /** Always the wrapped class variant of the primitive class for {@code T} */
     55         private final Class<T> mClass;
     56 
     57         @SuppressWarnings("unchecked")
     58         protected MarshalerPrimitive(TypeReference<T> typeReference, int nativeType) {
     59             super(MarshalQueryablePrimitive.this, typeReference, nativeType);
     60 
     61             // Turn primitives into wrappers, otherwise int.class.cast(Integer) will fail
     62             mClass = wrapClassIfPrimitive((Class<T>)typeReference.getRawType());
     63         }
     64 
     65         @Override
     66         public T unmarshal(ByteBuffer buffer) {
     67             return mClass.cast(unmarshalObject(buffer));
     68         }
     69 
     70         @Override
     71         public int calculateMarshalSize(T value) {
     72             return getPrimitiveTypeSize(mNativeType);
     73         }
     74 
     75         @Override
     76         public void marshal(T value, ByteBuffer buffer) {
     77             if (value instanceof Integer) {
     78                 checkNativeTypeEquals(TYPE_INT32, mNativeType);
     79                 final int val = (Integer) value;
     80                 marshalPrimitive(val, buffer);
     81             } else if (value instanceof Float) {
     82                 checkNativeTypeEquals(TYPE_FLOAT, mNativeType);
     83                 final float val = (Float) value;
     84                 marshalPrimitive(val, buffer);
     85             } else if (value instanceof Long) {
     86                 checkNativeTypeEquals(TYPE_INT64, mNativeType);
     87                 final long val = (Long) value;
     88                 marshalPrimitive(val, buffer);
     89             } else if (value instanceof Rational) {
     90                 checkNativeTypeEquals(TYPE_RATIONAL, mNativeType);
     91                 marshalPrimitive((Rational) value, buffer);
     92             } else if (value instanceof Double) {
     93                 checkNativeTypeEquals(TYPE_DOUBLE, mNativeType);
     94                 final double val = (Double) value;
     95                 marshalPrimitive(val, buffer);
     96             } else if (value instanceof Byte) {
     97                 checkNativeTypeEquals(TYPE_BYTE, mNativeType);
     98                 final byte val = (Byte) value;
     99                 marshalPrimitive(val, buffer);
    100             } else {
    101                 throw new UnsupportedOperationException(
    102                         "Can't marshal managed type " + mTypeReference);
    103             }
    104         }
    105 
    106         private void marshalPrimitive(int value, ByteBuffer buffer) {
    107             buffer.putInt(value);
    108         }
    109 
    110         private void marshalPrimitive(float value, ByteBuffer buffer) {
    111             buffer.putFloat(value);
    112         }
    113 
    114         private void marshalPrimitive(double value, ByteBuffer buffer) {
    115             buffer.putDouble(value);
    116         }
    117 
    118         private void marshalPrimitive(long value, ByteBuffer buffer) {
    119             buffer.putLong(value);
    120         }
    121 
    122         private void marshalPrimitive(Rational value, ByteBuffer buffer) {
    123             buffer.putInt(value.getNumerator());
    124             buffer.putInt(value.getDenominator());
    125         }
    126 
    127         private void marshalPrimitive(byte value, ByteBuffer buffer) {
    128             buffer.put(value);
    129         }
    130 
    131         private Object unmarshalObject(ByteBuffer buffer) {
    132             switch (mNativeType) {
    133                 case TYPE_INT32:
    134                     return buffer.getInt();
    135                 case TYPE_FLOAT:
    136                     return buffer.getFloat();
    137                 case TYPE_INT64:
    138                     return buffer.getLong();
    139                 case TYPE_RATIONAL:
    140                     int numerator = buffer.getInt();
    141                     int denominator = buffer.getInt();
    142                     return new Rational(numerator, denominator);
    143                 case TYPE_DOUBLE:
    144                     return buffer.getDouble();
    145                 case TYPE_BYTE:
    146                     return buffer.get(); // getByte
    147                 default:
    148                     throw new UnsupportedOperationException(
    149                             "Can't unmarshal native type " + mNativeType);
    150             }
    151         }
    152 
    153         @Override
    154         public int getNativeSize() {
    155             return getPrimitiveTypeSize(mNativeType);
    156         }
    157     }
    158 
    159     @Override
    160     public Marshaler<T> createMarshaler(TypeReference<T> managedType, int nativeType) {
    161         return new MarshalerPrimitive(managedType, nativeType);
    162     }
    163 
    164     @Override
    165     public boolean isTypeMappingSupported(TypeReference<T> managedType, int nativeType) {
    166         if (managedType.getType() instanceof Class<?>) {
    167             Class<?> klass = (Class<?>)managedType.getType();
    168 
    169             if (klass == byte.class || klass == Byte.class) {
    170                 return nativeType == TYPE_BYTE;
    171             } else if (klass == int.class || klass == Integer.class) {
    172                 return nativeType == TYPE_INT32;
    173             } else if (klass == float.class || klass == Float.class) {
    174                 return nativeType == TYPE_FLOAT;
    175             } else if (klass == long.class || klass == Long.class) {
    176                 return nativeType == TYPE_INT64;
    177             } else if (klass == double.class || klass == Double.class) {
    178                 return nativeType == TYPE_DOUBLE;
    179             } else if (klass == Rational.class) {
    180                 return nativeType == TYPE_RATIONAL;
    181             }
    182         }
    183         return false;
    184     }
    185 }
    186