Loading services/audiopolicy/managerdefault/AudioPolicyManager.cpp +32 −25 Original line number Diff line number Diff line Loading @@ -396,8 +396,12 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript // Before checking intputs, broadcast connect event to allow HAL to retrieve dynamic // parameters on newly connected devices (instead of opening the inputs...) broadcastDeviceConnectionState(device, media::DeviceConnectedState::CONNECTED); // Propagate device availability to Engine setEngineDeviceConnectionState(device, state); if (checkInputsForDevice(device, state) != NO_ERROR) { setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE); mAvailableInputDevices.remove(device); broadcastDeviceConnectionState(device, media::DeviceConnectedState::DISCONNECTED); Loading Loading @@ -431,6 +435,9 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript // remove device from mReportedFormatsMap cache mReportedFormatsMap.erase(device); // Propagate device availability to Engine setEngineDeviceConnectionState(device, state); } break; default: Loading @@ -438,9 +445,6 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript return BAD_VALUE; } // Propagate device availability to Engine setEngineDeviceConnectionState(device, state); checkCloseInputs(); // As the input device list can impact the output device selection, update // getDeviceForStrategy() cache Loading Loading @@ -3337,37 +3341,35 @@ void AudioPolicyManager::closeClient(audio_port_handle_t portId) releaseInput(portId); } void AudioPolicyManager::checkCloseInputs() { // After connecting or disconnecting an input device, close input if: // - it has no client (was just opened to check profile) OR // - none of its supported devices are connected anymore OR // - one of its clients cannot be routed to one of its supported // devices anymore. Otherwise update device selection std::vector<audio_io_handle_t> inputsToClose; for (size_t i = 0; i < mInputs.size(); i++) { const sp<AudioInputDescriptor> input = mInputs.valueAt(i); bool AudioPolicyManager::checkCloseInput(const sp<AudioInputDescriptor>& input) { if (input->clientsList().size() == 0 || !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())) { inputsToClose.push_back(mInputs.keyAt(i)); } else { bool close = false; return true; } for (const auto& client : input->clientsList()) { sp<DeviceDescriptor> device = mEngine->getInputDeviceForAttributes(client->attributes(), client->uid(), client->session()); if (!input->supportedDevices().contains(device)) { close = true; break; return true; } } if (close) { inputsToClose.push_back(mInputs.keyAt(i)); } else { setInputDevice(input->mIoHandle, getNewInputDevice(input)); return false; } void AudioPolicyManager::checkCloseInputs() { // After connecting or disconnecting an input device, close input if: // - it has no client (was just opened to check profile) OR // - none of its supported devices are connected anymore OR // - one of its clients cannot be routed to one of its supported // devices anymore. Otherwise update device selection std::vector<audio_io_handle_t> inputsToClose; for (size_t i = 0; i < mInputs.size(); i++) { if (checkCloseInput(mInputs.valueAt(i))) { inputsToClose.push_back(mInputs.keyAt(i)); } } for (const audio_io_handle_t handle : inputsToClose) { ALOGV("%s closing input %d", __func__, handle); closeInput(handle); Loading Loading @@ -6865,14 +6867,14 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& d status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& device, audio_policy_dev_state_t state) { sp<AudioInputDescriptor> desc; if (audio_device_is_digital(device->type())) { // erase all current sample rates, formats and channel masks device->clearAudioProfiles(); } if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { sp<AudioInputDescriptor> desc; // first call getAudioPort to get the supported attributes from the HAL struct audio_port_v7 port = {}; device->toAudioPort(&port); Loading Loading @@ -6963,6 +6965,11 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de device->importAudioPortAndPickAudioProfile(profile); } ALOGV("checkInputsForDevice(): adding input %d", input); if (checkCloseInput(desc)) { ALOGV("%s closing input %d", __func__, input); closeInput(input); } } } // end scan profiles Loading services/audiopolicy/managerdefault/AudioPolicyManager.h +1 −0 Original line number Diff line number Diff line Loading @@ -533,6 +533,7 @@ protected: void addOutput(audio_io_handle_t output, const sp<SwAudioOutputDescriptor>& outputDesc); void removeOutput(audio_io_handle_t output); void addInput(audio_io_handle_t input, const sp<AudioInputDescriptor>& inputDesc); bool checkCloseInput(const sp<AudioInputDescriptor>& input); /** * @brief setOutputDevices change the route of the specified output. Loading services/audiopolicy/tests/AudioPolicyManagerTestClient.h +19 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,22 @@ public: return BAD_VALUE; } *input = mNextIoHandle++; mOpenedInputs.insert(*input); ALOGD("%s: opened input %d", __func__, *input); return NO_ERROR; } status_t closeInput(audio_io_handle_t input) override { if (mOpenedInputs.erase(input) != 1) { if (input >= mNextIoHandle) { ALOGE("%s: I/O handle %d has not been allocated yet (next is %d)", __func__, input, mNextIoHandle); } else { ALOGE("%s: Attempt to close input %d twice", __func__, input); } return BAD_VALUE; } ALOGD("%s: closed input %d", __func__, input); return NO_ERROR; } Loading Loading @@ -124,6 +140,8 @@ public: return &it->second; }; size_t getOpenedInputsCount() const { return mOpenedInputs.size(); } audio_module_handle_t peekNextModuleHandle() const { return mNextModuleHandle; } void swapAllowedModuleNames(std::set<std::string>&& names = {}) { Loading Loading @@ -256,6 +274,7 @@ private: std::set<audio_format_t> mSupportedFormats; std::set<audio_channel_mask_t> mSupportedChannelMasks; std::map<audio_port_handle_t, bool> mTracksInternalMute; std::set<audio_io_handle_t> mOpenedInputs; }; } // namespace android services/audiopolicy/tests/AudioPolicyTestManager.h +2 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ class AudioPolicyTestManager : public AudioPolicyManager { using AudioPolicyManager::getInputs; using AudioPolicyManager::getAvailableOutputDevices; using AudioPolicyManager::getAvailableInputDevices; using AudioPolicyManager::checkInputsForDevice; using AudioPolicyManager::setSurroundFormatEnabled; using AudioPolicyManager::releaseMsdOutputPatches; using AudioPolicyManager::setMsdOutputPatches; Loading @@ -44,6 +45,7 @@ class AudioPolicyTestManager : public AudioPolicyManager { using AudioPolicyManager::deviceToAudioPort; using AudioPolicyManager::handleDeviceConfigChange; uint32_t getAudioPortGeneration() const { return mAudioPortGeneration; } HwModuleCollection getHwModules() const { return mHwModules; } }; } // namespace android services/audiopolicy/tests/audiopolicymanager_tests.cpp +29 −0 Original line number Diff line number Diff line Loading @@ -1204,6 +1204,35 @@ TEST_F(AudioPolicyManagerTestWithConfigurationFile, PreferExactConfigForInput) { "", "", AUDIO_FORMAT_DEFAULT)); } TEST_F(AudioPolicyManagerTestWithConfigurationFile, CheckInputsForDeviceClosesStreams) { mClient->addSupportedFormat(AUDIO_FORMAT_PCM_16_BIT); mClient->addSupportedFormat(AUDIO_FORMAT_PCM_24_BIT_PACKED); mClient->addSupportedChannelMask(AUDIO_CHANNEL_IN_MONO); mClient->addSupportedChannelMask(AUDIO_CHANNEL_IN_STEREO); // Since 'checkInputsForDevice' is called as part of the 'setDeviceConnectionState', // call it directly here, as we need to ensure that it does not keep all intermediate // streams opened, as it may cause a rejection from the HAL based on the cap. const size_t streamCountBefore = mClient->getOpenedInputsCount(); sp<DeviceDescriptor> device = mManager->getHwModules().getDeviceDescriptor( AUDIO_DEVICE_IN_USB_DEVICE, "", "", AUDIO_FORMAT_DEFAULT, true /*allowToCreate*/); ASSERT_NE(nullptr, device.get()); EXPECT_EQ(NO_ERROR, mManager->checkInputsForDevice(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE)); EXPECT_EQ(streamCountBefore, mClient->getOpenedInputsCount()); } TEST_F(AudioPolicyManagerTestWithConfigurationFile, SetDeviceConnectionStateClosesStreams) { mClient->addSupportedFormat(AUDIO_FORMAT_PCM_16_BIT); mClient->addSupportedFormat(AUDIO_FORMAT_PCM_24_BIT_PACKED); mClient->addSupportedChannelMask(AUDIO_CHANNEL_IN_MONO); mClient->addSupportedChannelMask(AUDIO_CHANNEL_IN_STEREO); const size_t streamCountBefore = mClient->getOpenedInputsCount(); EXPECT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_POLICY_DEVICE_STATE_AVAILABLE, "", "", AUDIO_FORMAT_DEFAULT)); EXPECT_EQ(streamCountBefore, mClient->getOpenedInputsCount()); } class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile { protected: void TearDown() override; Loading Loading
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +32 −25 Original line number Diff line number Diff line Loading @@ -396,8 +396,12 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript // Before checking intputs, broadcast connect event to allow HAL to retrieve dynamic // parameters on newly connected devices (instead of opening the inputs...) broadcastDeviceConnectionState(device, media::DeviceConnectedState::CONNECTED); // Propagate device availability to Engine setEngineDeviceConnectionState(device, state); if (checkInputsForDevice(device, state) != NO_ERROR) { setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE); mAvailableInputDevices.remove(device); broadcastDeviceConnectionState(device, media::DeviceConnectedState::DISCONNECTED); Loading Loading @@ -431,6 +435,9 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript // remove device from mReportedFormatsMap cache mReportedFormatsMap.erase(device); // Propagate device availability to Engine setEngineDeviceConnectionState(device, state); } break; default: Loading @@ -438,9 +445,6 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript return BAD_VALUE; } // Propagate device availability to Engine setEngineDeviceConnectionState(device, state); checkCloseInputs(); // As the input device list can impact the output device selection, update // getDeviceForStrategy() cache Loading Loading @@ -3337,37 +3341,35 @@ void AudioPolicyManager::closeClient(audio_port_handle_t portId) releaseInput(portId); } void AudioPolicyManager::checkCloseInputs() { // After connecting or disconnecting an input device, close input if: // - it has no client (was just opened to check profile) OR // - none of its supported devices are connected anymore OR // - one of its clients cannot be routed to one of its supported // devices anymore. Otherwise update device selection std::vector<audio_io_handle_t> inputsToClose; for (size_t i = 0; i < mInputs.size(); i++) { const sp<AudioInputDescriptor> input = mInputs.valueAt(i); bool AudioPolicyManager::checkCloseInput(const sp<AudioInputDescriptor>& input) { if (input->clientsList().size() == 0 || !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())) { inputsToClose.push_back(mInputs.keyAt(i)); } else { bool close = false; return true; } for (const auto& client : input->clientsList()) { sp<DeviceDescriptor> device = mEngine->getInputDeviceForAttributes(client->attributes(), client->uid(), client->session()); if (!input->supportedDevices().contains(device)) { close = true; break; return true; } } if (close) { inputsToClose.push_back(mInputs.keyAt(i)); } else { setInputDevice(input->mIoHandle, getNewInputDevice(input)); return false; } void AudioPolicyManager::checkCloseInputs() { // After connecting or disconnecting an input device, close input if: // - it has no client (was just opened to check profile) OR // - none of its supported devices are connected anymore OR // - one of its clients cannot be routed to one of its supported // devices anymore. Otherwise update device selection std::vector<audio_io_handle_t> inputsToClose; for (size_t i = 0; i < mInputs.size(); i++) { if (checkCloseInput(mInputs.valueAt(i))) { inputsToClose.push_back(mInputs.keyAt(i)); } } for (const audio_io_handle_t handle : inputsToClose) { ALOGV("%s closing input %d", __func__, handle); closeInput(handle); Loading Loading @@ -6865,14 +6867,14 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& d status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& device, audio_policy_dev_state_t state) { sp<AudioInputDescriptor> desc; if (audio_device_is_digital(device->type())) { // erase all current sample rates, formats and channel masks device->clearAudioProfiles(); } if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { sp<AudioInputDescriptor> desc; // first call getAudioPort to get the supported attributes from the HAL struct audio_port_v7 port = {}; device->toAudioPort(&port); Loading Loading @@ -6963,6 +6965,11 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de device->importAudioPortAndPickAudioProfile(profile); } ALOGV("checkInputsForDevice(): adding input %d", input); if (checkCloseInput(desc)) { ALOGV("%s closing input %d", __func__, input); closeInput(input); } } } // end scan profiles Loading
services/audiopolicy/managerdefault/AudioPolicyManager.h +1 −0 Original line number Diff line number Diff line Loading @@ -533,6 +533,7 @@ protected: void addOutput(audio_io_handle_t output, const sp<SwAudioOutputDescriptor>& outputDesc); void removeOutput(audio_io_handle_t output); void addInput(audio_io_handle_t input, const sp<AudioInputDescriptor>& inputDesc); bool checkCloseInput(const sp<AudioInputDescriptor>& input); /** * @brief setOutputDevices change the route of the specified output. Loading
services/audiopolicy/tests/AudioPolicyManagerTestClient.h +19 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,22 @@ public: return BAD_VALUE; } *input = mNextIoHandle++; mOpenedInputs.insert(*input); ALOGD("%s: opened input %d", __func__, *input); return NO_ERROR; } status_t closeInput(audio_io_handle_t input) override { if (mOpenedInputs.erase(input) != 1) { if (input >= mNextIoHandle) { ALOGE("%s: I/O handle %d has not been allocated yet (next is %d)", __func__, input, mNextIoHandle); } else { ALOGE("%s: Attempt to close input %d twice", __func__, input); } return BAD_VALUE; } ALOGD("%s: closed input %d", __func__, input); return NO_ERROR; } Loading Loading @@ -124,6 +140,8 @@ public: return &it->second; }; size_t getOpenedInputsCount() const { return mOpenedInputs.size(); } audio_module_handle_t peekNextModuleHandle() const { return mNextModuleHandle; } void swapAllowedModuleNames(std::set<std::string>&& names = {}) { Loading Loading @@ -256,6 +274,7 @@ private: std::set<audio_format_t> mSupportedFormats; std::set<audio_channel_mask_t> mSupportedChannelMasks; std::map<audio_port_handle_t, bool> mTracksInternalMute; std::set<audio_io_handle_t> mOpenedInputs; }; } // namespace android
services/audiopolicy/tests/AudioPolicyTestManager.h +2 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ class AudioPolicyTestManager : public AudioPolicyManager { using AudioPolicyManager::getInputs; using AudioPolicyManager::getAvailableOutputDevices; using AudioPolicyManager::getAvailableInputDevices; using AudioPolicyManager::checkInputsForDevice; using AudioPolicyManager::setSurroundFormatEnabled; using AudioPolicyManager::releaseMsdOutputPatches; using AudioPolicyManager::setMsdOutputPatches; Loading @@ -44,6 +45,7 @@ class AudioPolicyTestManager : public AudioPolicyManager { using AudioPolicyManager::deviceToAudioPort; using AudioPolicyManager::handleDeviceConfigChange; uint32_t getAudioPortGeneration() const { return mAudioPortGeneration; } HwModuleCollection getHwModules() const { return mHwModules; } }; } // namespace android
services/audiopolicy/tests/audiopolicymanager_tests.cpp +29 −0 Original line number Diff line number Diff line Loading @@ -1204,6 +1204,35 @@ TEST_F(AudioPolicyManagerTestWithConfigurationFile, PreferExactConfigForInput) { "", "", AUDIO_FORMAT_DEFAULT)); } TEST_F(AudioPolicyManagerTestWithConfigurationFile, CheckInputsForDeviceClosesStreams) { mClient->addSupportedFormat(AUDIO_FORMAT_PCM_16_BIT); mClient->addSupportedFormat(AUDIO_FORMAT_PCM_24_BIT_PACKED); mClient->addSupportedChannelMask(AUDIO_CHANNEL_IN_MONO); mClient->addSupportedChannelMask(AUDIO_CHANNEL_IN_STEREO); // Since 'checkInputsForDevice' is called as part of the 'setDeviceConnectionState', // call it directly here, as we need to ensure that it does not keep all intermediate // streams opened, as it may cause a rejection from the HAL based on the cap. const size_t streamCountBefore = mClient->getOpenedInputsCount(); sp<DeviceDescriptor> device = mManager->getHwModules().getDeviceDescriptor( AUDIO_DEVICE_IN_USB_DEVICE, "", "", AUDIO_FORMAT_DEFAULT, true /*allowToCreate*/); ASSERT_NE(nullptr, device.get()); EXPECT_EQ(NO_ERROR, mManager->checkInputsForDevice(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE)); EXPECT_EQ(streamCountBefore, mClient->getOpenedInputsCount()); } TEST_F(AudioPolicyManagerTestWithConfigurationFile, SetDeviceConnectionStateClosesStreams) { mClient->addSupportedFormat(AUDIO_FORMAT_PCM_16_BIT); mClient->addSupportedFormat(AUDIO_FORMAT_PCM_24_BIT_PACKED); mClient->addSupportedChannelMask(AUDIO_CHANNEL_IN_MONO); mClient->addSupportedChannelMask(AUDIO_CHANNEL_IN_STEREO); const size_t streamCountBefore = mClient->getOpenedInputsCount(); EXPECT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_POLICY_DEVICE_STATE_AVAILABLE, "", "", AUDIO_FORMAT_DEFAULT)); EXPECT_EQ(streamCountBefore, mClient->getOpenedInputsCount()); } class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile { protected: void TearDown() override; Loading