/*
 * Copyright (C) 2016 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.os;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;

import dalvik.annotation.optimization.FastNative;

import libcore.util.NativeAllocationRegistry;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;

/** @hide */
@SystemApi
@TestApi
public class HwParcel {
    private static final String TAG = "HwParcel";

    /** @hide */
    @IntDef(prefix = { "STATUS_" }, value = {
        STATUS_SUCCESS,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Status {}

    /**
     * Success return error for a transaction. Written to parcels
     * using writeStatus.
     */
    public static final int STATUS_SUCCESS      = 0;

    private static final NativeAllocationRegistry sNativeRegistry;

    @UnsupportedAppUsage
    private HwParcel(boolean allocate) {
        native_setup(allocate);

        sNativeRegistry.registerNativeAllocation(
                this,
                mNativeContext);
    }

    /**
     * Creates an initialized and empty parcel.
     */
    public HwParcel() {
        native_setup(true /* allocate */);

        sNativeRegistry.registerNativeAllocation(
                this,
                mNativeContext);
    }

    /**
     * Writes an interface token into the parcel used to verify that
     * a transaction has made it to the right type of interface.
     *
     * @param interfaceName fully qualified name of interface message
     *     is being sent to.
     */
    @FastNative
    public native final void writeInterfaceToken(String interfaceName);
    /**
     * Writes a boolean value to the end of the parcel.
     * @param val to write
     */
    @FastNative
    public native final void writeBool(boolean val);
    /**
     * Writes a byte value to the end of the parcel.
     * @param val to write
     */
    @FastNative
    public native final void writeInt8(byte val);
    /**
     * Writes a short value to the end of the parcel.
     * @param val to write
     */
    @FastNative
    public native final void writeInt16(short val);
    /**
     * Writes a int value to the end of the parcel.
     * @param val to write
     */
    @FastNative
    public native final void writeInt32(int val);
    /**
     * Writes a long value to the end of the parcel.
     * @param val to write
     */
    @FastNative
    public native final void writeInt64(long val);
    /**
     * Writes a float value to the end of the parcel.
     * @param val to write
     */
    @FastNative
    public native final void writeFloat(float val);
    /**
     * Writes a double value to the end of the parcel.
     * @param val to write
     */
    @FastNative
    public native final void writeDouble(double val);
    /**
     * Writes a String value to the end of the parcel.
     *
     * Note, this will be converted to UTF-8 when it is written.
     *
     * @param val to write
     */
    @FastNative
    public native final void writeString(String val);
    /**
     * Writes a native handle (without duplicating the underlying
     * file descriptors) to the end of the parcel.
     *
     * @param val to write
     */
    @FastNative
    public native final void writeNativeHandle(@Nullable NativeHandle val);

    /**
     * Writes an array of boolean values to the end of the parcel.
     * @param val to write
     */
    @FastNative
    private native final void writeBoolVector(boolean[] val);
    /**
     * Writes an array of byte values to the end of the parcel.
     * @param val to write
     */
    @FastNative
    private native final void writeInt8Vector(byte[] val);
    /**
     * Writes an array of short values to the end of the parcel.
     * @param val to write
     */
    @FastNative
    private native final void writeInt16Vector(short[] val);
    /**
     * Writes an array of int values to the end of the parcel.
     * @param val to write
     */
    @FastNative
    private native final void writeInt32Vector(int[] val);
    /**
     * Writes an array of long values to the end of the parcel.
     * @param val to write
     */
    @FastNative
    private native final void writeInt64Vector(long[] val);
    /**
     * Writes an array of float values to the end of the parcel.
     * @param val to write
     */
    @FastNative
    private native final void writeFloatVector(float[] val);
    /**
     * Writes an array of double values to the end of the parcel.
     * @param val to write
     */
    @FastNative
    private native final void writeDoubleVector(double[] val);
    /**
     * Writes an array of String values to the end of the parcel.
     *
     * Note, these will be converted to UTF-8 as they are written.
     *
     * @param val to write
     */
    @FastNative
    private native final void writeStringVector(String[] val);
    /**
     * Writes an array of native handles to the end of the parcel.
     *
     * Individual elements may be null but not the whole array.
     *
     * @param val array of {@link NativeHandle} objects to write
     */
    @FastNative
    private native final void writeNativeHandleVector(NativeHandle[] val);

    /**
     * Helper method to write a list of Booleans to val.
     * @param val list to write
     */
    public final void writeBoolVector(ArrayList<Boolean> val) {
        final int n = val.size();
        boolean[] array = new boolean[n];
        for (int i = 0; i < n; ++i) {
            array[i] = val.get(i);
        }

        writeBoolVector(array);
    }

    /**
     * Helper method to write a list of Booleans to the end of the parcel.
     * @param val list to write
     */
    public final void writeInt8Vector(ArrayList<Byte> val) {
        final int n = val.size();
        byte[] array = new byte[n];
        for (int i = 0; i < n; ++i) {
            array[i] = val.get(i);
        }

        writeInt8Vector(array);
    }

    /**
     * Helper method to write a list of Shorts to the end of the parcel.
     * @param val list to write
     */
    public final void writeInt16Vector(ArrayList<Short> val) {
        final int n = val.size();
        short[] array = new short[n];
        for (int i = 0; i < n; ++i) {
            array[i] = val.get(i);
        }

        writeInt16Vector(array);
    }

    /**
     * Helper method to write a list of Integers to the end of the parcel.
     * @param val list to write
     */
    public final void writeInt32Vector(ArrayList<Integer> val) {
        final int n = val.size();
        int[] array = new int[n];
        for (int i = 0; i < n; ++i) {
            array[i] = val.get(i);
        }

        writeInt32Vector(array);
    }

    /**
     * Helper method to write a list of Longs to the end of the parcel.
     * @param val list to write
     */
    public final void writeInt64Vector(ArrayList<Long> val) {
        final int n = val.size();
        long[] array = new long[n];
        for (int i = 0; i < n; ++i) {
            array[i] = val.get(i);
        }

        writeInt64Vector(array);
    }

    /**
     * Helper method to write a list of Floats to the end of the parcel.
     * @param val list to write
     */
    public final void writeFloatVector(ArrayList<Float> val) {
        final int n = val.size();
        float[] array = new float[n];
        for (int i = 0; i < n; ++i) {
            array[i] = val.get(i);
        }

        writeFloatVector(array);
    }

    /**
     * Helper method to write a list of Doubles to the end of the parcel.
     * @param val list to write
     */
    public final void writeDoubleVector(ArrayList<Double> val) {
        final int n = val.size();
        double[] array = new double[n];
        for (int i = 0; i < n; ++i) {
            array[i] = val.get(i);
        }

        writeDoubleVector(array);
    }

    /**
     * Helper method to write a list of Strings to the end of the parcel.
     * @param val list to write
     */
    public final void writeStringVector(ArrayList<String> val) {
        writeStringVector(val.toArray(new String[val.size()]));
    }

    /**
     * Helper method to write a list of native handles to the end of the parcel.
     * @param val list of {@link NativeHandle} objects to write
     */
    public final void writeNativeHandleVector(@NonNull ArrayList<NativeHandle> val) {
        writeNativeHandleVector(val.toArray(new NativeHandle[val.size()]));
    }

    /**
     * Write a hwbinder object to the end of the parcel.
     * @param binder value to write
     */
    @FastNative
    public native final void writeStrongBinder(IHwBinder binder);

    /**
     * Write a HidlMemory object (without duplicating the underlying file descriptors) to the end
     * of the parcel.
     *
     * @param memory value to write
     */
    @FastNative
    public native final void writeHidlMemory(@NonNull HidlMemory memory);

    /**
     * Checks to make sure that the interface name matches the name written by the parcel
     * sender by writeInterfaceToken
     *
     * @throws SecurityException interface doesn't match
     */
    public native final void enforceInterface(String interfaceName);

    /**
     * Reads a boolean value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    public native final boolean readBool();
    /**
     * Reads a byte value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    public native final byte readInt8();
    /**
     * Reads a short value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    public native final short readInt16();
    /**
     * Reads a int value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    public native final int readInt32();
    /**
     * Reads a long value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    public native final long readInt64();
    /**
     * Reads a float value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    public native final float readFloat();
    /**
     * Reads a double value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    public native final double readDouble();
    /**
     * Reads a String value from the current location in the parcel.
     * @return value parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    public native final String readString();
    /**
     * Reads a native handle (without duplicating the underlying file
     * descriptors) from the parcel. These file descriptors will only
     * be open for the duration that the binder window is open. If they
     * are needed further, you must call {@link NativeHandle#dup()}.
     *
     * @return a {@link NativeHandle} instance parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    public native final @Nullable NativeHandle readNativeHandle();
    /**
     * Reads an embedded native handle (without duplicating the underlying
     * file descriptors) from the parcel. These file descriptors will only
     * be open for the duration that the binder window is open. If they
     * are needed further, you must call {@link NativeHandle#dup()}. You
     * do not need to call close on the NativeHandle returned from this.
     *
     * @param parentHandle handle from which to read the embedded object
     * @param offset offset into parent
     * @return a {@link NativeHandle} instance parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    public native final @Nullable NativeHandle readEmbeddedNativeHandle(
            long parentHandle, long offset);

    /**
     * Reads an array of boolean values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    private native final boolean[] readBoolVectorAsArray();
    /**
     * Reads an array of byte values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    private native final byte[] readInt8VectorAsArray();
    /**
     * Reads an array of short values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    private native final short[] readInt16VectorAsArray();
    /**
     * Reads an array of int values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    private native final int[] readInt32VectorAsArray();
    /**
     * Reads an array of long values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    private native final long[] readInt64VectorAsArray();
    /**
     * Reads an array of float values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    private native final float[] readFloatVectorAsArray();
    /**
     * Reads an array of double values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    private native final double[] readDoubleVectorAsArray();
    /**
     * Reads an array of String values from the parcel.
     * @return array of parsed values
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    private native final String[] readStringVectorAsArray();
    /**
     * Reads an array of native handles from the parcel.
     * @return array of {@link NativeHandle} objects
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    private native final NativeHandle[] readNativeHandleAsArray();

    /**
     * Convenience method to read a Boolean vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<Boolean> readBoolVector() {
        Boolean[] array = HwBlob.wrapArray(readBoolVectorAsArray());

        return new ArrayList<Boolean>(Arrays.asList(array));
    }

    /**
     * Convenience method to read a Byte vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<Byte> readInt8Vector() {
        Byte[] array = HwBlob.wrapArray(readInt8VectorAsArray());

        return new ArrayList<Byte>(Arrays.asList(array));
    }

    /**
     * Convenience method to read a Short vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<Short> readInt16Vector() {
        Short[] array = HwBlob.wrapArray(readInt16VectorAsArray());

        return new ArrayList<Short>(Arrays.asList(array));
    }

    /**
     * Convenience method to read a Integer vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<Integer> readInt32Vector() {
        Integer[] array = HwBlob.wrapArray(readInt32VectorAsArray());

        return new ArrayList<Integer>(Arrays.asList(array));
    }

    /**
     * Convenience method to read a Long vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<Long> readInt64Vector() {
        Long[] array = HwBlob.wrapArray(readInt64VectorAsArray());

        return new ArrayList<Long>(Arrays.asList(array));
    }

    /**
     * Convenience method to read a Float vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<Float> readFloatVector() {
        Float[] array = HwBlob.wrapArray(readFloatVectorAsArray());

        return new ArrayList<Float>(Arrays.asList(array));
    }

    /**
     * Convenience method to read a Double vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<Double> readDoubleVector() {
        Double[] array = HwBlob.wrapArray(readDoubleVectorAsArray());

        return new ArrayList<Double>(Arrays.asList(array));
    }

    /**
     * Convenience method to read a String vector as an ArrayList.
     * @return array of parsed values.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final ArrayList<String> readStringVector() {
        return new ArrayList<String>(Arrays.asList(readStringVectorAsArray()));
    }

    /**
     * Convenience method to read a vector of native handles as an ArrayList.
     * @return array of {@link NativeHandle} objects.
     * @throws IllegalArgumentException if the parcel has no more data
     */
    public final @NonNull ArrayList<NativeHandle> readNativeHandleVector() {
        return new ArrayList<NativeHandle>(Arrays.asList(readNativeHandleAsArray()));
    }

    /**
     * Reads a strong binder value from the parcel.
     * @return binder object read from parcel or null if no binder can be read
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    public native final IHwBinder readStrongBinder();

    /**
     * Reads a HidlMemory value (without duplicating the underlying file
     * descriptors) from the parcel. These file descriptors will only
     * be open for the duration that the binder window is open. If they
     * are needed further, you must call {@link HidlMemory#dup()}, which makes you also
     * responsible for calling {@link HidlMemory#close()}.
     *
     * @return HidlMemory object read from parcel.
     * @throws IllegalArgumentException if the parcel has no more data or is otherwise corrupt.
     */
    @FastNative
    @NonNull
    public native final HidlMemory readHidlMemory();

    /**
     * Reads an embedded HidlMemory (without duplicating the underlying
     * file descriptors) from the parcel. These file descriptors will only
     * be open for the duration that the binder window is open. If they
     * are needed further, you must call {@link HidlMemory#dup()}. You
     * do not need to call close on the HidlMemory returned from this.
     *
     * @param fieldHandle  handle of the field, obtained from the {@link HwBlob}.
     * @param parentHandle parentHandle from which to read the embedded object
     * @param offset       offset into parent
     * @return a {@link HidlMemory} instance parsed from the parcel
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    @NonNull
    public native final @Nullable
    HidlMemory readEmbeddedHidlMemory(long fieldHandle, long parentHandle, long offset);

    /**
     * Read opaque segment of data as a blob.
     * @return blob of size expectedSize
     * @throws IllegalArgumentException if the parcel has no more data
     */
    @FastNative
    public native final HwBlob readBuffer(long expectedSize);

    /**
     * Read a buffer written using scatter gather.
     *
     * @param expectedSize size that buffer should be
     * @param parentHandle handle from which to read the embedded buffer
     * @param offset offset into parent
     * @param nullable whether or not to allow for a null return
     * @return blob of data with size expectedSize
     * @throws NoSuchElementException if an embedded buffer is not available to read
     * @throws IllegalArgumentException if expectedSize < 0
     * @throws NullPointerException if the transaction specified the blob to be null
     *    but nullable is false
     */
    @FastNative
    public native final HwBlob readEmbeddedBuffer(
            long expectedSize, long parentHandle, long offset,
            boolean nullable);

    /**
     * Write a buffer into the transaction.
     * @param blob blob to write into the parcel.
     */
    @FastNative
    public native final void writeBuffer(HwBlob blob);
    /**
     * Write a status value into the blob.
     * @param status value to write
     */
    @FastNative
    public native final void writeStatus(int status);
    /**
     * @throws IllegalArgumentException if a success vaue cannot be read
     * @throws RemoteException if success value indicates a transaction error
     */
    @FastNative
    public native final void verifySuccess();
    /**
     * Should be called to reduce memory pressure when this object no longer needs
     * to be written to.
     */
    @FastNative
    public native final void releaseTemporaryStorage();
    /**
     * Should be called when object is no longer needed to reduce possible memory
     * pressure if the Java GC does not get to this object in time.
     */
    @FastNative
    public native final void release();

    /**
     * Sends the parcel to the specified destination.
     */
    public native final void send();

    // Returns address of the "freeFunction".
    private static native final long native_init();

    @FastNative
    private native final void native_setup(boolean allocate);

    static {
        long freeFunction = native_init();

        sNativeRegistry = new NativeAllocationRegistry(
                HwParcel.class.getClassLoader(),
                freeFunction,
                128 /* size */);
    }

    private long mNativeContext;
}

