/*
 * Copyright (C) 2018 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.graphics.bufferqueue@2.0;

import android.hardware.graphics.common@1.2::HardwareBuffer;
import android.hardware.graphics.common@1.2::HardwareBufferDescription;
import android.hardware.graphics.common@1.2::Rect;

import IProducerListener;

/**
 * Ref: frameworks/native/include/gui/IGraphicBufferProducer.h:
 *      IGraphicBufferProducer
 * This is a wrapper/wrapped HAL interface for the actual binder interface.
 */
interface IGraphicBufferProducer {
    /**
     * Sets the maximum number of buffers that can be dequeued at one time. If
     * this method succeeds, any new buffer slots shall be both unallocated and
     * owned by the buffer queue, i.e., they are not owned by the producer or
     * the consumer. Calling this may cause some buffer slots to be emptied. If
     * the caller is caching the contents of the buffer slots, it must empty
     * that cache after calling this method.
     *
     * @p maxDequeuedBuffers must not be less than the number of currently
     * dequeued buffer slots; otherwise, the returned @p status shall be
     * `BAD_VALUE`.
     *
     * @p maxDequeuedBuffers must be at least 1 (inclusive), but at most
     * (`NUM_BUFFER_SLOTS` - the minimum undequeued buffer count) (exclusive).
     * The minimum undequeued buffer count can be obtained by calling
     * `query(ANATIVEWINDOW_QUERY_MIN_UNDEQUEUED_BUFFERS)`.
     *
     * Before calling setMaxDequeuedBufferCount(), the caller must make sure
     * that
     *   - @p maxDequeuedBuffers is greater than or equal to 1.
     *   - @p maxDequeuedBuffers is greater than or equal to the number of
     *     currently dequeued buffer slots.
     * If any of these conditions do not hold, or if the request to set the new
     * maximum number of dequeued buffers cannot be accomplished for any other
     * reasons, `BAD_VALUE` shall be returned in @p status.
     *
     * @param maxDequeuedBuffers The desired number of buffers that can be
     *     dequeued at one time.
     * @return status Status of the call.
     */
    setMaxDequeuedBufferCount(
            int32_t maxDequeuedBuffers
        ) generates (
            Status status
        );

    /**
     * Assigns a newly created buffer to the given slot index. The client is
     * expected to mirror the slot-to-buffer mapping so that it is not necessary
     * to transfer a `HardwareBuffer` object for every dequeue operation.
     *
     * If @p slot is not a valid slot index corresponding to a dequeued buffer,
     * the call shall fail with @p status set to `BAD_VALUE`.
     *
     * @param slot Slot index.
     * @return status Status of the call.
     * @return buffer New buffer associated to the given slot index.
     * @return generationNumber Generation number of the buffer. If
     *     requestBuffer() is called immediately after dequeueBuffer() returns
     *     with `bufferNeedsReallocation` set to `true`, @p generationNumber must
     *     match the current generation number of the buffer queue previously
     *     set by setGenerationNumber(). Otherwise, @p generationNumber may not
     *     match the current generation number of the buffer queue.
     */
    requestBuffer(
            int32_t slot
        ) generates (
            Status status,
            HardwareBuffer buffer,
            uint32_t generationNumber
        );

    /**
     * Sets the async flag: whether the producer intends to asynchronously queue
     * buffers without blocking. Typically this is used for triple-buffering
     * and/or when the swap interval is set to zero.
     *
     * Enabling async mode may internally allocate an additional buffer to allow
     * for the asynchronous behavior. If it is not enabled, queue/dequeue calls
     * may block.
     *
     * Changing the async flag may affect the number of available slots. If the
     * adjustment to the number of slots cannot be made, @p status shall be set
     * to `BAD_VALUE`.
     *
     * @param async True if the asynchronous operation is desired; false
     *     otherwise.
     * @return status Status of the call.
     */
    setAsyncMode(
            bool async
        ) generates (
            Status status
        );

