From c952527e6f89d5427881462823514be9d79f13e6 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Thu, 21 Jun 2012 09:55:49 -0700 Subject: audio policy: fix HDMI hot plug When an HDMI sink is connected it is possible that a direct output is made available for multichannel audio. In this case, the list of outputs available to reach the HDMI device after the connection is different from before. checkOutputForStrategy() must take this into account in order to invalidate tracks so that they can be re connected to the multi channel output if necessary. Change-Id: Id0baeb51688eba8017fe96bf92aaac52eb8e0f59 --- audio/AudioPolicyManagerBase.cpp | 37 ++++++++++++++---------- include/hardware_legacy/AudioPolicyManagerBase.h | 15 ++++++---- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/audio/AudioPolicyManagerBase.cpp b/audio/AudioPolicyManagerBase.cpp index cce60b5..d0adb3a 100644 --- a/audio/AudioPolicyManagerBase.cpp +++ b/audio/AudioPolicyManagerBase.cpp @@ -66,6 +66,9 @@ status_t AudioPolicyManagerBase::setDeviceConnectionState(AudioSystem::audio_dev return BAD_VALUE; } + // save a copy of the opened output descriptors before any output is opened or closed + // by checkOutputsForDevice(). This will be needed by checkOutputForAllStrategies() + mPreviousOutputs = mOutputs; switch (state) { // handle output device connection @@ -152,7 +155,7 @@ status_t AudioPolicyManagerBase::setDeviceConnectionState(AudioSystem::audio_dev } } - updateDeviceForStrategy(); + updateDevicesAndOutputs(); for (size_t i = 0; i < mOutputs.size(); i++) { setOutputDevice(mOutputs.keyAt(i), getNewDevice(mOutputs.keyAt(i), true /*fromCache*/)); } @@ -298,7 +301,7 @@ void AudioPolicyManagerBase::setPhoneState(int state) newDevice = getNewDevice(mPrimaryOutput, false /*fromCache*/); checkA2dpSuspend(); checkOutputForAllStrategies(); - updateDeviceForStrategy(); + updateDevicesAndOutputs(); AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mPrimaryOutput); @@ -399,7 +402,7 @@ void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSyst // check for device and output changes triggered by new force usage checkA2dpSuspend(); checkOutputForAllStrategies(); - updateDeviceForStrategy(); + updateDevicesAndOutputs(); for (size_t i = 0; i < mOutputs.size(); i++) { audio_io_handle_t output = mOutputs.keyAt(i); audio_devices_t newDevice = getNewDevice(output, true /*fromCache*/); @@ -567,7 +570,7 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str // get which output is suitable for the specified stream. The actual routing change will happen // when startOutput() will be called - SortedVector outputs = getOutputsForDevice(device); + SortedVector outputs = getOutputsForDevice(device, mOutputs); output = selectOutput(outputs, flags); @@ -1011,7 +1014,7 @@ audio_io_handle_t AudioPolicyManagerBase::getOutputForEffect(effect_descriptor_t routing_strategy strategy = getStrategy(AudioSystem::MUSIC); audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); - SortedVector dstOutputs = getOutputsForDevice(device); + SortedVector dstOutputs = getOutputsForDevice(device, mOutputs); int outIdx = 0; for (size_t i = 0; i < dstOutputs.size(); i++) { AudioOutputDescriptor *desc = mOutputs.valueFor(dstOutputs[i]); @@ -1308,7 +1311,7 @@ AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clien ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output"); - updateDeviceForStrategy(); + updateDevicesAndOutputs(); #ifdef AUDIO_POLICY_TEST if (mPrimaryOutput != 0) { @@ -1761,17 +1764,18 @@ void AudioPolicyManagerBase::closeOutput(audio_io_handle_t output) mOutputs.removeItem(output); } -SortedVector AudioPolicyManagerBase::getOutputsForDevice(audio_devices_t device) +SortedVector AudioPolicyManagerBase::getOutputsForDevice(audio_devices_t device, + DefaultKeyedVector openOutputs) { SortedVector outputs; ALOGVV("getOutputsForDevice() device %04x", device); - for (size_t i = 0; i < mOutputs.size(); i++) { + for (size_t i = 0; i < openOutputs.size(); i++) { ALOGVV("output %d isDuplicated=%d device=%04x", - i, mOutputs.valueAt(i)->isDuplicated(), mOutputs.valueAt(i)->supportedDevices()); - if ((device & mOutputs.valueAt(i)->supportedDevices()) == device) { - ALOGVV("getOutputsForDevice() found output %d", mOutputs.keyAt(i)); - outputs.add(mOutputs.keyAt(i)); + i, openOutputs.valueAt(i)->isDuplicated(), openOutputs.valueAt(i)->supportedDevices()); + if ((device & openOutputs.valueAt(i)->supportedDevices()) == device) { + ALOGVV("getOutputsForDevice() found output %d", openOutputs.keyAt(i)); + outputs.add(openOutputs.keyAt(i)); } } return outputs; @@ -1795,8 +1799,8 @@ void AudioPolicyManagerBase::checkOutputForStrategy(routing_strategy strategy) { audio_devices_t oldDevice = getDeviceForStrategy(strategy, true /*fromCache*/); audio_devices_t newDevice = getDeviceForStrategy(strategy, false /*fromCache*/); - SortedVector srcOutputs = getOutputsForDevice(oldDevice); - SortedVector dstOutputs = getOutputsForDevice(newDevice); + SortedVector srcOutputs = getOutputsForDevice(oldDevice, mPreviousOutputs); + SortedVector dstOutputs = getOutputsForDevice(newDevice, mOutputs); if (!vectorsEqual(srcOutputs,dstOutputs)) { ALOGV("checkOutputForStrategy() strategy %d, moving from output %d to output %d", @@ -2003,7 +2007,7 @@ void AudioPolicyManagerBase::handleNotificationRoutingForStream(AudioSystem::str switch(stream) { case AudioSystem::MUSIC: checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL); - updateDeviceForStrategy(); + updateDevicesAndOutputs(); break; default: break; @@ -2204,11 +2208,12 @@ audio_devices_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy st return (audio_devices_t)device; } -void AudioPolicyManagerBase::updateDeviceForStrategy() +void AudioPolicyManagerBase::updateDevicesAndOutputs() { for (int i = 0; i < NUM_STRATEGIES; i++) { mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false /*fromCache*/); } + mPreviousOutputs = mOutputs; } uint32_t AudioPolicyManagerBase::checkDeviceMuteStrategies(AudioOutputDescriptor *outputDesc, diff --git a/include/hardware_legacy/AudioPolicyManagerBase.h b/include/hardware_legacy/AudioPolicyManagerBase.h index 96041c6..1ab9431 100644 --- a/include/hardware_legacy/AudioPolicyManagerBase.h +++ b/include/hardware_legacy/AudioPolicyManagerBase.h @@ -330,7 +330,7 @@ protected: // 2 access to either current device selection (fromCache == true) or // "future" device selection (fromCache == false) when called from a context // where conditions are changing (setDeviceConnectionState(), setPhoneState()...) AND - // before updateDeviceForStrategy() is called. + // before updateDevicesAndOutputs() is called. virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy, bool fromCache); @@ -400,7 +400,7 @@ protected: // checks and if necessary changes outputs used for all strategies. // must be called every time a condition that affects the output choice for a given strategy // changes: connected device, phone state, force use... - // Must be called before updateDeviceForStrategy() + // Must be called before updateDevicesAndOutputs() void checkOutputForStrategy(routing_strategy strategy); // Same as checkOutputForStrategy() but for a all strategies in order of priority @@ -424,7 +424,7 @@ protected: // cached values are used by getDeviceForStrategy() if parameter fromCache is true. // Must be called after checkOutputForAllStrategies() - void updateDeviceForStrategy(); + void updateDevicesAndOutputs(); // true if current platform requires a specific output to be opened for this particular // set of parameters. This function is called by getOutput() and is implemented by platform @@ -452,7 +452,8 @@ protected: // extract one device relevant for volume control from multiple device selection static audio_devices_t getDeviceForVolume(audio_devices_t device); - SortedVector getOutputsForDevice(audio_devices_t device); + SortedVector getOutputsForDevice(audio_devices_t device, + DefaultKeyedVector openOutputs); bool vectorsEqual(SortedVector& outputs1, SortedVector& outputs2); @@ -498,7 +499,11 @@ protected: AudioPolicyClientInterface *mpClientInterface; // audio policy client interface audio_io_handle_t mPrimaryOutput; // primary output handle - DefaultKeyedVector mOutputs; // list of output descriptors + // list of descriptors for outputs currently opened + DefaultKeyedVector mOutputs; + // copy of mOutputs before setDeviceConnectionState() opens new outputs + // reset to mOutputs when updateDevicesAndOutputs() is called. + DefaultKeyedVector mPreviousOutputs; DefaultKeyedVector mInputs; // list of input descriptors audio_devices_t mAvailableOutputDevices; // bit field of all available output devices audio_devices_t mAvailableInputDevices; // bit field of all available input devices -- cgit v1.1