/*
 * Copyright (C) 2010 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.hardware.usb;

import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.util.Log;

import com.android.internal.util.Preconditions;

import dalvik.system.CloseGuard;

import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.util.Objects;

/**
 * A class representing USB request packet.
 * This can be used for both reading and writing data to or from a
 * {@link android.hardware.usb.UsbDeviceConnection}.
 * UsbRequests can be used to transfer data on bulk and interrupt endpoints.
 * Requests on bulk endpoints can be sent synchronously via {@link UsbDeviceConnection#bulkTransfer}
 * or asynchronously via {@link #queue} and {@link UsbDeviceConnection#requestWait}.
 * Requests on interrupt endpoints are only send and received asynchronously.
 *
 * <p>Requests on endpoint zero are not supported by this class;
 * use {@link UsbDeviceConnection#controlTransfer} for endpoint zero requests instead.
 */
public class UsbRequest {

    private static final String TAG = "UsbRequest";

    // From drivers/usb/core/devio.c
    static final int MAX_USBFS_BUFFER_SIZE = 16384;

    // used by the JNI code
    @UnsupportedAppUsage
    private long mNativeContext;

    private UsbEndpoint mEndpoint;

    /** The buffer that is currently being read / written */
    @UnsupportedAppUsage
    private ByteBuffer mBuffer;

    /** The amount of data to read / write when using {@link #queue} */
    @UnsupportedAppUsage
    private int mLength;

    // for client use
    private Object mClientData;

    // Prevent the connection from being finalized
    private UsbDeviceConnection mConnection;

    /**
     * Whether this buffer was {@link #queue(ByteBuffer) queued using the new behavior} or
     * {@link #queue(ByteBuffer, int) queued using the deprecated behavior}.
     */
    private boolean mIsUsingNewQueue;

    /** Temporary buffer than might be used while buffer is enqueued */
    private ByteBuffer mTempBuffer;

    private final CloseGuard mCloseGuard = CloseGuard.get();

    /**
     * Lock for queue, enqueue and dequeue, so a queue operation can be finished by a dequeue
     * operation on a different thread.
     */
    private final Object mLock = new Object();

    public UsbRequest() {
    }

    /**
     * Initializes the request so it can read or write data on the given endpoint.
     * Whether the request allows reading or writing depends on the direction of the endpoint.
     *
     * @param endpoint the endpoint to be used for this request.
     * @return true if the request was successfully opened.
     */
    public boolean initialize(UsbDeviceConnection connection, UsbEndpoint endpoint) {
        mEndpoint = endpoint;
        mConnection = Objects.requireNonNull(connection, "connection");

        boolean wasInitialized = native_init(connection, endpoint.getAddress(),
                endpoint.getAttributes(), endpoint.getMaxPacketSize(), endpoint.getInterval());

        if (wasInitialized) {
            mCloseGuard.open("close");
        }

        return wasInitialized;
    }

