Loading services/audiopolicy/managerdefault/AudioPolicyManager.cpp +94 −98 Original line number Diff line number Diff line Loading @@ -2928,20 +2928,53 @@ bool AudioPolicyManager::releaseOutput(audio_port_handle_t portId) return false; } static AudioPolicyClientInterface::MixType getMixType(audio_devices_t deviceType, bool externallyRouted, const sp<AudioPolicyMix>& mix) { using MixType = AudioPolicyClientInterface::MixType; // If the client chose the route, special perms if (externallyRouted) { if (is_mix_loopback_render(mix->mRouteFlags)) { return MixType::PUBLIC_CAPTURE_PLAYBACK; } return MixType::EXT_POLICY_REROUTE; } switch (deviceType) { case AUDIO_DEVICE_IN_ECHO_REFERENCE: return MixType::CAPTURE; case AUDIO_DEVICE_IN_TELEPHONY_RX: return MixType::TELEPHONY_RX_CAPTURE; case AUDIO_DEVICE_IN_REMOTE_SUBMIX: if (!mix) { return MixType::CAPTURE; } else { ALOG_ASSERT(mix->mMixType == MIX_TYPE_RECORDERS, "Invalid Mix Type"); // when routed due to a policy, no perms (client not in control) // there is an external policy, but this input is attached to a mix of recorders, // meaning it receives audio injected into the framework, so the recorder doesn't // know about it and is therefore considered "legacy" return MixType::NONE; } default: return MixType::NONE; } } base::expected<media::GetInputForAttrResponse, std::variant<binder::Status, AudioConfigBase>> AudioPolicyManager::getInputForAttr(audio_attributes_t attributes, AudioPolicyManager::getInputForAttr(audio_attributes_t attributes_, audio_io_handle_t requestedInput, audio_port_handle_t requestedDeviceId, audio_config_base_t config, audio_input_flags_t flags, const audio_input_flags_t flags, audio_unique_id_t riid, audio_session_t session, const AttributionSourceState& attributionSource) { ALOGV("%s() source %d, sampling rate %d, format %#x, channel mask %#x, session %d, " "flags %#x attributes=%s requested device ID %d", __func__, attributes.source, config.sample_rate, config.format, config.channel_mask, session, flags, toString(attributes).c_str(), requestedDeviceId); __func__, attributes_.source, config.sample_rate, config.format, config.channel_mask, session, flags, toString(attributes_).c_str(), requestedDeviceId); sp<AudioPolicyMix> policyMix; sp<DeviceDescriptor> device; Loading @@ -2953,21 +2986,13 @@ AudioPolicyManager::getInputForAttr(audio_attributes_t attributes, int vdi = 0 /* default device id */; audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; if (attributes.source == AUDIO_SOURCE_DEFAULT) { attributes.source = AUDIO_SOURCE_MIC; if (attributes_.source == AUDIO_SOURCE_DEFAULT) { attributes_.source = AUDIO_SOURCE_MIC; } using PermissionReqs = AudioPolicyClientInterface::PermissionReqs; using MixType = AudioPolicyClientInterface::MixType; PermissionReqs permReq { .source = legacy2aidl_audio_source_t_AudioSource(attributes.source).value(), .mixType = MixType::NONE, // can be modified .virtualDeviceId = 0, // can be modified .isHotword = (flags & (AUDIO_INPUT_FLAG_HW_HOTWORD | AUDIO_INPUT_FLAG_HOTWORD_TAP | AUDIO_INPUT_FLAG_HW_LOOKBACK)) != 0, .isCallRedir = (attributes.flags & AUDIO_FLAG_CALL_REDIRECTION) != 0, }; const auto& attributes = attributes_; bool externallyRouted = false; // Explicit routing? sp<DeviceDescriptor> explicitRoutingDevice = mAvailableInputDevices.getDeviceFromId(requestedDeviceId); Loading @@ -2976,7 +3001,6 @@ AudioPolicyManager::getInputForAttr(audio_attributes_t attributes, // possible if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) == AUDIO_INPUT_FLAG_MMAP_NOIRQ && requestedInput != AUDIO_IO_HANDLE_NONE) { input = requestedInput; ssize_t index = mInputs.indexOfKey(requestedInput); if (index < 0) { return base::unexpected{Status::fromExceptionCode( Loading Loading @@ -3011,22 +3035,9 @@ AudioPolicyManager::getInputForAttr(audio_attributes_t attributes, } } } input = requestedInput; device = inputDesc->getDevice(); ALOGV("%s reusing MMAP input %d for session %d", __FUNCTION__, requestedInput, session); auto permRes = mpClientInterface->checkPermissionForInput(attributionSource, permReq); if (!permRes.has_value()) return base::unexpected {permRes.error()}; if (!permRes.value()) { return base::unexpected{Status::fromExceptionCode( EX_SECURITY, String8::format("%s: %s missing perms for source %d mix %d vdi %d" "hotword? %d callredir? %d", __func__, attributionSource.toString().c_str(), static_cast<int>(permReq.source), static_cast<int>(permReq.mixType), permReq.virtualDeviceId, permReq.isHotword, permReq.isCallRedir))}; } } else { if (attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX && } else if (attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX && extractAddressFromAudioAttributes(attributes).has_value()) { status_t status = mPolicyMixes.getInputMixForAttr(attributes, &policyMix); if (status != NO_ERROR) { Loading @@ -3037,21 +3048,7 @@ AudioPolicyManager::getInputForAttr(audio_attributes_t attributes, device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX, String8(attributes.tags + strlen("addr=")), AUDIO_FORMAT_DEFAULT); if (device == nullptr) { return base::unexpected{Status::fromExceptionCode( EX_ILLEGAL_ARGUMENT, String8::format( "%s could not find in Remote Submix device for source %d, tags %s", __func__, attributes.source, attributes.tags))}; } if (is_mix_loopback_render(policyMix->mRouteFlags)) { permReq.mixType = MixType::PUBLIC_CAPTURE_PLAYBACK; } else { permReq.mixType = MixType::EXT_POLICY_REROUTE; } // TODO is this correct? permReq.virtualDeviceId = policyMix->mVirtualDeviceId; externallyRouted = true; } else { if (explicitRoutingDevice != nullptr) { device = explicitRoutingDevice; Loading @@ -3062,30 +3059,28 @@ AudioPolicyManager::getInputForAttr(audio_attributes_t attributes, ALOGV_IF(device != nullptr, "%s found device type is 0x%X", __FUNCTION__, device->type()); } } if (device == nullptr) { const auto attr = legacy2aidl_audio_attributes_t_AudioAttributes(attributes); return base::unexpected{Status::fromExceptionCode( EX_ILLEGAL_ARGUMENT, String8::format("%s could not find device for source %d", __func__, attributes.source))}; } if (device->type() == AUDIO_DEVICE_IN_ECHO_REFERENCE) { permReq.mixType = MixType::CAPTURE; } else if (policyMix) { ALOG_ASSERT(policyMix->mMixType == MIX_TYPE_RECORDERS, "Invalid Mix Type"); // there is an external policy, but this input is attached to a mix of recorders, // meaning it receives audio injected into the framework, so the recorder doesn't // know about it and is therefore considered "legacy" permReq.mixType = MixType::NONE; permReq.virtualDeviceId = policyMix->mVirtualDeviceId; } else if (audio_is_remote_submix_device(device->type())) { permReq.mixType = MixType::CAPTURE; } else if (device->type() == AUDIO_DEVICE_IN_TELEPHONY_RX) { permReq.mixType = MixType::TELEPHONY_RX_CAPTURE; } else { permReq.mixType = MixType::NONE; } String8::format("%s could not find device for attr %s", __func__, attr.has_value() ? attr->toString().c_str() : ""))}; } const auto mixType = getMixType(device->type(), externallyRouted, policyMix); const AudioPolicyClientInterface::PermissionReqs permReq { .source = legacy2aidl_audio_source_t_AudioSource(attributes.source).value(), .mixType = mixType, .virtualDeviceId = (mixType == AudioPolicyClientInterface::MixType::NONE && policyMix != nullptr) ? policyMix->mVirtualDeviceId : 0, .isHotword = (flags & (AUDIO_INPUT_FLAG_HW_HOTWORD | AUDIO_INPUT_FLAG_HOTWORD_TAP | AUDIO_INPUT_FLAG_HW_LOOKBACK)) != 0, .isCallRedir = (attributes.flags & AUDIO_FLAG_CALL_REDIRECTION) != 0, }; auto permRes = mpClientInterface->checkPermissionForInput(attributionSource, permReq); if (!permRes.has_value()) return base::unexpected {permRes.error()}; if (!permRes.value()) { Loading @@ -3099,6 +3094,7 @@ AudioPolicyManager::getInputForAttr(audio_attributes_t attributes, permReq.isCallRedir))}; } if (input == AUDIO_IO_HANDLE_NONE) { input = getInputForDevice(device, session, attributes, config, flags, policyMix); if (input == AUDIO_IO_HANDLE_NONE) { AudioProfileVector profiles; Loading Loading
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +94 −98 Original line number Diff line number Diff line Loading @@ -2928,20 +2928,53 @@ bool AudioPolicyManager::releaseOutput(audio_port_handle_t portId) return false; } static AudioPolicyClientInterface::MixType getMixType(audio_devices_t deviceType, bool externallyRouted, const sp<AudioPolicyMix>& mix) { using MixType = AudioPolicyClientInterface::MixType; // If the client chose the route, special perms if (externallyRouted) { if (is_mix_loopback_render(mix->mRouteFlags)) { return MixType::PUBLIC_CAPTURE_PLAYBACK; } return MixType::EXT_POLICY_REROUTE; } switch (deviceType) { case AUDIO_DEVICE_IN_ECHO_REFERENCE: return MixType::CAPTURE; case AUDIO_DEVICE_IN_TELEPHONY_RX: return MixType::TELEPHONY_RX_CAPTURE; case AUDIO_DEVICE_IN_REMOTE_SUBMIX: if (!mix) { return MixType::CAPTURE; } else { ALOG_ASSERT(mix->mMixType == MIX_TYPE_RECORDERS, "Invalid Mix Type"); // when routed due to a policy, no perms (client not in control) // there is an external policy, but this input is attached to a mix of recorders, // meaning it receives audio injected into the framework, so the recorder doesn't // know about it and is therefore considered "legacy" return MixType::NONE; } default: return MixType::NONE; } } base::expected<media::GetInputForAttrResponse, std::variant<binder::Status, AudioConfigBase>> AudioPolicyManager::getInputForAttr(audio_attributes_t attributes, AudioPolicyManager::getInputForAttr(audio_attributes_t attributes_, audio_io_handle_t requestedInput, audio_port_handle_t requestedDeviceId, audio_config_base_t config, audio_input_flags_t flags, const audio_input_flags_t flags, audio_unique_id_t riid, audio_session_t session, const AttributionSourceState& attributionSource) { ALOGV("%s() source %d, sampling rate %d, format %#x, channel mask %#x, session %d, " "flags %#x attributes=%s requested device ID %d", __func__, attributes.source, config.sample_rate, config.format, config.channel_mask, session, flags, toString(attributes).c_str(), requestedDeviceId); __func__, attributes_.source, config.sample_rate, config.format, config.channel_mask, session, flags, toString(attributes_).c_str(), requestedDeviceId); sp<AudioPolicyMix> policyMix; sp<DeviceDescriptor> device; Loading @@ -2953,21 +2986,13 @@ AudioPolicyManager::getInputForAttr(audio_attributes_t attributes, int vdi = 0 /* default device id */; audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; if (attributes.source == AUDIO_SOURCE_DEFAULT) { attributes.source = AUDIO_SOURCE_MIC; if (attributes_.source == AUDIO_SOURCE_DEFAULT) { attributes_.source = AUDIO_SOURCE_MIC; } using PermissionReqs = AudioPolicyClientInterface::PermissionReqs; using MixType = AudioPolicyClientInterface::MixType; PermissionReqs permReq { .source = legacy2aidl_audio_source_t_AudioSource(attributes.source).value(), .mixType = MixType::NONE, // can be modified .virtualDeviceId = 0, // can be modified .isHotword = (flags & (AUDIO_INPUT_FLAG_HW_HOTWORD | AUDIO_INPUT_FLAG_HOTWORD_TAP | AUDIO_INPUT_FLAG_HW_LOOKBACK)) != 0, .isCallRedir = (attributes.flags & AUDIO_FLAG_CALL_REDIRECTION) != 0, }; const auto& attributes = attributes_; bool externallyRouted = false; // Explicit routing? sp<DeviceDescriptor> explicitRoutingDevice = mAvailableInputDevices.getDeviceFromId(requestedDeviceId); Loading @@ -2976,7 +3001,6 @@ AudioPolicyManager::getInputForAttr(audio_attributes_t attributes, // possible if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) == AUDIO_INPUT_FLAG_MMAP_NOIRQ && requestedInput != AUDIO_IO_HANDLE_NONE) { input = requestedInput; ssize_t index = mInputs.indexOfKey(requestedInput); if (index < 0) { return base::unexpected{Status::fromExceptionCode( Loading Loading @@ -3011,22 +3035,9 @@ AudioPolicyManager::getInputForAttr(audio_attributes_t attributes, } } } input = requestedInput; device = inputDesc->getDevice(); ALOGV("%s reusing MMAP input %d for session %d", __FUNCTION__, requestedInput, session); auto permRes = mpClientInterface->checkPermissionForInput(attributionSource, permReq); if (!permRes.has_value()) return base::unexpected {permRes.error()}; if (!permRes.value()) { return base::unexpected{Status::fromExceptionCode( EX_SECURITY, String8::format("%s: %s missing perms for source %d mix %d vdi %d" "hotword? %d callredir? %d", __func__, attributionSource.toString().c_str(), static_cast<int>(permReq.source), static_cast<int>(permReq.mixType), permReq.virtualDeviceId, permReq.isHotword, permReq.isCallRedir))}; } } else { if (attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX && } else if (attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX && extractAddressFromAudioAttributes(attributes).has_value()) { status_t status = mPolicyMixes.getInputMixForAttr(attributes, &policyMix); if (status != NO_ERROR) { Loading @@ -3037,21 +3048,7 @@ AudioPolicyManager::getInputForAttr(audio_attributes_t attributes, device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX, String8(attributes.tags + strlen("addr=")), AUDIO_FORMAT_DEFAULT); if (device == nullptr) { return base::unexpected{Status::fromExceptionCode( EX_ILLEGAL_ARGUMENT, String8::format( "%s could not find in Remote Submix device for source %d, tags %s", __func__, attributes.source, attributes.tags))}; } if (is_mix_loopback_render(policyMix->mRouteFlags)) { permReq.mixType = MixType::PUBLIC_CAPTURE_PLAYBACK; } else { permReq.mixType = MixType::EXT_POLICY_REROUTE; } // TODO is this correct? permReq.virtualDeviceId = policyMix->mVirtualDeviceId; externallyRouted = true; } else { if (explicitRoutingDevice != nullptr) { device = explicitRoutingDevice; Loading @@ -3062,30 +3059,28 @@ AudioPolicyManager::getInputForAttr(audio_attributes_t attributes, ALOGV_IF(device != nullptr, "%s found device type is 0x%X", __FUNCTION__, device->type()); } } if (device == nullptr) { const auto attr = legacy2aidl_audio_attributes_t_AudioAttributes(attributes); return base::unexpected{Status::fromExceptionCode( EX_ILLEGAL_ARGUMENT, String8::format("%s could not find device for source %d", __func__, attributes.source))}; } if (device->type() == AUDIO_DEVICE_IN_ECHO_REFERENCE) { permReq.mixType = MixType::CAPTURE; } else if (policyMix) { ALOG_ASSERT(policyMix->mMixType == MIX_TYPE_RECORDERS, "Invalid Mix Type"); // there is an external policy, but this input is attached to a mix of recorders, // meaning it receives audio injected into the framework, so the recorder doesn't // know about it and is therefore considered "legacy" permReq.mixType = MixType::NONE; permReq.virtualDeviceId = policyMix->mVirtualDeviceId; } else if (audio_is_remote_submix_device(device->type())) { permReq.mixType = MixType::CAPTURE; } else if (device->type() == AUDIO_DEVICE_IN_TELEPHONY_RX) { permReq.mixType = MixType::TELEPHONY_RX_CAPTURE; } else { permReq.mixType = MixType::NONE; } String8::format("%s could not find device for attr %s", __func__, attr.has_value() ? attr->toString().c_str() : ""))}; } const auto mixType = getMixType(device->type(), externallyRouted, policyMix); const AudioPolicyClientInterface::PermissionReqs permReq { .source = legacy2aidl_audio_source_t_AudioSource(attributes.source).value(), .mixType = mixType, .virtualDeviceId = (mixType == AudioPolicyClientInterface::MixType::NONE && policyMix != nullptr) ? policyMix->mVirtualDeviceId : 0, .isHotword = (flags & (AUDIO_INPUT_FLAG_HW_HOTWORD | AUDIO_INPUT_FLAG_HOTWORD_TAP | AUDIO_INPUT_FLAG_HW_LOOKBACK)) != 0, .isCallRedir = (attributes.flags & AUDIO_FLAG_CALL_REDIRECTION) != 0, }; auto permRes = mpClientInterface->checkPermissionForInput(attributionSource, permReq); if (!permRes.has_value()) return base::unexpected {permRes.error()}; if (!permRes.value()) { Loading @@ -3099,6 +3094,7 @@ AudioPolicyManager::getInputForAttr(audio_attributes_t attributes, permReq.isCallRedir))}; } if (input == AUDIO_IO_HANDLE_NONE) { input = getInputForDevice(device, session, attributes, config, flags, policyMix); if (input == AUDIO_IO_HANDLE_NONE) { AudioProfileVector profiles; Loading