    /**
     * Input data for dequeueBuffer() specifying desired attributes of a buffer
     * to dequeue.
     *
     * This structure contains 4 fields from
     * +llndk libnativewindow#AHardwareBuffer_Desc.
     *
     * The `width` and `height` parameters must be no greater than the minimum
     * of `GL_MAX_VIEWPORT_DIMS` and `GL_MAX_TEXTURE_SIZE` (see:
     * glGetIntegerv()). An error due to invalid dimensions may not be reported
     * until updateTexImage() is called.
     *
     * If `width` and `height` are both zero, the default dimensions shall be
     * used. If only one of `width` and `height` is zero, dequeueBuffer() shall
     * return `BAD_VALUE` in `status`.
     *
     * If `format` is zero, the default format shall be used.
     *
     * `usage` shall be merged with the usage flags set from the consumer side.
     *
     * @sa +llndk libnativewindow#AHardwareBuffer_Desc.
     */
    struct DequeueBufferInput {
        uint32_t width;
        uint32_t height;
        uint32_t format;
        uint64_t usage;
    };

    /**
     * Output data for dequeueBuffer().
     *
     * A `DequeueBufferOutput` object returned from dequeueBuffer() shall be
     * valid if and only if `status` returned from the same call is `OK`.
     */
    struct DequeueBufferOutput {
        /**
         * The number of frames that have elapsed since the buffer was last
         * queued.
         */
        uint64_t bufferAge;
        /**
         * Whether the client must call requestBuffer().
         */
        bool bufferNeedsReallocation;
        /**
         * Whether the client must discard the mirrored slot-to-buffer
         * mapping.
         */
        bool releaseAllBuffers;
        /**
         * Fence associated with the buffer.
         *
         * If this is an empty fence, the buffer may be written immediately;
         * otherwise, the buffer must not be written to until the fence signals.
         */
        Fence fence;
    };

    /**
     * Requests a new buffer slot for the client to use. Ownership of the slot
     * is transfered to the client, meaning that the server shall not use the
     * contents of the buffer associated with that slot.
     *
     * On success, @p status shall be `OK`, and @p output shall contain valid
     * information of the call. Otherwise, the contents of @p output are
     * meaningless.
     *
     * The slot index returned in @p slot may or may not contain a buffer
     * (client-side). If the slot is empty, the client must call
     * requestBuffer() to assign a new buffer to that slot.
     *
     * Once the client is done filling this buffer, it is expected to transfer
     * buffer ownership back to the server with either cancelBuffer() on
     * the dequeued slot or to fill in the contents of its associated buffer
     * contents and call queueBuffer().
     *
     * If dequeueBuffer() returns with `output.releaseAllBuffers` set to `true`,
     * the client is expected to release all of the mirrored slot-to-buffer
     * mappings.
     *
     * If dequeueBuffer() returns with `output.bufferNeedsReallocation` set to
     * `true`, the client is expected to call requestBuffer() immediately.
     *
     * The returned `output.fence` shall be updated to hold the fence associated
     * with the buffer. The contents of the buffer must not be overwritten until
     * the fence signals. If the fence is an empty fence, the buffer may be
     * written immediately.
     *
     * This call shall block until a buffer is available to be dequeued. If
     * both the producer and consumer are controlled by the app, then this call
     * can never block and shall return `WOULD_BLOCK` in @p status if no buffer
     * is available.
     *
     * If a dequeue operation shall cause certain conditions on the number of
     * buffers to be violated (such as the maximum number of dequeued buffers),
     * @p status shall be set to `INVALID_OPERATION` to indicate failure.
     *
     * If a dequeue operation cannot be completed within the time period
     * previously set by setDequeueTimeout(), the return @p status shall
     * `TIMED_OUT`.
     *
     * See @ref DequeueBufferInput for more information on the @p input
     * parameter.
     *
     * @param input See #DequeueBufferInput for more information.
     * @return status Status of the call.
     * @return slot Slot index.
     * @return output See #DequeueBufferOutput for more information.
     *
     * @sa queueBuffer(), requestBuffer().
     */
    dequeueBuffer(
            DequeueBufferInput input
        ) generates (
            Status status,
            int32_t slot,
            DequeueBufferOutput output
        );

    /**
     * Attempts to remove all ownership of the buffer in the given slot from the
     * buffer queue.
     *
     * If this call succeeds, the slot shall be freed, and there shall be no way
     * to obtain the buffer from this interface. The freed slot shall remain
     * unallocated until either it is selected to hold a freshly allocated
     * buffer in dequeueBuffer() or a buffer is attached to the slot. The buffer
     * must have already been dequeued, and the caller must already possesses
     * the buffer (i.e., must have called requestBuffer()).
     *
     * @param slot Slot index.
     * @return status Status of the call.
     */
    detachBuffer(
            int32_t slot
        ) generates (
            Status status
        );

