Merge "audio: Allow Stream SM to stay in DRAINING state for early notify" into main

This commit is contained in:
Mikhail Naganov
2024-11-15 18:07:29 +00:00
committed by Gerrit Code Review
6 changed files with 173 additions and 77 deletions

View File

@@ -45,6 +45,8 @@ digraph stream_out_async_state_machine {
PAUSED -> ACTIVE [label="start"]; // consumer -> active
PAUSED -> IDLE [label="flush"]; // producer -> passive, buffer is cleared
DRAINING -> IDLE [label="←IStreamCallback.onDrainReady"];
DRAINING -> DRAINING [label="←IStreamCallback.onDrainReady"]; // allowed for `DRAIN_EARLY_NOTIFY`
DRAINING -> IDLE [label="<empty buffer>"]; // allowed for `DRAIN_EARLY_NOTIFY`
DRAINING -> TRANSFERRING [label="burst"]; // producer -> active
DRAINING -> ACTIVE [label="burst"]; // full write
DRAINING -> DRAIN_PAUSED [label="pause"]; // consumer -> passive (not consuming)

View File

@@ -207,9 +207,9 @@ ndk::ScopedAStatus Module::createStreamContext(
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
const auto& flags = portConfigIt->flags.value();
StreamContext::DebugParameters params{mDebug.streamTransientStateDelayMs,
mVendorDebug.forceTransientBurst,
mVendorDebug.forceSynchronousDrain};
StreamContext::DebugParameters params{
mDebug.streamTransientStateDelayMs, mVendorDebug.forceTransientBurst,
mVendorDebug.forceSynchronousDrain, mVendorDebug.forceDrainToDraining};
std::unique_ptr<StreamContext::DataMQ> dataMQ = nullptr;
std::shared_ptr<IStreamCallback> streamAsyncCallback = nullptr;
std::shared_ptr<ISoundDose> soundDose;
@@ -1524,6 +1524,7 @@ ndk::ScopedAStatus Module::generateHwAvSyncId(int32_t* _aidl_return) {
const std::string Module::VendorDebug::kForceTransientBurstName = "aosp.forceTransientBurst";
const std::string Module::VendorDebug::kForceSynchronousDrainName = "aosp.forceSynchronousDrain";
const std::string Module::VendorDebug::kForceDrainToDrainingName = "aosp.forceDrainToDraining";
ndk::ScopedAStatus Module::getVendorParameters(const std::vector<std::string>& in_ids,
std::vector<VendorParameter>* _aidl_return) {
@@ -1538,6 +1539,10 @@ ndk::ScopedAStatus Module::getVendorParameters(const std::vector<std::string>& i
VendorParameter forceSynchronousDrain{.id = id};
forceSynchronousDrain.ext.setParcelable(Boolean{mVendorDebug.forceSynchronousDrain});
_aidl_return->push_back(std::move(forceSynchronousDrain));
} else if (id == VendorDebug::kForceDrainToDrainingName) {
VendorParameter forceDrainToDraining{.id = id};
forceDrainToDraining.ext.setParcelable(Boolean{mVendorDebug.forceDrainToDraining});
_aidl_return->push_back(std::move(forceDrainToDraining));
} else {
allParametersKnown = false;
LOG(VERBOSE) << __func__ << ": " << mType << ": unrecognized parameter \"" << id << "\"";
@@ -1578,6 +1583,10 @@ ndk::ScopedAStatus Module::setVendorParameters(const std::vector<VendorParameter
if (!extractParameter<Boolean>(p, &mVendorDebug.forceSynchronousDrain)) {
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
} else if (p.id == VendorDebug::kForceDrainToDrainingName) {
if (!extractParameter<Boolean>(p, &mVendorDebug.forceDrainToDraining)) {
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
} else {
allParametersKnown = false;
LOG(VERBOSE) << __func__ << ": " << mType << ": unrecognized parameter \"" << p.id

View File

@@ -382,8 +382,20 @@ bool StreamInWorkerLogic::read(size_t clientSize, StreamDescriptor::Reply* reply
const std::string StreamOutWorkerLogic::kThreadName = "writer";
StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
if (mState == StreamDescriptor::State::DRAINING ||
mState == StreamDescriptor::State::TRANSFERRING) {
if (mState == StreamDescriptor::State::DRAINING && mContext->getForceDrainToDraining() &&
mOnDrainReadyStatus == OnDrainReadyStatus::UNSENT) {
std::shared_ptr<IStreamCallback> asyncCallback = mContext->getAsyncCallback();
if (asyncCallback != nullptr) {
ndk::ScopedAStatus status = asyncCallback->onDrainReady();
if (!status.isOk()) {
LOG(ERROR) << __func__ << ": error from onDrainReady: " << status;
}
// This sets the timeout for moving into IDLE on next iterations.
switchToTransientState(StreamDescriptor::State::DRAINING);
mOnDrainReadyStatus = OnDrainReadyStatus::SENT;
}
} else if (mState == StreamDescriptor::State::DRAINING ||
mState == StreamDescriptor::State::TRANSFERRING) {
if (auto stateDurationMs = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - mTransientStateStart);
stateDurationMs >= mTransientStateDelayMs) {
@@ -396,9 +408,12 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
// drain or transfer completion. In the stub, we switch unconditionally.
if (mState == StreamDescriptor::State::DRAINING) {
mState = StreamDescriptor::State::IDLE;
ndk::ScopedAStatus status = asyncCallback->onDrainReady();
if (!status.isOk()) {
LOG(ERROR) << __func__ << ": error from onDrainReady: " << status;
if (mOnDrainReadyStatus != OnDrainReadyStatus::SENT) {
ndk::ScopedAStatus status = asyncCallback->onDrainReady();
if (!status.isOk()) {
LOG(ERROR) << __func__ << ": error from onDrainReady: " << status;
}
mOnDrainReadyStatus = OnDrainReadyStatus::SENT;
}
} else {
mState = StreamDescriptor::State::ACTIVE;
@@ -537,6 +552,10 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
mState = StreamDescriptor::State::IDLE;
} else {
switchToTransientState(StreamDescriptor::State::DRAINING);
mOnDrainReadyStatus =
mode == StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY
? OnDrainReadyStatus::UNSENT
: OnDrainReadyStatus::IGNORE;
}
} else {
LOG(ERROR) << __func__ << ": drain failed: " << status;

View File

@@ -148,8 +148,10 @@ class Module : public BnModule {
struct VendorDebug {
static const std::string kForceTransientBurstName;
static const std::string kForceSynchronousDrainName;
static const std::string kForceDrainToDrainingName;
bool forceTransientBurst = false;
bool forceSynchronousDrain = false;
bool forceDrainToDraining = false;
};
// ids of device ports created at runtime via 'connectExternalDevice'.
// Also stores a list of ids of mix ports with dynamic profiles that were populated from

View File

@@ -78,6 +78,10 @@ class StreamContext {
bool forceTransientBurst = false;
// Force the "drain" command to be synchronous, going directly to the IDLE state.
bool forceSynchronousDrain = false;
// Force the "drain early notify" command to keep the SM in the DRAINING state
// after sending 'onDrainReady' callback. The SM moves to IDLE after
// 'transientStateDelayMs'.
bool forceDrainToDraining = false;
};
StreamContext() = default;
@@ -119,6 +123,7 @@ class StreamContext {
::aidl::android::media::audio::common::AudioIoFlags getFlags() const { return mFlags; }
bool getForceTransientBurst() const { return mDebugParameters.forceTransientBurst; }
bool getForceSynchronousDrain() const { return mDebugParameters.forceSynchronousDrain; }
bool getForceDrainToDraining() const { return mDebugParameters.forceDrainToDraining; }
size_t getFrameSize() const;
int getInternalCommandCookie() const { return mInternalCommandCookie; }
int32_t getMixPortHandle() const { return mMixPortHandle; }
@@ -301,6 +306,9 @@ class StreamOutWorkerLogic : public StreamWorkerCommonLogic {
bool write(size_t clientSize, StreamDescriptor::Reply* reply);
std::shared_ptr<IStreamOutEventCallback> mEventCallback;
enum OnDrainReadyStatus : int32_t { IGNORE /*used for DRAIN_ALL*/, UNSENT, SENT };
OnDrainReadyStatus mOnDrainReadyStatus = OnDrainReadyStatus::IGNORE;
};
using StreamOutWorker = StreamWorkerImpl<StreamOutWorkerLogic>;

View File

@@ -117,6 +117,10 @@ using android::hardware::audio::common::testing::detail::TestExecutionTracer;
using ndk::enum_range;
using ndk::ScopedAStatus;
static constexpr int32_t kAidlVersion1 = 1;
static constexpr int32_t kAidlVersion2 = 2;
static constexpr int32_t kAidlVersion3 = 3;
template <typename T>
std::set<int32_t> extractIds(const std::vector<T>& v) {
std::set<int32_t> ids;
@@ -452,7 +456,6 @@ class AudioCoreModuleBase {
// This is implemented by the 'StreamFixture' utility class.
static constexpr int kNegativeTestBufferSizeFrames = 256;
static constexpr int kDefaultLargeBufferSizeFrames = 48000;
static constexpr int32_t kAidlVersion3 = 3;
void SetUpImpl(const std::string& moduleName, bool setUpDebug = true) {
ASSERT_NO_FATAL_FAILURE(ConnectToService(moduleName, setUpDebug));
@@ -582,7 +585,7 @@ class AudioCoreModuleBase {
std::unique_ptr<WithDebugFlags> debug;
std::vector<AudioPort> initialPorts;
std::vector<AudioRoute> initialRoutes;
int32_t aidlVersion;
int32_t aidlVersion = -1;
};
class WithDevicePortConnectedState {
@@ -1837,6 +1840,7 @@ TEST_P(AudioCoreModule, SetAudioPortConfigInvalidPortConfigId) {
}
TEST_P(AudioCoreModule, SetAudioPortConfigInvalidPortAudioGain) {
ASSERT_GE(aidlVersion, kAidlVersion1);
if (aidlVersion < kAidlVersion3) {
GTEST_SKIP() << "Skip for audio HAL version lower than " << kAidlVersion3;
}
@@ -4021,6 +4025,7 @@ TEST_P(AudioStreamOut, UpdateOffloadMetadata) {
enum {
NAMED_CMD_NAME,
NAMED_CMD_MIN_INTERFACE_VERSION,
NAMED_CMD_DELAY_MS,
NAMED_CMD_STREAM_TYPE,
NAMED_CMD_CMDS,
@@ -4028,7 +4033,7 @@ enum {
};
enum class StreamTypeFilter { ANY, SYNC, ASYNC };
using NamedCommandSequence =
std::tuple<std::string, int /*cmdDelayMs*/, StreamTypeFilter,
std::tuple<std::string, int /*minInterfaceVersion*/, int /*cmdDelayMs*/, StreamTypeFilter,
std::shared_ptr<StateSequence>, bool /*validatePositionIncrease*/>;
enum { PARAM_MODULE_NAME, PARAM_CMD_SEQ, PARAM_SETUP_SEQ };
using StreamIoTestParameters =
@@ -4039,6 +4044,12 @@ class AudioStreamIo : public AudioCoreModuleBase,
public:
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(SetUpImpl(std::get<PARAM_MODULE_NAME>(GetParam())));
ASSERT_GE(aidlVersion, kAidlVersion1);
if (const int minVersion =
std::get<NAMED_CMD_MIN_INTERFACE_VERSION>(std::get<PARAM_CMD_SEQ>(GetParam()));
aidlVersion < minVersion) {
GTEST_SKIP() << "Skip for audio HAL version lower than " << minVersion;
}
ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
}
@@ -4048,6 +4059,20 @@ class AudioStreamIo : public AudioCoreModuleBase,
if (allPortConfigs.empty()) {
GTEST_SKIP() << "No mix ports have attached devices";
}
const auto& commandsAndStates =
std::get<NAMED_CMD_CMDS>(std::get<PARAM_CMD_SEQ>(GetParam()));
const bool validatePositionIncrease =
std::get<NAMED_CMD_VALIDATE_POS_INCREASE>(std::get<PARAM_CMD_SEQ>(GetParam()));
auto runStreamIoCommands = [&](const AudioPortConfig& portConfig) {
if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates,
validatePositionIncrease));
} else {
ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates,
validatePositionIncrease));
}
};
for (const auto& portConfig : allPortConfigs) {
auto port = moduleConfig->getPort(portConfig.portId);
ASSERT_TRUE(port.has_value());
@@ -4075,16 +4100,18 @@ class AudioStreamIo : public AudioCoreModuleBase,
delayTransientStates.flags().streamTransientStateDelayMs =
std::get<NAMED_CMD_DELAY_MS>(std::get<PARAM_CMD_SEQ>(GetParam()));
ASSERT_NO_FATAL_FAILURE(delayTransientStates.SetUp(module.get()));
const auto& commandsAndStates =
std::get<NAMED_CMD_CMDS>(std::get<PARAM_CMD_SEQ>(GetParam()));
const bool validatePositionIncrease =
std::get<NAMED_CMD_VALIDATE_POS_INCREASE>(std::get<PARAM_CMD_SEQ>(GetParam()));
if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates,
validatePositionIncrease));
} else {
ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates,
validatePositionIncrease));
ASSERT_NO_FATAL_FAILURE(runStreamIoCommands(portConfig));
if (aidlVersion >= kAidlVersion3 && isNonBlocking && !IOTraits<Stream>::is_input) {
// Also try running the same sequence with "aosp.forceDrainToDraining" set.
// This will only work with the default implementation. When it works, the stream
// tries always to move to the 'DRAINING' state after an "early notify" drain.
// This helps to check more paths for our test scenarios.
WithModuleParameter forceDrainToDraining("aosp.forceDrainToDraining",
Boolean{true});
if (forceDrainToDraining.SetUpNoChecks(module.get(), true /*failureExpected*/)
.isOk()) {
ASSERT_NO_FATAL_FAILURE(runStreamIoCommands(portConfig));
}
}
if (isNonBlocking) {
// Also try running the same sequence with "aosp.forceTransientBurst" set.
@@ -4094,13 +4121,7 @@ class AudioStreamIo : public AudioCoreModuleBase,
WithModuleParameter forceTransientBurst("aosp.forceTransientBurst", Boolean{true});
if (forceTransientBurst.SetUpNoChecks(module.get(), true /*failureExpected*/)
.isOk()) {
if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(
portConfig, commandsAndStates, validatePositionIncrease));
} else {
ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(
portConfig, commandsAndStates, validatePositionIncrease));
}
ASSERT_NO_FATAL_FAILURE(runStreamIoCommands(portConfig));
}
} else if (!IOTraits<Stream>::is_input) {
// Also try running the same sequence with "aosp.forceSynchronousDrain" set.
@@ -4111,13 +4132,7 @@ class AudioStreamIo : public AudioCoreModuleBase,
Boolean{true});
if (forceSynchronousDrain.SetUpNoChecks(module.get(), true /*failureExpected*/)
.isOk()) {
if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(
portConfig, commandsAndStates, validatePositionIncrease));
} else {
ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(
portConfig, commandsAndStates, validatePositionIncrease));
}
ASSERT_NO_FATAL_FAILURE(runStreamIoCommands(portConfig));
}
}
}
@@ -4570,14 +4585,14 @@ std::shared_ptr<StateSequence> makeBurstCommands(bool isSync) {
return std::make_shared<StateSequenceFollower>(std::move(d));
}
static const NamedCommandSequence kReadSeq =
std::make_tuple(std::string("Read"), 0, StreamTypeFilter::ANY, makeBurstCommands(true),
true /*validatePositionIncrease*/);
std::make_tuple(std::string("Read"), kAidlVersion1, 0, StreamTypeFilter::ANY,
makeBurstCommands(true), true /*validatePositionIncrease*/);
static const NamedCommandSequence kWriteSyncSeq =
std::make_tuple(std::string("Write"), 0, StreamTypeFilter::SYNC, makeBurstCommands(true),
true /*validatePositionIncrease*/);
std::make_tuple(std::string("Write"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
makeBurstCommands(true), true /*validatePositionIncrease*/);
static const NamedCommandSequence kWriteAsyncSeq =
std::make_tuple(std::string("Write"), 0, StreamTypeFilter::ASYNC, makeBurstCommands(false),
true /*validatePositionIncrease*/);
std::make_tuple(std::string("Write"), kAidlVersion1, 0, StreamTypeFilter::ASYNC,
makeBurstCommands(false), true /*validatePositionIncrease*/);
std::shared_ptr<StateSequence> makeAsyncDrainCommands(bool isInput) {
using State = StreamDescriptor::State;
@@ -4606,10 +4621,10 @@ std::shared_ptr<StateSequence> makeAsyncDrainCommands(bool isInput) {
return std::make_shared<StateSequenceFollower>(std::move(d));
}
static const NamedCommandSequence kWriteDrainAsyncSeq = std::make_tuple(
std::string("WriteDrain"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
makeAsyncDrainCommands(false), false /*validatePositionIncrease*/);
std::string("WriteDrain"), kAidlVersion1, kStreamTransientStateTransitionDelayMs,
StreamTypeFilter::ASYNC, makeAsyncDrainCommands(false), false /*validatePositionIncrease*/);
static const NamedCommandSequence kDrainInSeq =
std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::ANY,
std::make_tuple(std::string("Drain"), kAidlVersion1, 0, StreamTypeFilter::ANY,
makeAsyncDrainCommands(true), false /*validatePositionIncrease*/);
std::shared_ptr<StateSequence> makeDrainOutCommands(bool isSync) {
@@ -4631,12 +4646,28 @@ std::shared_ptr<StateSequence> makeDrainOutCommands(bool isSync) {
return std::make_shared<StateSequenceFollower>(std::move(d));
}
static const NamedCommandSequence kDrainOutSyncSeq =
std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::SYNC, makeDrainOutCommands(true),
false /*validatePositionIncrease*/);
std::make_tuple(std::string("Drain"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
makeDrainOutCommands(true), false /*validatePositionIncrease*/);
static const NamedCommandSequence kDrainOutAsyncSeq =
std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::ASYNC,
std::make_tuple(std::string("Drain"), kAidlVersion3, 0, StreamTypeFilter::ASYNC,
makeDrainOutCommands(false), false /*validatePositionIncrease*/);
std::shared_ptr<StateSequence> makeDrainEarlyOutCommands() {
using State = StreamDescriptor::State;
auto d = std::make_unique<StateDag>();
StateDag::Node last = d->makeFinalNode(State::IDLE);
StateDag::Node draining = d->makeNode(State::DRAINING, kDrainReadyEvent, last);
draining.children().push_back(d->makeNode(State::DRAINING, kGetStatusCommand, last));
StateDag::Node active = d->makeNode(State::ACTIVE, kDrainOutEarlyCommand, draining);
StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
idle.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active));
d->makeNode(State::STANDBY, kStartCommand, idle);
return std::make_shared<StateSequenceFollower>(std::move(d));
}
static const NamedCommandSequence kDrainEarlyOutAsyncSeq =
std::make_tuple(std::string("DrainEarly"), kAidlVersion3, 0, StreamTypeFilter::ASYNC,
makeDrainEarlyOutCommands(), false /*validatePositionIncrease*/);
std::shared_ptr<StateSequence> makeDrainPauseOutCommands(bool isSync) {
using State = StreamDescriptor::State;
auto d = std::make_unique<StateDag>();
@@ -4656,12 +4687,33 @@ std::shared_ptr<StateSequence> makeDrainPauseOutCommands(bool isSync) {
d->makeNode(State::STANDBY, kStartCommand, idle);
return std::make_shared<StateSequenceFollower>(std::move(d));
}
static const NamedCommandSequence kDrainPauseOutSyncSeq = std::make_tuple(
std::string("DrainPause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::SYNC,
makeDrainPauseOutCommands(true), false /*validatePositionIncrease*/);
static const NamedCommandSequence kDrainPauseOutAsyncSeq = std::make_tuple(
std::string("DrainPause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
makeDrainPauseOutCommands(false), false /*validatePositionIncrease*/);
static const NamedCommandSequence kDrainPauseOutSyncSeq =
std::make_tuple(std::string("DrainPause"), kAidlVersion1,
kStreamTransientStateTransitionDelayMs, StreamTypeFilter::SYNC,
makeDrainPauseOutCommands(true), false /*validatePositionIncrease*/);
static const NamedCommandSequence kDrainPauseOutAsyncSeq =
std::make_tuple(std::string("DrainPause"), kAidlVersion1,
kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
makeDrainPauseOutCommands(false), false /*validatePositionIncrease*/);
std::shared_ptr<StateSequence> makeDrainEarlyPauseOutCommands() {
using State = StreamDescriptor::State;
auto d = std::make_unique<StateDag>();
StateDag::Node draining = d->makeNodes({std::make_pair(State::DRAINING, kPauseCommand),
std::make_pair(State::DRAIN_PAUSED, kStartCommand),
std::make_pair(State::DRAINING, kPauseCommand),
std::make_pair(State::DRAIN_PAUSED, kBurstCommand)},
State::TRANSFER_PAUSED);
StateDag::Node active = d->makeNode(State::ACTIVE, kDrainOutEarlyCommand, draining);
StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
idle.children().push_back(d->makeNode(State::TRANSFERRING, kDrainOutEarlyCommand, draining));
d->makeNode(State::STANDBY, kStartCommand, idle);
return std::make_shared<StateSequenceFollower>(std::move(d));
}
static const NamedCommandSequence kDrainEarlyPauseOutAsyncSeq =
std::make_tuple(std::string("DrainEarlyPause"), kAidlVersion3,
kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
makeDrainEarlyPauseOutCommands(), false /*validatePositionIncrease*/);
// This sequence also verifies that the capture / presentation position is not reset on standby.
std::shared_ptr<StateSequence> makeStandbyCommands(bool isInput, bool isSync) {
@@ -4703,14 +4755,15 @@ std::shared_ptr<StateSequence> makeStandbyCommands(bool isInput, bool isSync) {
return std::make_shared<StateSequenceFollower>(std::move(d));
}
static const NamedCommandSequence kStandbyInSeq =
std::make_tuple(std::string("Standby"), 0, StreamTypeFilter::ANY,
std::make_tuple(std::string("Standby"), kAidlVersion1, 0, StreamTypeFilter::ANY,
makeStandbyCommands(true, false), false /*validatePositionIncrease*/);
static const NamedCommandSequence kStandbyOutSyncSeq =
std::make_tuple(std::string("Standby"), 0, StreamTypeFilter::SYNC,
std::make_tuple(std::string("Standby"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
makeStandbyCommands(false, true), false /*validatePositionIncrease*/);
static const NamedCommandSequence kStandbyOutAsyncSeq = std::make_tuple(
std::string("Standby"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
makeStandbyCommands(false, false), false /*validatePositionIncrease*/);
static const NamedCommandSequence kStandbyOutAsyncSeq =
std::make_tuple(std::string("Standby"), kAidlVersion1,
kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
makeStandbyCommands(false, false), false /*validatePositionIncrease*/);
std::shared_ptr<StateSequence> makePauseCommands(bool isInput, bool isSync) {
using State = StreamDescriptor::State;
@@ -4745,14 +4798,15 @@ std::shared_ptr<StateSequence> makePauseCommands(bool isInput, bool isSync) {
return std::make_shared<StateSequenceFollower>(std::move(d));
}
static const NamedCommandSequence kPauseInSeq =
std::make_tuple(std::string("Pause"), 0, StreamTypeFilter::ANY,
std::make_tuple(std::string("Pause"), kAidlVersion1, 0, StreamTypeFilter::ANY,
makePauseCommands(true, false), false /*validatePositionIncrease*/);
static const NamedCommandSequence kPauseOutSyncSeq =
std::make_tuple(std::string("Pause"), 0, StreamTypeFilter::SYNC,
std::make_tuple(std::string("Pause"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
makePauseCommands(false, true), false /*validatePositionIncrease*/);
static const NamedCommandSequence kPauseOutAsyncSeq = std::make_tuple(
std::string("Pause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
makePauseCommands(false, false), false /*validatePositionIncrease*/);
static const NamedCommandSequence kPauseOutAsyncSeq =
std::make_tuple(std::string("Pause"), kAidlVersion1, kStreamTransientStateTransitionDelayMs,
StreamTypeFilter::ASYNC, makePauseCommands(false, false),
false /*validatePositionIncrease*/);
std::shared_ptr<StateSequence> makeFlushCommands(bool isInput, bool isSync) {
using State = StreamDescriptor::State;
@@ -4780,14 +4834,15 @@ std::shared_ptr<StateSequence> makeFlushCommands(bool isInput, bool isSync) {
return std::make_shared<StateSequenceFollower>(std::move(d));
}
static const NamedCommandSequence kFlushInSeq =
std::make_tuple(std::string("Flush"), 0, StreamTypeFilter::ANY,
std::make_tuple(std::string("Flush"), kAidlVersion1, 0, StreamTypeFilter::ANY,
makeFlushCommands(true, false), false /*validatePositionIncrease*/);
static const NamedCommandSequence kFlushOutSyncSeq =
std::make_tuple(std::string("Flush"), 0, StreamTypeFilter::SYNC,
std::make_tuple(std::string("Flush"), kAidlVersion1, 0, StreamTypeFilter::SYNC,
makeFlushCommands(false, true), false /*validatePositionIncrease*/);
static const NamedCommandSequence kFlushOutAsyncSeq = std::make_tuple(
std::string("Flush"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
makeFlushCommands(false, false), false /*validatePositionIncrease*/);
static const NamedCommandSequence kFlushOutAsyncSeq =
std::make_tuple(std::string("Flush"), kAidlVersion1, kStreamTransientStateTransitionDelayMs,
StreamTypeFilter::ASYNC, makeFlushCommands(false, false),
false /*validatePositionIncrease*/);
std::shared_ptr<StateSequence> makeDrainPauseFlushOutCommands(bool isSync) {
using State = StreamDescriptor::State;
@@ -4807,13 +4862,13 @@ std::shared_ptr<StateSequence> makeDrainPauseFlushOutCommands(bool isSync) {
return std::make_shared<StateSequenceFollower>(std::move(d));
}
static const NamedCommandSequence kDrainPauseFlushOutSyncSeq =
std::make_tuple(std::string("DrainPauseFlush"), kStreamTransientStateTransitionDelayMs,
StreamTypeFilter::SYNC, makeDrainPauseFlushOutCommands(true),
false /*validatePositionIncrease*/);
std::make_tuple(std::string("DrainPauseFlush"), kAidlVersion1,
kStreamTransientStateTransitionDelayMs, StreamTypeFilter::SYNC,
makeDrainPauseFlushOutCommands(true), false /*validatePositionIncrease*/);
static const NamedCommandSequence kDrainPauseFlushOutAsyncSeq =
std::make_tuple(std::string("DrainPauseFlush"), kStreamTransientStateTransitionDelayMs,
StreamTypeFilter::ASYNC, makeDrainPauseFlushOutCommands(false),
false /*validatePositionIncrease*/);
std::make_tuple(std::string("DrainPauseFlush"), kAidlVersion1,
kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
makeDrainPauseFlushOutCommands(false), false /*validatePositionIncrease*/);
// Note, this isn't the "official" enum printer, it is only used to make the test name suffix.
std::string PrintStreamFilterToString(StreamTypeFilter filter) {
@@ -4851,9 +4906,10 @@ INSTANTIATE_TEST_SUITE_P(
AudioStreamIoOutTest, AudioStreamIoOut,
testing::Combine(testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
testing::Values(kWriteSyncSeq, kWriteAsyncSeq, kWriteDrainAsyncSeq,
kDrainOutSyncSeq, kDrainPauseOutSyncSeq,
kDrainPauseOutAsyncSeq, kStandbyOutSyncSeq,
kStandbyOutAsyncSeq,
kDrainOutSyncSeq, kDrainOutAsyncSeq,
kDrainEarlyOutAsyncSeq, kDrainPauseOutSyncSeq,
kDrainPauseOutAsyncSeq, kDrainEarlyPauseOutAsyncSeq,
kStandbyOutSyncSeq, kStandbyOutAsyncSeq,
kPauseOutSyncSeq, // kPauseOutAsyncSeq,
kFlushOutSyncSeq, kFlushOutAsyncSeq,
kDrainPauseFlushOutSyncSeq, kDrainPauseFlushOutAsyncSeq),