diff options
author | Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> | 2024-04-17 19:10:35 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-04-17 19:10:35 +0000 |
commit | 70f1225b350c6b17a4ec46e6aad40302b15ae404 (patch) | |
tree | 1b115acb21124c0ad75de4f370c234258afee1f6 | |
parent | c1654c6dd4dc3339c4e8b37aef00d037deb62ef4 (diff) | |
parent | 3754b64b391a04a09ea4679f6f214b88eaf3eb14 (diff) | |
download | av-70f1225b350c6b17a4ec46e6aad40302b15ae404.tar.gz |
Merge "audio policy: Fix handling of external device connection failure" into main
4 files changed, 273 insertions, 5 deletions
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index 42afa1e0fc..315e08defb 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -123,8 +123,8 @@ void AudioPolicyManager::broadcastDeviceConnectionState(const sp<DeviceDescripto device->toAudioPort(&devicePort); if (status_t status = mpClientInterface->setDeviceConnectedState(&devicePort, state); status != OK) { - ALOGE("Error %d while setting connected state for device %s", - static_cast<int>(state), + ALOGE("Error %d while setting connected state %d for device %s", + status, static_cast<int>(state), device->getDeviceTypeAddr().toString(false).c_str()); } } @@ -212,9 +212,9 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript if (checkOutputsForDevice(device, state, outputs) != NO_ERROR) { mAvailableOutputDevices.remove(device); - mHwModules.cleanUpForDevice(device); - broadcastDeviceConnectionState(device, media::DeviceConnectedState::DISCONNECTED); + + mHwModules.cleanUpForDevice(device); return INVALID_OPERATION; } diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp index 74d3474987..8642fd48a6 100644 --- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp +++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp @@ -2373,6 +2373,116 @@ INSTANTIATE_TEST_CASE_P( ) ); +namespace { + +class AudioPolicyManagerTestClientOpenFails : public AudioPolicyManagerTestClient { + public: + status_t openOutput(audio_module_handle_t module, + audio_io_handle_t *output, + audio_config_t * halConfig, + audio_config_base_t * mixerConfig, + const sp<DeviceDescriptorBase>& device, + uint32_t * latencyMs, + audio_output_flags_t flags) override { + return mSimulateFailure ? BAD_VALUE : + AudioPolicyManagerTestClient::openOutput( + module, output, halConfig, mixerConfig, device, latencyMs, flags); + } + + status_t openInput(audio_module_handle_t module, + audio_io_handle_t *input, + audio_config_t * config, + audio_devices_t * device, + const String8 & address, + audio_source_t source, + audio_input_flags_t flags) override { + return mSimulateFailure ? BAD_VALUE : + AudioPolicyManagerTestClient::openInput( + module, input, config, device, address, source, flags); + } + + void setSimulateFailure(bool simulateFailure) { mSimulateFailure = simulateFailure; } + + private: + bool mSimulateFailure = false; +}; + +} // namespace + +using DeviceConnectionWithFormatTestParams = + std::tuple<audio_devices_t /*type*/, std::string /*name*/, std::string /*address*/, + audio_format_t /*format*/>; + +class AudioPolicyManagerTestDeviceConnectionFailed : + public AudioPolicyManagerTestWithConfigurationFile, + public testing::WithParamInterface<DeviceConnectionWithFormatTestParams> { + protected: + std::string getConfigFile() override { return sBluetoothConfig; } + AudioPolicyManagerTestClient* getClient() override { + mFullClient = new AudioPolicyManagerTestClientOpenFails; + return mFullClient; + } + void setSimulateOpenFailure(bool simulateFailure) { + mFullClient->setSimulateFailure(simulateFailure); } + + static const std::string sBluetoothConfig; + + private: + AudioPolicyManagerTestClientOpenFails* mFullClient; +}; + +const std::string AudioPolicyManagerTestDeviceConnectionFailed::sBluetoothConfig = + AudioPolicyManagerTestDeviceConnectionFailed::sExecutableDir + + "test_audio_policy_configuration_bluetooth.xml"; + +TEST_P(AudioPolicyManagerTestDeviceConnectionFailed, SetDeviceConnectedStateHasAddress) { + const audio_devices_t type = std::get<0>(GetParam()); + const std::string name = std::get<1>(GetParam()); + const std::string address = std::get<2>(GetParam()); + const audio_format_t format = std::get<3>(GetParam()); + + EXPECT_EQ(0, mClient->getConnectedDevicePortCount()); + EXPECT_EQ(0, mClient->getDisconnectedDevicePortCount()); + + setSimulateOpenFailure(true); + ASSERT_EQ(INVALID_OPERATION, mManager->setDeviceConnectionState( + type, AUDIO_POLICY_DEVICE_STATE_AVAILABLE, + address.c_str(), name.c_str(), format)); + + // Since the failure happens when opening input/output, the device must be connected + // first and then disconnected. + EXPECT_EQ(1, mClient->getConnectedDevicePortCount()); + EXPECT_EQ(1, mClient->getDisconnectedDevicePortCount()); + + if (mClient->getConnectedDevicePortCount() > 0) { + auto port = mClient->getLastConnectedDevicePort(); + EXPECT_EQ(type, port->ext.device.type); + EXPECT_EQ(0, strncmp(port->ext.device.address, address.c_str(), + AUDIO_DEVICE_MAX_ADDRESS_LEN)) << "\"" << port->ext.device.address << "\""; + } + if (mClient->getDisconnectedDevicePortCount() > 0) { + auto port = mClient->getLastDisconnectedDevicePort(); + EXPECT_EQ(type, port->ext.device.type); + EXPECT_EQ(0, strncmp(port->ext.device.address, address.c_str(), + AUDIO_DEVICE_MAX_ADDRESS_LEN)) << "\"" << port->ext.device.address << "\""; + } +} + +INSTANTIATE_TEST_CASE_P( + DeviceConnectionFailure, + AudioPolicyManagerTestDeviceConnectionFailed, + testing::Values( + DeviceConnectionWithFormatTestParams({AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, + "bt_hfp_in", "00:11:22:33:44:55", AUDIO_FORMAT_DEFAULT}), + DeviceConnectionWithFormatTestParams({AUDIO_DEVICE_OUT_BLUETOOTH_SCO, + "bt_hfp_out", "00:11:22:33:44:55", AUDIO_FORMAT_DEFAULT}), + DeviceConnectionWithFormatTestParams({AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, + "bt_a2dp_out", "00:11:22:33:44:55", AUDIO_FORMAT_DEFAULT}), + DeviceConnectionWithFormatTestParams({AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, + "bt_a2dp_out", "00:11:22:33:44:66", AUDIO_FORMAT_LDAC}) + ) + ); + class AudioPolicyManagerCarTest : public AudioPolicyManagerTestDynamicPolicy { protected: std::string getConfigFile() override { return sCarConfig; } @@ -3283,4 +3393,4 @@ TEST_F(AudioPolicyManagerPreProcEffectTest, DeviceDisconnectWhileClientActive) { // unregister effect should succeed since effect shall have been restore on the client session ASSERT_EQ(NO_ERROR, mManager->unregisterEffect(effectId)); -}
\ No newline at end of file +} diff --git a/services/audiopolicy/tests/resources/Android.bp b/services/audiopolicy/tests/resources/Android.bp index 3f6a6e3954..535dd7ad45 100644 --- a/services/audiopolicy/tests/resources/Android.bp +++ b/services/audiopolicy/tests/resources/Android.bp @@ -11,6 +11,7 @@ filegroup { name: "audiopolicytest_configuration_files", srcs: [ "test_audio_policy_configuration.xml", + "test_audio_policy_configuration_bluetooth.xml", "test_audio_policy_primary_only_configuration.xml", "test_car_ap_atmos_offload_configuration.xml", "test_invalid_audio_policy_configuration.xml", diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration_bluetooth.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration_bluetooth.xml new file mode 100644 index 0000000000..0cf1688088 --- /dev/null +++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration_bluetooth.xml @@ -0,0 +1,157 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<!-- Copyright (C) 2024 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<audioPolicyConfiguration version="7.0" xmlns:xi="http://www.w3.org/2001/XInclude"> + <globalConfiguration speaker_drc_enabled="true"/> + + <modules> + <!-- Primary module --> + <module name="primary" halVersion="2.0"> + <attachedDevices> + <item>Speaker</item> + <item>Built-In Mic</item> + </attachedDevices> + <defaultOutputDevice>Speaker</defaultOutputDevice> + <mixPorts> + <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> + </mixPort> + <mixPort name="primary input" role="sink"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="48000" + channelMasks="AUDIO_CHANNEL_IN_STEREO"/> + </mixPort> + <mixPort name="mixport_bt_hfp_output" role="source"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> + </mixPort> + <mixPort name="mixport_bt_hfp_input" role="sink"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="8000 11025 16000 44100 48000" + channelMasks="AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_MONO"/> + </mixPort> + <mixPort name="voip_tx" role="sink" + flags="AUDIO_INPUT_FLAG_VOIP_TX"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/> + </mixPort> + <mixPort name="voip_rx" role="source" + flags="AUDIO_OUTPUT_FLAG_VOIP_RX"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> + </mixPort> + </mixPorts> + <devicePorts> + <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink"> + </devicePort> + <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source"> + </devicePort> + <devicePort tagName="Hdmi" type="AUDIO_DEVICE_OUT_HDMI" role="sink" + encodedFormats="AUDIO_FORMAT_AC3"> + </devicePort> + <devicePort tagName="Hdmi-In Mic" type="AUDIO_DEVICE_IN_HDMI" role="source"> + </devicePort> + <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink" /> + <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" + role="source" /> + <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink" + encodedFormats="AUDIO_FORMAT_SBC"> + <profile name="" format="AUDIO_FORMAT_PCM_8_BIT" + samplingRates="44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> + </devicePort> + <devicePort tagName="USB Device Out" type="AUDIO_DEVICE_OUT_USB_DEVICE" role="sink"> + </devicePort> + <devicePort tagName="USB Device In" type="AUDIO_DEVICE_IN_USB_DEVICE" role="source"> + </devicePort> + </devicePorts> + <routes> + <route type="mix" sink="Speaker" + sources="primary output,voip_rx"/> + <route type="mix" sink="primary input" + sources="Built-In Mic,Hdmi-In Mic,USB Device In"/> + <route type="mix" sink="voip_tx" + sources="Built-In Mic"/> + <route type="mix" sink="Hdmi" + sources="primary output"/> + <route type="mix" sink="BT SCO" + sources="mixport_bt_hfp_output"/> + <route type="mix" sink="mixport_bt_hfp_input" + sources="BT SCO Headset Mic"/> + <route type="mix" sink="BT A2DP Out" + sources="primary output"/> + <route type="mix" sink="USB Device Out" + sources="primary output"/> + </routes> + </module> + + <!-- Remote Submix module --> + <module name="r_submix" halVersion="2.0"> + <attachedDevices> + <item>Remote Submix In</item> + </attachedDevices> + <mixPorts> + <mixPort name="r_submix output" role="source"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> + </mixPort> + <mixPort name="r_submix input" role="sink"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/> + </mixPort> + </mixPorts> + <devicePorts> + <devicePort tagName="Remote Submix Out" type="AUDIO_DEVICE_OUT_REMOTE_SUBMIX" role="sink"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> + </devicePort> + <devicePort tagName="Remote Submix In" type="AUDIO_DEVICE_IN_REMOTE_SUBMIX" role="source"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/> + </devicePort> + </devicePorts> + <routes> + <route type="mix" sink="Remote Submix Out" + sources="r_submix output"/> + <route type="mix" sink="r_submix input" + sources="Remote Submix In"/> + </routes> + </module> + + <!-- Software Bluetooth Module --> + <module name="bluetooth" halVersion="2.0"> + <mixPorts> + <mixPort name="a2dp_sw_output" role="source"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="44100 48000 88200 96000" + channelMasks="AUDIO_CHANNEL_IN_STEREO"/> + </mixPort> + </mixPorts> + <devicePorts> + <devicePort tagName="BTS A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="44100 48000 88200 96000" + channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> + </devicePort> + </devicePorts> + <routes> + <route type="mix" sink="BTS A2DP Out" + sources="a2dp_sw_output"/> + </routes> + </module> + + </modules> +</audioPolicyConfiguration> |