diff options
-rw-r--r-- | audio/AudioPolicyManagerBase.cpp | 451 | ||||
-rw-r--r-- | include/hardware_legacy/AudioPolicyManagerBase.h | 10 | ||||
-rw-r--r-- | include/hardware_legacy/audio_policy_conf.h | 4 |
3 files changed, 309 insertions, 156 deletions
diff --git a/audio/AudioPolicyManagerBase.cpp b/audio/AudioPolicyManagerBase.cpp index d1cb63e..aaae2c2 100644 --- a/audio/AudioPolicyManagerBase.cpp +++ b/audio/AudioPolicyManagerBase.cpp @@ -16,6 +16,14 @@ #define LOG_TAG "AudioPolicyManagerBase" //#define LOG_NDEBUG 0 + +//#define VERY_VERBOSE_LOGGING +#ifdef VERY_VERBOSE_LOGGING +#define ALOGVV ALOGV +#else +#define ALOGVV(a...) do { } while(0) +#endif + #include <utils/Log.h> #include <hardware_legacy/AudioPolicyManagerBase.h> #include <hardware/audio_effect.h> @@ -34,7 +42,7 @@ status_t AudioPolicyManagerBase::setDeviceConnectionState(AudioSystem::audio_dev AudioSystem::device_connection_state state, const char *device_address) { - audio_io_handle_t output = 0; + SortedVector <audio_io_handle_t> outputs; ALOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address); @@ -68,28 +76,36 @@ status_t AudioPolicyManagerBase::setDeviceConnectionState(AudioSystem::audio_dev } ALOGV("setDeviceConnectionState() connecting device %x", device); + if (checkOutputsForDevice((audio_devices_t)device, state, outputs) != NO_ERROR) { + return INVALID_OPERATION; + } + ALOGV("setDeviceConnectionState() checkOutputsForDevice() returned %d outputs", + outputs.size()); // register new device as available mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices | device); - output = checkOutputForDevice((audio_devices_t)device, state); - if (output == 0) { - mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices & ~device); - return INVALID_OPERATION; - } - // handle A2DP device connection - if (mHasA2dp && AudioSystem::isA2dpDevice(device)) { - AudioParameter param; - param.add(String8(AUDIO_PARAMETER_A2DP_SINK_ADDRESS), String8(device_address)); - mpClientInterface->setParameters(output, param.toString()); - mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN); - mA2dpSuspended = false; - } else if (AudioSystem::isBluetoothScoDevice(device)) { - ALOGV("setDeviceConnectionState() BT SCO device, address %s", device_address); - // keep track of SCO device address - mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN); - } else if (mHasUsb && audio_is_usb_device((audio_devices_t)device)) { - mUsbCardAndDevice = String8(device_address, MAX_DEVICE_ADDRESS_LEN); - mpClientInterface->setParameters(output, mUsbCardAndDevice); + if (!outputs.isEmpty()) { + String8 paramStr; + if (mHasA2dp && AudioSystem::isA2dpDevice(device)) { + // handle A2DP device connection + AudioParameter param; + param.add(String8(AUDIO_PARAMETER_A2DP_SINK_ADDRESS), String8(device_address)); + paramStr = param.toString(); + mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN); + mA2dpSuspended = false; + } else if (AudioSystem::isBluetoothScoDevice(device)) { + // handle SCO device connection + mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN); + } else if (mHasUsb && audio_is_usb_device((audio_devices_t)device)) { + // handle USB device connection + mUsbCardAndDevice = String8(device_address, MAX_DEVICE_ADDRESS_LEN); + paramStr = mUsbCardAndDevice; + } + if (!paramStr.isEmpty()) { + for (size_t i = 0; i < outputs.size(); i++) { + mpClientInterface->setParameters(outputs[i], paramStr); + } + } } break; // handle output device disconnection @@ -99,19 +115,20 @@ status_t AudioPolicyManagerBase::setDeviceConnectionState(AudioSystem::audio_dev return INVALID_OPERATION; } - ALOGV("setDeviceConnectionState() disconnecting device %x", device); // remove device from available output devices mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices & ~device); - output = checkOutputForDevice((audio_devices_t)device, state); - // handle A2DP device disconnection + checkOutputsForDevice((audio_devices_t)device, state, outputs); if (mHasA2dp && AudioSystem::isA2dpDevice(device)) { + // handle A2DP device disconnection mA2dpDeviceAddress = ""; mA2dpSuspended = false; } else if (AudioSystem::isBluetoothScoDevice(device)) { + // handle SCO device disconnection mScoDeviceAddress = ""; } else if (mHasUsb && audio_is_usb_device((audio_devices_t)device)) { + // handle USB device disconnection mUsbCardAndDevice = ""; } } break; @@ -124,8 +141,15 @@ status_t AudioPolicyManagerBase::setDeviceConnectionState(AudioSystem::audio_dev checkA2dpSuspend(); checkOutputForAllStrategies(); // outputs must be closed after checkOutputForAllStrategies() is executed - if (state == AudioSystem::DEVICE_STATE_UNAVAILABLE && output != 0) { - closeOutput(output); + if (!outputs.isEmpty()) { + for (size_t i = 0; i < outputs.size(); i++) { + // close unused outputs after device disconnection or direct outputs that have been + // opened by checkOutputsForDevice() to query dynamic parameters + if ((state == AudioSystem::DEVICE_STATE_UNAVAILABLE) || + (mOutputs.valueFor(outputs[i])->mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) { + closeOutput(outputs[i]); + } + } } updateDeviceForStrategy(); @@ -420,7 +444,8 @@ void AudioPolicyManagerBase::setSystemProperty(const char* property, const char* } } -audio_module_handle_t AudioPolicyManagerBase::getModuleForDirectoutput(audio_devices_t device, +AudioPolicyManagerBase::IOProfile *AudioPolicyManagerBase::getProfileForDirectOutput( + audio_devices_t device, uint32_t samplingRate, uint32_t format, uint32_t channelMask, @@ -431,9 +456,13 @@ audio_module_handle_t AudioPolicyManagerBase::getModuleForDirectoutput(audio_dev continue; } for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) { - if (mHwModules[i]->mOutputProfiles[j]->isCompatibleProfile(device, samplingRate, format, - channelMask, flags)) { - return mHwModules[i]->mHandle; + IOProfile *profile = mHwModules[i]->mOutputProfiles[j]; + if (profile->isCompatibleProfile(device, samplingRate, format, + channelMask, + AUDIO_OUTPUT_FLAG_DIRECT)) { + if (mAvailableOutputDevices & profile->mSupportedDevices) { + return mHwModules[i]->mOutputProfiles[j]; + } } } } @@ -460,7 +489,7 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str if (mTestOutputs[mCurOutput] == 0) { ALOGV("getOutput() opening test output"); - AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(); + AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(NULL); outputDesc->mDevice = mTestDevice; outputDesc->mSamplingRate = mTestSamplingRate; outputDesc->mFormat = mTestFormat; @@ -486,33 +515,25 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str #endif //AUDIO_POLICY_TEST // open a direct output if required by specified parameters - if (needsDirectOuput((audio_stream_type_t)stream, - samplingRate, - (audio_format_t)format, - (audio_channel_mask_t)channelMask, - (audio_output_flags_t)flags, - device)) { + IOProfile *profile = getProfileForDirectOutput(device, + samplingRate, + format, + channelMask, + (audio_output_flags_t)flags); + if (profile != NULL) { ALOGV("getOutput() opening direct output device %x", device); - audio_module_handle_t module = getModuleForDirectoutput(device, - samplingRate, - format, - channelMask, - (audio_output_flags_t)flags); - if (module == 0) { - return 0; - } - AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(NULL); + AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(profile); outputDesc->mDevice = device; outputDesc->mSamplingRate = samplingRate; outputDesc->mFormat = (audio_format_t)format; outputDesc->mChannelMask = (audio_channel_mask_t)channelMask; outputDesc->mLatency = 0; - outputDesc->mFlags = (audio_output_flags_t)(flags | AudioSystem::OUTPUT_FLAG_DIRECT); + outputDesc->mFlags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);; outputDesc->mRefCount[stream] = 0; outputDesc->mStopTime[stream] = 0; - output = mpClientInterface->openOutput(module, + output = mpClientInterface->openOutput(profile->mModule->mHandle, &outputDesc->mDevice, &outputDesc->mSamplingRate, &outputDesc->mFormat, @@ -525,8 +546,10 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str (samplingRate != 0 && samplingRate != outputDesc->mSamplingRate) || (format != 0 && format != outputDesc->mFormat) || (channelMask != 0 && channelMask != outputDesc->mChannelMask)) { - ALOGV("getOutput() failed opening direct output: samplingRate %d," - "format %d, channelMask %d", samplingRate, format, channelMask); + ALOGV("getOutput() failed opening direct output: output %d samplingRate %d %d," + "format %d %d, channelMask %04x %04x", output, samplingRate, + outputDesc->mSamplingRate, format, outputDesc->mFormat, channelMask, + outputDesc->mChannelMask); if (output != 0) { mpClientInterface->closeOutput(output); } @@ -534,6 +557,7 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str return 0; } addOutput(output, outputDesc); + ALOGV("getOutput() returns direct output %d", output); return output; } @@ -801,8 +825,7 @@ audio_io_handle_t AudioPolicyManagerBase::getInput(int inputSource, } if (profile->mModule->mHandle == 0) { - ALOGE("checkOutputForDevice(): could not open HW module %s", - profile->mModule->mName); + ALOGE("getInput(): HW module %s not opened", profile->mModule->mName); return 0; } @@ -1250,13 +1273,8 @@ AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clien if (outProfile->mSupportedDevices & mAttachedOutputDevices) { AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(outProfile); - outputDesc->mDevice = (audio_devices_t)(mDefaultOutputDevice & outProfile->mSupportedDevices); - outputDesc->mSamplingRate = outProfile->mSamplingRates[0]; - outputDesc->mFormat = outProfile->mFormats[0]; - outputDesc->mChannelMask = outProfile->mChannelMasks[0]; - outputDesc->mFlags = outProfile->mFlags; audio_io_handle_t output = mpClientInterface->openOutput( outProfile->mModule->mHandle, &outputDesc->mDevice, @@ -1291,6 +1309,7 @@ AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clien ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output"); updateDeviceForStrategy(); + #ifdef AUDIO_POLICY_TEST if (mPrimaryOutput != 0) { AudioParameter outputCmd = AudioParameter(); @@ -1498,25 +1517,23 @@ void AudioPolicyManagerBase::addOutput(audio_io_handle_t id, AudioOutputDescript } -audio_io_handle_t AudioPolicyManagerBase::checkOutputForDevice( - audio_devices_t device, - AudioSystem::device_connection_state state) +status_t AudioPolicyManagerBase::checkOutputsForDevice(audio_devices_t device, + AudioSystem::device_connection_state state, + SortedVector<audio_io_handle_t>& outputs) { - audio_io_handle_t output = 0; - AudioOutputDescriptor *outputDesc; - - // TODO handle multiple outputs supporting overlapping sets of devices. + AudioOutputDescriptor *desc; if (state == AudioSystem::DEVICE_STATE_AVAILABLE) { - // first check if one output already open can be routed to this device + // first list already open outputs that can be routed to this device for (size_t i = 0; i < mOutputs.size(); i++) { - AudioOutputDescriptor *outputDesc = mOutputs.valueAt(i); - if (outputDesc->mProfile && outputDesc->mProfile->mSupportedDevices & device) { - return mOutputs.keyAt(i); + desc = mOutputs.valueAt(i); + if (!desc->isDuplicated() && (desc->mProfile->mSupportedDevices & device)) { + ALOGV("checkOutputsForDevice(): adding opened output %d", mOutputs.keyAt(i)); + outputs.add(mOutputs.keyAt(i)); } } - // then look for one available output that can be routed to this device - const IOProfile *outProfile = NULL; + // then look for output profiles that can be routed to this device + SortedVector<IOProfile *> profiles; for (size_t i = 0; i < mHwModules.size(); i++) { if (mHwModules[i]->mHandle == 0) { @@ -1525,86 +1542,175 @@ audio_io_handle_t AudioPolicyManagerBase::checkOutputForDevice( for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) { if (mHwModules[i]->mOutputProfiles[j]->mSupportedDevices & device) { - outProfile = mHwModules[i]->mOutputProfiles[j]; - break; + ALOGV("checkOutputsForDevice(): adding profile %d from module %d", j, i); + profiles.add(mHwModules[i]->mOutputProfiles[j]); } } - if (outProfile != NULL) { - break; - } } - if (outProfile == NULL) { - ALOGW("checkOutputForDevice(): No output available for device %04x", device); - return output; + if (profiles.isEmpty() && outputs.isEmpty()) { + ALOGW("checkOutputsForDevice(): No output available for device %04x", device); + return BAD_VALUE; } - if (outProfile->mModule->mHandle == 0) { - ALOGE("checkOutputForDevice(): could not open HW module %s", - outProfile->mModule->mName); - return output; - } + // open outputs for matching profiles if needed. Direct outputs are also opened to + // query for dynamic parameters and will be closed later by setDeviceConnectionState() + for (ssize_t profile_index = 0; profile_index < (ssize_t)profiles.size(); profile_index++) { + IOProfile *profile = profiles[profile_index]; - ALOGV("opening output for device %08x", device); - outputDesc = new AudioOutputDescriptor(outProfile); - outputDesc->mDevice = device; - output = mpClientInterface->openOutput(outProfile->mModule->mHandle, - &outputDesc->mDevice, - &outputDesc->mSamplingRate, - &outputDesc->mFormat, - &outputDesc->mChannelMask, - &outputDesc->mLatency, - outputDesc->mFlags); - - if (output != 0) { - audio_io_handle_t duplicatedOutput = 0; - // add output descriptor - addOutput(output, outputDesc); - // set initial stream volume for device - applyStreamVolumes(output, device); - - //TODO: configure audio effect output stage here - - // open a duplicating output thread for the new output and the primary output - duplicatedOutput = mpClientInterface->openDuplicateOutput(output, mPrimaryOutput); - if (duplicatedOutput != 0) { - // add duplicated output descriptor - AudioOutputDescriptor *dupOutputDesc = new AudioOutputDescriptor(NULL); - dupOutputDesc->mOutput1 = mOutputs.valueFor(mPrimaryOutput); - dupOutputDesc->mOutput2 = mOutputs.valueFor(output); - dupOutputDesc->mSamplingRate = outputDesc->mSamplingRate; - dupOutputDesc->mFormat = outputDesc->mFormat; - dupOutputDesc->mChannelMask = outputDesc->mChannelMask; - dupOutputDesc->mLatency = outputDesc->mLatency; - addOutput(duplicatedOutput, dupOutputDesc); - applyStreamVolumes(duplicatedOutput, device); + // nothing to do if one output is already opened for this profile + size_t j; + for (j = 0; j < outputs.size(); j++) { + desc = mOutputs.valueAt(j); + if (!desc->isDuplicated() && desc->mProfile == profile) { + break; + } + } + if (j != outputs.size()) { + continue; + } + + ALOGV("opening output for device %08x", device); + desc = new AudioOutputDescriptor(profile); + desc->mDevice = device; + audio_io_handle_t output = mpClientInterface->openOutput(profile->mModule->mHandle, + &desc->mDevice, + &desc->mSamplingRate, + &desc->mFormat, + &desc->mChannelMask, + &desc->mLatency, + desc->mFlags); + if (output != 0) { + if (desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) { + String8 reply; + char *value; + if (profile->mSamplingRates[0] == 0) { + reply = mpClientInterface->getParameters(output, + String8(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)); + ALOGV("checkOutputsForDevice() direct output sup sampling rates %s", + reply.string()); + value = strpbrk((char *)reply.string(), "="); + if (value != NULL) { + loadSamplingRates(value, profile); + } + } + if (profile->mFormats[0] == 0) { + reply = mpClientInterface->getParameters(output, + String8(AUDIO_PARAMETER_STREAM_SUP_FORMATS)); + ALOGV("checkOutputsForDevice() direct output sup formats %s", + reply.string()); + value = strpbrk((char *)reply.string(), "="); + if (value != NULL) { + loadFormats(value, profile); + } + } + if (profile->mChannelMasks[0] == 0) { + reply = mpClientInterface->getParameters(output, + String8(AUDIO_PARAMETER_STREAM_SUP_CHANNELS)); + ALOGV("checkOutputsForDevice() direct output sup channel masks %s", + reply.string()); + value = strpbrk((char *)reply.string(), "="); + if (value != NULL) { + loadOutChannels(value + 1, profile); + } + } + if (((profile->mSamplingRates[0] == 0) && + (profile->mSamplingRates.size() < 2)) || + ((profile->mFormats[0] == 0) && + (profile->mFormats.size() < 2)) || + ((profile->mFormats[0] == 0) && + (profile->mChannelMasks.size() < 2))) { + ALOGW("checkOutputsForDevice() direct output missing param"); + output = 0; + } else { + addOutput(output, desc); + } + } else { + audio_io_handle_t duplicatedOutput = 0; + // add output descriptor + addOutput(output, desc); + // set initial stream volume for device + applyStreamVolumes(output, device); + + //TODO: configure audio effect output stage here + + // open a duplicating output thread for the new output and the primary output + duplicatedOutput = mpClientInterface->openDuplicateOutput(output, + mPrimaryOutput); + if (duplicatedOutput != 0) { + // add duplicated output descriptor + AudioOutputDescriptor *dupOutputDesc = new AudioOutputDescriptor(NULL); + dupOutputDesc->mOutput1 = mOutputs.valueFor(mPrimaryOutput); + dupOutputDesc->mOutput2 = mOutputs.valueFor(output); + dupOutputDesc->mSamplingRate = desc->mSamplingRate; + dupOutputDesc->mFormat = desc->mFormat; + dupOutputDesc->mChannelMask = desc->mChannelMask; + dupOutputDesc->mLatency = desc->mLatency; + addOutput(duplicatedOutput, dupOutputDesc); + applyStreamVolumes(duplicatedOutput, device); + } else { + ALOGW("checkOutputsForDevice() could not open dup output for %d and %d", + mPrimaryOutput, output); + mpClientInterface->closeOutput(output); + mOutputs.removeItem(output); + output = 0; + } + } + } + if (output == 0) { + ALOGW("checkOutputsForDevice() could not open output for device %x", device); + delete desc; + profiles.removeAt(profile_index); + profile_index--; } else { - ALOGW("getOutput() could not open duplicated output for %d and %d", - mPrimaryOutput, output); - mpClientInterface->closeOutput(output); - mOutputs.removeItem(output); - delete outputDesc; - return 0; + outputs.add(output); + ALOGV("checkOutputsForDevice(): adding output %d", output); } - } else { - ALOGW("checkOutputForDevice() could not open output for device %x", device); - delete outputDesc; - return 0; + } + + if (profiles.isEmpty()) { + ALOGW("checkOutputsForDevice(): No output available for device %04x", device); + return BAD_VALUE; } } else { - // we assume that one given device is supported by zero or one output // check if one opened output is not needed any more after disconnecting one device for (size_t i = 0; i < mOutputs.size(); i++) { - outputDesc = mOutputs.valueAt(i); - if (outputDesc->mProfile && - !(outputDesc->mProfile->mSupportedDevices & mAvailableOutputDevices)) { - output = mOutputs.keyAt(i); - break; + desc = mOutputs.valueAt(i); + if (!desc->isDuplicated() && + !(desc->mProfile->mSupportedDevices & mAvailableOutputDevices)) { + ALOGV("checkOutputsForDevice(): disconnecting adding output %d", mOutputs.keyAt(i)); + outputs.add(mOutputs.keyAt(i)); + } + } + for (size_t i = 0; i < mHwModules.size(); i++) + { + if (mHwModules[i]->mHandle == 0) { + continue; + } + for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) + { + IOProfile *profile = mHwModules[i]->mOutputProfiles[j]; + if ((profile->mSupportedDevices & device) && + (profile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) { + ALOGV("checkOutputsForDevice(): clearing direct output profile %d on module %d", + j, i); + if (profile->mSamplingRates[0] == 0) { + profile->mSamplingRates.clear(); + profile->mSamplingRates.add(0); + } + if (profile->mFormats[0] == 0) { + profile->mFormats.clear(); + profile->mFormats.add((audio_format_t)0); + } + if (profile->mChannelMasks[0] == 0) { + profile->mChannelMasks.clear(); + profile->mChannelMasks.add((audio_channel_mask_t)0); + } + } } } } - - return output; + return NO_ERROR; } void AudioPolicyManagerBase::closeOutput(audio_io_handle_t output) @@ -1659,12 +1765,12 @@ SortedVector<audio_io_handle_t> AudioPolicyManagerBase::getOutputsForDevice(audi { SortedVector<audio_io_handle_t> outputs; - ALOGV("getOutputsForDevice() device %04x", device); + ALOGVV("getOutputsForDevice() device %04x", device); for (size_t i = 0; i < mOutputs.size(); i++) { - ALOGV("output %d isDuplicated=%d device=%04x", + ALOGVV("output %d isDuplicated=%d device=%04x", i, mOutputs.valueAt(i)->isDuplicated(), mOutputs.valueAt(i)->supportedDevices()); if ((device & mOutputs.valueAt(i)->supportedDevices()) == device) { - ALOGV("getOutputsForDevice() found output %d", mOutputs.keyAt(i)); + ALOGVV("getOutputsForDevice() found output %d", mOutputs.keyAt(i)); outputs.add(mOutputs.keyAt(i)); } } @@ -1697,8 +1803,11 @@ void AudioPolicyManagerBase::checkOutputForStrategy(routing_strategy strategy) strategy, srcOutputs[0], dstOutputs[0]); // mute strategy while moving tracks from one output to another for (size_t i = 0; i < srcOutputs.size(); i++) { - setStrategyMute(strategy, true, srcOutputs[i]); - setStrategyMute(strategy, false, srcOutputs[i], MUTE_TIME_MS, newDevice); + AudioOutputDescriptor *desc = mOutputs.valueFor(srcOutputs[i]); + if (desc->strategyRefCount(strategy) != 0) { + setStrategyMute(strategy, true, srcOutputs[i]); + setStrategyMute(strategy, false, srcOutputs[i], MUTE_TIME_MS, newDevice); + } } // Move effects associated to this strategy from previous output to new output @@ -1907,7 +2016,7 @@ audio_devices_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy st uint32_t device = 0; if (fromCache) { - ALOGV("getDeviceForStrategy() from cache strategy %d, device %x", + ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, mDeviceForStrategy[strategy]); return mDeviceForStrategy[strategy]; } @@ -2091,7 +2200,7 @@ audio_devices_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy st break; } - ALOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device); + ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device); return (audio_devices_t)device; } @@ -2140,7 +2249,7 @@ uint32_t AudioPolicyManagerBase::checkDeviceMuteStrategies(AudioOutputDescriptor continue; } audio_io_handle_t curOutput = mOutputs.keyAt(j); - ALOGV("checkDeviceMuteStrategies() %s strategy %d (curDevice %04x) on output %d", + ALOGVV("checkDeviceMuteStrategies() %s strategy %d (curDevice %04x) on output %d", mute ? "muting" : "unmuting", i, curDevice, curOutput); setStrategyMute((routing_strategy)i, mute, curOutput, mute ? 0 : delayMs); if (desc->strategyRefCount((routing_strategy)i) != 0) { @@ -2381,7 +2490,7 @@ float AudioPolicyManagerBase::volIndexToAmpl(audio_devices_t device, const Strea float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 ) - ALOGV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f", + ALOGVV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f", curve[segment].mIndex, volIdx, curve[segment+1].mIndex, curve[segment].mDBAttenuation, @@ -2533,7 +2642,8 @@ float AudioPolicyManagerBase::computeVolume(int stream, // when the phone is ringing we must consider that music could have been paused just before // by the music application and behave as if music was active if the last music track was // just stopped - if (outputDesc->mRefCount[AudioSystem::MUSIC] || mLimitRingtoneVolume) { + if (isStreamActive(AudioSystem::MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) || + mLimitRingtoneVolume) { float musicVol = computeVolume(AudioSystem::MUSIC, mStreams[AudioSystem::MUSIC].getVolumeIndex(device), output, @@ -2560,7 +2670,7 @@ status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, // do not change actual stream volume if the stream is muted if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) { - ALOGV("checkAndSetVolume() stream %d muted count %d", + ALOGVV("checkAndSetVolume() stream %d muted count %d", stream, mOutputs.valueFor(output)->mMuteCount[stream]); return NO_ERROR; } @@ -2580,7 +2690,7 @@ status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, if (volume != mOutputs.valueFor(output)->mCurVolume[stream] || force) { mOutputs.valueFor(output)->mCurVolume[stream] = volume; - ALOGV("checkAndSetVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs); + ALOGVV("checkAndSetVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs); if (stream == AudioSystem::VOICE_CALL || stream == AudioSystem::DTMF || stream == AudioSystem::BLUETOOTH_SCO) { @@ -2621,7 +2731,7 @@ void AudioPolicyManagerBase::applyStreamVolumes(audio_io_handle_t output, int delayMs, bool force) { - ALOGV("applyStreamVolumes() for output %d and device %x", output, device); + ALOGVV("applyStreamVolumes() for output %d and device %x", output, device); for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { checkAndSetVolume(stream, @@ -2639,7 +2749,7 @@ void AudioPolicyManagerBase::setStrategyMute(routing_strategy strategy, int delayMs, audio_devices_t device) { - ALOGV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output); + ALOGVV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output); for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { if (getStrategy((AudioSystem::stream_type)stream) == strategy) { setStreamMute(stream, on, output, delayMs, device); @@ -2659,7 +2769,7 @@ void AudioPolicyManagerBase::setStreamMute(int stream, device = outputDesc->device(); } - ALOGV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d device %04x", + ALOGVV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d device %04x", stream, on, output, outputDesc->mMuteCount[stream], device); if (on) { @@ -2672,7 +2782,7 @@ void AudioPolicyManagerBase::setStreamMute(int stream, outputDesc->mMuteCount[stream]++; } else { if (outputDesc->mMuteCount[stream] == 0) { - ALOGW("setStreamMute() unmuting non muted stream!"); + ALOGV("setStreamMute() unmuting non muted stream!"); return; } if (--outputDesc->mMuteCount[stream] == 0) { @@ -2775,6 +2885,12 @@ AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor( mMuteCount[i] = 0; mStopTime[i] = 0; } + if (profile != NULL) { + mSamplingRate = profile->mSamplingRates[0]; + mFormat = profile->mFormats[0]; + mChannelMask = profile->mChannelMasks[0]; + mFlags = profile->mFlags; + } } audio_devices_t AudioPolicyManagerBase::AudioOutputDescriptor::device() @@ -3229,6 +3345,13 @@ void AudioPolicyManagerBase::loadSamplingRates(char *name, IOProfile *profile) { char *str = strtok(name, "|"); + // by convention, "0' in the first entry in mSamplingRates indicates the supported sampling + // rates should be read from the output stream after it is opened for the first time + if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { + profile->mSamplingRates.add(0); + return; + } + while (str != NULL) { uint32_t rate = atoi(str); if (rate != 0) { @@ -3244,6 +3367,13 @@ void AudioPolicyManagerBase::loadFormats(char *name, IOProfile *profile) { char *str = strtok(name, "|"); + // by convention, "0' in the first entry in mFormats indicates the supported formats + // should be read from the output stream after it is opened for the first time + if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { + profile->mFormats.add((audio_format_t)0); + return; + } + while (str != NULL) { audio_format_t format = (audio_format_t)stringToEnum(sFormatNameToEnumTable, ARRAY_SIZE(sFormatNameToEnumTable), @@ -3261,6 +3391,12 @@ void AudioPolicyManagerBase::loadInChannels(char *name, IOProfile *profile) const char *str = strtok(name, "|"); ALOGV("loadInChannels() %s", name); + + if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { + profile->mChannelMasks.add((audio_channel_mask_t)0); + return; + } + while (str != NULL) { audio_channel_mask_t channelMask = (audio_channel_mask_t)stringToEnum(sInChannelsNameToEnumTable, @@ -3278,12 +3414,21 @@ void AudioPolicyManagerBase::loadInChannels(char *name, IOProfile *profile) void AudioPolicyManagerBase::loadOutChannels(char *name, IOProfile *profile) { const char *str = strtok(name, "|"); - audio_channel_mask_t channelMask; + + ALOGV("loadOutChannels() %s", name); + + // by convention, "0' in the first entry in mChannelMasks indicates the supported channel + // masks should be read from the output stream after it is opened for the first time + if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { + profile->mChannelMasks.add((audio_channel_mask_t)0); + return; + } while (str != NULL) { - channelMask = stringToEnum(sOutChannelsNameToEnumTable, - ARRAY_SIZE(sOutChannelsNameToEnumTable), - str); + audio_channel_mask_t channelMask = + (audio_channel_mask_t)stringToEnum(sOutChannelsNameToEnumTable, + ARRAY_SIZE(sOutChannelsNameToEnumTable), + str); if (channelMask != 0) { profile->mChannelMasks.add(channelMask); } diff --git a/include/hardware_legacy/AudioPolicyManagerBase.h b/include/hardware_legacy/AudioPolicyManagerBase.h index a918d39..96041c6 100644 --- a/include/hardware_legacy/AudioPolicyManagerBase.h +++ b/include/hardware_legacy/AudioPolicyManagerBase.h @@ -203,6 +203,9 @@ protected: void dump(int fd); + // by convention, "0' in the first entry in mSamplingRates, mChannelMasks or mFormats + // indicates the supported parameters should be read from the output stream + // after it is opened for the first time Vector <uint32_t> mSamplingRates; // supported sampling rates Vector <audio_channel_mask_t> mChannelMasks; // supported channel masks Vector <audio_format_t> mFormats; // supported audio formats @@ -387,8 +390,9 @@ protected: // when a device is disconnected, checks if an output is not used any more and // returns its handle if any. // transfers the audio tracks and effects from one output thread to another accordingly. - audio_io_handle_t checkOutputForDevice(audio_devices_t device, - AudioSystem::device_connection_state state); + status_t checkOutputsForDevice(audio_devices_t device, + AudioSystem::device_connection_state state, + SortedVector<audio_io_handle_t>& outputs); // close an output and its companion duplicating output. void closeOutput(audio_io_handle_t output); @@ -466,7 +470,7 @@ protected: uint32_t samplingRate, uint32_t format, uint32_t channelMask); - audio_module_handle_t getModuleForDirectoutput(audio_devices_t device, + IOProfile *getProfileForDirectOutput(audio_devices_t device, uint32_t samplingRate, uint32_t format, uint32_t channelMask, diff --git a/include/hardware_legacy/audio_policy_conf.h b/include/hardware_legacy/audio_policy_conf.h index c1fc0c1..fa58c36 100644 --- a/include/hardware_legacy/audio_policy_conf.h +++ b/include/hardware_legacy/audio_policy_conf.h @@ -47,4 +47,8 @@ #define DEVICES_TAG "devices" #define FLAGS_TAG "flags" +#define DYNAMIC_VALUE_TAG "dynamic" // special value for "channel_masks", "sampling_rates" and + // "formats" in outputs descriptors indicating that supported + // values should be queried after opening the output. + #endif // ANDROID_AUDIO_POLICY_CONF_H |