Merge "audio: Make StreamDescriptor::Command a union" am: 2b68543625 am: 224a3b1755
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2296167
Change-Id: I29a46c3c67df1311d9e1d9ed88e2b85b2de16f45
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/StreamDescriptor.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/StreamDescriptor.aidl
index da24a10..3a77ad1 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/StreamDescriptor.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/StreamDescriptor.aidl
@@ -55,19 +55,15 @@
DRAIN_PAUSED = 6,
ERROR = 100,
}
- @Backing(type="int") @VintfStability
- enum CommandCode {
- START = 1,
- BURST = 2,
- DRAIN = 3,
- STANDBY = 4,
- PAUSE = 5,
- FLUSH = 6,
- }
@FixedSize @VintfStability
- parcelable Command {
- android.hardware.audio.core.StreamDescriptor.CommandCode code = android.hardware.audio.core.StreamDescriptor.CommandCode.START;
- int fmqByteCount;
+ union Command {
+ int hal_reserved_exit;
+ android.media.audio.common.Void start;
+ int burst;
+ android.media.audio.common.Void drain;
+ android.media.audio.common.Void standby;
+ android.media.audio.common.Void pause;
+ android.media.audio.common.Void flush;
}
@FixedSize @VintfStability
parcelable Reply {
diff --git a/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl b/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl
index e5e56fc..2b1fc99 100644
--- a/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl
+++ b/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl
@@ -19,6 +19,7 @@
import android.hardware.audio.core.MmapBufferDescriptor;
import android.hardware.common.fmq.MQDescriptor;
import android.hardware.common.fmq.SynchronizedReadWrite;
+import android.media.audio.common.Void;
/**
* Stream descriptor contains fast message queues and buffers used for sending
@@ -177,76 +178,41 @@
ERROR = 100,
}
- @VintfStability
- @Backing(type="int")
- enum CommandCode {
- /**
- * See the state machines on the applicability of this command to
- * different states. The 'fmqByteCount' field must always be set to 0.
- */
- START = 1,
- /**
- * The BURST command used for audio I/O, see 'AudioBuffer'. Differences
- * for the MMap No IRQ mode:
- *
- * - this command only provides updated positions and latency because
- * actual audio I/O is done via the 'AudioBuffer.mmap' shared buffer.
- * The client does not synchronize reads and writes into the buffer
- * with sending of this command.
- *
- * - the 'fmqByteCount' must always be set to 0.
- */
- BURST = 2,
- /**
- * See the state machines on the applicability of this command to
- * different states. The 'fmqByteCount' field must always be set to 0.
- */
- DRAIN = 3,
- /**
- * See the state machines on the applicability of this command to
- * different states. The 'fmqByteCount' field must always be set to 0.
- *
- * Note that it's left on the discretion of the HAL implementation to
- * assess all the necessary conditions that could prevent hardware from
- * being suspended. Even if it can not be suspended, the state machine
- * must still enter the 'STANDBY' state for consistency. Since the
- * buffer must remain empty in this state, even if capturing hardware is
- * still active, captured data must be discarded.
- */
- STANDBY = 4,
- /**
- * See the state machines on the applicability of this command to
- * different states. The 'fmqByteCount' field must always be set to 0.
- */
- PAUSE = 5,
- /**
- * See the state machines on the applicability of this command to
- * different states. The 'fmqByteCount' field must always be set to 0.
- */
- FLUSH = 6,
- }
-
/**
* Used for sending commands to the HAL module. The client writes into
* the queue, the HAL module reads. The queue can only contain a single
* command.
+ *
+ * Variants of type 'Void' correspond to commands without
+ * arguments. Variants of other types correspond to commands with an
+ * argument. Would in future a need for a command with multiple argument
+ * arise, a Parcelable type should be used for the corresponding variant.
*/
@VintfStability
@FixedSize
- parcelable Command {
+ union Command {
/**
- * The code of the command.
+ * Reserved for the HAL implementation to allow unblocking the wait on a
+ * command and exiting the I/O thread. A command of this variant must
+ * never be sent from the client side. To prevent that, the
+ * implementation must pass a random cookie as the command argument,
+ * which is only known to the implementation.
*/
- CommandCode code = CommandCode.START;
+ int hal_reserved_exit;
/**
- * This field is only used for the BURST command. For all other commands
- * it must be set to 0. The following description applies to the use
- * of this field for the BURST command.
+ * See the state machines on the applicability of this command to
+ * different states.
+ */
+ Void start;
+ /**
+ * The 'burst' command used for audio I/O, see 'AudioBuffer'. The value
+ * specifies:
*
- * For output streams: the amount of bytes that the client requests the
- * HAL module to use out of the data contained in the 'audio.fmq' queue.
- * For input streams: the amount of bytes requested by the client to
- * read from the hardware into the 'audio.fmq' queue.
+ * - for output streams: the amount of bytes that the client requests the
+ * HAL module to use out of the data contained in the 'audio.fmq' queue.
+ *
+ * - for input streams: the amount of bytes requested by the client to
+ * read from the hardware into the 'audio.fmq' queue.
*
* In both cases it is allowed for this field to contain any
* non-negative number. The value 0 can be used if the client only needs
@@ -258,8 +224,44 @@
* return the amount of actually read or written data via the
* 'Reply.fmqByteCount' field. Thus, only attempts to pass a negative
* number must be constituted as a client's error.
+ *
+ * Differences for the MMap No IRQ mode:
+ *
+ * - this command only provides updated positions and latency because
+ * actual audio I/O is done via the 'AudioBuffer.mmap' shared buffer.
+ * The client does not synchronize reads and writes into the buffer
+ * with sending of this command.
+ *
+ * - the value must always be set to 0.
*/
- int fmqByteCount;
+ int burst;
+ /**
+ * See the state machines on the applicability of this command to
+ * different states.
+ */
+ Void drain;
+ /**
+ * See the state machines on the applicability of this command to
+ * different states.
+ *
+ * Note that it's left on the discretion of the HAL implementation to
+ * assess all the necessary conditions that could prevent hardware from
+ * being suspended. Even if it can not be suspended, the state machine
+ * must still enter the 'STANDBY' state for consistency. Since the
+ * buffer must remain empty in this state, even if capturing hardware is
+ * still active, captured data must be discarded.
+ */
+ Void standby;
+ /**
+ * See the state machines on the applicability of this command to
+ * different states.
+ */
+ Void pause;
+ /**
+ * See the state machines on the applicability of this command to
+ * different states.
+ */
+ Void flush;
}
MQDescriptor<Command, SynchronizedReadWrite> command;
@@ -293,15 +295,15 @@
*/
int status;
/**
- * Used with the BURST command only.
+ * Used with the 'burst' command only.
*
* For output streams: the amount of bytes of data actually consumed
* by the HAL module.
* For input streams: the amount of bytes actually provided by the HAL
* in the 'audio.fmq' queue.
*
- * The returned value must not exceed the value passed in the
- * 'fmqByteCount' field of the corresponding command or be negative.
+ * The returned value must not exceed the value passed as the
+ * argument of the corresponding command, or be negative.
*/
int fmqByteCount;
/**
diff --git a/audio/aidl/android/hardware/audio/core/stream-in-sm.gv b/audio/aidl/android/hardware/audio/core/stream-in-sm.gv
index 889a14b..805dc32 100644
--- a/audio/aidl/android/hardware/audio/core/stream-in-sm.gv
+++ b/audio/aidl/android/hardware/audio/core/stream-in-sm.gv
@@ -23,16 +23,16 @@
node [style=dashed] ANY_STATE;
node [fillcolor=lightblue style=filled];
I -> STANDBY;
- STANDBY -> IDLE [label="START"]; // producer -> active
- IDLE -> STANDBY [label="STANDBY"]; // producer -> passive, buffer is cleared
- IDLE -> ACTIVE [label="BURST"]; // consumer -> active
- ACTIVE -> ACTIVE [label="BURST"];
- ACTIVE -> PAUSED [label="PAUSE"]; // consumer -> passive
- ACTIVE -> DRAINING [label="DRAIN"]; // producer -> passive
- PAUSED -> ACTIVE [label="BURST"]; // consumer -> active
- PAUSED -> STANDBY [label="FLUSH"]; // producer -> passive, buffer is cleared
- DRAINING -> DRAINING [label="BURST"];
- DRAINING -> ACTIVE [label="START"]; // producer -> active
+ STANDBY -> IDLE [label="start"]; // producer -> active
+ IDLE -> STANDBY [label="standby"]; // producer -> passive, buffer is cleared
+ IDLE -> ACTIVE [label="burst"]; // consumer -> active
+ ACTIVE -> ACTIVE [label="burst"];
+ ACTIVE -> PAUSED [label="pause"]; // consumer -> passive
+ ACTIVE -> DRAINING [label="drain"]; // producer -> passive
+ PAUSED -> ACTIVE [label="burst"]; // consumer -> active
+ PAUSED -> STANDBY [label="flush"]; // producer -> passive, buffer is cleared
+ DRAINING -> DRAINING [label="burst"];
+ DRAINING -> ACTIVE [label="start"]; // producer -> active
DRAINING -> STANDBY [label="<empty buffer>"]; // consumer deactivates
IDLE -> ERROR [label="<hardware failure>"];
ACTIVE -> ERROR [label="<hardware failure>"];
diff --git a/audio/aidl/android/hardware/audio/core/stream-out-sm.gv b/audio/aidl/android/hardware/audio/core/stream-out-sm.gv
index 56dd5290..6aa5c61 100644
--- a/audio/aidl/android/hardware/audio/core/stream-out-sm.gv
+++ b/audio/aidl/android/hardware/audio/core/stream-out-sm.gv
@@ -24,22 +24,22 @@
node [style=dashed] ANY_STATE;
node [fillcolor=lightblue style=filled];
I -> STANDBY;
- STANDBY -> IDLE [label="START"]; // consumer -> active
- STANDBY -> PAUSED [label="BURST"]; // producer -> active
- IDLE -> STANDBY [label="STANDBY"]; // consumer -> passive
- IDLE -> ACTIVE [label="BURST"]; // producer -> active
- ACTIVE -> ACTIVE [label="BURST"];
- ACTIVE -> PAUSED [label="PAUSE"]; // consumer -> passive (not consuming)
- ACTIVE -> DRAINING [label="DRAIN"]; // producer -> passive
- PAUSED -> PAUSED [label="BURST"];
- PAUSED -> ACTIVE [label="START"]; // consumer -> active
- PAUSED -> IDLE [label="FLUSH"]; // producer -> passive, buffer is cleared
+ STANDBY -> IDLE [label="start"]; // consumer -> active
+ STANDBY -> PAUSED [label="burst"]; // producer -> active
+ IDLE -> STANDBY [label="standby"]; // consumer -> passive
+ IDLE -> ACTIVE [label="burst"]; // producer -> active
+ ACTIVE -> ACTIVE [label="burst"];
+ ACTIVE -> PAUSED [label="pause"]; // consumer -> passive (not consuming)
+ ACTIVE -> DRAINING [label="drain"]; // producer -> passive
+ PAUSED -> PAUSED [label="burst"];
+ PAUSED -> ACTIVE [label="start"]; // consumer -> active
+ PAUSED -> IDLE [label="flush"]; // producer -> passive, buffer is cleared
DRAINING -> IDLE [label="<empty buffer>"];
- DRAINING -> ACTIVE [label="BURST"]; // producer -> active
- DRAINING -> DRAIN_PAUSED [label="PAUSE"]; // consumer -> passive (not consuming)
- DRAIN_PAUSED -> DRAINING [label="START"]; // consumer -> active
- DRAIN_PAUSED -> PAUSED [label="BURST"]; // producer -> active
- DRAIN_PAUSED -> IDLE [label="FLUSH"]; // buffer is cleared
+ DRAINING -> ACTIVE [label="burst"]; // producer -> active
+ DRAINING -> DRAIN_PAUSED [label="pause"]; // consumer -> passive (not consuming)
+ DRAIN_PAUSED -> DRAINING [label="start"]; // consumer -> active
+ DRAIN_PAUSED -> PAUSED [label="burst"]; // producer -> active
+ DRAIN_PAUSED -> IDLE [label="flush"]; // buffer is cleared
IDLE -> ERROR [label="<hardware failure>"];
ACTIVE -> ERROR [label="<hardware failure>"];
DRAINING -> ERROR [label="<hardware failure>"];
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index 7b544a1..21dc4b6 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -106,101 +106,116 @@
return Status::ABORT;
}
StreamDescriptor::Reply reply{};
- if (static_cast<int32_t>(command.code) == StreamContext::COMMAND_EXIT &&
- command.fmqByteCount == mInternalCommandCookie) {
- LOG(DEBUG) << __func__ << ": received EXIT command";
- setClosed();
- // This is an internal command, no need to reply.
- return Status::EXIT;
- } else if (command.code == StreamDescriptor::CommandCode::START && command.fmqByteCount >= 0) {
- LOG(DEBUG) << __func__ << ": received START read command";
- if (mState == StreamDescriptor::State::STANDBY ||
- mState == StreamDescriptor::State::DRAINING) {
- populateReply(&reply, mIsConnected);
- mState = mState == StreamDescriptor::State::STANDBY ? StreamDescriptor::State::IDLE
- : StreamDescriptor::State::ACTIVE;
- } else {
- LOG(WARNING) << __func__ << ": START command can not be handled in the state "
- << toString(mState);
- reply.status = STATUS_INVALID_OPERATION;
- }
- } else if (command.code == StreamDescriptor::CommandCode::BURST && command.fmqByteCount >= 0) {
- LOG(DEBUG) << __func__ << ": received BURST read command for " << command.fmqByteCount
- << " bytes";
- if (mState == StreamDescriptor::State::IDLE || mState == StreamDescriptor::State::ACTIVE ||
- mState == StreamDescriptor::State::PAUSED ||
- mState == StreamDescriptor::State::DRAINING) {
- if (!read(command.fmqByteCount, &reply)) {
- mState = StreamDescriptor::State::ERROR;
+ reply.status = STATUS_BAD_VALUE;
+ using Tag = StreamDescriptor::Command::Tag;
+ switch (command.getTag()) {
+ case Tag::hal_reserved_exit:
+ if (const int32_t cookie = command.get<Tag::hal_reserved_exit>();
+ cookie == mInternalCommandCookie) {
+ LOG(DEBUG) << __func__ << ": received EXIT command";
+ setClosed();
+ // This is an internal command, no need to reply.
+ return Status::EXIT;
+ } else {
+ LOG(WARNING) << __func__ << ": EXIT command has a bad cookie: " << cookie;
}
- if (mState == StreamDescriptor::State::IDLE ||
- mState == StreamDescriptor::State::PAUSED) {
- mState = StreamDescriptor::State::ACTIVE;
- } else if (mState == StreamDescriptor::State::DRAINING) {
- // To simplify the reference code, we assume that the read operation
- // has consumed all the data remaining in the hardware buffer.
- // TODO: Provide parametrization on the duration of draining to test
- // handling of commands during the 'DRAINING' state.
+ break;
+ case Tag::start:
+ LOG(DEBUG) << __func__ << ": received START read command";
+ if (mState == StreamDescriptor::State::STANDBY ||
+ mState == StreamDescriptor::State::DRAINING) {
+ populateReply(&reply, mIsConnected);
+ mState = mState == StreamDescriptor::State::STANDBY
+ ? StreamDescriptor::State::IDLE
+ : StreamDescriptor::State::ACTIVE;
+ } else {
+ LOG(WARNING) << __func__ << ": START command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ break;
+ case Tag::burst:
+ if (const int32_t fmqByteCount = command.get<Tag::burst>(); fmqByteCount >= 0) {
+ LOG(DEBUG) << __func__ << ": received BURST read command for " << fmqByteCount
+ << " bytes";
+ if (mState == StreamDescriptor::State::IDLE ||
+ mState == StreamDescriptor::State::ACTIVE ||
+ mState == StreamDescriptor::State::PAUSED ||
+ mState == StreamDescriptor::State::DRAINING) {
+ if (!read(fmqByteCount, &reply)) {
+ mState = StreamDescriptor::State::ERROR;
+ }
+ if (mState == StreamDescriptor::State::IDLE ||
+ mState == StreamDescriptor::State::PAUSED) {
+ mState = StreamDescriptor::State::ACTIVE;
+ } else if (mState == StreamDescriptor::State::DRAINING) {
+ // To simplify the reference code, we assume that the read operation
+ // has consumed all the data remaining in the hardware buffer.
+ // TODO: Provide parametrization on the duration of draining to test
+ // handling of commands during the 'DRAINING' state.
+ mState = StreamDescriptor::State::STANDBY;
+ }
+ } else {
+ LOG(WARNING) << __func__ << ": BURST command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ } else {
+ LOG(WARNING) << __func__ << ": invalid burst byte count: " << fmqByteCount;
+ }
+ break;
+ case Tag::drain:
+ LOG(DEBUG) << __func__ << ": received DRAIN read command";
+ if (mState == StreamDescriptor::State::ACTIVE) {
+ usleep(1000); // Simulate a blocking call into the driver.
+ populateReply(&reply, mIsConnected);
+ // Can switch the state to ERROR if a driver error occurs.
+ mState = StreamDescriptor::State::DRAINING;
+ } else {
+ LOG(WARNING) << __func__ << ": DRAIN command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ break;
+ case Tag::standby:
+ LOG(DEBUG) << __func__ << ": received STANDBY read command";
+ if (mState == StreamDescriptor::State::IDLE) {
+ usleep(1000); // Simulate a blocking call into the driver.
+ populateReply(&reply, mIsConnected);
+ // Can switch the state to ERROR if a driver error occurs.
mState = StreamDescriptor::State::STANDBY;
+ } else {
+ LOG(WARNING) << __func__ << ": FLUSH command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
}
- } else {
- LOG(WARNING) << __func__ << ": BURST command can not be handled in the state "
- << toString(mState);
- reply.status = STATUS_INVALID_OPERATION;
- }
- } else if (command.code == StreamDescriptor::CommandCode::DRAIN && command.fmqByteCount == 0) {
- LOG(DEBUG) << __func__ << ": received DRAIN read command";
- if (mState == StreamDescriptor::State::ACTIVE) {
- usleep(1000); // Simulate a blocking call into the driver.
- populateReply(&reply, mIsConnected);
- // Can switch the state to ERROR if a driver error occurs.
- mState = StreamDescriptor::State::DRAINING;
- } else {
- LOG(WARNING) << __func__ << ": DRAIN command can not be handled in the state "
- << toString(mState);
- reply.status = STATUS_INVALID_OPERATION;
- }
- } else if (command.code == StreamDescriptor::CommandCode::PAUSE && command.fmqByteCount == 0) {
- LOG(DEBUG) << __func__ << ": received PAUSE read command";
- if (mState == StreamDescriptor::State::ACTIVE) {
- usleep(1000); // Simulate a blocking call into the driver.
- populateReply(&reply, mIsConnected);
- // Can switch the state to ERROR if a driver error occurs.
- mState = StreamDescriptor::State::PAUSED;
- } else {
- LOG(WARNING) << __func__ << ": PAUSE command can not be handled in the state "
- << toString(mState);
- reply.status = STATUS_INVALID_OPERATION;
- }
- } else if (command.code == StreamDescriptor::CommandCode::FLUSH && command.fmqByteCount == 0) {
- LOG(DEBUG) << __func__ << ": received FLUSH read command";
- if (mState == StreamDescriptor::State::PAUSED) {
- usleep(1000); // Simulate a blocking call into the driver.
- populateReply(&reply, mIsConnected);
- // Can switch the state to ERROR if a driver error occurs.
- mState = StreamDescriptor::State::STANDBY;
- } else {
- LOG(WARNING) << __func__ << ": FLUSH command can not be handled in the state "
- << toString(mState);
- reply.status = STATUS_INVALID_OPERATION;
- }
- } else if (command.code == StreamDescriptor::CommandCode::STANDBY &&
- command.fmqByteCount == 0) {
- LOG(DEBUG) << __func__ << ": received STANDBY read command";
- if (mState == StreamDescriptor::State::IDLE) {
- usleep(1000); // Simulate a blocking call into the driver.
- populateReply(&reply, mIsConnected);
- // Can switch the state to ERROR if a driver error occurs.
- mState = StreamDescriptor::State::STANDBY;
- } else {
- LOG(WARNING) << __func__ << ": FLUSH command can not be handled in the state "
- << toString(mState);
- reply.status = STATUS_INVALID_OPERATION;
- }
- } else {
- LOG(WARNING) << __func__ << ": invalid command (" << command.toString()
- << ") or count: " << command.fmqByteCount;
- reply.status = STATUS_BAD_VALUE;
+ break;
+ case Tag::pause:
+ LOG(DEBUG) << __func__ << ": received PAUSE read command";
+ if (mState == StreamDescriptor::State::ACTIVE) {
+ usleep(1000); // Simulate a blocking call into the driver.
+ populateReply(&reply, mIsConnected);
+ // Can switch the state to ERROR if a driver error occurs.
+ mState = StreamDescriptor::State::PAUSED;
+ } else {
+ LOG(WARNING) << __func__ << ": PAUSE command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ break;
+ case Tag::flush:
+ LOG(DEBUG) << __func__ << ": received FLUSH read command";
+ if (mState == StreamDescriptor::State::PAUSED) {
+ usleep(1000); // Simulate a blocking call into the driver.
+ populateReply(&reply, mIsConnected);
+ // Can switch the state to ERROR if a driver error occurs.
+ mState = StreamDescriptor::State::STANDBY;
+ } else {
+ LOG(WARNING) << __func__ << ": FLUSH command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ break;
}
reply.state = mState;
LOG(DEBUG) << __func__ << ": writing reply " << reply.toString();
@@ -253,109 +268,123 @@
return Status::ABORT;
}
StreamDescriptor::Reply reply{};
- if (static_cast<int32_t>(command.code) == StreamContext::COMMAND_EXIT &&
- command.fmqByteCount == mInternalCommandCookie) {
- LOG(DEBUG) << __func__ << ": received EXIT command";
- setClosed();
- // This is an internal command, no need to reply.
- return Status::EXIT;
- } else if (command.code == StreamDescriptor::CommandCode::START && command.fmqByteCount >= 0) {
- LOG(DEBUG) << __func__ << ": received START read command";
- switch (mState) {
- case StreamDescriptor::State::STANDBY:
+ reply.status = STATUS_BAD_VALUE;
+ using Tag = StreamDescriptor::Command::Tag;
+ switch (command.getTag()) {
+ case Tag::hal_reserved_exit:
+ if (const int32_t cookie = command.get<Tag::hal_reserved_exit>();
+ cookie == mInternalCommandCookie) {
+ LOG(DEBUG) << __func__ << ": received EXIT command";
+ setClosed();
+ // This is an internal command, no need to reply.
+ return Status::EXIT;
+ } else {
+ LOG(WARNING) << __func__ << ": EXIT command has a bad cookie: " << cookie;
+ }
+ break;
+ case Tag::start:
+ LOG(DEBUG) << __func__ << ": received START write command";
+ switch (mState) {
+ case StreamDescriptor::State::STANDBY:
+ mState = StreamDescriptor::State::IDLE;
+ break;
+ case StreamDescriptor::State::PAUSED:
+ mState = StreamDescriptor::State::ACTIVE;
+ break;
+ case StreamDescriptor::State::DRAIN_PAUSED:
+ mState = StreamDescriptor::State::PAUSED;
+ break;
+ default:
+ LOG(WARNING) << __func__ << ": START command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ if (reply.status != STATUS_INVALID_OPERATION) {
+ populateReply(&reply, mIsConnected);
+ }
+ break;
+ case Tag::burst:
+ if (const int32_t fmqByteCount = command.get<Tag::burst>(); fmqByteCount >= 0) {
+ LOG(DEBUG) << __func__ << ": received BURST write command for " << fmqByteCount
+ << " bytes";
+ if (mState !=
+ StreamDescriptor::State::ERROR) { // BURST can be handled in all valid states
+ if (!write(fmqByteCount, &reply)) {
+ mState = StreamDescriptor::State::ERROR;
+ }
+ if (mState == StreamDescriptor::State::STANDBY ||
+ mState == StreamDescriptor::State::DRAIN_PAUSED) {
+ mState = StreamDescriptor::State::PAUSED;
+ } else if (mState == StreamDescriptor::State::IDLE ||
+ mState == StreamDescriptor::State::DRAINING) {
+ mState = StreamDescriptor::State::ACTIVE;
+ } // When in 'ACTIVE' and 'PAUSED' do not need to change the state.
+ } else {
+ LOG(WARNING) << __func__ << ": BURST command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ } else {
+ LOG(WARNING) << __func__ << ": invalid burst byte count: " << fmqByteCount;
+ }
+ break;
+ case Tag::drain:
+ LOG(DEBUG) << __func__ << ": received DRAIN write command";
+ if (mState == StreamDescriptor::State::ACTIVE) {
+ usleep(1000); // Simulate a blocking call into the driver.
+ populateReply(&reply, mIsConnected);
+ // Can switch the state to ERROR if a driver error occurs.
mState = StreamDescriptor::State::IDLE;
- break;
- case StreamDescriptor::State::PAUSED:
- mState = StreamDescriptor::State::ACTIVE;
- break;
- case StreamDescriptor::State::DRAIN_PAUSED:
- mState = StreamDescriptor::State::PAUSED;
- break;
- default:
- LOG(WARNING) << __func__ << ": START command can not be handled in the state "
+ // Since there is no actual hardware that would be draining the buffer,
+ // in order to simplify the reference code, we assume that draining
+ // happens instantly, thus skipping the 'DRAINING' state.
+ // TODO: Provide parametrization on the duration of draining to test
+ // handling of commands during the 'DRAINING' state.
+ } else {
+ LOG(WARNING) << __func__ << ": DRAIN command can not be handled in the state "
<< toString(mState);
reply.status = STATUS_INVALID_OPERATION;
- }
- if (reply.status != STATUS_INVALID_OPERATION) {
- populateReply(&reply, mIsConnected);
- }
- } else if (command.code == StreamDescriptor::CommandCode::BURST && command.fmqByteCount >= 0) {
- LOG(DEBUG) << __func__ << ": received BURST write command for " << command.fmqByteCount
- << " bytes";
- if (mState != StreamDescriptor::State::ERROR) { // BURST can be handled in all valid states
- if (!write(command.fmqByteCount, &reply)) {
- mState = StreamDescriptor::State::ERROR;
}
- if (mState == StreamDescriptor::State::STANDBY ||
+ break;
+ case Tag::standby:
+ LOG(DEBUG) << __func__ << ": received STANDBY write command";
+ if (mState == StreamDescriptor::State::IDLE) {
+ usleep(1000); // Simulate a blocking call into the driver.
+ populateReply(&reply, mIsConnected);
+ // Can switch the state to ERROR if a driver error occurs.
+ mState = StreamDescriptor::State::STANDBY;
+ } else {
+ LOG(WARNING) << __func__ << ": STANDBY command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ break;
+ case Tag::pause:
+ LOG(DEBUG) << __func__ << ": received PAUSE write command";
+ if (mState == StreamDescriptor::State::ACTIVE ||
+ mState == StreamDescriptor::State::DRAINING) {
+ populateReply(&reply, mIsConnected);
+ mState = mState == StreamDescriptor::State::ACTIVE
+ ? StreamDescriptor::State::PAUSED
+ : StreamDescriptor::State::DRAIN_PAUSED;
+ } else {
+ LOG(WARNING) << __func__ << ": PAUSE command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ break;
+ case Tag::flush:
+ LOG(DEBUG) << __func__ << ": received FLUSH write command";
+ if (mState == StreamDescriptor::State::PAUSED ||
mState == StreamDescriptor::State::DRAIN_PAUSED) {
- mState = StreamDescriptor::State::PAUSED;
- } else if (mState == StreamDescriptor::State::IDLE ||
- mState == StreamDescriptor::State::DRAINING) {
- mState = StreamDescriptor::State::ACTIVE;
- } // When in 'ACTIVE' and 'PAUSED' do not need to change the state.
- } else {
- LOG(WARNING) << __func__ << ": BURST command can not be handled in the state "
- << toString(mState);
- reply.status = STATUS_INVALID_OPERATION;
- }
- } else if (command.code == StreamDescriptor::CommandCode::DRAIN && command.fmqByteCount == 0) {
- LOG(DEBUG) << __func__ << ": received DRAIN write command";
- if (mState == StreamDescriptor::State::ACTIVE) {
- usleep(1000); // Simulate a blocking call into the driver.
- populateReply(&reply, mIsConnected);
- // Can switch the state to ERROR if a driver error occurs.
- mState = StreamDescriptor::State::IDLE;
- // Since there is no actual hardware that would be draining the buffer,
- // in order to simplify the reference code, we assume that draining
- // happens instantly, thus skipping the 'DRAINING' state.
- // TODO: Provide parametrization on the duration of draining to test
- // handling of commands during the 'DRAINING' state.
- } else {
- LOG(WARNING) << __func__ << ": DRAIN command can not be handled in the state "
- << toString(mState);
- reply.status = STATUS_INVALID_OPERATION;
- }
- } else if (command.code == StreamDescriptor::CommandCode::STANDBY &&
- command.fmqByteCount == 0) {
- LOG(DEBUG) << __func__ << ": received STANDBY write command";
- if (mState == StreamDescriptor::State::IDLE) {
- usleep(1000); // Simulate a blocking call into the driver.
- populateReply(&reply, mIsConnected);
- // Can switch the state to ERROR if a driver error occurs.
- mState = StreamDescriptor::State::STANDBY;
- } else {
- LOG(WARNING) << __func__ << ": STANDBY command can not be handled in the state "
- << toString(mState);
- reply.status = STATUS_INVALID_OPERATION;
- }
- } else if (command.code == StreamDescriptor::CommandCode::PAUSE && command.fmqByteCount == 0) {
- LOG(DEBUG) << __func__ << ": received PAUSE write command";
- if (mState == StreamDescriptor::State::ACTIVE ||
- mState == StreamDescriptor::State::DRAINING) {
- populateReply(&reply, mIsConnected);
- mState = mState == StreamDescriptor::State::ACTIVE
- ? StreamDescriptor::State::PAUSED
- : StreamDescriptor::State::DRAIN_PAUSED;
- } else {
- LOG(WARNING) << __func__ << ": PAUSE command can not be handled in the state "
- << toString(mState);
- reply.status = STATUS_INVALID_OPERATION;
- }
- } else if (command.code == StreamDescriptor::CommandCode::FLUSH && command.fmqByteCount == 0) {
- LOG(DEBUG) << __func__ << ": received FLUSH write command";
- if (mState == StreamDescriptor::State::PAUSED ||
- mState == StreamDescriptor::State::DRAIN_PAUSED) {
- populateReply(&reply, mIsConnected);
- mState = StreamDescriptor::State::IDLE;
- } else {
- LOG(WARNING) << __func__ << ": FLUSH command can not be handled in the state "
- << toString(mState);
- reply.status = STATUS_INVALID_OPERATION;
- }
- } else {
- LOG(WARNING) << __func__ << ": invalid command (" << command.toString()
- << ") or count: " << command.fmqByteCount;
- reply.status = STATUS_BAD_VALUE;
+ populateReply(&reply, mIsConnected);
+ mState = StreamDescriptor::State::IDLE;
+ } else {
+ LOG(WARNING) << __func__ << ": FLUSH command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ break;
}
reply.state = mState;
LOG(DEBUG) << __func__ << ": writing reply " << reply.toString();
@@ -421,9 +450,9 @@
void StreamCommon<Metadata, StreamWorker>::stopWorker() {
if (auto commandMQ = mContext.getCommandMQ(); commandMQ != nullptr) {
LOG(DEBUG) << __func__ << ": asking the worker to exit...";
- StreamDescriptor::Command cmd;
- cmd.code = StreamDescriptor::CommandCode(StreamContext::COMMAND_EXIT);
- cmd.fmqByteCount = mContext.getInternalCommandCookie();
+ auto cmd =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::hal_reserved_exit>(
+ mContext.getInternalCommandCookie());
// Note: never call 'pause' and 'resume' methods of StreamWorker
// in the HAL implementation. These methods are to be used by
// the client side only. Preventing the worker loop from running
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 539fa8b..5ee0f82 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -54,8 +54,6 @@
int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
DataMQ;
- // Ensure that this value is not used by any of StreamDescriptor.CommandCode enums
- static constexpr int32_t COMMAND_EXIT = -1;
// Ensure that this value is not used by any of StreamDescriptor.State enums
static constexpr int32_t STATE_CLOSED = -1;
diff --git a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
index 7faa93e..2f72bb0 100644
--- a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
@@ -70,6 +70,7 @@
using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioSource;
using aidl::android::media::audio::common::AudioUsage;
+using aidl::android::media::audio::common::Void;
using android::hardware::audio::common::isBitPositionFlagSet;
using android::hardware::audio::common::StreamLogic;
using android::hardware::audio::common::StreamWorker;
@@ -455,7 +456,9 @@
LOG(ERROR) << __func__ << ": received error status: " << statusToString(reply.status);
return Status::ABORT;
}
- if (reply.fmqByteCount < 0 || reply.fmqByteCount > command.fmqByteCount) {
+ if (reply.fmqByteCount < 0 ||
+ (command.getTag() == StreamDescriptor::Command::Tag::burst &&
+ reply.fmqByteCount > command.get<StreamDescriptor::Command::Tag::burst>())) {
LOG(ERROR) << __func__
<< ": received invalid byte count in the reply: " << reply.fmqByteCount;
return Status::ABORT;
@@ -532,7 +535,9 @@
LOG(ERROR) << __func__ << ": received error status: " << statusToString(reply.status);
return Status::ABORT;
}
- if (reply.fmqByteCount < 0 || reply.fmqByteCount > command.fmqByteCount) {
+ if (reply.fmqByteCount < 0 ||
+ (command.getTag() == StreamDescriptor::Command::Tag::burst &&
+ reply.fmqByteCount > command.get<StreamDescriptor::Command::Tag::burst>())) {
LOG(ERROR) << __func__
<< ": received invalid byte count in the reply: " << reply.fmqByteCount;
return Status::ABORT;
@@ -1551,18 +1556,15 @@
}
void SendInvalidCommandImpl(const AudioPortConfig& portConfig) {
- std::vector<StreamDescriptor::Command> commands(6);
- commands[0].code = StreamDescriptor::CommandCode(-1);
- commands[1].code = StreamDescriptor::CommandCode(
- static_cast<int32_t>(StreamDescriptor::CommandCode::START) - 1);
- commands[2].code = StreamDescriptor::CommandCode(std::numeric_limits<int32_t>::min());
- commands[3].code = StreamDescriptor::CommandCode(std::numeric_limits<int32_t>::max());
- // TODO: For proper testing of input streams, need to put the stream into
- // a state which accepts BURST commands.
- commands[4].code = StreamDescriptor::CommandCode::BURST;
- commands[4].fmqByteCount = -1;
- commands[5].code = StreamDescriptor::CommandCode::BURST;
- commands[5].fmqByteCount = std::numeric_limits<int32_t>::min();
+ std::vector<StreamDescriptor::Command> commands = {
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::hal_reserved_exit>(
+ 0),
+ // TODO: For proper testing of input streams, need to put the stream into
+ // a state which accepts BURST commands.
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(-1),
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(
+ std::numeric_limits<int32_t>::min()),
+ };
WithStream<Stream> stream(portConfig);
ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
StreamLogicDriverInvalidCommand driver(commands);
@@ -1628,7 +1630,7 @@
<< "when no offload info is provided for a compressed offload mix port";
}
-using CommandAndState = std::pair<StreamDescriptor::CommandCode, StreamDescriptor::State>;
+using CommandAndState = std::pair<StreamDescriptor::Command, StreamDescriptor::State>;
class StreamLogicDefaultDriver : public StreamLogicDriver {
public:
@@ -1643,15 +1645,17 @@
bool done() override { return mNextCommand >= mCommands.size(); }
StreamDescriptor::Command getNextCommand(int maxDataSize, int* actualSize) override {
- StreamDescriptor::Command command{};
- command.code = mCommands[mNextCommand++].first;
- const int dataSize = command.code == StreamDescriptor::CommandCode::BURST ? maxDataSize : 0;
- command.fmqByteCount = dataSize;
- if (actualSize != nullptr) {
- // In the output scenario, reduce slightly the fmqByteCount to verify
- // that the HAL module always consumes all data from the MQ.
- if (command.fmqByteCount > 1) command.fmqByteCount--;
- *actualSize = dataSize;
+ auto command = mCommands[mNextCommand++].first;
+ if (command.getTag() == StreamDescriptor::Command::Tag::burst) {
+ if (actualSize != nullptr) {
+ // In the output scenario, reduce slightly the fmqByteCount to verify
+ // that the HAL module always consumes all data from the MQ.
+ if (maxDataSize > 1) maxDataSize--;
+ *actualSize = maxDataSize;
+ }
+ command.set<StreamDescriptor::Command::Tag::burst>(maxDataSize);
+ } else {
+ if (actualSize != nullptr) *actualSize = 0;
}
return command;
}
@@ -1673,7 +1677,7 @@
.append(" to ")
.append(toString(reply.state))
.append(" caused by the command ")
- .append(toString(lastCommandState.first));
+ .append(lastCommandState.first.toString());
LOG(ERROR) << __func__ << ": " << s;
mUnexpectedTransition = std::move(s);
return false;
@@ -1970,112 +1974,90 @@
android::PrintInstanceNameToString);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioStreamOut);
-static const NamedCommandSequence kReadOrWriteSeq = std::make_pair(
- std::string("ReadOrWrite"),
- std::vector<CommandAndState>{
- std::make_pair(StreamDescriptor::CommandCode::START, StreamDescriptor::State::IDLE),
- std::make_pair(StreamDescriptor::CommandCode::BURST,
- StreamDescriptor::State::ACTIVE),
- std::make_pair(StreamDescriptor::CommandCode::BURST,
- StreamDescriptor::State::ACTIVE),
- std::make_pair(StreamDescriptor::CommandCode::BURST,
- StreamDescriptor::State::ACTIVE)});
-static const NamedCommandSequence kDrainInSeq = std::make_pair(
- std::string("Drain"),
- std::vector<CommandAndState>{
- std::make_pair(StreamDescriptor::CommandCode::START, StreamDescriptor::State::IDLE),
- std::make_pair(StreamDescriptor::CommandCode::BURST,
- StreamDescriptor::State::ACTIVE),
- std::make_pair(StreamDescriptor::CommandCode::DRAIN,
- StreamDescriptor::State::DRAINING),
- std::make_pair(StreamDescriptor::CommandCode::START,
- StreamDescriptor::State::ACTIVE),
- std::make_pair(StreamDescriptor::CommandCode::DRAIN,
- StreamDescriptor::State::DRAINING),
- // TODO: This will need to be changed once DRAIN starts taking time.
- std::make_pair(StreamDescriptor::CommandCode::BURST,
- StreamDescriptor::State::STANDBY)});
-static const NamedCommandSequence kDrainOutSeq = std::make_pair(
- std::string("Drain"),
- std::vector<CommandAndState>{
- std::make_pair(StreamDescriptor::CommandCode::START, StreamDescriptor::State::IDLE),
- std::make_pair(StreamDescriptor::CommandCode::BURST,
- StreamDescriptor::State::ACTIVE),
- // TODO: This will need to be changed once DRAIN starts taking time.
- std::make_pair(StreamDescriptor::CommandCode::DRAIN,
- StreamDescriptor::State::IDLE)});
+static const StreamDescriptor::Command kStartCommand =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::start>(Void{});
+static const StreamDescriptor::Command kBurstCommand =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(0);
+static const StreamDescriptor::Command kDrainCommand =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::drain>(Void{});
+static const StreamDescriptor::Command kStandbyCommand =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::standby>(Void{});
+static const StreamDescriptor::Command kPauseCommand =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::pause>(Void{});
+static const StreamDescriptor::Command kFlushCommand =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::flush>(Void{});
+static const NamedCommandSequence kReadOrWriteSeq =
+ std::make_pair(std::string("ReadOrWrite"),
+ std::vector<CommandAndState>{
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE)});
+static const NamedCommandSequence kDrainInSeq =
+ std::make_pair(std::string("Drain"),
+ std::vector<CommandAndState>{
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kDrainCommand, StreamDescriptor::State::DRAINING),
+ std::make_pair(kStartCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kDrainCommand, StreamDescriptor::State::DRAINING),
+ // TODO: This will need to be changed once DRAIN starts taking time.
+ std::make_pair(kBurstCommand, StreamDescriptor::State::STANDBY)});
+static const NamedCommandSequence kDrainOutSeq =
+ std::make_pair(std::string("Drain"),
+ std::vector<CommandAndState>{
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ // TODO: This will need to be changed once DRAIN starts taking time.
+ std::make_pair(kDrainCommand, StreamDescriptor::State::IDLE)});
// TODO: This will need to be changed once DRAIN starts taking time so we can pause it.
static const NamedCommandSequence kDrainPauseOutSeq = std::make_pair(
std::string("DrainPause"),
- std::vector<CommandAndState>{
- std::make_pair(StreamDescriptor::CommandCode::START, StreamDescriptor::State::IDLE),
- std::make_pair(StreamDescriptor::CommandCode::BURST,
- StreamDescriptor::State::ACTIVE),
- std::make_pair(StreamDescriptor::CommandCode::DRAIN,
- StreamDescriptor::State::IDLE)});
-static const NamedCommandSequence kStandbySeq = std::make_pair(
- std::string("Standby"),
- std::vector<CommandAndState>{
- std::make_pair(StreamDescriptor::CommandCode::START, StreamDescriptor::State::IDLE),
- std::make_pair(StreamDescriptor::CommandCode::STANDBY,
- StreamDescriptor::State::STANDBY),
- // Perform a read or write in order to advance observable position
- // (this is verified by tests).
- std::make_pair(StreamDescriptor::CommandCode::START, StreamDescriptor::State::IDLE),
- std::make_pair(StreamDescriptor::CommandCode::BURST,
- StreamDescriptor::State::ACTIVE)});
-static const NamedCommandSequence kPauseInSeq = std::make_pair(
- std::string("Pause"),
- std::vector<CommandAndState>{
- std::make_pair(StreamDescriptor::CommandCode::START, StreamDescriptor::State::IDLE),
- std::make_pair(StreamDescriptor::CommandCode::BURST,
- StreamDescriptor::State::ACTIVE),
- std::make_pair(StreamDescriptor::CommandCode::PAUSE,
- StreamDescriptor::State::PAUSED),
- std::make_pair(StreamDescriptor::CommandCode::BURST,
- StreamDescriptor::State::ACTIVE),
- std::make_pair(StreamDescriptor::CommandCode::PAUSE,
- StreamDescriptor::State::PAUSED),
- std::make_pair(StreamDescriptor::CommandCode::FLUSH,
- StreamDescriptor::State::STANDBY)});
-static const NamedCommandSequence kPauseOutSeq = std::make_pair(
- std::string("Pause"),
- std::vector<CommandAndState>{
- std::make_pair(StreamDescriptor::CommandCode::START, StreamDescriptor::State::IDLE),
- std::make_pair(StreamDescriptor::CommandCode::BURST,
- StreamDescriptor::State::ACTIVE),
- std::make_pair(StreamDescriptor::CommandCode::PAUSE,
- StreamDescriptor::State::PAUSED),
- std::make_pair(StreamDescriptor::CommandCode::START,
- StreamDescriptor::State::ACTIVE),
- std::make_pair(StreamDescriptor::CommandCode::PAUSE,
- StreamDescriptor::State::PAUSED),
- std::make_pair(StreamDescriptor::CommandCode::BURST,
- StreamDescriptor::State::PAUSED),
- std::make_pair(StreamDescriptor::CommandCode::START,
- StreamDescriptor::State::ACTIVE),
- std::make_pair(StreamDescriptor::CommandCode::PAUSE,
- StreamDescriptor::State::PAUSED)});
-static const NamedCommandSequence kFlushInSeq = std::make_pair(
- std::string("Flush"),
- std::vector<CommandAndState>{
- std::make_pair(StreamDescriptor::CommandCode::START, StreamDescriptor::State::IDLE),
- std::make_pair(StreamDescriptor::CommandCode::BURST,
- StreamDescriptor::State::ACTIVE),
- std::make_pair(StreamDescriptor::CommandCode::PAUSE,
- StreamDescriptor::State::PAUSED),
- std::make_pair(StreamDescriptor::CommandCode::FLUSH,
- StreamDescriptor::State::STANDBY)});
+ std::vector<CommandAndState>{std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kDrainCommand, StreamDescriptor::State::IDLE)});
+static const NamedCommandSequence kStandbySeq =
+ std::make_pair(std::string("Standby"),
+ std::vector<CommandAndState>{
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kStandbyCommand, StreamDescriptor::State::STANDBY),
+ // Perform a read or write in order to advance observable position
+ // (this is verified by tests).
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE)});
+static const NamedCommandSequence kPauseInSeq =
+ std::make_pair(std::string("Pause"),
+ std::vector<CommandAndState>{
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kPauseCommand, StreamDescriptor::State::PAUSED),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kPauseCommand, StreamDescriptor::State::PAUSED),
+ std::make_pair(kFlushCommand, StreamDescriptor::State::STANDBY)});
+static const NamedCommandSequence kPauseOutSeq =
+ std::make_pair(std::string("Pause"),
+ std::vector<CommandAndState>{
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kPauseCommand, StreamDescriptor::State::PAUSED),
+ std::make_pair(kStartCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kPauseCommand, StreamDescriptor::State::PAUSED),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::PAUSED),
+ std::make_pair(kStartCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kPauseCommand, StreamDescriptor::State::PAUSED)});
+static const NamedCommandSequence kFlushInSeq =
+ std::make_pair(std::string("Flush"),
+ std::vector<CommandAndState>{
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kPauseCommand, StreamDescriptor::State::PAUSED),
+ std::make_pair(kFlushCommand, StreamDescriptor::State::STANDBY)});
static const NamedCommandSequence kFlushOutSeq = std::make_pair(
std::string("Flush"),
- std::vector<CommandAndState>{
- std::make_pair(StreamDescriptor::CommandCode::START, StreamDescriptor::State::IDLE),
- std::make_pair(StreamDescriptor::CommandCode::BURST,
- StreamDescriptor::State::ACTIVE),
- std::make_pair(StreamDescriptor::CommandCode::PAUSE,
- StreamDescriptor::State::PAUSED),
- std::make_pair(StreamDescriptor::CommandCode::FLUSH,
- StreamDescriptor::State::IDLE)});
+ std::vector<CommandAndState>{std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kPauseCommand, StreamDescriptor::State::PAUSED),
+ std::make_pair(kFlushCommand, StreamDescriptor::State::IDLE)});
std::string GetStreamIoTestName(const testing::TestParamInfo<StreamIoTestParameters>& info) {
return android::PrintInstanceNameToString(
testing::TestParamInfo<std::string>{std::get<PARAM_MODULE_NAME>(info.param),