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

Commit 7663233f authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes from topic "upstream-close-fixes"

* changes:
  audio: Add check to IDevice.close for currently opened streams
  audio: Factor out IStream operations into a helper class
  audio: Cleanup VTS tests
  Audio VTS: Fix MMAP tests
  Audio V6 wrapper: IDevice|IStream|IEffect.close releases HAL resource
parents 2db42995 ed261bbf
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -280,4 +280,19 @@ interface IDevice {
     */
    setConnectedState(DeviceAddress address, bool connected)
            generates (Result retval);

    /**
     * Called by the framework to deinitialize the device and free up
     * all currently allocated resources. It is recommended to close
     * the device on the client side as soon as it is becomes unused.
     *
     * Note that all streams must be closed by the client before
     * attempting to close the device they belong to.
     *
     * @return retval OK in case the success.
     *                INVALID_STATE if the device was already closed
     *                or there are streams currently opened.
     */
    @exit
    close() generates (Result retval);
};
+6 −2
Original line number Diff line number Diff line
@@ -277,7 +277,7 @@ interface IStream {
     * @return retval OK in case the success.
     *                NOT_SUPPORTED on non mmap mode streams
     *                NOT_INITIALIZED in case of memory allocation error
     *                INVALID_ARGUMENTS if the requested buffer size is too large
     *                INVALID_ARGUMENTS if the requested buffer size is invalid
     *                INVALID_STATE if called out of sequence
     * @return info    a MmapBufferInfo struct containing information on the MMMAP buffer created.
     */
@@ -300,13 +300,17 @@ interface IStream {

    /**
     * Called by the framework to deinitialize the stream and free up
     * all the currently allocated resources. It is recommended to close
     * all currently allocated resources. It is recommended to close
     * the stream on the client side as soon as it is becomes unused.
     *
     * The client must ensure that this function is not called while
     * audio data is being transferred through the stream's message queues.
     *
     * @return retval OK in case the success.
     *                NOT_SUPPORTED if called on IStream instead of input or
     *                              output stream interface.
     *                INVALID_STATE if the stream was already closed.
     */
    @exit
    close() generates (Result retval);
};
+20 −3
Original line number Diff line number Diff line
@@ -39,11 +39,10 @@ namespace implementation {

using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;

Device::Device(audio_hw_device_t* device) : mDevice(device) {}
Device::Device(audio_hw_device_t* device) : mIsClosed(false), mDevice(device) {}

Device::~Device() {
    int status = audio_hw_device_close(mDevice);
    ALOGW_IF(status, "Error closing audio hw device %p: %s", mDevice, strerror(-status));
    (void)doClose();
    mDevice = nullptr;
}

@@ -54,10 +53,14 @@ Result Device::analyzeStatus(const char* funcName, int status,

void Device::closeInputStream(audio_stream_in_t* stream) {
    mDevice->close_input_stream(mDevice, stream);
    LOG_ALWAYS_FATAL_IF(mOpenedStreamsCount == 0, "mOpenedStreamsCount is already 0");
    --mOpenedStreamsCount;
}

void Device::closeOutputStream(audio_stream_out_t* stream) {
    mDevice->close_output_stream(mDevice, stream);
    LOG_ALWAYS_FATAL_IF(mOpenedStreamsCount == 0, "mOpenedStreamsCount is already 0");
    --mOpenedStreamsCount;
}

char* Device::halGetParameters(const char* keys) {
@@ -159,6 +162,7 @@ std::tuple<Result, sp<IStreamOut>> Device::openOutputStreamImpl(int32_t ioHandle
    sp<IStreamOut> streamOut;
    if (status == OK) {
        streamOut = new StreamOut(this, halStream);
        ++mOpenedStreamsCount;
    }
    HidlUtils::audioConfigFromHal(halConfig, suggestedConfig);
    return {analyzeStatus("open_output_stream", status, {EINVAL} /*ignore*/), streamOut};
@@ -185,6 +189,7 @@ std::tuple<Result, sp<IStreamIn>> Device::openInputStreamImpl(
    sp<IStreamIn> streamIn;
    if (status == OK) {
        streamIn = new StreamIn(this, halStream);
        ++mOpenedStreamsCount;
    }
    HidlUtils::audioConfigFromHal(halConfig, suggestedConfig);
    return {analyzeStatus("open_input_stream", status, {EINVAL} /*ignore*/), streamIn};
@@ -383,6 +388,18 @@ Return<Result> Device::setConnectedState(const DeviceAddress& address, bool conn
}
#endif

Result Device::doClose() {
    if (mIsClosed || mOpenedStreamsCount != 0) return Result::INVALID_STATE;
    mIsClosed = true;
    return analyzeStatus("close", audio_hw_device_close(mDevice));
}

#if MAJOR_VERSION >= 6
Return<Result> Device::close() {
    return doClose();
}
#endif

}  // namespace implementation
}  // namespace CPP_VERSION
}  // namespace audio
+10 −1
Original line number Diff line number Diff line
@@ -31,7 +31,11 @@ namespace implementation {

PrimaryDevice::PrimaryDevice(audio_hw_device_t* device) : mDevice(new Device(device)) {}

PrimaryDevice::~PrimaryDevice() {}
PrimaryDevice::~PrimaryDevice() {
    // Do not call mDevice->close here. If there are any unclosed streams,
    // they only hold IDevice instance, not IPrimaryDevice, thus IPrimaryDevice
    // "part" of a device can be destroyed before the streams.
}

// Methods from ::android::hardware::audio::CPP_VERSION::IDevice follow.
Return<Result> PrimaryDevice::initCheck() {
@@ -160,6 +164,11 @@ Return<Result> PrimaryDevice::setConnectedState(const DeviceAddress& address, bo
    return mDevice->setConnectedState(address, connected);
}
#endif
#if MAJOR_VERSION >= 6
Return<Result> PrimaryDevice::close() {
    return mDevice->close();
}
#endif

// Methods from ::android::hardware::audio::CPP_VERSION::IPrimaryDevice follow.
Return<Result> PrimaryDevice::setVoiceVolume(float volume) {
+9 −6
Original line number Diff line number Diff line
@@ -139,8 +139,7 @@ bool ReadThread::threadLoop() {
}  // namespace

StreamIn::StreamIn(const sp<Device>& device, audio_stream_in_t* stream)
    : mIsClosed(false),
      mDevice(device),
    : mDevice(device),
      mStream(stream),
      mStreamCommon(new Stream(&stream->common)),
      mStreamMmap(new StreamMmap<audio_stream_in_t>(stream)),
@@ -159,7 +158,9 @@ StreamIn::~StreamIn() {
        status_t status = EventFlag::deleteEventFlag(&mEfGroup);
        ALOGE_IF(status, "read MQ event flag deletion error: %s", strerror(-status));
    }
#if MAJOR_VERSION <= 5
    mDevice->closeInputStream(mStream);
#endif
    mStream = nullptr;
}

@@ -303,14 +304,16 @@ Return<void> StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) {
}

Return<Result> StreamIn::close() {
    if (mIsClosed) return Result::INVALID_STATE;
    mIsClosed = true;
    if (mReadThread.get()) {
        mStopReadThread.store(true, std::memory_order_release);
    if (mStopReadThread.load(std::memory_order_relaxed)) {  // only this thread writes
        return Result::INVALID_STATE;
    }
    mStopReadThread.store(true, std::memory_order_release);
    if (mEfGroup) {
        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
    }
#if MAJOR_VERSION >= 6
    mDevice->closeInputStream(mStream);
#endif
    return Result::OK;
}

Loading