Loading services/audioflinger/PatchPanel.cpp +35 −29 Original line number Diff line number Diff line Loading @@ -151,12 +151,15 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa if (handle == NULL || patch == NULL) { return BAD_VALUE; } // limit number of sources to 1 for now or 2 sources for special cross hw module case. // only the audio policy manager can request a patch creation with 2 sources. if (patch->num_sources == 0 || patch->num_sources > 2 || if (patch->num_sources == 0 || patch->num_sources > AUDIO_PATCH_PORTS_MAX || patch->num_sinks == 0 || patch->num_sinks > AUDIO_PATCH_PORTS_MAX) { return BAD_VALUE; } // limit number of sources to 1 for now or 2 sources for special cross hw module case. // only the audio policy manager can request a patch creation with 2 sources. if (patch->num_sources > 2) { return INVALID_OPERATION; } if (*handle != AUDIO_PATCH_HANDLE_NONE) { for (size_t index = 0; *handle != 0 && index < mPatches.size(); index++) { Loading @@ -173,20 +176,22 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa switch (patch->sources[0].type) { case AUDIO_PORT_TYPE_DEVICE: { // limit number of sinks to 1 for now if (patch->num_sinks > 1) { status = BAD_VALUE; goto exit; } audio_module_handle_t src_module = patch->sources[0].ext.device.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(src_module); audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); if (index < 0) { ALOGW("createAudioPatch() bad src hw module %d", src_module); ALOGW("createAudioPatch() bad src hw module %d", srcModule); status = BAD_VALUE; goto exit; } AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); for (unsigned int i = 0; i < patch->num_sinks; i++) { // support only one sink if connection to a mix or across HW modules if ((patch->sinks[i].type == AUDIO_PORT_TYPE_MIX || patch->sinks[i].ext.mix.hw_module != srcModule) && patch->num_sinks > 1) { status = INVALID_OPERATION; goto exit; } // reject connection to different sink types if (patch->sinks[i].type != patch->sinks[0].type) { ALOGW("createAudioPatch() different sink types in same patch not supported"); Loading @@ -194,7 +199,7 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa goto exit; } // limit to connections between devices and input streams for HAL before 3.0 if (patch->sinks[i].ext.mix.hw_module == src_module && if (patch->sinks[i].ext.mix.hw_module == srcModule && (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) && (patch->sinks[i].type != AUDIO_PORT_TYPE_MIX)) { ALOGW("createAudioPatch() invalid sink type %d for device source", Loading @@ -204,7 +209,7 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa } } if (patch->sinks[0].ext.device.hw_module != src_module) { if (patch->sinks[0].ext.device.hw_module != srcModule) { // limit to device to device connection if not on same hw module if (patch->sinks[0].type != AUDIO_PORT_TYPE_DEVICE) { ALOGW("createAudioPatch() invalid sink type for cross hw module"); Loading Loading @@ -258,7 +263,7 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa config.channel_mask = inChannelMask; config.format = newPatch->mPlaybackThread->format(); audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; newPatch->mRecordThread = audioflinger->openInput_l(src_module, newPatch->mRecordThread = audioflinger->openInput_l(srcModule, &input, &config, device, Loading Loading @@ -326,10 +331,10 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa } } break; case AUDIO_PORT_TYPE_MIX: { audio_module_handle_t src_module = patch->sources[0].ext.mix.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(src_module); audio_module_handle_t srcModule = patch->sources[0].ext.mix.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); if (index < 0) { ALOGW("createAudioPatch() bad src hw module %d", src_module); ALOGW("createAudioPatch() bad src hw module %d", srcModule); status = BAD_VALUE; goto exit; } Loading @@ -342,7 +347,7 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa goto exit; } // limit to connections between sinks and sources on same HW module if (patch->sinks[i].ext.device.hw_module != src_module) { if (patch->sinks[i].ext.device.hw_module != srcModule) { status = BAD_VALUE; goto exit; } Loading @@ -365,6 +370,7 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa } char *address; if (strcmp(patch->sinks[0].ext.device.address, "") != 0) { //FIXME: we only support address on first sink with HAL version < 3.0 address = audio_device_address_to_parameter( patch->sinks[0].ext.device.type, patch->sinks[0].ext.device.address); Loading Loading @@ -562,16 +568,16 @@ status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle switch (patch->sources[0].type) { case AUDIO_PORT_TYPE_DEVICE: { audio_module_handle_t src_module = patch->sources[0].ext.device.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(src_module); audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); if (index < 0) { ALOGW("releaseAudioPatch() bad src hw module %d", src_module); ALOGW("releaseAudioPatch() bad src hw module %d", srcModule); status = BAD_VALUE; break; } if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE && patch->sinks[0].ext.device.hw_module != src_module) { patch->sinks[0].ext.device.hw_module != srcModule) { clearPatchConnections(removedPatch); break; } Loading Loading @@ -609,10 +615,10 @@ status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle } } break; case AUDIO_PORT_TYPE_MIX: { audio_module_handle_t src_module = patch->sources[0].ext.mix.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(src_module); audio_module_handle_t srcModule = patch->sources[0].ext.mix.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); if (index < 0) { ALOGW("releaseAudioPatch() bad src hw module %d", src_module); ALOGW("releaseAudioPatch() bad src hw module %d", srcModule); status = BAD_VALUE; break; } Loading services/audiopolicy/AudioPolicyManager.cpp +91 −55 Original line number Diff line number Diff line Loading @@ -2078,22 +2078,37 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, } ALOGV("createAudioPatch() num sources %d num sinks %d", patch->num_sources, patch->num_sinks); if (patch->num_sources > 1 || patch->num_sinks > 1) { if (patch->num_sources == 0 || patch->num_sources > AUDIO_PATCH_PORTS_MAX || patch->num_sinks == 0 || patch->num_sinks > AUDIO_PATCH_PORTS_MAX) { return BAD_VALUE; } // only one source per audio patch supported for now if (patch->num_sources > 1) { return INVALID_OPERATION; } if (patch->sources[0].role != AUDIO_PORT_ROLE_SOURCE) { return INVALID_OPERATION; } if (patch->sources[0].role != AUDIO_PORT_ROLE_SOURCE || patch->sinks[0].role != AUDIO_PORT_ROLE_SINK) { for (size_t i = 0; i < patch->num_sinks; i++) { if (patch->sinks[i].role != AUDIO_PORT_ROLE_SINK) { return INVALID_OPERATION; } } sp<AudioPatch> patchDesc; ssize_t index = mAudioPatches.indexOfKey(*handle); ALOGV("createAudioPatch sink id %d role %d type %d", patch->sinks[0].id, patch->sinks[0].role, patch->sinks[0].type); ALOGV("createAudioPatch source id %d role %d type %d", patch->sources[0].id, patch->sources[0].role, patch->sources[0].type); #if LOG_NDEBUG == 0 for (size_t i = 0; i < patch->num_sinks; i++) { ALOGV("createAudioPatch sink %d: id %d role %d type %d", i, patch->sinks[i].id, patch->sinks[i].role, patch->sinks[i].type); } #endif if (index >= 0) { patchDesc = mAudioPatches.valueAt(index); Loading @@ -2107,12 +2122,6 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, } if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) { // TODO add support for mix to mix connection if (patch->sinks[0].type != AUDIO_PORT_TYPE_DEVICE) { ALOGV("createAudioPatch() source mix sink not device"); return BAD_VALUE; } // output mix to output device connection sp<AudioOutputDescriptor> outputDesc = getOutputFromId(patch->sources[0].id); if (outputDesc == NULL) { ALOGV("createAudioPatch() output not found for id %d", patch->sources[0].id); Loading @@ -2127,10 +2136,18 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, return BAD_VALUE; } } DeviceVector devices; for (size_t i = 0; i < patch->num_sinks; i++) { // Only support mix to devices connection // TODO add support for mix to mix connection if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) { ALOGV("createAudioPatch() source mix but sink is not a device"); return INVALID_OPERATION; } sp<DeviceDescriptor> devDesc = mAvailableOutputDevices.getDeviceFromId(patch->sinks[0].id); mAvailableOutputDevices.getDeviceFromId(patch->sinks[i].id); if (devDesc == 0) { ALOGV("createAudioPatch() out device not found for id %d", patch->sinks[0].id); ALOGV("createAudioPatch() out device not found for id %d", patch->sinks[i].id); return BAD_VALUE; } Loading @@ -2140,17 +2157,20 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, patch->sources[0].format, patch->sources[0].channel_mask, AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) { ALOGV("createAudioPatch() profile not supported"); ALOGV("createAudioPatch() profile not supported for device %08x", devDesc->mDeviceType); return INVALID_OPERATION; } devices.add(devDesc); } if (devices.size() == 0) { return INVALID_OPERATION; } // TODO: reconfigure output format and channels here ALOGV("createAudioPatch() setting device %08x on output %d", devDesc->mDeviceType, outputDesc->mIoHandle); setOutputDevice(outputDesc->mIoHandle, devDesc->mDeviceType, true, 0, handle); devices.types(), outputDesc->mIoHandle); setOutputDevice(outputDesc->mIoHandle, devices.types(), true, 0, handle); index = mAudioPatches.indexOfKey(*handle); if (index >= 0) { if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) { Loading @@ -2166,6 +2186,10 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, } else if (patch->sources[0].type == AUDIO_PORT_TYPE_DEVICE) { if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { // input device to input mix connection // only one sink supported when connecting an input device to a mix if (patch->num_sinks > 1) { return INVALID_OPERATION; } sp<AudioInputDescriptor> inputDesc = getInputFromId(patch->sinks[0].id); if (inputDesc == NULL) { return BAD_VALUE; Loading Loading @@ -2195,10 +2219,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, // TODO: reconfigure output format and channels here ALOGV("createAudioPatch() setting device %08x on output %d", devDesc->mDeviceType, inputDesc->mIoHandle); setInputDevice(inputDesc->mIoHandle, devDesc->mDeviceType, true, handle); setInputDevice(inputDesc->mIoHandle, devDesc->mDeviceType, true, handle); index = mAudioPatches.indexOfKey(*handle); if (index >= 0) { if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) { Loading @@ -2214,28 +2235,42 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, } else if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) { // device to device connection if (patchDesc != 0) { if (patchDesc->mPatch.sources[0].id != patch->sources[0].id && patchDesc->mPatch.sinks[0].id != patch->sinks[0].id) { if (patchDesc->mPatch.sources[0].id != patch->sources[0].id) { return BAD_VALUE; } } sp<DeviceDescriptor> srcDeviceDesc = mAvailableInputDevices.getDeviceFromId(patch->sources[0].id); sp<DeviceDescriptor> sinkDeviceDesc = mAvailableOutputDevices.getDeviceFromId(patch->sinks[0].id); if (srcDeviceDesc == 0 || sinkDeviceDesc == 0) { return BAD_VALUE; } //update source and sink with our own data as the data passed in the patch may // be incomplete. struct audio_patch newPatch = *patch; srcDeviceDesc->toAudioPortConfig(&newPatch.sources[0], &patch->sources[0]); sinkDeviceDesc->toAudioPortConfig(&newPatch.sinks[0], &patch->sinks[0]); if (srcDeviceDesc == 0) { return BAD_VALUE; } for (size_t i = 0; i < patch->num_sinks; i++) { if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) { ALOGV("createAudioPatch() source device but one sink is not a device"); return INVALID_OPERATION; } sp<DeviceDescriptor> sinkDeviceDesc = mAvailableOutputDevices.getDeviceFromId(patch->sinks[i].id); if (sinkDeviceDesc == 0) { return BAD_VALUE; } sinkDeviceDesc->toAudioPortConfig(&newPatch.sinks[i], &patch->sinks[i]); if (srcDeviceDesc->mModule != sinkDeviceDesc->mModule) { // only one sink supported when connected devices across HW modules if (patch->num_sinks > 1) { return INVALID_OPERATION; } SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(sinkDeviceDesc->mDeviceType, mOutputs); 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); Loading @@ -2248,6 +2283,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, newPatch.num_sources = 2; } } } // TODO: check from routing capabilities in config file and other conflicting patches audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE; Loading Loading
services/audioflinger/PatchPanel.cpp +35 −29 Original line number Diff line number Diff line Loading @@ -151,12 +151,15 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa if (handle == NULL || patch == NULL) { return BAD_VALUE; } // limit number of sources to 1 for now or 2 sources for special cross hw module case. // only the audio policy manager can request a patch creation with 2 sources. if (patch->num_sources == 0 || patch->num_sources > 2 || if (patch->num_sources == 0 || patch->num_sources > AUDIO_PATCH_PORTS_MAX || patch->num_sinks == 0 || patch->num_sinks > AUDIO_PATCH_PORTS_MAX) { return BAD_VALUE; } // limit number of sources to 1 for now or 2 sources for special cross hw module case. // only the audio policy manager can request a patch creation with 2 sources. if (patch->num_sources > 2) { return INVALID_OPERATION; } if (*handle != AUDIO_PATCH_HANDLE_NONE) { for (size_t index = 0; *handle != 0 && index < mPatches.size(); index++) { Loading @@ -173,20 +176,22 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa switch (patch->sources[0].type) { case AUDIO_PORT_TYPE_DEVICE: { // limit number of sinks to 1 for now if (patch->num_sinks > 1) { status = BAD_VALUE; goto exit; } audio_module_handle_t src_module = patch->sources[0].ext.device.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(src_module); audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); if (index < 0) { ALOGW("createAudioPatch() bad src hw module %d", src_module); ALOGW("createAudioPatch() bad src hw module %d", srcModule); status = BAD_VALUE; goto exit; } AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); for (unsigned int i = 0; i < patch->num_sinks; i++) { // support only one sink if connection to a mix or across HW modules if ((patch->sinks[i].type == AUDIO_PORT_TYPE_MIX || patch->sinks[i].ext.mix.hw_module != srcModule) && patch->num_sinks > 1) { status = INVALID_OPERATION; goto exit; } // reject connection to different sink types if (patch->sinks[i].type != patch->sinks[0].type) { ALOGW("createAudioPatch() different sink types in same patch not supported"); Loading @@ -194,7 +199,7 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa goto exit; } // limit to connections between devices and input streams for HAL before 3.0 if (patch->sinks[i].ext.mix.hw_module == src_module && if (patch->sinks[i].ext.mix.hw_module == srcModule && (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) && (patch->sinks[i].type != AUDIO_PORT_TYPE_MIX)) { ALOGW("createAudioPatch() invalid sink type %d for device source", Loading @@ -204,7 +209,7 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa } } if (patch->sinks[0].ext.device.hw_module != src_module) { if (patch->sinks[0].ext.device.hw_module != srcModule) { // limit to device to device connection if not on same hw module if (patch->sinks[0].type != AUDIO_PORT_TYPE_DEVICE) { ALOGW("createAudioPatch() invalid sink type for cross hw module"); Loading Loading @@ -258,7 +263,7 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa config.channel_mask = inChannelMask; config.format = newPatch->mPlaybackThread->format(); audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; newPatch->mRecordThread = audioflinger->openInput_l(src_module, newPatch->mRecordThread = audioflinger->openInput_l(srcModule, &input, &config, device, Loading Loading @@ -326,10 +331,10 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa } } break; case AUDIO_PORT_TYPE_MIX: { audio_module_handle_t src_module = patch->sources[0].ext.mix.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(src_module); audio_module_handle_t srcModule = patch->sources[0].ext.mix.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); if (index < 0) { ALOGW("createAudioPatch() bad src hw module %d", src_module); ALOGW("createAudioPatch() bad src hw module %d", srcModule); status = BAD_VALUE; goto exit; } Loading @@ -342,7 +347,7 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa goto exit; } // limit to connections between sinks and sources on same HW module if (patch->sinks[i].ext.device.hw_module != src_module) { if (patch->sinks[i].ext.device.hw_module != srcModule) { status = BAD_VALUE; goto exit; } Loading @@ -365,6 +370,7 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa } char *address; if (strcmp(patch->sinks[0].ext.device.address, "") != 0) { //FIXME: we only support address on first sink with HAL version < 3.0 address = audio_device_address_to_parameter( patch->sinks[0].ext.device.type, patch->sinks[0].ext.device.address); Loading Loading @@ -562,16 +568,16 @@ status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle switch (patch->sources[0].type) { case AUDIO_PORT_TYPE_DEVICE: { audio_module_handle_t src_module = patch->sources[0].ext.device.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(src_module); audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); if (index < 0) { ALOGW("releaseAudioPatch() bad src hw module %d", src_module); ALOGW("releaseAudioPatch() bad src hw module %d", srcModule); status = BAD_VALUE; break; } if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE && patch->sinks[0].ext.device.hw_module != src_module) { patch->sinks[0].ext.device.hw_module != srcModule) { clearPatchConnections(removedPatch); break; } Loading Loading @@ -609,10 +615,10 @@ status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle } } break; case AUDIO_PORT_TYPE_MIX: { audio_module_handle_t src_module = patch->sources[0].ext.mix.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(src_module); audio_module_handle_t srcModule = patch->sources[0].ext.mix.hw_module; ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); if (index < 0) { ALOGW("releaseAudioPatch() bad src hw module %d", src_module); ALOGW("releaseAudioPatch() bad src hw module %d", srcModule); status = BAD_VALUE; break; } Loading
services/audiopolicy/AudioPolicyManager.cpp +91 −55 Original line number Diff line number Diff line Loading @@ -2078,22 +2078,37 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, } ALOGV("createAudioPatch() num sources %d num sinks %d", patch->num_sources, patch->num_sinks); if (patch->num_sources > 1 || patch->num_sinks > 1) { if (patch->num_sources == 0 || patch->num_sources > AUDIO_PATCH_PORTS_MAX || patch->num_sinks == 0 || patch->num_sinks > AUDIO_PATCH_PORTS_MAX) { return BAD_VALUE; } // only one source per audio patch supported for now if (patch->num_sources > 1) { return INVALID_OPERATION; } if (patch->sources[0].role != AUDIO_PORT_ROLE_SOURCE) { return INVALID_OPERATION; } if (patch->sources[0].role != AUDIO_PORT_ROLE_SOURCE || patch->sinks[0].role != AUDIO_PORT_ROLE_SINK) { for (size_t i = 0; i < patch->num_sinks; i++) { if (patch->sinks[i].role != AUDIO_PORT_ROLE_SINK) { return INVALID_OPERATION; } } sp<AudioPatch> patchDesc; ssize_t index = mAudioPatches.indexOfKey(*handle); ALOGV("createAudioPatch sink id %d role %d type %d", patch->sinks[0].id, patch->sinks[0].role, patch->sinks[0].type); ALOGV("createAudioPatch source id %d role %d type %d", patch->sources[0].id, patch->sources[0].role, patch->sources[0].type); #if LOG_NDEBUG == 0 for (size_t i = 0; i < patch->num_sinks; i++) { ALOGV("createAudioPatch sink %d: id %d role %d type %d", i, patch->sinks[i].id, patch->sinks[i].role, patch->sinks[i].type); } #endif if (index >= 0) { patchDesc = mAudioPatches.valueAt(index); Loading @@ -2107,12 +2122,6 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, } if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) { // TODO add support for mix to mix connection if (patch->sinks[0].type != AUDIO_PORT_TYPE_DEVICE) { ALOGV("createAudioPatch() source mix sink not device"); return BAD_VALUE; } // output mix to output device connection sp<AudioOutputDescriptor> outputDesc = getOutputFromId(patch->sources[0].id); if (outputDesc == NULL) { ALOGV("createAudioPatch() output not found for id %d", patch->sources[0].id); Loading @@ -2127,10 +2136,18 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, return BAD_VALUE; } } DeviceVector devices; for (size_t i = 0; i < patch->num_sinks; i++) { // Only support mix to devices connection // TODO add support for mix to mix connection if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) { ALOGV("createAudioPatch() source mix but sink is not a device"); return INVALID_OPERATION; } sp<DeviceDescriptor> devDesc = mAvailableOutputDevices.getDeviceFromId(patch->sinks[0].id); mAvailableOutputDevices.getDeviceFromId(patch->sinks[i].id); if (devDesc == 0) { ALOGV("createAudioPatch() out device not found for id %d", patch->sinks[0].id); ALOGV("createAudioPatch() out device not found for id %d", patch->sinks[i].id); return BAD_VALUE; } Loading @@ -2140,17 +2157,20 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, patch->sources[0].format, patch->sources[0].channel_mask, AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) { ALOGV("createAudioPatch() profile not supported"); ALOGV("createAudioPatch() profile not supported for device %08x", devDesc->mDeviceType); return INVALID_OPERATION; } devices.add(devDesc); } if (devices.size() == 0) { return INVALID_OPERATION; } // TODO: reconfigure output format and channels here ALOGV("createAudioPatch() setting device %08x on output %d", devDesc->mDeviceType, outputDesc->mIoHandle); setOutputDevice(outputDesc->mIoHandle, devDesc->mDeviceType, true, 0, handle); devices.types(), outputDesc->mIoHandle); setOutputDevice(outputDesc->mIoHandle, devices.types(), true, 0, handle); index = mAudioPatches.indexOfKey(*handle); if (index >= 0) { if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) { Loading @@ -2166,6 +2186,10 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, } else if (patch->sources[0].type == AUDIO_PORT_TYPE_DEVICE) { if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { // input device to input mix connection // only one sink supported when connecting an input device to a mix if (patch->num_sinks > 1) { return INVALID_OPERATION; } sp<AudioInputDescriptor> inputDesc = getInputFromId(patch->sinks[0].id); if (inputDesc == NULL) { return BAD_VALUE; Loading Loading @@ -2195,10 +2219,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, // TODO: reconfigure output format and channels here ALOGV("createAudioPatch() setting device %08x on output %d", devDesc->mDeviceType, inputDesc->mIoHandle); setInputDevice(inputDesc->mIoHandle, devDesc->mDeviceType, true, handle); setInputDevice(inputDesc->mIoHandle, devDesc->mDeviceType, true, handle); index = mAudioPatches.indexOfKey(*handle); if (index >= 0) { if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) { Loading @@ -2214,28 +2235,42 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, } else if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) { // device to device connection if (patchDesc != 0) { if (patchDesc->mPatch.sources[0].id != patch->sources[0].id && patchDesc->mPatch.sinks[0].id != patch->sinks[0].id) { if (patchDesc->mPatch.sources[0].id != patch->sources[0].id) { return BAD_VALUE; } } sp<DeviceDescriptor> srcDeviceDesc = mAvailableInputDevices.getDeviceFromId(patch->sources[0].id); sp<DeviceDescriptor> sinkDeviceDesc = mAvailableOutputDevices.getDeviceFromId(patch->sinks[0].id); if (srcDeviceDesc == 0 || sinkDeviceDesc == 0) { return BAD_VALUE; } //update source and sink with our own data as the data passed in the patch may // be incomplete. struct audio_patch newPatch = *patch; srcDeviceDesc->toAudioPortConfig(&newPatch.sources[0], &patch->sources[0]); sinkDeviceDesc->toAudioPortConfig(&newPatch.sinks[0], &patch->sinks[0]); if (srcDeviceDesc == 0) { return BAD_VALUE; } for (size_t i = 0; i < patch->num_sinks; i++) { if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) { ALOGV("createAudioPatch() source device but one sink is not a device"); return INVALID_OPERATION; } sp<DeviceDescriptor> sinkDeviceDesc = mAvailableOutputDevices.getDeviceFromId(patch->sinks[i].id); if (sinkDeviceDesc == 0) { return BAD_VALUE; } sinkDeviceDesc->toAudioPortConfig(&newPatch.sinks[i], &patch->sinks[i]); if (srcDeviceDesc->mModule != sinkDeviceDesc->mModule) { // only one sink supported when connected devices across HW modules if (patch->num_sinks > 1) { return INVALID_OPERATION; } SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(sinkDeviceDesc->mDeviceType, mOutputs); 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); Loading @@ -2248,6 +2283,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, newPatch.num_sources = 2; } } } // TODO: check from routing capabilities in config file and other conflicting patches audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE; Loading