/*
 * 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.hardware.benchmarks.msgq@1.0;

interface IBenchmarkMsgQ {
    /*
     * This method requests the service to set up Synchronous read/write
     * wait-free FMQ with the client as reader.
     * @return ret Will be true if the setup was successful, false otherwise.
     * @return mqDescIn This structure describes the FMQ that was set up
     * by the service. Client can use it to set up the FMQ at its end.
     */
    configureClientInboxSyncReadWrite()
        generates(bool ret, fmq_sync<uint8_t> mqDescIn);

    /*
     * This method requests the service to set up Synchronous read/write
     * wait-free FMQ with the client as writer.
     * @return ret Will be true if the setup was successful, false otherwise.
     * @return mqDescOut This structure describes the FMQ that was set up
     * by the service. Client can use it to set up the FMQ at its end.
     */
    configureClientOutboxSyncReadWrite()
        generates(bool ret, fmq_sync<uint8_t> mqDescOut);

    /*
     * This method request the service to write into the FMQ.
     * @param count Number to messages to write.
     * @return ret Will be true if the write operation was successful,
     * false otherwise.
     */
    requestWrite(int32_t count) generates (bool ret);

    /*
     * This method request the service to read from the FMQ.
     * @param count Number to messages to read.
     * @ret Will be true if the read operation was successful, false otherwise.
     */
    requestRead(int32_t count) generates (bool ret);

    /*
     * This method kicks off a benchmarking experiment where
     * the client writes a message into its outbox FMQ,
     * the service reads it and writes it into the client's
     * inbox FMQ and the client reads the message.
     * The average time taken for the experiment is measured.
     * @param numIter The number of iterations to run the experiment.
     */
    benchmarkPingPong(uint32_t numIter);

    /*
     * This method kicks off a benchmarking experiment where
     * the service writes into an FMQ and the client reads the same.
     * @param numIter The number of iterations to run the experiment.
     */
    benchmarkServiceWriteClientRead(uint32_t numIter);

    /*
     * This method sends a vector of time duration(in ns).
     * @param timeData vector of time instants measured by client.
     * Each entry is the number of ns between the epoch and a
     * std::chrono::time_point.
     */
    sendTimeData(vec<int64_t> timeData);
};
