mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 22:04:26 +00:00
Merge "audio: Allow Stream SM to stay in DRAINING state for early notify" into main
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>;
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user