/*
 * 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.neuralnetworks@1.2;

import @1.0::ErrorStatus;
import @1.0::IPreparedModel;
import @1.0::Request;
import IBurstCallback;
import IBurstContext;
import IExecutionCallback;

/**
 * IPreparedModel describes a model that has been prepared for execution and
 * is used to launch executions.
 */
interface IPreparedModel extends @1.0::IPreparedModel {
    /**
     * Launches an asynchronous execution on a prepared model.
     *
     * The execution is performed asynchronously with respect to the caller.
     * execute_1_2 must verify the inputs to the function are correct. If there is
     * an error, execute_1_2 must immediately invoke the callback with the
     * appropriate ErrorStatus value, then return with the same ErrorStatus. If
     * the inputs to the function are valid and there is no error, execute_1_2 must
     * launch an asynchronous task to perform the execution in the background,
     * and immediately return with ErrorStatus::NONE. If the asynchronous task
     * fails to launch, execute_1_2 must immediately invoke the callback with
     * ErrorStatus::GENERAL_FAILURE, then return with
     * ErrorStatus::GENERAL_FAILURE.
     *
     * When the asynchronous task has finished its execution, it must
     * immediately invoke the callback object provided as an input to the
     * execute_1_2 function. This callback must be provided with the ErrorStatus of
     * the execution.
     *
     * If the launch is successful, the caller must not change the content of
     * any data object referenced by 'request' (described by the
     * {@link @1.0::DataLocation} of a {@link @1.0::RequestArgument}) until the
     * asynchronous task has invoked the callback object. The asynchronous task
     * must not change the content of any of the data objects corresponding to
     * 'request' inputs.
     *
     * If the prepared model was prepared from a model wherein all tensor
     * operands have fully specified dimensions, and the inputs to the function
     * are valid, then:
     * - the execution should launch successfully (ErrorStatus::NONE): There
     *   must be no failure unless the device itself is in a bad state.
     * - if at execution time every operation's input operands have legal
     *   values, the execution should complete successfully (ErrorStatus::NONE):
     *   There must be no failure unless the device itself is in a bad state.
     *
     * Any number of calls to the execute, execute_1_2, and executeSynchronously
     * functions, in any combination, may be made concurrently, even on the same
     * IPreparedModel object.
     *
     * @param request The input and output information on which the prepared
     *                model is to be executed.
     * @param measure Specifies whether or not to measure duration of the execution.
     *                The duration runs from the time the driver sees the call
     *                to the execute_1_2 function to the time the driver invokes
     *                the callback.
     * @param callback A callback object used to return the error status of
     *                 the execution. The callback object's notify function must
     *                 be called exactly once, even if the execution was
     *                 unsuccessful.
     * @return status Error status of the call, must be:
     *                - NONE if task is successfully launched
     *                - DEVICE_UNAVAILABLE if driver is offline or busy
     *                - GENERAL_FAILURE if there is an unspecified error
     *                - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is
     *                  not large enough to store the resultant values
     *                - INVALID_ARGUMENT if one of the input arguments is
     *                  invalid
     */
    execute_1_2(Request request, MeasureTiming measure, IExecutionCallback callback)
        generates (ErrorStatus status);

