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