Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2619aa42 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "audio: Add IStreamCommon.prepareToClose method" am: 940ca899 am: 1dbc39ea

parents 877eb23e 1dbc39ea
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+27 −0
Original line number Diff line number Diff line
@@ -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.
     *
+10 −0
Original line number Diff line number Diff line
@@ -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) {
+7 −0
Original line number Diff line number Diff line
@@ -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;
+23 −0
Original line number Diff line number Diff line
@@ -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);