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

Commit d041930d authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

Audio V6 wrapper: IDevice|IStream|IEffect.close releases HAL resource

Fixed behavior of IStream|IEffect.close to release the underlying
HAL resource synchronously. This is to avoid adding artificial
delays in VTS that become totally unpractical in V6.

Added clarification about expected client behavior for
IStream|IEffect.close w.r.t. audio data transfer.

Added IDevice.close method which releases HAL device resource.

Updated VTS tests to remove delays in V6.

Bug: 114451103
Bug: 141989952
Test: atest VtsHalAudioV6_0TargetTest
Change-Id: I439f0f923c091af2ab234d15ca847cfade341f25
Merged-In: I439f0f923c091af2ab234d15ca847cfade341f25
parent 942de9e6
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -280,4 +280,15 @@ 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.
     *
     * @return retval OK in case the success.
     *                INVALID_STATE if the device was already closed.
     */
    @exit
    close() generates (Result retval);
};
+5 −1
Original line number Diff line number Diff line
@@ -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);
};
+14 −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;
}

@@ -383,6 +382,18 @@ Return<Result> Device::setConnectedState(const DeviceAddress& address, bool conn
}
#endif

Result Device::doClose() {
    if (mIsClosed) 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