    /**
     * Performs a synchronous execution on a prepared model.
     *
     * The execution is performed synchronously with respect to the caller.
     * executeSynchronously must verify the inputs to the function are
     * correct. If there is an error, executeSynchronously must immediately
     * return with the appropriate ErrorStatus value. If the inputs to the
     * function are valid and there is no error, executeSynchronously must
     * perform the execution, and must not return until the execution is
     * complete.
     *
     * The caller must not change the content of any data object referenced by
     * 'request' (described by the {@link @1.0::DataLocation} of a
     * {@link @1.0::RequestArgument}) until executeSynchronously
     * returns. executeSynchronously must not change the content of any of the
     * data objects corresponding to 'request' inputs.
     *
     * If the prepared model was prepared from a model wherein all tensor
     * operands have fully specified dimensions, and the inputs to the function
     * are valid, and at execution time every operation's input operands have
     * legal values, then the execution should complete successfully
     * (ErrorStatus::NONE): There must be no failure unless the device itself is
     * in a bad state.
     *
     * Any number of calls to the execute, execute_1_2, and executeSynchronously
     * functions, in any combination, may be made concurrently, even on the same
     * IPreparedModel object.
     *
     * @param request The input and output information on which the prepared
     *                model is to be executed.
     * @param measure Specifies whether or not to measure duration of the execution.
     *                The duration runs from the time the driver sees the call
     *                to the executeSynchronously function to the time the driver
     *                returns from the function.
     * @return status Error status of the execution, must be:
     *                - NONE if execution is performed successfully
     *                - DEVICE_UNAVAILABLE if driver is offline or busy
     *                - GENERAL_FAILURE if there is an unspecified error
     *                - OUTPUT_INSUFFICIENT_SIZE if at least one output
     *                  operand buffer is not large enough to store the
     *                  corresponding output
     *                - INVALID_ARGUMENT if one of the input arguments is
     *                  invalid
     * @return outputShapes A list of shape information of model output operands.
     *                      The index into "outputShapes" corresponds to the index
     *                      of the output operand in the Request outputs vector.
     *                      outputShapes must be empty unless the status is either
     *                      NONE or OUTPUT_INSUFFICIENT_SIZE.
     * @return Timing Duration of execution. Unless measure is YES and status is
     *                NONE, all times must be reported as UINT64_MAX. A driver may
     *                choose to report any time as UINT64_MAX, indicating that
     *                measurement is not available.
     */
    executeSynchronously(Request request, MeasureTiming measure)
            generates (ErrorStatus status, vec<OutputShape> outputShapes, Timing timing);

    /**
     * Configure a Burst object used to execute multiple inferences on a
     * prepared model in rapid succession.
     *
     * If the prepared model was prepared from a model wherein all tensor
     * operands have fully specified dimensions, and a valid serialized Request
     * is sent to the Burst for execution, and at execution time every
     * operation's input operands have legal values, then the execution should
     * complete successfully (ErrorStatus::NONE): There must be no failure
     * unless the device itself is in a bad state.
     *
     * @param callback A callback object used to retrieve memory resources
     *                 corresponding to unique identifiers ("slots").
     * @param requestChannel FMQ used by the client to send a serialized Request
     *                       to the Burst for execution. The client must not
     *                       change the content of any data object referenced by
     *                       the Request (described by the
     *                       {@link @1.0::DataLocation} of an
     *                       {@link OperandInformation}) until a result has been
     *                       received from resultChannel. Execution must not
     *                       change the content of any of the data objects
     *                       corresponding to Request inputs. requestChannel
     *                       must not be used to pass a second Request object
     *                       until a result has been received from
     *                       resultChannel. The client must send the request
     *                       messages to the consumer atomically by using
     *                       MessageQueue::writeBlocking if the queue is
     *                       blocking, or by using MessageQueue::write if the
     *                       queue is non-blocking. When the service receives a
     *                       packet, it must dequeue the entire packet from the
     *                       requestChannel. The client must not send a request
     *                       packet that exceeds the length of the FMQ.
     * @param resultChannel FMQ used by the service to return the results of an
     *                      execution to the client: the status of the
     *                      execution, OutputShape of all output tensors, and
     *                      timing information. resultChannel must be used to
     *                      return the results if a Request was sent through the
     *                      requestChannel. The service must send the result
     *                      messages to the consumer atomically by using
     *                      MessageQueue::writeBlocking if the queue is
     *                      blocking, or by using MessageQueue::write if the
     *                      queue is non-blocking. When the client receives a
     *                      packet, it must dequeue the entire packet from the
     *                      resultChannel. If the packet's length exceeds the
     *                      size of the FMQ, the service must not send this
     *                      result packet; instead, the service must send a
     *                      packet consisting of the error code
     *                      ErrorStatus::GENERAL_FAILURE, no information for the
     *                      outputShapes, and an indication that timing
     *                      information is unavailable.
     * @return status Error status of configuring the execution burst, must be:
     *                - NONE if the burst is successfully configured
     *                - DEVICE_UNAVAILABLE if driver is offline or busy
     *                - GENERAL_FAILURE if there is an unspecified error
     *                - INVALID_ARGUMENT if one of the input arguments is
     *                  invalid
     * @return context Object containing all resources (such as cached
     *                 hidl_memory) related to a Burst if successful, otherwise
     *                 nullptr.
     */
    configureExecutionBurst(IBurstCallback callback,
                            fmq_sync<FmqRequestDatum> requestChannel,
                            fmq_sync<FmqResultDatum> resultChannel)
                 generates (ErrorStatus status, IBurstContext context);
};
