Loading services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h +5 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,8 @@ class AudioInputDescriptor: public AudioPortConfig, { public: AudioInputDescriptor(const sp<IOProfile>& profile, AudioPolicyClientInterface *clientInterface); AudioPolicyClientInterface *clientInterface, bool isPreemptor); virtual ~AudioInputDescriptor() = default; Loading Loading @@ -127,6 +128,8 @@ public: // active use case void checkSuspendEffects(); bool isPreemptor() const { return mIsPreemptor; } private: void updateClientRecordingConfiguration(int event, const sp<RecordClientDescriptor>& client); Loading @@ -145,6 +148,7 @@ public: int32_t mGlobalActiveCount = 0; // non-client-specific activity ref count EffectDescriptorCollection mEnabledEffects; audio_input_flags_t& mFlags = AudioPortConfig::mFlags.input; bool mIsPreemptor; // true if this input was opened after preemting another one }; class AudioInputCollection : Loading services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -30,9 +30,10 @@ namespace android { AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile, AudioPolicyClientInterface *clientInterface) AudioPolicyClientInterface *clientInterface, bool isPreemptor) : mProfile(profile) , mClientInterface(clientInterface) , mClientInterface(clientInterface), mIsPreemptor(isPreemptor) { if (profile != NULL) { profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat); Loading Loading @@ -275,6 +276,9 @@ void AudioInputDescriptor::stop() "%s invalid profile active count %u", __func__, mProfile->curActiveCount); mProfile->curActiveCount--; // allow preemption again now that at least one client was able to // capture on this input mIsPreemptor = false; } } Loading services/audiopolicy/managerdefault/AudioPolicyManager.cpp +100 −28 Original line number Diff line number Diff line Loading @@ -3125,7 +3125,77 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescripto } } bool isPreemptor = false; if (!profile->canOpenNewIo()) { if (com::android::media::audioserver::fix_input_sharing_logic()) { // First pick best candidate for preemption (there may not be any): // - Preempt and input if: // - It has only strictly lower priority use cases than the new client // - It has equal priority use cases than the new client, was not // opened thanks to preemption or has been active since opened. // - Order the preemption candidates by inactive first and priority second sp<AudioInputDescriptor> closeCandidate; int leastCloseRank = INT_MAX; static const int sCloseActive = 0x100; for (size_t i = 0; i < mInputs.size(); i++) { sp<AudioInputDescriptor> desc = mInputs.valueAt(i); if (desc->mProfile != profile) { continue; } sp<RecordClientDescriptor> topPrioClient = desc->getHighestPriorityClient(); if (topPrioClient == nullptr) { continue; } int topPrio = source_priority(topPrioClient->source()); if (topPrio < source_priority(attributes.source) || (topPrio == source_priority(attributes.source) && !desc->isPreemptor())) { int closeRank = (desc->isActive() ? sCloseActive : 0) + topPrio; if (closeRank < leastCloseRank) { leastCloseRank = closeRank; closeCandidate = desc; } } } if (closeCandidate != nullptr) { closeInput(closeCandidate->mIoHandle); // Mark the new input as being issued from a preemption // so that is will not be preempted later isPreemptor = true; } else { // Then pick the best reusable input (There is always one) // The order of preference is: // 1) active inputs with same use case as the new client // 2) inactive inputs with same use case // 3) active inputs with different use cases // 4) inactive inputs with different use cases sp<AudioInputDescriptor> reuseCandidate; int leastReuseRank = INT_MAX; static const int sReuseDifferentUseCase = 0x100; for (size_t i = 0; i < mInputs.size(); i++) { sp<AudioInputDescriptor> desc = mInputs.valueAt(i); if (desc->mProfile != profile) { continue; } int reuseRank = sReuseDifferentUseCase; for (const auto& client: desc->getClientIterable()) { if (client->source() == attributes.source) { reuseRank = 0; break; } } reuseRank += desc->isActive() ? 0 : 1; if (reuseRank < leastReuseRank) { leastReuseRank = reuseRank; reuseCandidate = desc; } } return reuseCandidate->mIoHandle; } } else { // fix_input_sharing_logic() for (size_t i = 0; i < mInputs.size(); ) { sp<AudioInputDescriptor> desc = mInputs.valueAt(i); if (desc->mProfile != profile) { Loading Loading @@ -3160,8 +3230,10 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescripto } } } } sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(profile, mpClientInterface); sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor( profile, mpClientInterface, isPreemptor); audio_config_t lConfig = AUDIO_CONFIG_INITIALIZER; lConfig.sample_rate = profileSamplingRate; Loading Loading @@ -6672,8 +6744,8 @@ void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices) __func__, inProfile->getTagName().c_str()); continue; } sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(inProfile, mpClientInterface); sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor( inProfile, mpClientInterface, false /*isPreemptor*/); audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; status_t status = inputDesc->open(nullptr, Loading Loading @@ -6983,7 +7055,7 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de continue; } desc = new AudioInputDescriptor(profile, mpClientInterface); desc = new AudioInputDescriptor(profile, mpClientInterface, false /*isPreemptor*/); audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; status = desc->open(nullptr, device, AUDIO_SOURCE_MIC, AUDIO_INPUT_FLAG_NONE, &input); Loading services/audiopolicy/tests/AudioPolicyManagerTestClient.h +16 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ public: *input = mNextIoHandle++; mOpenedInputs.insert(*input); ALOGD("%s: opened input %d", __func__, *input); mOpenInputCallsCount++; return NO_ERROR; } Loading @@ -86,6 +87,7 @@ public: return BAD_VALUE; } ALOGD("%s: closed input %d", __func__, input); mCloseInputCallsCount++; return NO_ERROR; } Loading Loading @@ -260,6 +262,18 @@ public: auto it = mTracksInternalMute.find(portId); return it == mTracksInternalMute.end() ? false : it->second; } void resetInputApiCallsCounters() { mOpenInputCallsCount = 0; mCloseInputCallsCount = 0; } size_t getCloseInputCallsCount() const { return mCloseInputCallsCount; } size_t getOpenInputCallsCount() const { return mOpenInputCallsCount; } private: audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1; Loading @@ -275,6 +289,8 @@ private: std::set<audio_channel_mask_t> mSupportedChannelMasks; std::map<audio_port_handle_t, bool> mTracksInternalMute; std::set<audio_io_handle_t> mOpenedInputs; size_t mOpenInputCallsCount = 0; size_t mCloseInputCallsCount = 0; }; } // namespace android services/audiopolicy/tests/audiopolicymanager_tests.cpp +89 −0 Original line number Diff line number Diff line Loading @@ -3830,3 +3830,92 @@ INSTANTIATE_TEST_CASE_P( testing::Values(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_USAGE_ALARM) ); class AudioPolicyManagerInputPreemptionTest : public AudioPolicyManagerTestWithConfigurationFile { }; TEST_F_WITH_FLAGS( AudioPolicyManagerInputPreemptionTest, SameSessionReusesInput, REQUIRES_FLAGS_ENABLED( ACONFIG_FLAG(com::android::media::audioserver, fix_input_sharing_logic)) ) { mClient->resetInputApiCallsCounters(); audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER; attr.source = AUDIO_SOURCE_MIC; audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE; audio_io_handle_t input1 = AUDIO_PORT_HANDLE_NONE; ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input1, TEST_SESSION_ID, 1, &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 48000)); EXPECT_EQ(1, mClient->getOpenInputCallsCount()); audio_io_handle_t input2 = AUDIO_PORT_HANDLE_NONE; ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input2, TEST_SESSION_ID, 1, &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 48000)); EXPECT_EQ(1, mClient->getOpenInputCallsCount()); EXPECT_EQ(0, mClient->getCloseInputCallsCount()); EXPECT_EQ(input1, input2); } TEST_F_WITH_FLAGS( AudioPolicyManagerInputPreemptionTest, LesserPriorityReusesInput, REQUIRES_FLAGS_ENABLED( ACONFIG_FLAG(com::android::media::audioserver, fix_input_sharing_logic)) ) { mClient->resetInputApiCallsCounters(); audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER; attr.source = AUDIO_SOURCE_MIC; audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE; audio_io_handle_t input1 = AUDIO_PORT_HANDLE_NONE; ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input1, TEST_SESSION_ID, 1, &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 48000)); EXPECT_EQ(1, mClient->getOpenInputCallsCount()); audio_io_handle_t input2 = AUDIO_PORT_HANDLE_NONE; attr.source = AUDIO_SOURCE_VOICE_RECOGNITION; ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input2, OTHER_SESSION_ID, 1, &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 48000)); EXPECT_EQ(1, mClient->getOpenInputCallsCount()); EXPECT_EQ(0, mClient->getCloseInputCallsCount()); EXPECT_EQ(input1, input2); } TEST_F_WITH_FLAGS( AudioPolicyManagerInputPreemptionTest, HigherPriorityPreemptsInput, REQUIRES_FLAGS_ENABLED( ACONFIG_FLAG(com::android::media::audioserver, fix_input_sharing_logic)) ) { mClient->resetInputApiCallsCounters(); audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER; attr.source = AUDIO_SOURCE_MIC; audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE; audio_io_handle_t input1 = AUDIO_PORT_HANDLE_NONE; ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input1, TEST_SESSION_ID, 1, &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 48000)); EXPECT_EQ(1, mClient->getOpenInputCallsCount()); audio_io_handle_t input2 = AUDIO_PORT_HANDLE_NONE; attr.source = AUDIO_SOURCE_CAMCORDER; ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input2, OTHER_SESSION_ID, 1, &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 48000)); EXPECT_EQ(2, mClient->getOpenInputCallsCount()); EXPECT_EQ(1, mClient->getCloseInputCallsCount()); EXPECT_NE(input1, input2); } Loading
services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h +5 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,8 @@ class AudioInputDescriptor: public AudioPortConfig, { public: AudioInputDescriptor(const sp<IOProfile>& profile, AudioPolicyClientInterface *clientInterface); AudioPolicyClientInterface *clientInterface, bool isPreemptor); virtual ~AudioInputDescriptor() = default; Loading Loading @@ -127,6 +128,8 @@ public: // active use case void checkSuspendEffects(); bool isPreemptor() const { return mIsPreemptor; } private: void updateClientRecordingConfiguration(int event, const sp<RecordClientDescriptor>& client); Loading @@ -145,6 +148,7 @@ public: int32_t mGlobalActiveCount = 0; // non-client-specific activity ref count EffectDescriptorCollection mEnabledEffects; audio_input_flags_t& mFlags = AudioPortConfig::mFlags.input; bool mIsPreemptor; // true if this input was opened after preemting another one }; class AudioInputCollection : Loading
services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -30,9 +30,10 @@ namespace android { AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile, AudioPolicyClientInterface *clientInterface) AudioPolicyClientInterface *clientInterface, bool isPreemptor) : mProfile(profile) , mClientInterface(clientInterface) , mClientInterface(clientInterface), mIsPreemptor(isPreemptor) { if (profile != NULL) { profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat); Loading Loading @@ -275,6 +276,9 @@ void AudioInputDescriptor::stop() "%s invalid profile active count %u", __func__, mProfile->curActiveCount); mProfile->curActiveCount--; // allow preemption again now that at least one client was able to // capture on this input mIsPreemptor = false; } } Loading
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +100 −28 Original line number Diff line number Diff line Loading @@ -3125,7 +3125,77 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescripto } } bool isPreemptor = false; if (!profile->canOpenNewIo()) { if (com::android::media::audioserver::fix_input_sharing_logic()) { // First pick best candidate for preemption (there may not be any): // - Preempt and input if: // - It has only strictly lower priority use cases than the new client // - It has equal priority use cases than the new client, was not // opened thanks to preemption or has been active since opened. // - Order the preemption candidates by inactive first and priority second sp<AudioInputDescriptor> closeCandidate; int leastCloseRank = INT_MAX; static const int sCloseActive = 0x100; for (size_t i = 0; i < mInputs.size(); i++) { sp<AudioInputDescriptor> desc = mInputs.valueAt(i); if (desc->mProfile != profile) { continue; } sp<RecordClientDescriptor> topPrioClient = desc->getHighestPriorityClient(); if (topPrioClient == nullptr) { continue; } int topPrio = source_priority(topPrioClient->source()); if (topPrio < source_priority(attributes.source) || (topPrio == source_priority(attributes.source) && !desc->isPreemptor())) { int closeRank = (desc->isActive() ? sCloseActive : 0) + topPrio; if (closeRank < leastCloseRank) { leastCloseRank = closeRank; closeCandidate = desc; } } } if (closeCandidate != nullptr) { closeInput(closeCandidate->mIoHandle); // Mark the new input as being issued from a preemption // so that is will not be preempted later isPreemptor = true; } else { // Then pick the best reusable input (There is always one) // The order of preference is: // 1) active inputs with same use case as the new client // 2) inactive inputs with same use case // 3) active inputs with different use cases // 4) inactive inputs with different use cases sp<AudioInputDescriptor> reuseCandidate; int leastReuseRank = INT_MAX; static const int sReuseDifferentUseCase = 0x100; for (size_t i = 0; i < mInputs.size(); i++) { sp<AudioInputDescriptor> desc = mInputs.valueAt(i); if (desc->mProfile != profile) { continue; } int reuseRank = sReuseDifferentUseCase; for (const auto& client: desc->getClientIterable()) { if (client->source() == attributes.source) { reuseRank = 0; break; } } reuseRank += desc->isActive() ? 0 : 1; if (reuseRank < leastReuseRank) { leastReuseRank = reuseRank; reuseCandidate = desc; } } return reuseCandidate->mIoHandle; } } else { // fix_input_sharing_logic() for (size_t i = 0; i < mInputs.size(); ) { sp<AudioInputDescriptor> desc = mInputs.valueAt(i); if (desc->mProfile != profile) { Loading Loading @@ -3160,8 +3230,10 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescripto } } } } sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(profile, mpClientInterface); sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor( profile, mpClientInterface, isPreemptor); audio_config_t lConfig = AUDIO_CONFIG_INITIALIZER; lConfig.sample_rate = profileSamplingRate; Loading Loading @@ -6672,8 +6744,8 @@ void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices) __func__, inProfile->getTagName().c_str()); continue; } sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(inProfile, mpClientInterface); sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor( inProfile, mpClientInterface, false /*isPreemptor*/); audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; status_t status = inputDesc->open(nullptr, Loading Loading @@ -6983,7 +7055,7 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de continue; } desc = new AudioInputDescriptor(profile, mpClientInterface); desc = new AudioInputDescriptor(profile, mpClientInterface, false /*isPreemptor*/); audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; status = desc->open(nullptr, device, AUDIO_SOURCE_MIC, AUDIO_INPUT_FLAG_NONE, &input); Loading
services/audiopolicy/tests/AudioPolicyManagerTestClient.h +16 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ public: *input = mNextIoHandle++; mOpenedInputs.insert(*input); ALOGD("%s: opened input %d", __func__, *input); mOpenInputCallsCount++; return NO_ERROR; } Loading @@ -86,6 +87,7 @@ public: return BAD_VALUE; } ALOGD("%s: closed input %d", __func__, input); mCloseInputCallsCount++; return NO_ERROR; } Loading Loading @@ -260,6 +262,18 @@ public: auto it = mTracksInternalMute.find(portId); return it == mTracksInternalMute.end() ? false : it->second; } void resetInputApiCallsCounters() { mOpenInputCallsCount = 0; mCloseInputCallsCount = 0; } size_t getCloseInputCallsCount() const { return mCloseInputCallsCount; } size_t getOpenInputCallsCount() const { return mOpenInputCallsCount; } private: audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1; Loading @@ -275,6 +289,8 @@ private: std::set<audio_channel_mask_t> mSupportedChannelMasks; std::map<audio_port_handle_t, bool> mTracksInternalMute; std::set<audio_io_handle_t> mOpenedInputs; size_t mOpenInputCallsCount = 0; size_t mCloseInputCallsCount = 0; }; } // namespace android
services/audiopolicy/tests/audiopolicymanager_tests.cpp +89 −0 Original line number Diff line number Diff line Loading @@ -3830,3 +3830,92 @@ INSTANTIATE_TEST_CASE_P( testing::Values(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_USAGE_ALARM) ); class AudioPolicyManagerInputPreemptionTest : public AudioPolicyManagerTestWithConfigurationFile { }; TEST_F_WITH_FLAGS( AudioPolicyManagerInputPreemptionTest, SameSessionReusesInput, REQUIRES_FLAGS_ENABLED( ACONFIG_FLAG(com::android::media::audioserver, fix_input_sharing_logic)) ) { mClient->resetInputApiCallsCounters(); audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER; attr.source = AUDIO_SOURCE_MIC; audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE; audio_io_handle_t input1 = AUDIO_PORT_HANDLE_NONE; ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input1, TEST_SESSION_ID, 1, &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 48000)); EXPECT_EQ(1, mClient->getOpenInputCallsCount()); audio_io_handle_t input2 = AUDIO_PORT_HANDLE_NONE; ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input2, TEST_SESSION_ID, 1, &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 48000)); EXPECT_EQ(1, mClient->getOpenInputCallsCount()); EXPECT_EQ(0, mClient->getCloseInputCallsCount()); EXPECT_EQ(input1, input2); } TEST_F_WITH_FLAGS( AudioPolicyManagerInputPreemptionTest, LesserPriorityReusesInput, REQUIRES_FLAGS_ENABLED( ACONFIG_FLAG(com::android::media::audioserver, fix_input_sharing_logic)) ) { mClient->resetInputApiCallsCounters(); audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER; attr.source = AUDIO_SOURCE_MIC; audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE; audio_io_handle_t input1 = AUDIO_PORT_HANDLE_NONE; ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input1, TEST_SESSION_ID, 1, &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 48000)); EXPECT_EQ(1, mClient->getOpenInputCallsCount()); audio_io_handle_t input2 = AUDIO_PORT_HANDLE_NONE; attr.source = AUDIO_SOURCE_VOICE_RECOGNITION; ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input2, OTHER_SESSION_ID, 1, &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 48000)); EXPECT_EQ(1, mClient->getOpenInputCallsCount()); EXPECT_EQ(0, mClient->getCloseInputCallsCount()); EXPECT_EQ(input1, input2); } TEST_F_WITH_FLAGS( AudioPolicyManagerInputPreemptionTest, HigherPriorityPreemptsInput, REQUIRES_FLAGS_ENABLED( ACONFIG_FLAG(com::android::media::audioserver, fix_input_sharing_logic)) ) { mClient->resetInputApiCallsCounters(); audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER; attr.source = AUDIO_SOURCE_MIC; audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE; audio_io_handle_t input1 = AUDIO_PORT_HANDLE_NONE; ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input1, TEST_SESSION_ID, 1, &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 48000)); EXPECT_EQ(1, mClient->getOpenInputCallsCount()); audio_io_handle_t input2 = AUDIO_PORT_HANDLE_NONE; attr.source = AUDIO_SOURCE_CAMCORDER; ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input2, OTHER_SESSION_ID, 1, &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 48000)); EXPECT_EQ(2, mClient->getOpenInputCallsCount()); EXPECT_EQ(1, mClient->getCloseInputCallsCount()); EXPECT_NE(input1, input2); }