Loading media/libaudioclient/aidl/android/media/GetInputForAttrResponse.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ parcelable GetInputForAttrResponse { int selectedDeviceId; /** Interpreted as audio_port_handle_t. */ int portId; /** The virtual device id corresponding to the opened input. */ int virtualDeviceId; /** The suggested config if fails to get an input. **/ AudioConfigBase config; } services/audiopolicy/AudioPolicyInterface.h +22 −11 Original line number Diff line number Diff line Loading @@ -19,15 +19,17 @@ #include <android/media/DeviceConnectedState.h> #include <android/media/TrackInternalMuteInfo.h> #include <android/media/audio/common/AudioConfigBase.h> #include <android/media/audio/common/AudioMMapPolicyInfo.h> #include <android/media/audio/common/AudioMMapPolicyType.h> #include <android/media/GetInputForAttrResponse.h> #include <android/content/AttributionSourceState.h> #include <media/AudioCommonTypes.h> #include <media/AudioContainers.h> #include <media/AudioDeviceTypeAddr.h> #include <media/AudioSystem.h> #include <media/AudioPolicy.h> #include <media/AudioSystem.h> #include <media/DeviceDescriptorBase.h> #include <android/content/AttributionSourceState.h> #include <utils/String8.h> namespace android { Loading Loading @@ -161,18 +163,27 @@ public: // releases the output, return true if the output descriptor is reopened. virtual bool releaseOutput(audio_port_handle_t portId) = 0; // request an input appropriate for record from the supplied device with supplied parameters. virtual status_t getInputForAttr(const audio_attributes_t *attr, audio_io_handle_t *input, // Request an input appropriate for record from the supplied device with supplied parameters. // attr -- attributes for the requested record // requestedInput -- input only for MMAP mode where an input is re-used, otherwise output param // requestedDeviceId, config, flags -- additional params for matching // riid, session, attributionSource -- params which encapsulate client info to associate with // this input // // On most errors, return a Status describing the error in the error object. // However, in cases where an appropriate device cannot be found for a config, the error side of // the unexpected will contain a suggested config. virtual base::expected<media::GetInputForAttrResponse, std::variant<binder::Status, media::audio::common::AudioConfigBase>> 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, audio_unique_id_t riid, audio_session_t session, const AttributionSourceState& attributionSource, audio_config_base_t *config, audio_input_flags_t flags, audio_port_handle_t *selectedDeviceId, input_type_t *inputType, audio_port_handle_t *portId, uint32_t *virtualDeviceId) = 0; input_type_t *inputType /* out param */) = 0; // indicates to the audio policy manager that the input starts being used. virtual status_t startInput(audio_port_handle_t portId) = 0; // indicates to the audio policy manager that the input stops being used. Loading services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp +7 −6 Original line number Diff line number Diff line Loading @@ -286,7 +286,7 @@ bool AudioPolicyManagerFuzzer::getOutputForAttr( bool AudioPolicyManagerFuzzer::getInputForAttr( const audio_attributes_t &attr, audio_unique_id_t riid, audio_port_handle_t *selectedDeviceId, audio_format_t format, audio_channel_mask_t channelMask, int sampleRate, audio_input_flags_t flags, audio_port_handle_t *portId, uint32_t *virtualDeviceId) { audio_input_flags_t flags, audio_port_handle_t *portId, uint32_t*) { audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER; config.sample_rate = sampleRate; Loading @@ -300,11 +300,12 @@ bool AudioPolicyManagerFuzzer::getInputForAttr( AttributionSourceState attributionSource; attributionSource.uid = 0; attributionSource.token = sp<BBinder>::make(); if (mManager->getInputForAttr(&attr, &input, riid, AUDIO_SESSION_NONE, attributionSource, &config, flags, selectedDeviceId, &inputType, portId, virtualDeviceId) != OK) { return false; } if (*portId == AUDIO_PORT_HANDLE_NONE || input == AUDIO_IO_HANDLE_NONE) { const auto inputRes = mManager->getInputForAttr(attr, input, *selectedDeviceId, config, flags, riid, AUDIO_SESSION_NONE, attributionSource, &inputType); if (!inputRes.has_value()) return false; if (inputRes->portId == AUDIO_PORT_HANDLE_NONE || inputRes->input == AUDIO_IO_HANDLE_NONE) { return false; } return true; Loading services/audiopolicy/managerdefault/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ cc_library_shared { // a dependency on it in the device makefile. There will be no build time // conflict with libaudiopolicyenginedefault. "audioclient-types-aidl-cpp", "audiopolicy-aidl-cpp", // Flag support "android.media.audiopolicy-aconfig-cc", "com.android.media.audioserver-aconfig-cc", Loading services/audiopolicy/managerdefault/AudioPolicyManager.cpp +137 −148 Original line number Diff line number Diff line Loading @@ -14,7 +14,6 @@ * limitations under the License. */ #include "utils/Errors.h" #define LOG_TAG "APM_AudioPolicyManager" // Need to keep the log statements even in production builds Loading Loading @@ -46,6 +45,7 @@ #include <android_media_audiopolicy.h> #include <com_android_media_audioserver.h> #include <cutils/bitops.h> #include <error/expected_utils.h> #include <media/AudioParameter.h> #include <policy.h> #include <private/android_filesystem_config.h> Loading @@ -71,6 +71,8 @@ using android::media::audio::common::AudioMMapPolicyInfo; using android::media::audio::common::AudioMMapPolicyType; using android::media::audio::common::AudioPortDeviceExt; using android::media::audio::common::AudioPortExt; using android::media::audio::common::AudioConfigBase; using binder::Status; using com::android::media::audioserver::fix_call_audio_patch; using content::AttributionSourceState; Loading Loading @@ -2925,63 +2927,57 @@ bool AudioPolicyManager::releaseOutput(audio_port_handle_t portId) return false; } status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, audio_io_handle_t *input, base::expected<media::GetInputForAttrResponse, std::variant<binder::Status, AudioConfigBase>> 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, audio_unique_id_t riid, audio_session_t session, const AttributionSourceState& attributionSource, audio_config_base_t *config, audio_input_flags_t flags, audio_port_handle_t *selectedDeviceId, input_type_t *inputType, audio_port_handle_t *portId, uint32_t *virtualDeviceId) input_type_t *inputType) { ALOGV("%s() source %d, sampling rate %d, format %#x, channel mask %#x, session %d, " "flags %#x attributes=%s requested device ID %d", __func__, attr->source, config->sample_rate, config->format, config->channel_mask, session, flags, toString(*attr).c_str(), *selectedDeviceId); __func__, attributes.source, config.sample_rate, config.format, config.channel_mask, session, flags, toString(attributes).c_str(), requestedDeviceId); status_t status = NO_ERROR; audio_attributes_t attributes = *attr; sp<AudioPolicyMix> policyMix; sp<DeviceDescriptor> device; sp<AudioInputDescriptor> inputDesc; sp<AudioInputDescriptor> previousInputDesc; sp<RecordClientDescriptor> clientDesc; audio_port_handle_t requestedDeviceId = *selectedDeviceId; uid_t uid = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_uid_t(attributionSource.uid)); uid_t uid = static_cast<uid_t>(attributionSource.uid); bool isSoundTrigger; int vdi = 0 /* default device id */; audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; // The supplied portId must be AUDIO_PORT_HANDLE_NONE if (*portId != AUDIO_PORT_HANDLE_NONE) { return INVALID_OPERATION; } if (attr->source == AUDIO_SOURCE_DEFAULT) { if (attributes.source == AUDIO_SOURCE_DEFAULT) { attributes.source = AUDIO_SOURCE_MIC; } // Explicit routing? sp<DeviceDescriptor> explicitRoutingDevice = mAvailableInputDevices.getDeviceFromId(*selectedDeviceId); mAvailableInputDevices.getDeviceFromId(requestedDeviceId); // special case for mmap capture: if an input IO handle is specified, we reuse this input if // possible if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) == AUDIO_INPUT_FLAG_MMAP_NOIRQ && *input != AUDIO_IO_HANDLE_NONE) { ssize_t index = mInputs.indexOfKey(*input); requestedInput != AUDIO_IO_HANDLE_NONE) { input = requestedInput; ssize_t index = mInputs.indexOfKey(requestedInput); if (index < 0) { ALOGW("getInputForAttr() unknown MMAP input %d", *input); status = BAD_VALUE; goto error; return base::unexpected{Status::fromExceptionCode( EX_ILLEGAL_ARGUMENT, String8::format("%s unknown MMAP input %d", __func__, requestedInput))}; } sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index); RecordClientVector clients = inputDesc->getClientsForSession(session); if (clients.size() == 0) { ALOGW("getInputForAttr() unknown session %d on input %d", session, *input); status = BAD_VALUE; goto error; return base::unexpected{Status::fromExceptionCode( EX_ILLEGAL_ARGUMENT, String8::format("%s unknown session %d on input %d", __func__, session, requestedInput))}; } // For MMAP mode, the first call to getInputForAttr() is made on behalf of audioflinger. // The second call is for the first active client and sets the UID. Any further call Loading @@ -2997,39 +2993,37 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, continue; } if (uid != client->uid() && !client->isSilenced()) { ALOGW("getInputForAttr() bad uid %d for client %d uid %d", uid, client->portId(), client->uid()); status = INVALID_OPERATION; goto error; return base::unexpected{Status::fromExceptionCode( EX_ILLEGAL_STATE, String8::format("%s bad uid %d for client %d uid %d", __func__, uid, client->portId(), client->uid()))}; } } } *inputType = API_INPUT_LEGACY; device = inputDesc->getDevice(); ALOGV("%s reusing MMAP input %d for session %d", __FUNCTION__, *input, session); goto exit; } *input = AUDIO_IO_HANDLE_NONE; ALOGV("%s reusing MMAP input %d for session %d", __FUNCTION__, requestedInput, session); // TODO perm check } else { *inputType = API_INPUT_INVALID; if (attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX && extractAddressFromAudioAttributes(attributes).has_value()) { status = mPolicyMixes.getInputMixForAttr(attributes, &policyMix); status_t status = mPolicyMixes.getInputMixForAttr(attributes, &policyMix); if (status != NO_ERROR) { ALOGW("%s could not find input mix for attr %s", __func__, toString(attributes).c_str()); goto error; return base::unexpected {aidl_utils::binderStatusFromStatusT(status)}; } device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX, String8(attr->tags + strlen("addr=")), String8(attributes.tags + strlen("addr=")), AUDIO_FORMAT_DEFAULT); if (device == nullptr) { ALOGW("%s could not find in Remote Submix device for source %d, tags %s", __func__, attributes.source, attributes.tags); status = BAD_VALUE; goto error; 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)) { Loading @@ -3037,9 +3031,8 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, } else { *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE; } if (virtualDeviceId) { *virtualDeviceId = policyMix->mVirtualDeviceId; } // TODO is this correct? vdi = policyMix->mVirtualDeviceId; } else { if (explicitRoutingDevice != nullptr) { device = explicitRoutingDevice; Loading @@ -3051,9 +3044,10 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, __FUNCTION__, device->type()); } if (device == nullptr) { ALOGW("getInputForAttr() could not find device for source %d", attributes.source); status = BAD_VALUE; goto error; 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) { *inputType = API_INPUT_MIX_CAPTURE; Loading @@ -3063,10 +3057,7 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, // meaning it receives audio injected into the framework, so the recorder doesn't // know about it and is therefore considered "legacy" *inputType = API_INPUT_LEGACY; if (virtualDeviceId) { *virtualDeviceId = policyMix->mVirtualDeviceId; } vdi = policyMix->mVirtualDeviceId; } else if (audio_is_remote_submix_device(device->type())) { *inputType = API_INPUT_MIX_CAPTURE; } else if (device->type() == AUDIO_DEVICE_IN_TELEPHONY_RX) { Loading @@ -3074,69 +3065,67 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, } else { *inputType = API_INPUT_LEGACY; } } *input = getInputForDevice(device, session, attributes, config, flags, policyMix); if (*input == AUDIO_IO_HANDLE_NONE) { status = INVALID_OPERATION; // TODO perm check input = getInputForDevice(device, session, attributes, config, flags, policyMix); if (input == AUDIO_IO_HANDLE_NONE) { AudioProfileVector profiles; status_t ret = getProfilesForDevices( DeviceVector(device), profiles, flags, true /*isInput*/); if (ret == NO_ERROR && !profiles.empty()) { const auto channels = profiles[0]->getChannels(); if (!channels.empty() && (channels.find(config->channel_mask) == channels.end())) { config->channel_mask = *channels.begin(); if (!channels.empty() && (channels.find(config.channel_mask) == channels.end())) { config.channel_mask = *channels.begin(); } const auto sampleRates = profiles[0]->getSampleRates(); if (!sampleRates.empty() && (sampleRates.find(config->sample_rate) == sampleRates.end())) { config->sample_rate = *sampleRates.begin(); (sampleRates.find(config.sample_rate) == sampleRates.end())) { config.sample_rate = *sampleRates.begin(); } config->format = profiles[0]->getFormat(); config.format = profiles[0]->getFormat(); } goto error; const auto suggestedConfig = VALUE_OR_FATAL( legacy2aidl_audio_config_base_t_AudioConfigBase(config, true /*isInput*/)); return base::unexpected {suggestedConfig}; } if (policyMix != nullptr && virtualDeviceId != nullptr) { *virtualDeviceId = policyMix->mVirtualDeviceId; } exit: *selectedDeviceId = mAvailableInputDevices.contains(device) ? auto selectedDeviceId = mAvailableInputDevices.contains(device) ? device->getId() : AUDIO_PORT_HANDLE_NONE; isSoundTrigger = attributes.source == AUDIO_SOURCE_HOTWORD && mSoundTriggerSessions.indexOfKey(session) >= 0; *portId = PolicyAudioPort::getNextUniqueId(); clientDesc = new RecordClientDescriptor(*portId, riid, uid, session, attributes, *config, const auto allocatedPortId = PolicyAudioPort::getNextUniqueId(); clientDesc = new RecordClientDescriptor(allocatedPortId, riid, uid, session, attributes, config, requestedDeviceId, attributes.source, flags, isSoundTrigger); inputDesc = mInputs.valueFor(*input); inputDesc = mInputs.valueFor(input); // Move (if found) effect for the client session to its input mEffects.moveEffectsForIo(session, *input, &mInputs, mpClientInterface); mEffects.moveEffectsForIo(session, input, &mInputs, mpClientInterface); inputDesc->addClient(clientDesc); ALOGV("getInputForAttr() returns input %d type %d selectedDeviceId %d for port ID %d", *input, *inputType, *selectedDeviceId, *portId); input, *inputType, selectedDeviceId, allocatedPortId); return NO_ERROR; error: return status; auto ret = media::GetInputForAttrResponse {}; ret.input = input; ret.selectedDeviceId = selectedDeviceId; ret.portId = allocatedPortId; ret.virtualDeviceId = vdi; ret.config = legacy2aidl_audio_config_base_t_AudioConfigBase(config, true /*isInput*/).value(); return ret; } audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescriptor>& device, audio_session_t session, const audio_attributes_t& attributes, audio_config_base_t *config, const audio_config_base_t& config, audio_input_flags_t flags, const sp<AudioPolicyMix> &policyMix) { const sp<AudioPolicyMix>& policyMix) { audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; audio_source_t halInputSource = attributes.source; bool isSoundTrigger = false; Loading @@ -3152,7 +3141,7 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescripto halInputSource = AUDIO_SOURCE_VOICE_RECOGNITION; } } else if (attributes.source == AUDIO_SOURCE_VOICE_COMMUNICATION && audio_is_linear_pcm(config->format)) { audio_is_linear_pcm(config.format)) { flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_VOIP_TX); } Loading @@ -3161,10 +3150,10 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescripto } // sampling rate and flags may be updated by getInputProfile uint32_t profileSamplingRate = (config->sample_rate == 0) ? SAMPLE_RATE_HZ_DEFAULT : config->sample_rate; audio_format_t profileFormat = config->format; audio_channel_mask_t profileChannelMask = config->channel_mask; uint32_t profileSamplingRate = (config.sample_rate == 0) ? SAMPLE_RATE_HZ_DEFAULT : config.sample_rate; audio_format_t profileFormat = config.format; audio_channel_mask_t profileChannelMask = config.channel_mask; audio_input_flags_t profileFlags = flags; // find a compatible input profile (not necessarily identical in parameters) sp<IOProfile> profile = getInputProfile( Loading @@ -3174,7 +3163,7 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescripto } // Pick input sampling rate if not specified by client uint32_t samplingRate = config->sample_rate; uint32_t samplingRate = config.sample_rate; if (samplingRate == 0) { samplingRate = profileSamplingRate; } Loading Loading
media/libaudioclient/aidl/android/media/GetInputForAttrResponse.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ parcelable GetInputForAttrResponse { int selectedDeviceId; /** Interpreted as audio_port_handle_t. */ int portId; /** The virtual device id corresponding to the opened input. */ int virtualDeviceId; /** The suggested config if fails to get an input. **/ AudioConfigBase config; }
services/audiopolicy/AudioPolicyInterface.h +22 −11 Original line number Diff line number Diff line Loading @@ -19,15 +19,17 @@ #include <android/media/DeviceConnectedState.h> #include <android/media/TrackInternalMuteInfo.h> #include <android/media/audio/common/AudioConfigBase.h> #include <android/media/audio/common/AudioMMapPolicyInfo.h> #include <android/media/audio/common/AudioMMapPolicyType.h> #include <android/media/GetInputForAttrResponse.h> #include <android/content/AttributionSourceState.h> #include <media/AudioCommonTypes.h> #include <media/AudioContainers.h> #include <media/AudioDeviceTypeAddr.h> #include <media/AudioSystem.h> #include <media/AudioPolicy.h> #include <media/AudioSystem.h> #include <media/DeviceDescriptorBase.h> #include <android/content/AttributionSourceState.h> #include <utils/String8.h> namespace android { Loading Loading @@ -161,18 +163,27 @@ public: // releases the output, return true if the output descriptor is reopened. virtual bool releaseOutput(audio_port_handle_t portId) = 0; // request an input appropriate for record from the supplied device with supplied parameters. virtual status_t getInputForAttr(const audio_attributes_t *attr, audio_io_handle_t *input, // Request an input appropriate for record from the supplied device with supplied parameters. // attr -- attributes for the requested record // requestedInput -- input only for MMAP mode where an input is re-used, otherwise output param // requestedDeviceId, config, flags -- additional params for matching // riid, session, attributionSource -- params which encapsulate client info to associate with // this input // // On most errors, return a Status describing the error in the error object. // However, in cases where an appropriate device cannot be found for a config, the error side of // the unexpected will contain a suggested config. virtual base::expected<media::GetInputForAttrResponse, std::variant<binder::Status, media::audio::common::AudioConfigBase>> 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, audio_unique_id_t riid, audio_session_t session, const AttributionSourceState& attributionSource, audio_config_base_t *config, audio_input_flags_t flags, audio_port_handle_t *selectedDeviceId, input_type_t *inputType, audio_port_handle_t *portId, uint32_t *virtualDeviceId) = 0; input_type_t *inputType /* out param */) = 0; // indicates to the audio policy manager that the input starts being used. virtual status_t startInput(audio_port_handle_t portId) = 0; // indicates to the audio policy manager that the input stops being used. Loading
services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp +7 −6 Original line number Diff line number Diff line Loading @@ -286,7 +286,7 @@ bool AudioPolicyManagerFuzzer::getOutputForAttr( bool AudioPolicyManagerFuzzer::getInputForAttr( const audio_attributes_t &attr, audio_unique_id_t riid, audio_port_handle_t *selectedDeviceId, audio_format_t format, audio_channel_mask_t channelMask, int sampleRate, audio_input_flags_t flags, audio_port_handle_t *portId, uint32_t *virtualDeviceId) { audio_input_flags_t flags, audio_port_handle_t *portId, uint32_t*) { audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER; config.sample_rate = sampleRate; Loading @@ -300,11 +300,12 @@ bool AudioPolicyManagerFuzzer::getInputForAttr( AttributionSourceState attributionSource; attributionSource.uid = 0; attributionSource.token = sp<BBinder>::make(); if (mManager->getInputForAttr(&attr, &input, riid, AUDIO_SESSION_NONE, attributionSource, &config, flags, selectedDeviceId, &inputType, portId, virtualDeviceId) != OK) { return false; } if (*portId == AUDIO_PORT_HANDLE_NONE || input == AUDIO_IO_HANDLE_NONE) { const auto inputRes = mManager->getInputForAttr(attr, input, *selectedDeviceId, config, flags, riid, AUDIO_SESSION_NONE, attributionSource, &inputType); if (!inputRes.has_value()) return false; if (inputRes->portId == AUDIO_PORT_HANDLE_NONE || inputRes->input == AUDIO_IO_HANDLE_NONE) { return false; } return true; Loading
services/audiopolicy/managerdefault/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ cc_library_shared { // a dependency on it in the device makefile. There will be no build time // conflict with libaudiopolicyenginedefault. "audioclient-types-aidl-cpp", "audiopolicy-aidl-cpp", // Flag support "android.media.audiopolicy-aconfig-cc", "com.android.media.audioserver-aconfig-cc", Loading
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +137 −148 Original line number Diff line number Diff line Loading @@ -14,7 +14,6 @@ * limitations under the License. */ #include "utils/Errors.h" #define LOG_TAG "APM_AudioPolicyManager" // Need to keep the log statements even in production builds Loading Loading @@ -46,6 +45,7 @@ #include <android_media_audiopolicy.h> #include <com_android_media_audioserver.h> #include <cutils/bitops.h> #include <error/expected_utils.h> #include <media/AudioParameter.h> #include <policy.h> #include <private/android_filesystem_config.h> Loading @@ -71,6 +71,8 @@ using android::media::audio::common::AudioMMapPolicyInfo; using android::media::audio::common::AudioMMapPolicyType; using android::media::audio::common::AudioPortDeviceExt; using android::media::audio::common::AudioPortExt; using android::media::audio::common::AudioConfigBase; using binder::Status; using com::android::media::audioserver::fix_call_audio_patch; using content::AttributionSourceState; Loading Loading @@ -2925,63 +2927,57 @@ bool AudioPolicyManager::releaseOutput(audio_port_handle_t portId) return false; } status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, audio_io_handle_t *input, base::expected<media::GetInputForAttrResponse, std::variant<binder::Status, AudioConfigBase>> 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, audio_unique_id_t riid, audio_session_t session, const AttributionSourceState& attributionSource, audio_config_base_t *config, audio_input_flags_t flags, audio_port_handle_t *selectedDeviceId, input_type_t *inputType, audio_port_handle_t *portId, uint32_t *virtualDeviceId) input_type_t *inputType) { ALOGV("%s() source %d, sampling rate %d, format %#x, channel mask %#x, session %d, " "flags %#x attributes=%s requested device ID %d", __func__, attr->source, config->sample_rate, config->format, config->channel_mask, session, flags, toString(*attr).c_str(), *selectedDeviceId); __func__, attributes.source, config.sample_rate, config.format, config.channel_mask, session, flags, toString(attributes).c_str(), requestedDeviceId); status_t status = NO_ERROR; audio_attributes_t attributes = *attr; sp<AudioPolicyMix> policyMix; sp<DeviceDescriptor> device; sp<AudioInputDescriptor> inputDesc; sp<AudioInputDescriptor> previousInputDesc; sp<RecordClientDescriptor> clientDesc; audio_port_handle_t requestedDeviceId = *selectedDeviceId; uid_t uid = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_uid_t(attributionSource.uid)); uid_t uid = static_cast<uid_t>(attributionSource.uid); bool isSoundTrigger; int vdi = 0 /* default device id */; audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; // The supplied portId must be AUDIO_PORT_HANDLE_NONE if (*portId != AUDIO_PORT_HANDLE_NONE) { return INVALID_OPERATION; } if (attr->source == AUDIO_SOURCE_DEFAULT) { if (attributes.source == AUDIO_SOURCE_DEFAULT) { attributes.source = AUDIO_SOURCE_MIC; } // Explicit routing? sp<DeviceDescriptor> explicitRoutingDevice = mAvailableInputDevices.getDeviceFromId(*selectedDeviceId); mAvailableInputDevices.getDeviceFromId(requestedDeviceId); // special case for mmap capture: if an input IO handle is specified, we reuse this input if // possible if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) == AUDIO_INPUT_FLAG_MMAP_NOIRQ && *input != AUDIO_IO_HANDLE_NONE) { ssize_t index = mInputs.indexOfKey(*input); requestedInput != AUDIO_IO_HANDLE_NONE) { input = requestedInput; ssize_t index = mInputs.indexOfKey(requestedInput); if (index < 0) { ALOGW("getInputForAttr() unknown MMAP input %d", *input); status = BAD_VALUE; goto error; return base::unexpected{Status::fromExceptionCode( EX_ILLEGAL_ARGUMENT, String8::format("%s unknown MMAP input %d", __func__, requestedInput))}; } sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index); RecordClientVector clients = inputDesc->getClientsForSession(session); if (clients.size() == 0) { ALOGW("getInputForAttr() unknown session %d on input %d", session, *input); status = BAD_VALUE; goto error; return base::unexpected{Status::fromExceptionCode( EX_ILLEGAL_ARGUMENT, String8::format("%s unknown session %d on input %d", __func__, session, requestedInput))}; } // For MMAP mode, the first call to getInputForAttr() is made on behalf of audioflinger. // The second call is for the first active client and sets the UID. Any further call Loading @@ -2997,39 +2993,37 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, continue; } if (uid != client->uid() && !client->isSilenced()) { ALOGW("getInputForAttr() bad uid %d for client %d uid %d", uid, client->portId(), client->uid()); status = INVALID_OPERATION; goto error; return base::unexpected{Status::fromExceptionCode( EX_ILLEGAL_STATE, String8::format("%s bad uid %d for client %d uid %d", __func__, uid, client->portId(), client->uid()))}; } } } *inputType = API_INPUT_LEGACY; device = inputDesc->getDevice(); ALOGV("%s reusing MMAP input %d for session %d", __FUNCTION__, *input, session); goto exit; } *input = AUDIO_IO_HANDLE_NONE; ALOGV("%s reusing MMAP input %d for session %d", __FUNCTION__, requestedInput, session); // TODO perm check } else { *inputType = API_INPUT_INVALID; if (attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX && extractAddressFromAudioAttributes(attributes).has_value()) { status = mPolicyMixes.getInputMixForAttr(attributes, &policyMix); status_t status = mPolicyMixes.getInputMixForAttr(attributes, &policyMix); if (status != NO_ERROR) { ALOGW("%s could not find input mix for attr %s", __func__, toString(attributes).c_str()); goto error; return base::unexpected {aidl_utils::binderStatusFromStatusT(status)}; } device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX, String8(attr->tags + strlen("addr=")), String8(attributes.tags + strlen("addr=")), AUDIO_FORMAT_DEFAULT); if (device == nullptr) { ALOGW("%s could not find in Remote Submix device for source %d, tags %s", __func__, attributes.source, attributes.tags); status = BAD_VALUE; goto error; 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)) { Loading @@ -3037,9 +3031,8 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, } else { *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE; } if (virtualDeviceId) { *virtualDeviceId = policyMix->mVirtualDeviceId; } // TODO is this correct? vdi = policyMix->mVirtualDeviceId; } else { if (explicitRoutingDevice != nullptr) { device = explicitRoutingDevice; Loading @@ -3051,9 +3044,10 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, __FUNCTION__, device->type()); } if (device == nullptr) { ALOGW("getInputForAttr() could not find device for source %d", attributes.source); status = BAD_VALUE; goto error; 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) { *inputType = API_INPUT_MIX_CAPTURE; Loading @@ -3063,10 +3057,7 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, // meaning it receives audio injected into the framework, so the recorder doesn't // know about it and is therefore considered "legacy" *inputType = API_INPUT_LEGACY; if (virtualDeviceId) { *virtualDeviceId = policyMix->mVirtualDeviceId; } vdi = policyMix->mVirtualDeviceId; } else if (audio_is_remote_submix_device(device->type())) { *inputType = API_INPUT_MIX_CAPTURE; } else if (device->type() == AUDIO_DEVICE_IN_TELEPHONY_RX) { Loading @@ -3074,69 +3065,67 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, } else { *inputType = API_INPUT_LEGACY; } } *input = getInputForDevice(device, session, attributes, config, flags, policyMix); if (*input == AUDIO_IO_HANDLE_NONE) { status = INVALID_OPERATION; // TODO perm check input = getInputForDevice(device, session, attributes, config, flags, policyMix); if (input == AUDIO_IO_HANDLE_NONE) { AudioProfileVector profiles; status_t ret = getProfilesForDevices( DeviceVector(device), profiles, flags, true /*isInput*/); if (ret == NO_ERROR && !profiles.empty()) { const auto channels = profiles[0]->getChannels(); if (!channels.empty() && (channels.find(config->channel_mask) == channels.end())) { config->channel_mask = *channels.begin(); if (!channels.empty() && (channels.find(config.channel_mask) == channels.end())) { config.channel_mask = *channels.begin(); } const auto sampleRates = profiles[0]->getSampleRates(); if (!sampleRates.empty() && (sampleRates.find(config->sample_rate) == sampleRates.end())) { config->sample_rate = *sampleRates.begin(); (sampleRates.find(config.sample_rate) == sampleRates.end())) { config.sample_rate = *sampleRates.begin(); } config->format = profiles[0]->getFormat(); config.format = profiles[0]->getFormat(); } goto error; const auto suggestedConfig = VALUE_OR_FATAL( legacy2aidl_audio_config_base_t_AudioConfigBase(config, true /*isInput*/)); return base::unexpected {suggestedConfig}; } if (policyMix != nullptr && virtualDeviceId != nullptr) { *virtualDeviceId = policyMix->mVirtualDeviceId; } exit: *selectedDeviceId = mAvailableInputDevices.contains(device) ? auto selectedDeviceId = mAvailableInputDevices.contains(device) ? device->getId() : AUDIO_PORT_HANDLE_NONE; isSoundTrigger = attributes.source == AUDIO_SOURCE_HOTWORD && mSoundTriggerSessions.indexOfKey(session) >= 0; *portId = PolicyAudioPort::getNextUniqueId(); clientDesc = new RecordClientDescriptor(*portId, riid, uid, session, attributes, *config, const auto allocatedPortId = PolicyAudioPort::getNextUniqueId(); clientDesc = new RecordClientDescriptor(allocatedPortId, riid, uid, session, attributes, config, requestedDeviceId, attributes.source, flags, isSoundTrigger); inputDesc = mInputs.valueFor(*input); inputDesc = mInputs.valueFor(input); // Move (if found) effect for the client session to its input mEffects.moveEffectsForIo(session, *input, &mInputs, mpClientInterface); mEffects.moveEffectsForIo(session, input, &mInputs, mpClientInterface); inputDesc->addClient(clientDesc); ALOGV("getInputForAttr() returns input %d type %d selectedDeviceId %d for port ID %d", *input, *inputType, *selectedDeviceId, *portId); input, *inputType, selectedDeviceId, allocatedPortId); return NO_ERROR; error: return status; auto ret = media::GetInputForAttrResponse {}; ret.input = input; ret.selectedDeviceId = selectedDeviceId; ret.portId = allocatedPortId; ret.virtualDeviceId = vdi; ret.config = legacy2aidl_audio_config_base_t_AudioConfigBase(config, true /*isInput*/).value(); return ret; } audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescriptor>& device, audio_session_t session, const audio_attributes_t& attributes, audio_config_base_t *config, const audio_config_base_t& config, audio_input_flags_t flags, const sp<AudioPolicyMix> &policyMix) { const sp<AudioPolicyMix>& policyMix) { audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; audio_source_t halInputSource = attributes.source; bool isSoundTrigger = false; Loading @@ -3152,7 +3141,7 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescripto halInputSource = AUDIO_SOURCE_VOICE_RECOGNITION; } } else if (attributes.source == AUDIO_SOURCE_VOICE_COMMUNICATION && audio_is_linear_pcm(config->format)) { audio_is_linear_pcm(config.format)) { flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_VOIP_TX); } Loading @@ -3161,10 +3150,10 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescripto } // sampling rate and flags may be updated by getInputProfile uint32_t profileSamplingRate = (config->sample_rate == 0) ? SAMPLE_RATE_HZ_DEFAULT : config->sample_rate; audio_format_t profileFormat = config->format; audio_channel_mask_t profileChannelMask = config->channel_mask; uint32_t profileSamplingRate = (config.sample_rate == 0) ? SAMPLE_RATE_HZ_DEFAULT : config.sample_rate; audio_format_t profileFormat = config.format; audio_channel_mask_t profileChannelMask = config.channel_mask; audio_input_flags_t profileFlags = flags; // find a compatible input profile (not necessarily identical in parameters) sp<IOProfile> profile = getInputProfile( Loading @@ -3174,7 +3163,7 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescripto } // Pick input sampling rate if not specified by client uint32_t samplingRate = config->sample_rate; uint32_t samplingRate = config.sample_rate; if (samplingRate == 0) { samplingRate = profileSamplingRate; } Loading