Loading audio/6.0/IDevice.hal +5 −1 Original line number Diff line number Diff line Loading @@ -286,8 +286,12 @@ interface IDevice { * 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. * INVALID_STATE if the device was already closed * or there are streams currently opened. */ @exit close() generates (Result retval); Loading audio/core/all-versions/default/Device.cpp +7 −1 Original line number Diff line number Diff line Loading @@ -53,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) { Loading Loading @@ -158,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}; Loading @@ -184,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}; Loading Loading @@ -383,7 +389,7 @@ Return<Result> Device::setConnectedState(const DeviceAddress& address, bool conn #endif Result Device::doClose() { if (mIsClosed) return Result::INVALID_STATE; if (mIsClosed || mOpenedStreamsCount != 0) return Result::INVALID_STATE; mIsClosed = true; return analyzeStatus("close", audio_hw_device_close(mDevice)); } Loading audio/core/all-versions/default/include/core/default/Device.h +1 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ struct Device : public IDevice, public ParametersUtil { private: bool mIsClosed; audio_hw_device_t* mDevice; int mOpenedStreamsCount = 0; virtual ~Device(); Loading audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp +46 −0 Original line number Diff line number Diff line Loading @@ -145,3 +145,49 @@ const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters() { }(); return parameters; } TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedOutputStreams) { doc::test("Verify that a device can't be closed if there are streams opened"); DeviceAddress address{.device = AudioDevice::OUT_DEFAULT}; AudioConfig config{}; auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE); SourceMetadata initMetadata = {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 1 /* gain */}}}; sp<IStreamOut> stream; StreamHelper<IStreamOut> helper(stream); AudioConfig suggestedConfig{}; ASSERT_NO_FATAL_FAILURE(helper.open( [&](AudioIoHandle handle, AudioConfig config, auto cb) { return getDevice()->openOutputStream(handle, address, config, flags, initMetadata, cb); }, config, &res, &suggestedConfig)); ASSERT_RESULT(Result::INVALID_STATE, getDevice()->close()); ASSERT_NO_FATAL_FAILURE(helper.close(true /*clear*/, &res)); ASSERT_OK(getDevice()->close()); ASSERT_TRUE(resetDevice()); } TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedInputStreams) { doc::test("Verify that a device can't be closed if there are streams opened"); auto module = getCachedPolicyConfig().getModuleFromName(getDeviceName()); if (module->getInputProfiles().empty()) { GTEST_SKIP() << "Device doesn't have input profiles"; } DeviceAddress address{.device = AudioDevice::IN_DEFAULT}; AudioConfig config{}; auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE); SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}}; sp<IStreamIn> stream; StreamHelper<IStreamIn> helper(stream); AudioConfig suggestedConfig{}; ASSERT_NO_FATAL_FAILURE(helper.open( [&](AudioIoHandle handle, AudioConfig config, auto cb) { return getDevice()->openInputStream(handle, address, config, flags, initMetadata, cb); }, config, &res, &suggestedConfig)); ASSERT_RESULT(Result::INVALID_STATE, getDevice()->close()); ASSERT_NO_FATAL_FAILURE(helper.close(true /*clear*/, &res)); ASSERT_OK(getDevice()->close()); ASSERT_TRUE(resetDevice()); } Loading
audio/6.0/IDevice.hal +5 −1 Original line number Diff line number Diff line Loading @@ -286,8 +286,12 @@ interface IDevice { * 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. * INVALID_STATE if the device was already closed * or there are streams currently opened. */ @exit close() generates (Result retval); Loading
audio/core/all-versions/default/Device.cpp +7 −1 Original line number Diff line number Diff line Loading @@ -53,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) { Loading Loading @@ -158,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}; Loading @@ -184,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}; Loading Loading @@ -383,7 +389,7 @@ Return<Result> Device::setConnectedState(const DeviceAddress& address, bool conn #endif Result Device::doClose() { if (mIsClosed) return Result::INVALID_STATE; if (mIsClosed || mOpenedStreamsCount != 0) return Result::INVALID_STATE; mIsClosed = true; return analyzeStatus("close", audio_hw_device_close(mDevice)); } Loading
audio/core/all-versions/default/include/core/default/Device.h +1 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ struct Device : public IDevice, public ParametersUtil { private: bool mIsClosed; audio_hw_device_t* mDevice; int mOpenedStreamsCount = 0; virtual ~Device(); Loading
audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp +46 −0 Original line number Diff line number Diff line Loading @@ -145,3 +145,49 @@ const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters() { }(); return parameters; } TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedOutputStreams) { doc::test("Verify that a device can't be closed if there are streams opened"); DeviceAddress address{.device = AudioDevice::OUT_DEFAULT}; AudioConfig config{}; auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE); SourceMetadata initMetadata = {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 1 /* gain */}}}; sp<IStreamOut> stream; StreamHelper<IStreamOut> helper(stream); AudioConfig suggestedConfig{}; ASSERT_NO_FATAL_FAILURE(helper.open( [&](AudioIoHandle handle, AudioConfig config, auto cb) { return getDevice()->openOutputStream(handle, address, config, flags, initMetadata, cb); }, config, &res, &suggestedConfig)); ASSERT_RESULT(Result::INVALID_STATE, getDevice()->close()); ASSERT_NO_FATAL_FAILURE(helper.close(true /*clear*/, &res)); ASSERT_OK(getDevice()->close()); ASSERT_TRUE(resetDevice()); } TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedInputStreams) { doc::test("Verify that a device can't be closed if there are streams opened"); auto module = getCachedPolicyConfig().getModuleFromName(getDeviceName()); if (module->getInputProfiles().empty()) { GTEST_SKIP() << "Device doesn't have input profiles"; } DeviceAddress address{.device = AudioDevice::IN_DEFAULT}; AudioConfig config{}; auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE); SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}}; sp<IStreamIn> stream; StreamHelper<IStreamIn> helper(stream); AudioConfig suggestedConfig{}; ASSERT_NO_FATAL_FAILURE(helper.open( [&](AudioIoHandle handle, AudioConfig config, auto cb) { return getDevice()->openInputStream(handle, address, config, flags, initMetadata, cb); }, config, &res, &suggestedConfig)); ASSERT_RESULT(Result::INVALID_STATE, getDevice()->close()); ASSERT_NO_FATAL_FAILURE(helper.close(true /*clear*/, &res)); ASSERT_OK(getDevice()->close()); ASSERT_TRUE(resetDevice()); }