13c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin/*
23c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Copyright (C) 2014 The Android Open Source Project
33c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin *
43c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Licensed under the Apache License, Version 2.0 (the "License");
53c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * you may not use this file except in compliance with the License.
63c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * You may obtain a copy of the License at
73c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin *
83c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin *      http://www.apache.org/licenses/LICENSE-2.0
93c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin *
103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Unless required by applicable law or agreed to in writing, software
113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * distributed under the License is distributed on an "AS IS" BASIS,
123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * See the License for the specific language governing permissions and
143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * limitations under the License.
153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */
163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinpackage android.hardware.camera2.marshal;
173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.utils.TypeReference;
193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport java.nio.ByteBuffer;
213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport static android.hardware.camera2.marshal.MarshalHelpers.*;
233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport static com.android.internal.util.Preconditions.*;
243c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin/**
263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * Base class to marshal data to/from managed/native metadata byte buffers.
273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin *
283c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * <p>This class should not be created directly; an instance of it can be obtained
293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * using {@link MarshalQueryable#createMarshaler} for the same type {@code T} if the native type
303c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * mapping for {@code T} {@link MarshalQueryable#isTypeMappingSupported supported}.</p>
313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin *
323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin * @param <T> the compile-time managed type
333c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin */
343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinpublic abstract class Marshaler<T> {
353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    protected final TypeReference<T> mTypeReference;
373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    protected final int mNativeType;
383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /**
403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * Instantiate a marshaler between a single managed/native type combination.
413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <p>This particular managed/native type combination must be supported by
433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * {@link #isTypeMappingSupported}.</p>
443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @param query an instance of {@link MarshalQueryable}
463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @param typeReference the managed type reference
473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *        Must be one for which {@link #isTypeMappingSupported} returns {@code true}
483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @param nativeType the native type, e.g.
493c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *        {@link android.hardware.camera2.impl.CameraMetadataNative#TYPE_BYTE TYPE_BYTE}.
503c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *        Must be one for which {@link #isTypeMappingSupported} returns {@code true}.
513c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
523c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @throws NullPointerException if any args were {@code null}
533c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @throws UnsupportedOperationException if the type mapping was not supported
543c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     */
553c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    protected Marshaler(
563c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            MarshalQueryable<T> query, TypeReference<T> typeReference, int nativeType) {
573c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        mTypeReference = checkNotNull(typeReference, "typeReference must not be null");
583c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        mNativeType = checkNativeType(nativeType);
593c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
603c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        if (!query.isTypeMappingSupported(typeReference, nativeType)) {
613c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            throw new UnsupportedOperationException(
623c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                    "Unsupported type marshaling for managed type "
633c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                            + typeReference + " and native type "
643c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin                            + MarshalHelpers.toStringNativeType(nativeType));
653c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
663c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
673c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
683c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /**
693c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * Marshal the specified object instance (value) into a byte buffer.
703c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
713c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <p>Upon completion, the {@link ByteBuffer#position()} will have advanced by
723c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * the {@link #calculateMarshalSize marshal size} of {@code value}.</p>
733c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
743c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @param value the value of type T that we wish to write into the byte buffer
753c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @param buffer the byte buffer into which the marshaled object will be written
763c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     */
773c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public abstract void marshal(T value, ByteBuffer buffer);
783c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
793c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /**
803c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * Get the size in bytes for how much space would be required to write this {@code value}
813c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * into a byte buffer using the given {@code nativeType}.
823c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
833c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <p>If the size of this {@code T} instance when serialized into a buffer is always constant,
843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * then this method will always return the same value (and particularly, it will return
853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * an equivalent value to {@link #getNativeSize()}.</p>
863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
873c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <p>Overriding this method is a must when the size is {@link NATIVE_SIZE_DYNAMIC dynamic}.</p>
883c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @param value the value of type T that we wish to write into the byte buffer
903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @return the size that would need to be written to the byte buffer
913c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     */
923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public int calculateMarshalSize(T value) {
933c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        int nativeSize = getNativeSize();
943c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
953c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        if (nativeSize == NATIVE_SIZE_DYNAMIC) {
963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin            throw new AssertionError("Override this function for dynamically-sized objects");
973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        }
983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
993c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        return nativeSize;
1003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
1013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /**
1033c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * Unmarshal a new object instance from the byte buffer into its managed type.
1043c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
1053c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <p>Upon completion, the {@link ByteBuffer#position()} will have advanced by
1063c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * the {@link #calculateMarshalSize marshal size} of the returned {@code T} instance.</p>
1073c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
1083c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @param buffer the byte buffer, from which we will read the object
1093c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @return a new instance of type T read from the byte buffer
1103c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     */
1113c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public abstract T unmarshal(ByteBuffer buffer);
1123c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1133c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /**
1143c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * Used to denote variable-length data structures.
1153c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
1163c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <p>If the size is dynamic then we can't know ahead of time how big of a data structure
1173c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * to preallocate for e.g. arrays, so one object must be unmarshaled at a time.</p>
1183c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     */
1193c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public static int NATIVE_SIZE_DYNAMIC = -1;
1203c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1213c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /**
1223c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * How many bytes a single instance of {@code T} will take up if marshalled to/from
1233c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * {@code nativeType}.
1243c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
1253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <p>When unmarshaling data from native to managed, the instance {@code T} is not yet
1263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * available. If the native size is always a fixed mapping regardless of the instance of
1273c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * {@code T} (e.g. if the type is not a container of some sort), it can be used to preallocate
1283c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * containers for {@code T} to avoid resizing them.</p>
1293c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
1303c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <p>In particular, the array marshaler takes advantage of this (when size is not dynamic)
1313c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * to preallocate arrays of the right length when unmarshaling an array {@code T[]}.</p>
1323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     *
1333c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * @return a size in bytes, or {@link #NATIVE_SIZE_DYNAMIC} if the size is dynamic
1343c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     */
1353c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public abstract int getNativeSize();
1363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /**
1383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * The type reference for {@code T} for the managed type side of this marshaler.
1393c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     */
1403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public TypeReference<T> getTypeReference() {
1413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        return mTypeReference;
1423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
1433c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
1443c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /** The native type corresponding to this marshaler for the native side of this marshaler.*/
1453c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    public int getNativeType() {
1463c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        return mNativeType;
1473c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
1483c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin}
149