Loading services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h +11 −1 Original line number Original line Diff line number Diff line Loading @@ -239,12 +239,13 @@ public: } } void setUseSwBridge() { mUseSwBridge = true; } void setUseSwBridge() { mUseSwBridge = true; } bool useSwBridge() const { return mUseSwBridge; } bool useSwBridge() const { return mUseSwBridge; } bool canCloseOutput() const { return mCloseOutput; } bool isConnected() const { return mPatchHandle != AUDIO_PATCH_HANDLE_NONE; } bool isConnected() const { return mPatchHandle != AUDIO_PATCH_HANDLE_NONE; } audio_patch_handle_t getPatchHandle() const { return mPatchHandle; } audio_patch_handle_t getPatchHandle() const { return mPatchHandle; } sp<DeviceDescriptor> srcDevice() const { return mSrcDevice; } sp<DeviceDescriptor> srcDevice() const { return mSrcDevice; } sp<DeviceDescriptor> sinkDevice() const { return mSinkDevice; } sp<DeviceDescriptor> sinkDevice() const { return mSinkDevice; } wp<SwAudioOutputDescriptor> swOutput() const { return mSwOutput; } wp<SwAudioOutputDescriptor> swOutput() const { return mSwOutput; } void setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput); void setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput, bool closeOutput = false); wp<HwAudioOutputDescriptor> hwOutput() const { return mHwOutput; } wp<HwAudioOutputDescriptor> hwOutput() const { return mHwOutput; } void setHwOutput(const sp<HwAudioOutputDescriptor>& hwOutput); void setHwOutput(const sp<HwAudioOutputDescriptor>& hwOutput); Loading @@ -258,6 +259,15 @@ public: wp<SwAudioOutputDescriptor> mSwOutput; wp<SwAudioOutputDescriptor> mSwOutput; wp<HwAudioOutputDescriptor> mHwOutput; wp<HwAudioOutputDescriptor> mHwOutput; bool mUseSwBridge = false; bool mUseSwBridge = false; /** * For either HW bridge associated to a SwOutput for activity / volume or SwBridge for also * sample rendering / activity & volume, an existing playback thread may be reused (e.g. * not already opened at APM startup or Direct Output). * If reusing an already opened output, when this output is not used anymore, the AudioFlinger * patch must be updated to refine the output device(s) information and ensure the right * behavior of AudioDeviceCallback. */ bool mCloseOutput = false; }; }; /** /** Loading services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp +3 −1 Original line number Original line Diff line number Diff line Loading @@ -105,9 +105,11 @@ SourceClientDescriptor::SourceClientDescriptor(audio_port_handle_t portId, uid_t { { } } void SourceClientDescriptor::setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput) void SourceClientDescriptor::setSwOutput( const sp<SwAudioOutputDescriptor>& swOutput, bool closeOutput) { { mSwOutput = swOutput; mSwOutput = swOutput; mCloseOutput = closeOutput; } } void SourceClientDescriptor::setHwOutput(const sp<HwAudioOutputDescriptor>& hwOutput) void SourceClientDescriptor::setHwOutput(const sp<HwAudioOutputDescriptor>& hwOutput) Loading services/audiopolicy/managerdefault/AudioPolicyManager.cpp +26 −13 Original line number Original line Diff line number Diff line Loading @@ -4539,7 +4539,8 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch * ALOGE("%s output is duplicated", __func__); ALOGE("%s output is duplicated", __func__); return INVALID_OPERATION; return INVALID_OPERATION; } } sourceDesc->setSwOutput(outputDesc); bool closeOutput = outputDesc->mDirectOpenCount != 0; sourceDesc->setSwOutput(outputDesc, closeOutput); } else { } else { // Same for "raw patches" aka created from createAudioPatch API // Same for "raw patches" aka created from createAudioPatch API SortedVector<audio_io_handle_t> outputs = SortedVector<audio_io_handle_t> outputs = Loading @@ -4558,7 +4559,7 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch * __func__, sinkDevice->toString().c_str()); __func__, sinkDevice->toString().c_str()); return INVALID_OPERATION; return INVALID_OPERATION; } } sourceDesc->setSwOutput(outputDesc); sourceDesc->setSwOutput(outputDesc, /* closeOutput= */ false); } } // create a software bridge in PatchPanel if: // create a software bridge in PatchPanel if: // - source and sink devices are on different HW modules OR // - source and sink devices are on different HW modules OR Loading Loading @@ -4687,17 +4688,29 @@ status_t AudioPolicyManager::releaseAudioPatchInternal(audio_patch_handle_t hand // releaseOutput has already called closeOutput in case of direct output // releaseOutput has already called closeOutput in case of direct output return NO_ERROR; return NO_ERROR; } } if (!outputDesc->isActive() && !sourceDesc->useSwBridge()) { resetOutputDevice(outputDesc); } else { // Reuse patch handle if still valid / do not force rerouting if still routed patchHandle = outputDesc->getPatchHandle(); patchHandle = outputDesc->getPatchHandle(); // When a Sw bridge is released, the mixer used by this bridge will release its // patch at AudioFlinger side. Hence, the mixer audio patch must be recreated // Reuse patch handle to force audio flinger removing initial mixer patch removal // updating hal patch handle (prevent leaks). // While using a HwBridge, force reconsidering device only if not reusing an existing // output and no more activity on output (will force to close). bool force = sourceDesc->useSwBridge() || (sourceDesc->canCloseOutput() && !outputDesc->isActive()); // APM pattern is to have always outputs opened / patch realized for reachable devices. // Update device may result to NONE (empty), coupled with force, it releases the patch. // Reconsider device only for cases: // 1 / Active Output // 2 / Inactive Output previously hosting HwBridge // 3 / Inactive Output previously hosting SwBridge that can be closed. bool updateDevice = outputDesc->isActive() || !sourceDesc->useSwBridge() || sourceDesc->canCloseOutput(); setOutputDevices(outputDesc, setOutputDevices(outputDesc, getNewOutputDevices(outputDesc, true /*fromCache*/), updateDevice ? getNewOutputDevices(outputDesc, true /*fromCache*/) : patchHandle == AUDIO_PATCH_HANDLE_NONE, /*force*/ outputDesc->devices(), force, 0, 0, patchHandle == AUDIO_PATCH_HANDLE_NONE ? nullptr : &patchHandle); patchHandle == AUDIO_PATCH_HANDLE_NONE ? nullptr : &patchHandle); } } else { } else { return BAD_VALUE; return BAD_VALUE; } } Loading Loading
services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h +11 −1 Original line number Original line Diff line number Diff line Loading @@ -239,12 +239,13 @@ public: } } void setUseSwBridge() { mUseSwBridge = true; } void setUseSwBridge() { mUseSwBridge = true; } bool useSwBridge() const { return mUseSwBridge; } bool useSwBridge() const { return mUseSwBridge; } bool canCloseOutput() const { return mCloseOutput; } bool isConnected() const { return mPatchHandle != AUDIO_PATCH_HANDLE_NONE; } bool isConnected() const { return mPatchHandle != AUDIO_PATCH_HANDLE_NONE; } audio_patch_handle_t getPatchHandle() const { return mPatchHandle; } audio_patch_handle_t getPatchHandle() const { return mPatchHandle; } sp<DeviceDescriptor> srcDevice() const { return mSrcDevice; } sp<DeviceDescriptor> srcDevice() const { return mSrcDevice; } sp<DeviceDescriptor> sinkDevice() const { return mSinkDevice; } sp<DeviceDescriptor> sinkDevice() const { return mSinkDevice; } wp<SwAudioOutputDescriptor> swOutput() const { return mSwOutput; } wp<SwAudioOutputDescriptor> swOutput() const { return mSwOutput; } void setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput); void setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput, bool closeOutput = false); wp<HwAudioOutputDescriptor> hwOutput() const { return mHwOutput; } wp<HwAudioOutputDescriptor> hwOutput() const { return mHwOutput; } void setHwOutput(const sp<HwAudioOutputDescriptor>& hwOutput); void setHwOutput(const sp<HwAudioOutputDescriptor>& hwOutput); Loading @@ -258,6 +259,15 @@ public: wp<SwAudioOutputDescriptor> mSwOutput; wp<SwAudioOutputDescriptor> mSwOutput; wp<HwAudioOutputDescriptor> mHwOutput; wp<HwAudioOutputDescriptor> mHwOutput; bool mUseSwBridge = false; bool mUseSwBridge = false; /** * For either HW bridge associated to a SwOutput for activity / volume or SwBridge for also * sample rendering / activity & volume, an existing playback thread may be reused (e.g. * not already opened at APM startup or Direct Output). * If reusing an already opened output, when this output is not used anymore, the AudioFlinger * patch must be updated to refine the output device(s) information and ensure the right * behavior of AudioDeviceCallback. */ bool mCloseOutput = false; }; }; /** /** Loading
services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp +3 −1 Original line number Original line Diff line number Diff line Loading @@ -105,9 +105,11 @@ SourceClientDescriptor::SourceClientDescriptor(audio_port_handle_t portId, uid_t { { } } void SourceClientDescriptor::setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput) void SourceClientDescriptor::setSwOutput( const sp<SwAudioOutputDescriptor>& swOutput, bool closeOutput) { { mSwOutput = swOutput; mSwOutput = swOutput; mCloseOutput = closeOutput; } } void SourceClientDescriptor::setHwOutput(const sp<HwAudioOutputDescriptor>& hwOutput) void SourceClientDescriptor::setHwOutput(const sp<HwAudioOutputDescriptor>& hwOutput) Loading
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +26 −13 Original line number Original line Diff line number Diff line Loading @@ -4539,7 +4539,8 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch * ALOGE("%s output is duplicated", __func__); ALOGE("%s output is duplicated", __func__); return INVALID_OPERATION; return INVALID_OPERATION; } } sourceDesc->setSwOutput(outputDesc); bool closeOutput = outputDesc->mDirectOpenCount != 0; sourceDesc->setSwOutput(outputDesc, closeOutput); } else { } else { // Same for "raw patches" aka created from createAudioPatch API // Same for "raw patches" aka created from createAudioPatch API SortedVector<audio_io_handle_t> outputs = SortedVector<audio_io_handle_t> outputs = Loading @@ -4558,7 +4559,7 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch * __func__, sinkDevice->toString().c_str()); __func__, sinkDevice->toString().c_str()); return INVALID_OPERATION; return INVALID_OPERATION; } } sourceDesc->setSwOutput(outputDesc); sourceDesc->setSwOutput(outputDesc, /* closeOutput= */ false); } } // create a software bridge in PatchPanel if: // create a software bridge in PatchPanel if: // - source and sink devices are on different HW modules OR // - source and sink devices are on different HW modules OR Loading Loading @@ -4687,17 +4688,29 @@ status_t AudioPolicyManager::releaseAudioPatchInternal(audio_patch_handle_t hand // releaseOutput has already called closeOutput in case of direct output // releaseOutput has already called closeOutput in case of direct output return NO_ERROR; return NO_ERROR; } } if (!outputDesc->isActive() && !sourceDesc->useSwBridge()) { resetOutputDevice(outputDesc); } else { // Reuse patch handle if still valid / do not force rerouting if still routed patchHandle = outputDesc->getPatchHandle(); patchHandle = outputDesc->getPatchHandle(); // When a Sw bridge is released, the mixer used by this bridge will release its // patch at AudioFlinger side. Hence, the mixer audio patch must be recreated // Reuse patch handle to force audio flinger removing initial mixer patch removal // updating hal patch handle (prevent leaks). // While using a HwBridge, force reconsidering device only if not reusing an existing // output and no more activity on output (will force to close). bool force = sourceDesc->useSwBridge() || (sourceDesc->canCloseOutput() && !outputDesc->isActive()); // APM pattern is to have always outputs opened / patch realized for reachable devices. // Update device may result to NONE (empty), coupled with force, it releases the patch. // Reconsider device only for cases: // 1 / Active Output // 2 / Inactive Output previously hosting HwBridge // 3 / Inactive Output previously hosting SwBridge that can be closed. bool updateDevice = outputDesc->isActive() || !sourceDesc->useSwBridge() || sourceDesc->canCloseOutput(); setOutputDevices(outputDesc, setOutputDevices(outputDesc, getNewOutputDevices(outputDesc, true /*fromCache*/), updateDevice ? getNewOutputDevices(outputDesc, true /*fromCache*/) : patchHandle == AUDIO_PATCH_HANDLE_NONE, /*force*/ outputDesc->devices(), force, 0, 0, patchHandle == AUDIO_PATCH_HANDLE_NONE ? nullptr : &patchHandle); patchHandle == AUDIO_PATCH_HANDLE_NONE ? nullptr : &patchHandle); } } else { } else { return BAD_VALUE; return BAD_VALUE; } } Loading