    /**
     * Dequeues a buffer slot, requests the buffer associated to the slot, and
     * detaches it from the buffer queue. This is equivalent to calling
     * dequeueBuffer(), requestBuffer(), and detachBuffer() in succession except
     * for two things:
     *   1. It is unnecessary to provide a #DequeueBufferInput object.
     *   2. The call shall not block, since if it cannot find an appropriate
     *      buffer to return, it shall return an error instead.
     *
     * Only slots that are free but still contain a buffer shall be considered,
     * and the oldest of those shall be returned. @p buffer is equivalent to the
     * buffer that would be returned from requestBuffer(), and @p fence is
     * equivalent to the fence that would be returned from dequeueBuffer().
     *
     * @return status Status of the call.
     * @return buffer Buffer just released from the buffer queue.
     * @return fence Fence associated to @p buffer.
     *
     * @sa dequeueBuffer(), requestBuffer(), detachBuffer().
     */
    detachNextBuffer(
        ) generates (
            Status status,
            HardwareBuffer buffer,
            Fence fence
        );

    /**
     * Attempts to transfer ownership of a buffer to the buffer queue.
     *
     * If this call succeeds, it shall be as if this buffer was dequeued from the
     * returned slot index. As such, this call shall fail if attaching this
     * buffer would cause too many buffers to be simultaneously dequeued.
     *
     * If the returned @p releaseAllBuffers is `true`, the caller is expected to
     * release all of the mirrored slot-to-buffer mappings.
     *
     * See dequeueBuffer() for conditions that may cause the call to fail.
     *
     * @param buffer Buffer to attach to the buffer queue.
     * @param generationNumber Generation number of the buffer. If this does not
     *     match the current generation number of the buffer queue, the call
     *     must fail with @p status set to `BAD_VALUE`.
     * @return status Status of the call.
     * @return slot Slot index assigned to @p buffer.
     * @return releaseAllBuffers Whether the caller is expected to release all
     *     of the mirrored slot-to-buffer mappings.
     *
     * @sa dequeueBuffer().
     */
    attachBuffer(
            HardwareBuffer buffer,
            uint32_t generationNumber
        ) generates (
            Status status,
            int32_t slot,
            bool releaseAllBuffers
        );

    struct QueueBufferInput {
        /**
         * Timestamp in nanoseconds.
         */
        int64_t timestamp;
        /**
         * Whether the timestamp was synthesized at queue time.
         */
        bool isAutoTimestamp;
        /**
         * Dataspace of the contents.
         *
         * @sa +ndk libnativewindow#ADataSpace.
         */
        int32_t dataSpace;
        /**
         * Crop rectangle that is used as a hint to the consumer.
         */
        Rect crop;
        /**
         * Transformation flags.
         *
         * @sa +ndk libnativewindow#ANativeWindowTransform.
         */
        int32_t transform;
        /**
         * The sticky transform set in Surface (only used by the LEGACY camera
         * mode).
         *
         * @sa +ndk libnativewindow#ANativeWindowTransform.
         */
        int32_t stickyTransform;
        /**
         * Fence that the consumer must wait on before reading the buffer. An
         * empty fence indicates that the buffer is ready immediately.
         */
        Fence fence;
        /**
         * List of rectangular pieces covering the damage region.
         */
        vec<Rect> surfaceDamage;
    };

    /**
     * Information about the queued buffer. `QueueBufferOutput` is used in both
     * queueBuffer() and connect().
     */
    struct QueueBufferOutput {
        /**
         * Default width of a buffer in the buffer queue.
         */
        uint32_t width;
        /**
         * Default height of a buffer in the buffer queue.
         */
        uint32_t height;
        /**
         * The transform hint of the buffer queue.
         *
         * @sa +ndk libnativewindow#ANativeWindowTransform.
         */
        int32_t transformHint;
        /**
         * The number of pending buffers in the buffer queue. If this is
         * returned from queueBuffer(), the number shall include the buffer that
         * has just been queued.
         */
        uint32_t numPendingBuffers;
        /**
         * The frame number of the next frame. The buffer queue maintains this
         * number and makes sure that it is increasing for every successful
         * queueBuffer() call.
         */
        uint64_t nextFrameNumber;
        /**
         * After a successful queueBuffer() call, #bufferReplaced shall be set to
         * true if the queued buffer replaced a previously queued buffer that
         * has not been consumed.
         */
        bool bufferReplaced;
    };

