Home | History | Annotate | Download | only in marshal
      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;
     17 
     18 import android.hardware.camera2.utils.TypeReference;
     19 
     20 import java.nio.ByteBuffer;
     21 
     22 import static android.hardware.camera2.marshal.MarshalHelpers.*;
     23 import static com.android.internal.util.Preconditions.*;
     24 
     25 /**
     26  * Base class to marshal data to/from managed/native metadata byte buffers.
     27  *
     28  * <p>This class should not be created directly; an instance of it can be obtained
     29  * using {@link MarshalQueryable#createMarshaler} for the same type {@code T} if the native type
     30  * mapping for {@code T} {@link MarshalQueryable#isTypeMappingSupported supported}.</p>
     31  *
     32  * @param <T> the compile-time managed type
     33  */
     34 public abstract class Marshaler<T> {
     35 
     36     protected final TypeReference<T> mTypeReference;
     37     protected final int mNativeType;
     38 
     39     /**
     40      * Instantiate a marshaler between a single managed/native type combination.
     41      *
     42      * <p>This particular managed/native type combination must be supported by
     43      * {@link #isTypeMappingSupported}.</p>
     44      *
     45      * @param query an instance of {@link MarshalQueryable}
     46      * @param typeReference the managed type reference
     47      *        Must be one for which {@link #isTypeMappingSupported} returns {@code true}
     48      * @param nativeType the native type, e.g.
     49      *        {@link android.hardware.camera2.impl.CameraMetadataNative#TYPE_BYTE TYPE_BYTE}.
     50      *        Must be one for which {@link #isTypeMappingSupported} returns {@code true}.
     51      *
     52      * @throws NullPointerException if any args were {@code null}
     53      * @throws UnsupportedOperationException if the type mapping was not supported
     54      */
     55     protected Marshaler(
     56             MarshalQueryable<T> query, TypeReference<T> typeReference, int nativeType) {
     57         mTypeReference = checkNotNull(typeReference, "typeReference must not be null");
     58         mNativeType = checkNativeType(nativeType);
     59 
     60         if (!query.isTypeMappingSupported(typeReference, nativeType)) {
     61             throw new UnsupportedOperationException(
     62                     "Unsupported type marshaling for managed type "
     63                             + typeReference + " and native type "
     64                             + MarshalHelpers.toStringNativeType(nativeType));
     65         }
     66     }
     67 
     68     /**
     69      * Marshal the specified object instance (value) into a byte buffer.
     70      *
     71      * <p>Upon completion, the {@link ByteBuffer#position()} will have advanced by
     72      * the {@link #calculateMarshalSize marshal size} of {@code value}.</p>
     73      *
     74      * @param value the value of type T that we wish to write into the byte buffer
     75      * @param buffer the byte buffer into which the marshaled object will be written
     76      */
     77     public abstract void marshal(T value, ByteBuffer buffer);
     78 
     79     /**
     80      * Get the size in bytes for how much space would be required to write this {@code value}
     81      * into a byte buffer using the given {@code nativeType}.
     82      *
     83      * <p>If the size of this {@code T} instance when serialized into a buffer is always constant,
     84      * then this method will always return the same value (and particularly, it will return
     85      * an equivalent value to {@link #getNativeSize()}.</p>
     86      *
     87      * <p>Overriding this method is a must when the size is {@link NATIVE_SIZE_DYNAMIC dynamic}.</p>
     88      *
     89      * @param value the value of type T that we wish to write into the byte buffer
     90      * @return the size that would need to be written to the byte buffer
     91      */
     92     public int calculateMarshalSize(T value) {
     93         int nativeSize = getNativeSize();
     94 
     95         if (nativeSize == NATIVE_SIZE_DYNAMIC) {
     96             throw new AssertionError("Override this function for dynamically-sized objects");
     97         }
     98 
     99         return nativeSize;
    100     }
    101 
    102     /**
    103      * Unmarshal a new object instance from the byte buffer into its managed type.
    104      *
    105      * <p>Upon completion, the {@link ByteBuffer#position()} will have advanced by
    106      * the {@link #calculateMarshalSize marshal size} of the returned {@code T} instance.</p>
    107      *
    108      * @param buffer the byte buffer, from which we will read the object
    109      * @return a new instance of type T read from the byte buffer
    110      */
    111     public abstract T unmarshal(ByteBuffer buffer);
    112 
    113     /**
    114      * Used to denote variable-length data structures.
    115      *
    116      * <p>If the size is dynamic then we can't know ahead of time how big of a data structure
    117      * to preallocate for e.g. arrays, so one object must be unmarshaled at a time.</p>
    118      */
    119     public static int NATIVE_SIZE_DYNAMIC = -1;
    120 
    121     /**
    122      * How many bytes a single instance of {@code T} will take up if marshalled to/from
    123      * {@code nativeType}.
    124      *
    125      * <p>When unmarshaling data from native to managed, the instance {@code T} is not yet
    126      * available. If the native size is always a fixed mapping regardless of the instance of
    127      * {@code T} (e.g. if the type is not a container of some sort), it can be used to preallocate
    128      * containers for {@code T} to avoid resizing them.</p>
    129      *
    130      * <p>In particular, the array marshaler takes advantage of this (when size is not dynamic)
    131      * to preallocate arrays of the right length when unmarshaling an array {@code T[]}.</p>
    132      *
    133      * @return a size in bytes, or {@link #NATIVE_SIZE_DYNAMIC} if the size is dynamic
    134      */
    135     public abstract int getNativeSize();
    136 
    137     /**
    138      * The type reference for {@code T} for the managed type side of this marshaler.
    139      */
    140     public TypeReference<T> getTypeReference() {
    141         return mTypeReference;
    142     }
    143 
    144     /** The native type corresponding to this marshaler for the native side of this marshaler.*/
    145     public int getNativeType() {
    146         return mNativeType;
    147     }
    148 }
    149