Merge "audio: Add IStreamCommon.prepareToClose method" am: 940ca8996a
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2475087 Change-Id: Ie919fad86d8da35b0fa297bcf66e4322d0ae0611 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
1dbc39ea23
5 changed files with 68 additions and 0 deletions
|
@ -35,6 +35,7 @@ package android.hardware.audio.core;
|
|||
@VintfStability
|
||||
interface IStreamCommon {
|
||||
void close();
|
||||
void prepareToClose();
|
||||
void updateHwAvSyncId(int hwAvSyncId);
|
||||
android.hardware.audio.core.VendorParameter[] getVendorParameters(in @utf8InCpp String[] ids);
|
||||
void setVendorParameters(in android.hardware.audio.core.VendorParameter[] parameters, boolean async);
|
||||
|
|
|
@ -43,6 +43,33 @@ interface IStreamCommon {
|
|||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Notify the stream that it is about to be closed.
|
||||
*
|
||||
* This is a notification sent by the client to indicate that it intends to
|
||||
* close the stream "soon" (the actual time period is unspecified). The
|
||||
* purpose of this notification is to allow the stream implementation to
|
||||
* unblock the I/O thread. This is useful for HAL modules that act as
|
||||
* proxies to other subsystems, examples are "bluetooth" and "r_submix"
|
||||
* modules. In such modules the I/O thread might get blocked on a read or
|
||||
* write operation to the external subsystem. Thus, calling 'close' directly
|
||||
* will stall, as it will try to send the 'Command.halReservedExit' on the
|
||||
* I/O thread which is blocked and is not reading commands from the FMQ. The
|
||||
* HAL implementation must initiate unblocking as a result of receiving the
|
||||
* 'prepareToClose' notification.
|
||||
*
|
||||
* This operation must be handled by the HAL module in an "asynchronous"
|
||||
* manner, returning control back as quick as possible.
|
||||
*
|
||||
* Since this operation does not have any effects observable from the client
|
||||
* side, the HAL module must be able to handle multiple calls of this method
|
||||
* without throwing any errors. The only case when this method is allowed
|
||||
* to throw is when the stream has been closed.
|
||||
*
|
||||
* @throws EX_ILLEGAL_STATE If the stream is closed.
|
||||
*/
|
||||
void prepareToClose();
|
||||
|
||||
/**
|
||||
* Update the HW AV Sync identifier for the stream.
|
||||
*
|
||||
|
|
|
@ -659,6 +659,16 @@ ndk::ScopedAStatus StreamCommonImpl<Metadata>::close() {
|
|||
}
|
||||
}
|
||||
|
||||
template <class Metadata>
|
||||
ndk::ScopedAStatus StreamCommonImpl<Metadata>::prepareToClose() {
|
||||
LOG(DEBUG) << __func__;
|
||||
if (!isClosed()) {
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
LOG(ERROR) << __func__ << ": stream was closed";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
|
||||
}
|
||||
|
||||
template <class Metadata>
|
||||
void StreamCommonImpl<Metadata>::stopWorker() {
|
||||
if (auto commandMQ = mContext.getCommandMQ(); commandMQ != nullptr) {
|
||||
|
|
|
@ -294,6 +294,7 @@ using StreamOutWorker = StreamWorkerImpl<StreamOutWorkerLogic>;
|
|||
struct StreamCommonInterface {
|
||||
virtual ~StreamCommonInterface() = default;
|
||||
virtual ndk::ScopedAStatus close() = 0;
|
||||
virtual ndk::ScopedAStatus prepareToClose() = 0;
|
||||
virtual ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) = 0;
|
||||
virtual ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
|
||||
std::vector<VendorParameter>* _aidl_return) = 0;
|
||||
|
@ -318,6 +319,11 @@ class StreamCommon : public BnStreamCommon {
|
|||
return delegate != nullptr ? delegate->close()
|
||||
: ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
|
||||
}
|
||||
ndk::ScopedAStatus prepareToClose() override {
|
||||
auto delegate = mDelegate.lock();
|
||||
return delegate != nullptr ? delegate->prepareToClose()
|
||||
: ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
|
||||
}
|
||||
ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) override {
|
||||
auto delegate = mDelegate.lock();
|
||||
return delegate != nullptr ? delegate->updateHwAvSyncId(in_hwAvSyncId)
|
||||
|
@ -359,6 +365,7 @@ template <class Metadata>
|
|||
class StreamCommonImpl : public StreamCommonInterface {
|
||||
public:
|
||||
ndk::ScopedAStatus close() override;
|
||||
ndk::ScopedAStatus prepareToClose() override;
|
||||
ndk::ScopedAStatus updateHwAvSyncId(int32_t in_hwAvSyncId) override;
|
||||
ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_ids,
|
||||
std::vector<VendorParameter>* _aidl_return) override;
|
||||
|
|
|
@ -1070,6 +1070,8 @@ class WithStream {
|
|||
std::shared_ptr<IStreamCommon> common;
|
||||
ndk::ScopedAStatus status = stream->getStreamCommon(&common);
|
||||
if (!status.isOk()) return status;
|
||||
status = common->prepareToClose();
|
||||
if (!status.isOk()) return status;
|
||||
return common->close();
|
||||
}
|
||||
|
||||
|
@ -2302,6 +2304,26 @@ class AudioStream : public AudioCoreModule {
|
|||
<< "when closing the stream twice";
|
||||
}
|
||||
|
||||
void PrepareToCloseTwice() {
|
||||
const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
|
||||
if (!portConfig.has_value()) {
|
||||
GTEST_SKIP() << "No mix port for attached devices";
|
||||
}
|
||||
std::shared_ptr<IStreamCommon> heldStreamCommon;
|
||||
{
|
||||
WithStream<Stream> stream(portConfig.value());
|
||||
ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
|
||||
std::shared_ptr<IStreamCommon> streamCommon;
|
||||
ASSERT_IS_OK(stream.get()->getStreamCommon(&streamCommon));
|
||||
heldStreamCommon = streamCommon;
|
||||
EXPECT_IS_OK(streamCommon->prepareToClose());
|
||||
EXPECT_IS_OK(streamCommon->prepareToClose())
|
||||
<< "when calling prepareToClose second time";
|
||||
}
|
||||
EXPECT_STATUS(EX_ILLEGAL_STATE, heldStreamCommon->prepareToClose())
|
||||
<< "when calling prepareToClose on a closed stream";
|
||||
}
|
||||
|
||||
void OpenAllConfigs() {
|
||||
const auto allPortConfigs =
|
||||
moduleConfig->getPortConfigsForMixPorts(IOTraits<Stream>::is_input);
|
||||
|
@ -2597,6 +2619,7 @@ using AudioStreamOut = AudioStream<IStreamOut>;
|
|||
}
|
||||
|
||||
TEST_IN_AND_OUT_STREAM(CloseTwice);
|
||||
TEST_IN_AND_OUT_STREAM(PrepareToCloseTwice);
|
||||
TEST_IN_AND_OUT_STREAM(GetStreamCommon);
|
||||
TEST_IN_AND_OUT_STREAM(OpenAllConfigs);
|
||||
TEST_IN_AND_OUT_STREAM(OpenInvalidBufferSize);
|
||||
|
|
Loading…
Reference in a new issue