    /**
     * Indicates that the client has finished filling in the contents of the
     * buffer associated with slot and transfers ownership of that slot back to
     * the buffer queue.
     *
     * @p status may be set to `BAD_VALUE` if any of the following conditions
     * hold:
     *   - The buffer queue is operating in the asynchronous mode, and the
     *     buffer count was smaller than the maximum number of buffers that can
     *     be allocated at once.
     *   - @p slot is an invalid slot index, i.e., the slot is not owned by the
     *     client by previously calling dequeueBuffer(), requestBuffer() or
     *     attachBuffer().
     *   - The crop rectangle is not contained in the buffer.
     *
     * Upon success, the output shall be filled with meaningful values
     * (refer to the documentation of @ref QueueBufferOutput).
     *
     * @param slot Slot index.
     * @param input See @ref QueueBufferInput.
     * @return status Status of the call.
     * @return output See @ref QueueBufferOutput.
     *
     * @sa #QueueBufferInput, #QueueBufferOutput, dequeueBuffer().
     */
    queueBuffer(
            int32_t slot,
            QueueBufferInput input
        ) generates (
            Status status,
            QueueBufferOutput output
        );

    /**
     * Indicates that the client does not wish to fill in the buffer associated
     * with the slot and transfers ownership of the slot back to the server. The
     * buffer is not queued for use by the consumer.
     *
     * If @p fence is not an empty fence, the buffer shall not be overwritten
     * until the fence signals. @p fence is usually obtained from
     * dequeueBuffer().
     *
     * @param slot Slot index.
     * @param fence Fence for the canceled buffer.
     * @return status Status of the call.
     */
    cancelBuffer(
            int32_t slot,
            Fence fence
        ) generates (
            Status status
        );

    /**
     * Retrieves information for this surface.
     *
     * @param what What to query. @p what must be one of the values in
     *     +llndk libnativewindow#ANativeWindowQuery.
     * @return status Status of the call.
     * @return value The value queried. The set of possible values depends on
     *     the value of @p what.
     *
     * @sa +llndk libnativewindow#ANativeWindowQuery.
     */
    query(
            int32_t what
        ) generates (
            int32_t result,
            int32_t value
        );

    /**
     * Attempts to connect the client as a producer of the buffer queue.
     * This method must be called before any other methods in this interface.
     *
     * If the buffer queue does not have a consumer ready (connected), the
     * return @p status shall be `NO_INIT`.
     *
     * If any of the following conditions hold, the error code `BAD_VALUE` shall
     * be reported in @p status:
     *   - The producer is already connected.
     *   - The number of available slots cannot be adjusted to accommodate the
     *     supplied value of @p producerControlledByApp.
     *
     * @param listener An optional callback object that can be provided if the
     *     client wants to be notified when the consumer releases a buffer back
     *     to the buffer queue.
     * @param api How the client shall write to buffers.
     * @param producerControlledByApp `true` if the producer is hosted by an
     *     untrusted process (typically application-forked processes). If both
     *     the producer and the consumer are controlled by app, the buffer queue
     *     shall operate in the asynchronous mode regardless of the async flag
     *     set by setAsyncMode().
     * @return status Status of the call.
     * @return output See #QueueBufferOutput for more information.
     *
     * @sa #QueueBufferOutput, disconnect(), setAsyncMode().
     */
    connect(
            IProducerListener listener,
            ConnectionType api,
            bool producerControlledByApp
        ) generates (
            Status status,
            QueueBufferOutput output
        );

    /**
     * Attempts to disconnect the client from the producer end of the buffer
     * queue.
     *
     * Calling this method shall cause any subsequent calls to other
     * @ref IGraphicBufferProducer methods apart from connect() to fail.
     * A successful connect() call afterwards may allow other methods to succeed
     * again.
     *
     * Disconnecting from an abandoned buffer queue is legal and is considered a
     * no-op.
     *
     * @param api The type of connection to disconnect. Supplying the value of
     *     `CURRENTLY_CONNECTED` to @p api has the same effect as supplying the
     *     current connection type. If the producer end is not connected,
     *     supplying `CURRENTLY_CONNECTED` shall result in a successful no-op
     *     call.
     * @return status Status of the call.
     *
     * @sa connect().
     */
    disconnect(
            ConnectionType api
        ) generates (
            Status status
        );

