diff options
Diffstat (limited to 'services/audiopolicy/AudioPolicyManager.cpp')
-rw-r--r-- | services/audiopolicy/AudioPolicyManager.cpp | 141 |
1 files changed, 94 insertions, 47 deletions
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp index e449863..737cacd 100644 --- a/services/audiopolicy/AudioPolicyManager.cpp +++ b/services/audiopolicy/AudioPolicyManager.cpp @@ -1055,13 +1055,14 @@ audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - audio_in_acoustics_t acoustics) + audio_in_acoustics_t acoustics, + audio_input_flags_t flags) { - audio_io_handle_t input = 0; - audio_devices_t device = getDeviceForInputSource(inputSource); + ALOGV("getInput() inputSource %d, samplingRate %d, format %d, channelMask %x, acoustics %x, " + "flags %#x", + inputSource, samplingRate, format, channelMask, acoustics, flags); - ALOGV("getInput() inputSource %d, samplingRate %d, format %d, channelMask %x, acoustics %x", - inputSource, samplingRate, format, channelMask, acoustics); + audio_devices_t device = getDeviceForInputSource(inputSource); if (device == AUDIO_DEVICE_NONE) { ALOGW("getInput() could not find device for inputSource %d", inputSource); @@ -1069,7 +1070,7 @@ audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource, } // adapt channel selection to input source - switch(inputSource) { + switch (inputSource) { case AUDIO_SOURCE_VOICE_UPLINK: channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK; break; @@ -1086,11 +1087,12 @@ audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource, sp<IOProfile> profile = getInputProfile(device, samplingRate, format, - channelMask); + channelMask, + flags); if (profile == 0) { - ALOGW("getInput() could not find profile for device %04x, samplingRate %d, format %d, " - "channelMask %04x", - device, samplingRate, format, channelMask); + ALOGW("getInput() could not find profile for device 0x%X, samplingRate %u, format %#x, " + "channelMask 0x%X, flags %#x", + device, samplingRate, format, channelMask, flags); return 0; } @@ -1107,19 +1109,21 @@ audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource, inputDesc->mFormat = format; inputDesc->mChannelMask = channelMask; inputDesc->mRefCount = 0; - input = mpClientInterface->openInput(profile->mModule->mHandle, + inputDesc->mOpenRefCount = 1; + + audio_io_handle_t input = mpClientInterface->openInput(profile->mModule->mHandle, &inputDesc->mDevice, &inputDesc->mSamplingRate, &inputDesc->mFormat, &inputDesc->mChannelMask, - AUDIO_INPUT_FLAG_FAST /*FIXME*/); + flags); // only accept input with the exact requested set of parameters if (input == 0 || (samplingRate != inputDesc->mSamplingRate) || (format != inputDesc->mFormat) || (channelMask != inputDesc->mChannelMask)) { - ALOGI("getInput() failed opening input: samplingRate %d, format %d, channelMask %x", + ALOGW("getInput() failed opening input: samplingRate %d, format %d, channelMask %x", samplingRate, format, channelMask); if (input != 0) { mpClientInterface->closeInput(input); @@ -1141,37 +1145,41 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input) } sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index); -#ifdef AUDIO_POLICY_TEST - if (mTestInput == 0) -#endif //AUDIO_POLICY_TEST - { - // refuse 2 active AudioRecord clients at the same time except if the active input - // uses AUDIO_SOURCE_HOTWORD in which case it is closed. + // virtual input devices are compatible with other input devices + if (!isVirtualInputDevice(inputDesc->mDevice)) { + + // for a non-virtual input device, check if there is another (non-virtual) active input audio_io_handle_t activeInput = getActiveInput(); - if (!isVirtualInputDevice(inputDesc->mDevice) && activeInput != 0) { + if (activeInput != 0 && activeInput != input) { + + // If the already active input uses AUDIO_SOURCE_HOTWORD then it is closed, + // otherwise the active input continues and the new input cannot be started. sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput); if (activeDesc->mInputSource == AUDIO_SOURCE_HOTWORD) { - ALOGW("startInput() preempting already started low-priority input %d", activeInput); + ALOGW("startInput(%d) preempting low-priority input %d", input, activeInput); stopInput(activeInput); releaseInput(activeInput); } else { - ALOGW("startInput() input %d failed: other input already started", input); + ALOGE("startInput(%d) failed: other input %d already started", input, activeInput); return INVALID_OPERATION; } } } - setInputDevice(input, getNewInputDevice(input), true /* force */); + if (inputDesc->mRefCount == 0) { + setInputDevice(input, getNewInputDevice(input), true /* force */); - // automatically enable the remote submix output when input is started - if (audio_is_remote_submix_device(inputDesc->mDevice)) { - setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, - AUDIO_POLICY_DEVICE_STATE_AVAILABLE, AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS); + // Automatically enable the remote submix output when input is started. + // For remote submix (a virtual device), we open only one input per capture request. + if (audio_is_remote_submix_device(inputDesc->mDevice)) { + setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, + AUDIO_POLICY_DEVICE_STATE_AVAILABLE, AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS); + } } ALOGV("AudioPolicyManager::startInput() input source = %d", inputDesc->mInputSource); - inputDesc->mRefCount = 1; + inputDesc->mRefCount++; return NO_ERROR; } @@ -1188,7 +1196,11 @@ status_t AudioPolicyManager::stopInput(audio_io_handle_t input) if (inputDesc->mRefCount == 0) { ALOGW("stopInput() input %d already stopped", input); return INVALID_OPERATION; - } else { + } + + inputDesc->mRefCount--; + if (inputDesc->mRefCount == 0) { + // automatically disable the remote submix output when input is stopped if (audio_is_remote_submix_device(inputDesc->mDevice)) { setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, @@ -1196,9 +1208,8 @@ status_t AudioPolicyManager::stopInput(audio_io_handle_t input) } resetInputDevice(input); - inputDesc->mRefCount = 0; - return NO_ERROR; } + return NO_ERROR; } void AudioPolicyManager::releaseInput(audio_io_handle_t input) @@ -1209,6 +1220,18 @@ void AudioPolicyManager::releaseInput(audio_io_handle_t input) ALOGW("releaseInput() releasing unknown input %d", input); return; } + sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index); + ALOG_ASSERT(inputDesc != 0); + if (inputDesc->mOpenRefCount == 0) { + ALOGW("releaseInput() invalid open ref count %d", inputDesc->mOpenRefCount); + return; + } + inputDesc->mOpenRefCount--; + if (inputDesc->mOpenRefCount > 0) { + ALOGV("releaseInput() exit > 0"); + return; + } + mpClientInterface->closeInput(input); mInputs.removeItem(input); nextAudioPortGeneration(); @@ -1874,7 +1897,8 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, patch->sources[0].sample_rate, patch->sources[0].format, patch->sources[0].channel_mask, - AUDIO_OUTPUT_FLAG_NONE)) { + AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) { + ALOGV("createAudioPatch() profile not supported"); return INVALID_OPERATION; } // TODO: reconfigure output format and channels here @@ -1919,7 +1943,10 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, patch->sinks[0].sample_rate, patch->sinks[0].format, patch->sinks[0].channel_mask, - AUDIO_OUTPUT_FLAG_NONE)) { + // FIXME for the parameter type, + // and the NONE + (audio_output_flags_t) + AUDIO_INPUT_FLAG_NONE)) { return INVALID_OPERATION; } // TODO: reconfigure output format and channels here @@ -1963,9 +1990,20 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, srcDeviceDesc->toAudioPortConfig(&newPatch.sources[0], &patch->sources[0]); sinkDeviceDesc->toAudioPortConfig(&newPatch.sinks[0], &patch->sinks[0]); - // TODO: add support for devices on different HW modules if (srcDeviceDesc->mModule != sinkDeviceDesc->mModule) { - return INVALID_OPERATION; + SortedVector<audio_io_handle_t> outputs = + getOutputsForDevice(sinkDeviceDesc->mDeviceType, mOutputs); + // if the sink device is reachable via an opened output stream, request to go via + // this output stream by adding a second source to the patch description + audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE); + if (output != AUDIO_IO_HANDLE_NONE) { + sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); + if (outputDesc->isDuplicated()) { + return INVALID_OPERATION; + } + outputDesc->toAudioPortConfig(&newPatch.sources[1], &patch->sources[0]); + newPatch.num_sources = 2; + } } // TODO: check from routing capabilities in config file and other conflicting patches @@ -2270,12 +2308,17 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa continue; } - audio_devices_t profileTypes = outProfile->mSupportedDevices.types(); - if ((profileTypes & outputDeviceTypes) && + audio_devices_t profileType = outProfile->mSupportedDevices.types(); + if ((profileType & mDefaultOutputDevice->mDeviceType) != AUDIO_DEVICE_NONE) { + profileType = mDefaultOutputDevice->mDeviceType; + } else { + profileType = outProfile->mSupportedDevices[0]->mDeviceType; + } + if ((profileType & outputDeviceTypes) && ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) { sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(outProfile); - outputDesc->mDevice = (audio_devices_t)(mDefaultOutputDevice->mDeviceType & profileTypes); + outputDesc->mDevice = profileType; audio_io_handle_t output = mpClientInterface->openOutput( outProfile->mModule->mHandle, &outputDesc->mDevice, @@ -2304,7 +2347,6 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa mPrimaryOutput = output; } addOutput(output, outputDesc); - ALOGI("CSTOR setOutputDevice %08x", outputDesc->mDevice); setOutputDevice(output, outputDesc->mDevice, true); @@ -2322,19 +2364,19 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa continue; } - audio_devices_t profileTypes = inProfile->mSupportedDevices.types(); - if (profileTypes & inputDeviceTypes) { + audio_devices_t profileType = inProfile->mSupportedDevices[0]->mDeviceType; + if (profileType & inputDeviceTypes) { sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(inProfile); inputDesc->mInputSource = AUDIO_SOURCE_MIC; - inputDesc->mDevice = inProfile->mSupportedDevices[0]->mDeviceType; + inputDesc->mDevice = profileType; audio_io_handle_t input = mpClientInterface->openInput( inProfile->mModule->mHandle, &inputDesc->mDevice, &inputDesc->mSamplingRate, &inputDesc->mFormat, &inputDesc->mChannelMask, - AUDIO_INPUT_FLAG_FAST /*FIXME*/); + AUDIO_INPUT_FLAG_NONE /*FIXME*/); if (input != 0) { for (size_t k = 0; k < inProfile->mSupportedDevices.size(); k++) { @@ -2659,7 +2701,8 @@ status_t AudioPolicyManager::checkOutputsForDevice(audio_devices_t device, continue; } - ALOGV("opening output for device %08x with params %s", device, address.string()); + ALOGV("opening output for device %08x with params %s profile %p", + device, address.string(), profile.get()); desc = new AudioOutputDescriptor(profile); desc->mDevice = device; audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER; @@ -2901,7 +2944,7 @@ status_t AudioPolicyManager::checkInputsForDevice(audio_devices_t device, &desc->mSamplingRate, &desc->mFormat, &desc->mChannelMask, - AUDIO_INPUT_FLAG_FAST /*FIXME*/); + AUDIO_INPUT_FLAG_NONE /*FIXME*/); if (input != 0) { if (!address.isEmpty()) { @@ -3908,7 +3951,8 @@ status_t AudioPolicyManager::resetInputDevice(audio_io_handle_t input, sp<AudioPolicyManager::IOProfile> AudioPolicyManager::getInputProfile(audio_devices_t device, uint32_t samplingRate, audio_format_t format, - audio_channel_mask_t channelMask) + audio_channel_mask_t channelMask, + audio_input_flags_t flags __unused) { // Choose an input profile based on the requested capture parameters: select the first available // profile supporting all requested parameters. @@ -4763,6 +4807,9 @@ status_t AudioPolicyManager::AudioInputDescriptor::dump(int fd) result.append(buffer); snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount); result.append(buffer); + snprintf(buffer, SIZE, " Open Ref Count %d\n", mOpenRefCount); + result.append(buffer); + write(fd, result.string(), result.size()); return NO_ERROR; @@ -5942,7 +5989,7 @@ void AudioPolicyManager::DeviceDescriptor::toAudioPortConfig( void AudioPolicyManager::DeviceDescriptor::toAudioPort(struct audio_port *port) const { - ALOGV("DeviceVector::toAudioPort() handle %d type %x", mId, mDeviceType); + ALOGV("DeviceDescriptor::toAudioPort() handle %d type %x", mId, mDeviceType); AudioPort::toAudioPort(port); port->id = mId; toAudioPortConfig(&port->active_config); |