mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:23:37 +00:00
audio: Add check to IDevice.close for currently opened streams
IDevice.close must not proceed if there are streams that are currently opened on this device. Bug: 114451103 Test: atest VtsHalAudioV6_0TargetTest Change-Id: I61d81bc0333098c341d5d551bf59331e49fcf682
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
@@ -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};
|
||||
@@ -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};
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -130,6 +130,7 @@ struct Device : public IDevice, public ParametersUtil {
|
||||
private:
|
||||
bool mIsClosed;
|
||||
audio_hw_device_t* mDevice;
|
||||
int mOpenedStreamsCount = 0;
|
||||
|
||||
virtual ~Device();
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user