From 5bd3f38638acab633d181359cc9ec27b80f84d43 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Fri, 13 Jun 2014 16:06:54 -0700 Subject: AudioPolicyManager: return output for audio attributes In AudioPolicyManager, support querying an output or playback strategy for audio attributes, instead of a stream type, In AudioTrack creation, use the output returned for the track's attributes. Change-Id: I0fef05845ba676404775e2e338c10e6a96237268 --- include/media/AudioSystem.h | 9 +- include/media/IAudioPolicyService.h | 6 ++ media/libmedia/AudioSystem.cpp | 26 +++++ media/libmedia/AudioTrack.cpp | 15 ++- media/libmedia/IAudioPolicyService.cpp | 57 +++++++++- services/audiopolicy/AudioPolicyInterface.h | 6 ++ services/audiopolicy/AudioPolicyInterfaceImpl.cpp | 16 +++ services/audiopolicy/AudioPolicyManager.cpp | 124 +++++++++++++++++++++- services/audiopolicy/AudioPolicyManager.h | 19 ++++ services/audiopolicy/AudioPolicyService.h | 6 ++ 10 files changed, 271 insertions(+), 13 deletions(-) diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index a4722cb..c89ceaa 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -99,6 +99,8 @@ public: // to be non-zero if status == NO_ERROR static status_t getOutputSamplingRate(uint32_t* samplingRate, audio_stream_type_t stream); + static status_t getOutputSamplingRateForAttr(uint32_t* samplingRate, + const audio_attributes_t *attr); static status_t getOutputFrameCount(size_t* frameCount, audio_stream_type_t stream); static status_t getOutputLatency(uint32_t* latency, @@ -212,7 +214,12 @@ public: audio_channel_mask_t channelMask = AUDIO_CHANNEL_OUT_STEREO, audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, const audio_offload_info_t *offloadInfo = NULL); - + static audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr, + uint32_t samplingRate = 0, + audio_format_t format = AUDIO_FORMAT_DEFAULT, + audio_channel_mask_t channelMask = AUDIO_CHANNEL_OUT_STEREO, + audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, + const audio_offload_info_t *offloadInfo = NULL); static status_t startOutput(audio_io_handle_t output, audio_stream_type_t stream, int session); diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h index d422aa3..959e4c3 100644 --- a/include/media/IAudioPolicyService.h +++ b/include/media/IAudioPolicyService.h @@ -56,6 +56,12 @@ public: audio_channel_mask_t channelMask = 0, audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, const audio_offload_info_t *offloadInfo = NULL) = 0; + virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr, + uint32_t samplingRate = 0, + audio_format_t format = AUDIO_FORMAT_DEFAULT, + audio_channel_mask_t channelMask = 0, + audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, + const audio_offload_info_t *offloadInfo = NULL) = 0; virtual status_t startOutput(audio_io_handle_t output, audio_stream_type_t stream, int session = 0) = 0; diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 15b32ff..f5e7a78 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -245,6 +245,19 @@ status_t AudioSystem::getOutputSamplingRate(uint32_t* samplingRate, audio_stream return getSamplingRate(output, samplingRate); } +status_t AudioSystem::getOutputSamplingRateForAttr(uint32_t* samplingRate, + const audio_attributes_t *attr) +{ + if (attr == NULL) { + return BAD_VALUE; + } + audio_io_handle_t output = getOutputForAttr(attr); + if (output == 0) { + return PERMISSION_DENIED; + } + return getSamplingRate(output, samplingRate); +} + status_t AudioSystem::getSamplingRate(audio_io_handle_t output, uint32_t* samplingRate) { @@ -633,6 +646,19 @@ audio_io_handle_t AudioSystem::getOutput(audio_stream_type_t stream, return aps->getOutput(stream, samplingRate, format, channelMask, flags, offloadInfo); } +audio_io_handle_t AudioSystem::getOutputForAttr(const audio_attributes_t *attr, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo) +{ + if (attr == NULL) return 0; + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return 0; + return aps->getOutputForAttr(attr, samplingRate, format, channelMask, flags, offloadInfo); +} + status_t AudioSystem::startOutput(audio_io_handle_t output, audio_stream_type_t stream, int session) diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 000185b..77419f0 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -287,8 +287,7 @@ status_t AudioTrack::set( status_t status; if (sampleRate == 0) { - // TODO replace with new APM method with support for audio_attributes_t - status = AudioSystem::getOutputSamplingRate(&sampleRate, mStreamType); + status = AudioSystem::getOutputSamplingRateForAttr(&sampleRate, &mAttributes); if (status != NO_ERROR) { ALOGE("Could not get output sample rate for stream type %d; status %d", mStreamType, status); @@ -641,8 +640,7 @@ status_t AudioTrack::setSampleRate(uint32_t rate) } uint32_t afSamplingRate; - // TODO replace with new APM method with support for audio_attributes_t - if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) { + if (AudioSystem::getOutputSamplingRateForAttr(&afSamplingRate, &mAttributes) != NO_ERROR) { return NO_INIT; } // Resampler implementation limits input sampling rate to 2 x output sampling rate. @@ -889,13 +887,12 @@ status_t AudioTrack::createTrack_l(size_t epoch) return NO_INIT; } - // TODO replace with new APM method with support for audio_attributes_t - audio_io_handle_t output = AudioSystem::getOutput(mStreamType, mSampleRate, mFormat, + audio_io_handle_t output = AudioSystem::getOutputForAttr(&mAttributes, mSampleRate, mFormat, mChannelMask, mFlags, mOffloadInfo); if (output == AUDIO_IO_HANDLE_NONE) { - ALOGE("Could not get audio output for stream type %d, sample rate %u, format %#x, " - "channel mask %#x, flags %#x", - mStreamType, mSampleRate, mFormat, mChannelMask, mFlags); + ALOGE("Could not get audio output for stream type %d, usage %d, sample rate %u, format %#x," + " channel mask %#x, flags %#x", + mStreamType, mAttributes.usage, mSampleRate, mFormat, mChannelMask, mFlags); return BAD_VALUE; } { diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 77d131b..41a9065 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -64,7 +64,8 @@ enum { RELEASE_AUDIO_PATCH, LIST_AUDIO_PATCHES, SET_AUDIO_PORT_CONFIG, - REGISTER_CLIENT + REGISTER_CLIENT, + GET_OUTPUT_FOR_ATTR }; class BpAudioPolicyService : public BpInterface @@ -155,6 +156,36 @@ public: return static_cast (reply.readInt32()); } + virtual audio_io_handle_t getOutputForAttr( + const audio_attributes_t *attr, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + if (attr == NULL) { + ALOGE("Writing NULL audio attributes - shouldn't happen"); + return (audio_io_handle_t) 0; + } + data.write(attr, sizeof(audio_attributes_t)); + data.writeInt32(samplingRate); + data.writeInt32(static_cast (format)); + data.writeInt32(channelMask); + data.writeInt32(static_cast (flags)); + // hasOffloadInfo + if (offloadInfo == NULL) { + data.writeInt32(0); + } else { + data.writeInt32(1); + data.write(offloadInfo, sizeof(audio_offload_info_t)); + } + remote()->transact(GET_OUTPUT_FOR_ATTR, data, &reply); + return static_cast (reply.readInt32()); + } + virtual status_t startOutput(audio_io_handle_t output, audio_stream_type_t stream, int session) @@ -614,6 +645,30 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case GET_OUTPUT_FOR_ATTR: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_attributes_t *attr = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t)); + data.read(attr, sizeof(audio_attributes_t)); + uint32_t samplingRate = data.readInt32(); + audio_format_t format = (audio_format_t) data.readInt32(); + audio_channel_mask_t channelMask = data.readInt32(); + audio_output_flags_t flags = + static_cast (data.readInt32()); + bool hasOffloadInfo = data.readInt32() != 0; + audio_offload_info_t offloadInfo; + if (hasOffloadInfo) { + data.read(&offloadInfo, sizeof(audio_offload_info_t)); + } + audio_io_handle_t output = getOutputForAttr(attr, + samplingRate, + format, + channelMask, + flags, + hasOffloadInfo ? &offloadInfo : NULL); + reply->writeInt32(static_cast (output)); + return NO_ERROR; + } break; + case START_OUTPUT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_io_handle_t output = static_cast (data.readInt32()); diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h index c025a45..33e4397 100644 --- a/services/audiopolicy/AudioPolicyInterface.h +++ b/services/audiopolicy/AudioPolicyInterface.h @@ -90,6 +90,12 @@ public: audio_channel_mask_t channelMask, audio_output_flags_t flags, const audio_offload_info_t *offloadInfo) = 0; + virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo) = 0; // indicates to the audio policy manager that the output starts being used by corresponding stream. virtual status_t startOutput(audio_io_handle_t output, audio_stream_type_t stream, diff --git a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp index 8cc386a..6342d8f 100644 --- a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp @@ -131,6 +131,22 @@ audio_io_handle_t AudioPolicyService::getOutput(audio_stream_type_t stream, format, channelMask, flags, offloadInfo); } +audio_io_handle_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo) +{ + if (mAudioPolicyManager == NULL) { + return 0; + } + ALOGV("getOutput()"); + Mutex::Autolock _l(mLock); + return mAudioPolicyManager->getOutputForAttr(attr, samplingRate, + format, channelMask, flags, offloadInfo); +} + status_t AudioPolicyService::startOutput(audio_io_handle_t output, audio_stream_type_t stream, int session) diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp index d4c9374..70dcb4c 100644 --- a/services/audiopolicy/AudioPolicyManager.cpp +++ b/services/audiopolicy/AudioPolicyManager.cpp @@ -623,13 +623,53 @@ audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream, audio_output_flags_t flags, const audio_offload_info_t *offloadInfo) { - audio_io_handle_t output = 0; - uint32_t latency = 0; + routing_strategy strategy = getStrategy(stream); audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); ALOGV("getOutput() device %d, stream %d, samplingRate %d, format %x, channelMask %x, flags %x", device, stream, samplingRate, format, channelMask, flags); + return getOutputForDevice(device, stream, samplingRate,format, channelMask, flags, + offloadInfo); +} + +audio_io_handle_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo) +{ + if (attr == NULL) { + ALOGE("getOutputForAttr() called with NULL audio attributes"); + return 0; + } + ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s", + attr->usage, attr->content_type, attr->tags); + + // TODO this is where filtering for custom policies (rerouting, dynamic sources) will go + routing_strategy strategy = (routing_strategy) getStrategyForAttr(attr); + audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); + ALOGV("getOutputForAttr() device %d, samplingRate %d, format %x, channelMask %x, flags %x", + device, samplingRate, format, channelMask, flags); + + audio_stream_type_t stream = streamTypefromAttributesInt(attr); + return getOutputForDevice(device, stream, samplingRate, format, channelMask, flags, + offloadInfo); +} + +audio_io_handle_t AudioPolicyManager::getOutputForDevice( + audio_devices_t device, + audio_stream_type_t stream, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo) +{ + audio_io_handle_t output = 0; + uint32_t latency = 0; + #ifdef AUDIO_POLICY_TEST if (mCurOutput != 0) { ALOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channelMask %x, mDirectOutput %d", @@ -3239,6 +3279,44 @@ AudioPolicyManager::routing_strategy AudioPolicyManager::getStrategy( } } +uint32_t AudioPolicyManager::getStrategyForAttr(const audio_attributes_t *attr) { + // flags to strategy mapping + if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) { + return (uint32_t) STRATEGY_ENFORCED_AUDIBLE; + } + + // usage to strategy mapping + switch (attr->usage) { + case AUDIO_USAGE_MEDIA: + case AUDIO_USAGE_GAME: + case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: + case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: + case AUDIO_USAGE_ASSISTANCE_SONIFICATION: + return (uint32_t) STRATEGY_MEDIA; + + case AUDIO_USAGE_VOICE_COMMUNICATION: + return (uint32_t) STRATEGY_PHONE; + + case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: + return (uint32_t) STRATEGY_DTMF; + + case AUDIO_USAGE_ALARM: + case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: + return (uint32_t) STRATEGY_SONIFICATION; + + case AUDIO_USAGE_NOTIFICATION: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: + case AUDIO_USAGE_NOTIFICATION_EVENT: + return (uint32_t) STRATEGY_SONIFICATION_RESPECTFUL; + + case AUDIO_USAGE_UNKNOWN: + default: + return (uint32_t) STRATEGY_MEDIA; + } +} + void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t stream) { switch(stream) { case AUDIO_STREAM_MUSIC: @@ -5916,4 +5994,46 @@ void AudioPolicyManager::defaultAudioPolicyConfig(void) mHwModules.add(module); } +audio_stream_type_t AudioPolicyManager::streamTypefromAttributesInt(const audio_attributes_t *attr) +{ + // flags to stream type mapping + if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) { + return AUDIO_STREAM_ENFORCED_AUDIBLE; + } + if ((attr->flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) { + return AUDIO_STREAM_BLUETOOTH_SCO; + } + + // usage to stream type mapping + switch (attr->usage) { + case AUDIO_USAGE_MEDIA: + case AUDIO_USAGE_GAME: + case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: + case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: + return AUDIO_STREAM_MUSIC; + case AUDIO_USAGE_ASSISTANCE_SONIFICATION: + return AUDIO_STREAM_SYSTEM; + case AUDIO_USAGE_VOICE_COMMUNICATION: + return AUDIO_STREAM_VOICE_CALL; + + case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: + return AUDIO_STREAM_DTMF; + + case AUDIO_USAGE_ALARM: + return AUDIO_STREAM_ALARM; + case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: + return AUDIO_STREAM_RING; + + case AUDIO_USAGE_NOTIFICATION: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: + case AUDIO_USAGE_NOTIFICATION_EVENT: + return AUDIO_STREAM_NOTIFICATION; + + case AUDIO_USAGE_UNKNOWN: + default: + return AUDIO_STREAM_MUSIC; + } +} }; // namespace android diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h index 1abeb6a..c23d994 100644 --- a/services/audiopolicy/AudioPolicyManager.h +++ b/services/audiopolicy/AudioPolicyManager.h @@ -84,6 +84,12 @@ public: audio_channel_mask_t channelMask, audio_output_flags_t flags, const audio_offload_info_t *offloadInfo); + virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo); virtual status_t startOutput(audio_io_handle_t output, audio_stream_type_t stream, int session = 0); @@ -116,6 +122,8 @@ public: // return the strategy corresponding to a given stream type virtual uint32_t getStrategyForStream(audio_stream_type_t stream); + // return the strategy corresponding to the given audio attributes + virtual uint32_t getStrategyForAttr(const audio_attributes_t *attr); // return the enabled output devices for the given stream type virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream); @@ -755,6 +763,17 @@ private: uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; } // converts device address to string sent to audio HAL via setParameters static String8 addressToParameter(audio_devices_t device, const String8 address); + // internal method to return the output handle for the given device and format + audio_io_handle_t getOutputForDevice( + audio_devices_t device, + audio_stream_type_t stream, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + const audio_offload_info_t *offloadInfo); + // internal function to derive a stream type value from audio attributes + audio_stream_type_t streamTypefromAttributesInt(const audio_attributes_t *attr); }; }; diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h index 66d9cad..69673cd 100644 --- a/services/audiopolicy/AudioPolicyService.h +++ b/services/audiopolicy/AudioPolicyService.h @@ -70,6 +70,12 @@ public: audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, const audio_offload_info_t *offloadInfo = NULL); + virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr, + uint32_t samplingRate = 0, + audio_format_t format = AUDIO_FORMAT_DEFAULT, + audio_channel_mask_t channelMask = 0, + audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, + const audio_offload_info_t *offloadInfo = NULL); virtual status_t startOutput(audio_io_handle_t output, audio_stream_type_t stream, int session = 0); -- cgit v1.1