    /**
     * Releases all resources related to this request.
     */
    public void close() {
        if (mNativeContext != 0) {
            mEndpoint = null;
            mConnection = null;
            native_close();
            mCloseGuard.close();
        }
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            if (mCloseGuard != null) {
                mCloseGuard.warnIfOpen();
            }

            close();
        } finally {
            super.finalize();
        }
    }

    /**
     * Returns the endpoint for the request, or null if the request is not opened.
     *
     * @return the request's endpoint
     */
    public UsbEndpoint getEndpoint() {
        return mEndpoint;
    }

    /**
     * Returns the client data for the request.
     * This can be used in conjunction with {@link #setClientData}
     * to associate another object with this request, which can be useful for
     * maintaining state between calls to {@link #queue} and
     * {@link android.hardware.usb.UsbDeviceConnection#requestWait}
     *
     * @return the client data for the request
     */
    public Object getClientData() {
        return mClientData;
    }

    /**
     * Sets the client data for the request.
     * This can be used in conjunction with {@link #getClientData}
     * to associate another object with this request, which can be useful for
     * maintaining state between calls to {@link #queue} and
     * {@link android.hardware.usb.UsbDeviceConnection#requestWait}
     *
     * @param data the client data for the request
     */
    public void setClientData(Object data) {
        mClientData = data;
    }

    /**
     * Queues the request to send or receive data on its endpoint.
     * <p>For OUT endpoints, the given buffer data will be sent on the endpoint. For IN endpoints,
     * the endpoint will attempt to read the given number of bytes into the specified buffer. If the
     * queueing operation is successful, return true. The result will be returned via
     * {@link UsbDeviceConnection#requestWait}</p>
     *
     * @param buffer the buffer containing the bytes to write, or location to store the results of a
     *               read. Position and array offset will be ignored and assumed to be 0. Limit and
     *               capacity will be ignored. Once the request
     *               {@link UsbDeviceConnection#requestWait() is processed} the position will be set
     *               to the number of bytes read/written.
     * @param length number of bytes to read or write. Before {@value Build.VERSION_CODES#P}, a
     *               value larger than 16384 bytes would be truncated down to 16384. In API
     *               {@value Build.VERSION_CODES#P} and after, any value of length is valid.
     *
     * @return true if the queueing operation succeeded
     *
     * @deprecated Use {@link #queue(ByteBuffer)} instead.
     */
    @Deprecated
    public boolean queue(ByteBuffer buffer, int length) {
        boolean out = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT);
        boolean result;

        if (mConnection.getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.P
                && length > MAX_USBFS_BUFFER_SIZE) {
            length = MAX_USBFS_BUFFER_SIZE;
        }

        synchronized (mLock) {
            // save our buffer for when the request has completed
            mBuffer = buffer;
            mLength = length;

            // Note: On a buffer slice we lost the capacity information about the underlying buffer,
            // hence we cannot check if the access would be a data leak/memory corruption.

            if (buffer.isDirect()) {
                result = native_queue_direct(buffer, length, out);
            } else if (buffer.hasArray()) {
                result = native_queue_array(buffer.array(), length, out);
            } else {
                throw new IllegalArgumentException("buffer is not direct and has no array");
            }
            if (!result) {
                mBuffer = null;
                mLength = 0;
            }
        }

        return result;
    }

    /**
     * Queues the request to send or receive data on its endpoint.
     *
     * <p>For OUT endpoints, the remaining bytes of the buffer will be sent on the endpoint. For IN
     * endpoints, the endpoint will attempt to fill the remaining bytes of the buffer. If the
     * queueing operation is successful, return true. The result will be returned via
     * {@link UsbDeviceConnection#requestWait}</p>
     *
     * @param buffer the buffer containing the bytes to send, or the buffer to fill. The state
     *               of the buffer is undefined until the request is returned by
     *               {@link UsbDeviceConnection#requestWait}. If the request failed the buffer
     *               will be unchanged; if the request succeeded the position of the buffer is
     *               incremented by the number of bytes sent/received. Before
     *               {@value Build.VERSION_CODES#P}, a buffer of length larger than 16384 bytes
     *               would throw IllegalArgumentException. In API {@value Build.VERSION_CODES#P}
     *               and after, any size buffer is valid.
     *
     * @return true if the queueing operation succeeded
     */
    public boolean queue(@Nullable ByteBuffer buffer) {
        // Request need to be initialized
        Preconditions.checkState(mNativeContext != 0, "request is not initialized");

        // Request can not be currently queued
        Preconditions.checkState(!mIsUsingNewQueue, "this request is currently queued");

        boolean isSend = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT);
        boolean wasQueued;

        synchronized (mLock) {
            mBuffer = buffer;

            if (buffer == null) {
                // Null buffers enqueue empty USB requests which is supported
                mIsUsingNewQueue = true;
                wasQueued = native_queue(null, 0, 0);
            } else {
                if (mConnection.getContext().getApplicationInfo().targetSdkVersion
                        < Build.VERSION_CODES.P) {
                    // Can only send/receive MAX_USBFS_BUFFER_SIZE bytes at once
                    Preconditions.checkArgumentInRange(buffer.remaining(), 0, MAX_USBFS_BUFFER_SIZE,
                            "number of remaining bytes");
                }

                // Can not receive into read-only buffers.
                Preconditions.checkArgument(!(buffer.isReadOnly() && !isSend), "buffer can not be "
                        + "read-only when receiving data");

                if (!buffer.isDirect()) {
                    mTempBuffer = ByteBuffer.allocateDirect(mBuffer.remaining());

                    if (isSend) {
                        // Copy buffer into temporary buffer
                        mBuffer.mark();
                        mTempBuffer.put(mBuffer);
                        mTempBuffer.flip();
                        mBuffer.reset();
                    }

                    // Send/Receive into the temp buffer instead
                    buffer = mTempBuffer;
                }

                mIsUsingNewQueue = true;
                wasQueued = native_queue(buffer, buffer.position(), buffer.remaining());
            }
        }

        if (!wasQueued) {
            mIsUsingNewQueue = false;
            mTempBuffer = null;
            mBuffer = null;
        }

        return wasQueued;
    }

    /* package */ void dequeue(boolean useBufferOverflowInsteadOfIllegalArg) {
        boolean isSend = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT);
        int bytesTransferred;

        synchronized (mLock) {
            if (mIsUsingNewQueue) {
                bytesTransferred = native_dequeue_direct();
                mIsUsingNewQueue = false;

                if (mBuffer == null) {
                    // Nothing to do
                } else if (mTempBuffer == null) {
                    mBuffer.position(mBuffer.position() + bytesTransferred);
                } else {
                    mTempBuffer.limit(bytesTransferred);

                    // The user might have modified mBuffer which might make put/position fail.
                    // Changing the buffer while a request is in flight is not supported. Still,
                    // make sure to free mTempBuffer correctly.
                    try {
                        if (isSend) {
                            mBuffer.position(mBuffer.position() + bytesTransferred);
                        } else {
                            // Copy temp buffer back into original buffer
                            mBuffer.put(mTempBuffer);
                        }
                    } finally {
                        mTempBuffer = null;
                    }
                }
            } else {
                if (mBuffer.isDirect()) {
                    bytesTransferred = native_dequeue_direct();
                } else {
                    bytesTransferred = native_dequeue_array(mBuffer.array(), mLength, isSend);
                }
                if (bytesTransferred >= 0) {
                    int bytesToStore = Math.min(bytesTransferred, mLength);
                    try {
                        mBuffer.position(bytesToStore);
                    } catch (IllegalArgumentException e) {
                        if (useBufferOverflowInsteadOfIllegalArg) {
                            Log.e(TAG, "Buffer " + mBuffer + " does not have enough space to read "
                                    + bytesToStore + " bytes", e);
                            throw new BufferOverflowException();
                        } else {
                            throw e;
                        }
                    }
                }
            }

            mBuffer = null;
            mLength = 0;
        }
    }

    /**
     * Cancels a pending queue operation.
     *
     * @return true if cancelling succeeded
     */
    public boolean cancel() {
        if (mConnection == null) {
            return false;
        }

        return mConnection.cancelRequest(this);
    }

    /**
     * Cancels a pending queue operation (for use when the UsbDeviceConnection associated
     * with this request is synchronized). This ensures we don't have a race where the
     * device is closed and then the request is canceled which would lead to a
     * use-after-free because the cancel operation uses the device connection
     * information freed in the when UsbDeviceConnection is closed.<br/>
     *
     * This method assumes the connected is not closed while this method is executed.
     *
     * @return true if cancelling succeeded.
     */
    /* package */ boolean cancelIfOpen() {
        if (mNativeContext == 0 || (mConnection != null && !mConnection.isOpen())) {
            Log.w(TAG,
                    "Detected attempt to cancel a request on a connection which isn't open");
            return false;
        }
        return native_cancel();
    }

    private native boolean native_init(UsbDeviceConnection connection, int ep_address,
            int ep_attributes, int ep_max_packet_size, int ep_interval);
    private native void native_close();
    private native boolean native_queue(ByteBuffer buffer, int offset, int length);
    private native boolean native_queue_array(byte[] buffer, int length, boolean out);
    private native int native_dequeue_array(byte[] buffer, int length, boolean out);
    private native boolean native_queue_direct(ByteBuffer buffer, int length, boolean out);
    private native int native_dequeue_direct();
    private native boolean native_cancel();
}