    /**
     * Allocates buffers based on the given dimensions, format and usage.
     *
     * This function shall allocate up to the maximum number of buffers
     * permitted by the current buffer queue configuration. It shall use the
     * given format, dimensions, and usage bits, which are interpreted in the
     * same way as for dequeueBuffer(), and the async flag must be set the same
     * way as for dequeueBuffer() to ensure that the correct number of buffers
     * are allocated. This is most useful to avoid an allocation delay during
     * dequeueBuffer(). If there are already the maximum number of buffers
     * allocated, this function has no effect.
     *
     * A value of 0 in @p width, @p height or @p format indicates that the
     * buffer queue can pick the default value.
     *
     * @param width Width of buffers to allocate.
     * @param height Height of buffers to allocate.
     * @param format Format of buffers to allocate.
     * @param usage Usage of bufferes to allocate.
     * @return status Status of the call.
     */
    allocateBuffers(
            uint32_t width,
            uint32_t height,
            uint32_t format,
            uint64_t usage
        ) generates (
            Status status
        );

    /**
     * Sets whether dequeueBuffer() is allowed to allocate new buffers.
     *
     * Normally dequeueBuffer() does not discriminate between free slots which
     * already have an allocated buffer and those which do not, and shall
     * allocate a new buffer if the slot doesn't have a buffer or if the slot's
     * buffer doesn't match the requested size, format, or usage. This method
     * allows the producer to restrict the eligible slots to those which already
     * have an allocated buffer of the correct size, format, and usage. If no
     * eligible slot is available, dequeueBuffer() shall block or return an
     * error.
     *
     * @param allow Whether to allow new buffers to be allocated in
     *     dequeueBuffer().
     * @return status Status of the call.
     */
    allowAllocation(
            bool allow
        ) generates (
            Status status
        );

    /**
     * Sets the current generation number of the buffer queue.
     *
     * This generation number shall be inserted into any buffers allocated by the
     * buffer queue, and any attempts to attach a buffer with a different
     * generation number shall fail. Buffers already in the queue are not
     * affected and shall retain their current generation number. The generation
     * number defaults to 0, i.e., buffers allocated before the first call to
     * setGenerationNumber() shall be given 0 as their generation numbers.
     *
     * @param generationNumber New generation number. The client must make sure
     *     that @p generationNumber is different from the previous generation
     *     number if it wants to deprecate old buffers.
     * @return status Status of the call.
     */
    setGenerationNumber(
            uint32_t generationNumber
        ) generates (
            Status status
        );

    /**
     * Sets how long dequeueBuffer() shall wait for a buffer to become available
     * before returning an error `TIMED_OUT`.
     *
     * This timeout also affects the attachBuffer() call, which shall block if
     * there is not a free slot available into which the attached buffer can be
     * placed.
     *
     * By default, the buffer queue shall wait forever, which is equivalent to
     * setting @p timeoutNs equal to any negative number (such as `-1`). If
     * @p timeoutNs is non-negative, setDequeueTimeout() shall disable
     * non-blocking mode and its corresponding spare buffer (which is used to
     * ensure a buffer is always available).
     *
     * Changing the dequeue timeout may affect the number of buffers. (See
     * setAsyncMode().) If the adjustment to the number of buffers inside the
     * buffer queue is not feasible, @p status shall be set to `BAD_VALUE`.
     *
     * @param timeoutNs Amount of time dequeueBuffer() is allowed to block
     *     before returning `TIMED_OUT`. If @p timeoutNs is negative,
     *     dequeueBuffer() shall not be able to return `TIMED_OUT`. Instead, it
     *     may block forever or return `WOULD_BLOCK`.
     * @return status Status of the call.
     *
     * @sa dequeueBuffer(), setAsyncMode(), query().
     */
    setDequeueTimeout(
            int64_t timeoutNs
        ) generates (
            Status status
        );

    /**
     * Returns a unique id for this buffer queue.
     *
     * @return id System-wide unique id of the buffer queue.
     */
    getUniqueId(
        ) generates (
            uint64_t id
        );

    /**
     * Returns the name of the connected consumer.
     *
     * \note This is used for debugging only.
     *
     * @return name Name of the consumer.
     */
    getConsumerName(
        ) generates (
            string name
        );

};

