diff options
-rw-r--r-- | include/media/AudioPolicyHelper.h | 53 | ||||
-rw-r--r-- | include/media/AudioSystem.h | 15 | ||||
-rw-r--r-- | include/media/AudioTrack.h | 11 | ||||
-rw-r--r-- | include/media/IAudioPolicyService.h | 25 | ||||
-rw-r--r-- | media/libmedia/AudioRecord.cpp | 2 | ||||
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 34 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 202 | ||||
-rw-r--r-- | media/libmedia/IAudioPolicyService.cpp | 113 | ||||
-rw-r--r-- | services/audioflinger/Threads.cpp | 12 | ||||
-rw-r--r-- | services/audioflinger/Tracks.cpp | 2 | ||||
-rw-r--r-- | services/audiopolicy/AudioPolicyInterface.h | 23 | ||||
-rw-r--r-- | services/audiopolicy/AudioPolicyInterfaceImpl.cpp | 41 | ||||
-rw-r--r-- | services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp | 49 | ||||
-rw-r--r-- | services/audiopolicy/AudioPolicyManager.cpp | 116 | ||||
-rw-r--r-- | services/audiopolicy/AudioPolicyManager.h | 25 | ||||
-rw-r--r-- | services/audiopolicy/AudioPolicyService.cpp | 10 | ||||
-rw-r--r-- | services/audiopolicy/AudioPolicyService.h | 41 |
17 files changed, 433 insertions, 341 deletions
diff --git a/include/media/AudioPolicyHelper.h b/include/media/AudioPolicyHelper.h index f4afd45..3ed0b74 100644 --- a/include/media/AudioPolicyHelper.h +++ b/include/media/AudioPolicyHelper.h @@ -18,7 +18,7 @@ #include <system/audio.h> -audio_stream_type_t audio_attributes_to_stream_type(const audio_attributes_t *attr) +static audio_stream_type_t audio_attributes_to_stream_type(const audio_attributes_t *attr) { // flags to stream type mapping if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) { @@ -61,4 +61,55 @@ audio_stream_type_t audio_attributes_to_stream_type(const audio_attributes_t *at } } +static void stream_type_to_audio_attributes(audio_stream_type_t streamType, + audio_attributes_t *attr) { + attr->flags = 0x0; + + switch (streamType) { + case AUDIO_STREAM_DEFAULT: + case AUDIO_STREAM_MUSIC: + attr->content_type = AUDIO_CONTENT_TYPE_MUSIC; + attr->usage = AUDIO_USAGE_MEDIA; + break; + case AUDIO_STREAM_VOICE_CALL: + attr->content_type = AUDIO_CONTENT_TYPE_SPEECH; + attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION; + break; + case AUDIO_STREAM_ENFORCED_AUDIBLE: + attr->flags |= AUDIO_FLAG_AUDIBILITY_ENFORCED; + // intended fall through, attributes in common with STREAM_SYSTEM + case AUDIO_STREAM_SYSTEM: + attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION; + attr->usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION; + break; + case AUDIO_STREAM_RING: + attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION; + attr->usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE; + break; + case AUDIO_STREAM_ALARM: + attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION; + attr->usage = AUDIO_USAGE_ALARM; + break; + case AUDIO_STREAM_NOTIFICATION: + attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION; + attr->usage = AUDIO_USAGE_NOTIFICATION; + break; + case AUDIO_STREAM_BLUETOOTH_SCO: + attr->content_type = AUDIO_CONTENT_TYPE_SPEECH; + attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION; + attr->flags |= AUDIO_FLAG_SCO; + break; + case AUDIO_STREAM_DTMF: + attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION; + attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING; + break; + case AUDIO_STREAM_TTS: + attr->content_type = AUDIO_CONTENT_TYPE_SPEECH; + attr->usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY; + break; + default: + ALOGE("invalid stream type %d when converting to attributes", streamType); + } +} + #endif //AUDIO_POLICY_HELPER_H_ diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 1614525..7f1afb3 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -215,7 +215,10 @@ 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, + static status_t getOutputForAttr(const audio_attributes_t *attr, + audio_io_handle_t *output, + audio_session_t session, + audio_stream_type_t *stream, uint32_t samplingRate = 0, audio_format_t format = AUDIO_FORMAT_DEFAULT, audio_channel_mask_t channelMask = AUDIO_CHANNEL_OUT_STEREO, @@ -223,11 +226,13 @@ public: const audio_offload_info_t *offloadInfo = NULL); static status_t startOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session); + audio_session_t session); static status_t stopOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session); - static void releaseOutput(audio_io_handle_t output); + audio_session_t session); + static void releaseOutput(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t session); // Client must successfully hand off the handle reference to AudioFlinger via openRecord(), // or release it with releaseInput(). @@ -235,7 +240,7 @@ public: uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - int sessionId, + audio_session_t sessionId, audio_input_flags_t); static status_t startInput(audio_io_handle_t input, diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index b5256f0..fd51b8f 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -239,6 +239,9 @@ public: * Parameters not listed in the AudioTrack constructors above: * * threadCanCallJava: Whether callbacks are made from an attached thread and thus can call JNI. + * + * Internal state post condition: + * (mStreamType == AUDIO_STREAM_DEFAULT) implies this AudioTrack has valid attributes */ status_t set(audio_stream_type_t streamType, uint32_t sampleRate, @@ -273,7 +276,7 @@ public: /* getters, see constructors and set() */ - audio_stream_type_t streamType() const { return mStreamType; } + audio_stream_type_t streamType() const; audio_format_t format() const { return mFormat; } /* Return frame size in bytes, which for linear PCM is @@ -598,9 +601,6 @@ protected: AudioTrack& operator = (const AudioTrack& other); void setAttributesFromStreamType(audio_stream_type_t streamType); - void setStreamTypeFromAttributes(audio_attributes_t& aa); - /* paa is guaranteed non-NULL */ - bool isValidAttributes(const audio_attributes_t *paa); /* a small internal class to handle the callback */ class AudioTrackThread : public Thread @@ -688,7 +688,8 @@ protected: // constant after constructor or set() audio_format_t mFormat; // as requested by client, not forced to 16-bit - audio_stream_type_t mStreamType; + audio_stream_type_t mStreamType; // mStreamType == AUDIO_STREAM_DEFAULT implies + // this AudioTrack has valid attributes uint32_t mChannelCount; audio_channel_mask_t mChannelMask; sp<IMemory> mSharedBuffer; diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h index 16fe9cf..2f30304 100644 --- a/include/media/IAudioPolicyService.h +++ b/include/media/IAudioPolicyService.h @@ -56,24 +56,29 @@ 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 getOutputForAttr(const audio_attributes_t *attr, + audio_io_handle_t *output, + audio_session_t session, + audio_stream_type_t *stream, + 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; + audio_session_t session) = 0; virtual status_t stopOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session = 0) = 0; - virtual void releaseOutput(audio_io_handle_t output) = 0; + audio_session_t session) = 0; + virtual void releaseOutput(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t session) = 0; virtual audio_io_handle_t getInput(audio_source_t inputSource, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - int audioSession, + audio_session_t audioSession, audio_input_flags_t flags) = 0; virtual status_t startInput(audio_io_handle_t input, audio_session_t session) = 0; diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 9e7ba88..77437d1 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -445,7 +445,7 @@ status_t AudioRecord::openRecord_l(size_t epoch) } audio_io_handle_t input = AudioSystem::getInput(mInputSource, mSampleRate, mFormat, - mChannelMask, mSessionId, mFlags); + mChannelMask, (audio_session_t)mSessionId, mFlags); if (input == AUDIO_IO_HANDLE_NONE) { ALOGE("Could not get audio input for record source %d, sample rate %u, format %#x, " "channel mask %#x, session %d, flags %#x", diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 1f8e9b6..5f42f25 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -649,22 +649,26 @@ 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) +status_t AudioSystem::getOutputForAttr(const audio_attributes_t *attr, + audio_io_handle_t *output, + audio_session_t session, + 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) { - if (attr == NULL) return 0; const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); - if (aps == 0) return 0; - return aps->getOutputForAttr(attr, samplingRate, format, channelMask, flags, offloadInfo); + if (aps == 0) return NO_INIT; + return aps->getOutputForAttr(attr, output, session, stream, + samplingRate, format, channelMask, + flags, offloadInfo); } status_t AudioSystem::startOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session) + audio_session_t session) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; @@ -673,25 +677,27 @@ status_t AudioSystem::startOutput(audio_io_handle_t output, status_t AudioSystem::stopOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session) + audio_session_t session) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; return aps->stopOutput(output, stream, session); } -void AudioSystem::releaseOutput(audio_io_handle_t output) +void AudioSystem::releaseOutput(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t session) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return; - aps->releaseOutput(output); + aps->releaseOutput(output, stream, session); } audio_io_handle_t AudioSystem::getInput(audio_source_t inputSource, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - int sessionId, + audio_session_t sessionId, audio_input_flags_t flags) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index d6c3bc5..0c69ec2 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -28,6 +28,7 @@ #include <utils/Log.h> #include <private/media/AudioTrackShared.h> #include <media/IAudioFlinger.h> +#include <media/AudioPolicyHelper.h> #include <media/AudioResamplerPublic.h> #define WAIT_PERIOD_MS 10 @@ -278,30 +279,22 @@ status_t AudioTrack::set( } // handle default values first. - // TODO once AudioPolicyManager fully supports audio_attributes_t, - // remove stream "text-to-speech" redirect - if ((streamType == AUDIO_STREAM_DEFAULT) || (streamType == AUDIO_STREAM_TTS)) { + if (streamType == AUDIO_STREAM_DEFAULT) { streamType = AUDIO_STREAM_MUSIC; } - if (pAttributes == NULL) { if (uint32_t(streamType) >= AUDIO_STREAM_PUBLIC_CNT) { ALOGE("Invalid stream type %d", streamType); return BAD_VALUE; } - setAttributesFromStreamType(streamType); mStreamType = streamType; + } else { - if (!isValidAttributes(pAttributes)) { - ALOGE("Invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]", - pAttributes->usage, pAttributes->content_type, pAttributes->flags, - pAttributes->tags); - } // stream type shouldn't be looked at, this track has audio attributes memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t)); - setStreamTypeFromAttributes(mAttributes); ALOGV("Building AudioTrack with attributes: usage=%d content=%d flags=0x%x tags=[%s]", mAttributes.usage, mAttributes.content_type, mAttributes.flags, mAttributes.tags); + mStreamType = AUDIO_STREAM_DEFAULT; } // these below should probably come from the audioFlinger too... @@ -341,10 +334,6 @@ status_t AudioTrack::set( // FIXME why can't we allow direct AND fast? ((flags | AUDIO_OUTPUT_FLAG_DIRECT) & ~AUDIO_OUTPUT_FLAG_FAST); } - // only allow deep buffering for music stream type - if (mStreamType != AUDIO_STREAM_MUSIC) { - flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER); - } if (flags & AUDIO_OUTPUT_FLAG_DIRECT) { if (audio_is_linear_pcm(format)) { @@ -915,24 +904,38 @@ status_t AudioTrack::attachAuxEffect(int effectId) return status; } +audio_stream_type_t AudioTrack::streamType() const +{ + if (mStreamType == AUDIO_STREAM_DEFAULT) { + return audio_attributes_to_stream_type(&mAttributes); + } + return mStreamType; +} + // ------------------------------------------------------------------------- // must be called with mLock held status_t AudioTrack::createTrack_l() { - status_t status; const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); if (audioFlinger == 0) { ALOGE("Could not get audioflinger"); return NO_INIT; } - audio_io_handle_t output = AudioSystem::getOutputForAttr(&mAttributes, mSampleRate, mFormat, - mChannelMask, mFlags, mOffloadInfo); - if (output == AUDIO_IO_HANDLE_NONE) { + audio_io_handle_t output; + audio_stream_type_t streamType = mStreamType; + audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL; + status_t status = AudioSystem::getOutputForAttr(attr, &output, + (audio_session_t)mSessionId, &streamType, + mSampleRate, mFormat, mChannelMask, + mFlags, mOffloadInfo); + + + if (status != NO_ERROR || output == AUDIO_IO_HANDLE_NONE) { 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); + streamType, mAttributes.usage, mSampleRate, mFormat, mChannelMask, mFlags); return BAD_VALUE; } { @@ -1086,7 +1089,7 @@ status_t AudioTrack::createTrack_l() size_t temp = frameCount; // temp may be replaced by a revised value of frameCount, // but we will still need the original value also - sp<IAudioTrack> track = audioFlinger->createTrack(mStreamType, + sp<IAudioTrack> track = audioFlinger->createTrack(streamType, mSampleRate, // AudioFlinger only sees 16-bit PCM mFormat == AUDIO_FORMAT_PCM_8_BIT && @@ -1232,7 +1235,7 @@ status_t AudioTrack::createTrack_l() } release: - AudioSystem::releaseOutput(output); + AudioSystem::releaseOutput(output, streamType, (audio_session_t)mSessionId); if (status == NO_ERROR) { status = NO_INIT; } @@ -2066,161 +2069,6 @@ uint32_t AudioTrack::getUnderrunFrames() const return mProxy->getUnderrunFrames(); } -void AudioTrack::setAttributesFromStreamType(audio_stream_type_t streamType) { - mAttributes.flags = 0x0; - - switch(streamType) { - case AUDIO_STREAM_DEFAULT: - case AUDIO_STREAM_MUSIC: - mAttributes.content_type = AUDIO_CONTENT_TYPE_MUSIC; - mAttributes.usage = AUDIO_USAGE_MEDIA; - break; - case AUDIO_STREAM_VOICE_CALL: - mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH; - mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION; - break; - case AUDIO_STREAM_ENFORCED_AUDIBLE: - mAttributes.flags |= AUDIO_FLAG_AUDIBILITY_ENFORCED; - // intended fall through, attributes in common with STREAM_SYSTEM - case AUDIO_STREAM_SYSTEM: - mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION; - mAttributes.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION; - break; - case AUDIO_STREAM_RING: - mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION; - mAttributes.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE; - break; - case AUDIO_STREAM_ALARM: - mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION; - mAttributes.usage = AUDIO_USAGE_ALARM; - break; - case AUDIO_STREAM_NOTIFICATION: - mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION; - mAttributes.usage = AUDIO_USAGE_NOTIFICATION; - break; - case AUDIO_STREAM_BLUETOOTH_SCO: - mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH; - mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION; - mAttributes.flags |= AUDIO_FLAG_SCO; - break; - case AUDIO_STREAM_DTMF: - mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION; - mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING; - break; - case AUDIO_STREAM_TTS: - mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH; - mAttributes.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY; - break; - default: - ALOGE("invalid stream type %d when converting to attributes", streamType); - } -} - -void AudioTrack::setStreamTypeFromAttributes(audio_attributes_t& aa) { - // flags to stream type mapping - if ((aa.flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) { - mStreamType = AUDIO_STREAM_ENFORCED_AUDIBLE; - return; - } - if ((aa.flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) { - mStreamType = AUDIO_STREAM_BLUETOOTH_SCO; - return; - } - // TODO once AudioPolicyManager fully supports audio_attributes_t, - // remove stream remap, the flag will be enough - if ((aa.flags & AUDIO_FLAG_BEACON) == AUDIO_FLAG_BEACON) { - mStreamType = AUDIO_STREAM_TTS; - return; - } - - // usage to stream type mapping - switch (aa.usage) { - case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: { - // TODO once AudioPolicyManager fully supports audio_attributes_t, - // remove stream change based on stream activity - bool active; - status_t status = AudioSystem::isStreamActive(AUDIO_STREAM_RING, &active, 0); - if (status == NO_ERROR && active == true) { - mStreamType = AUDIO_STREAM_RING; - break; - } - status = AudioSystem::isStreamActive(AUDIO_STREAM_ALARM, &active, 0); - if (status == NO_ERROR && active == true) { - mStreamType = AUDIO_STREAM_ALARM; - break; - } - audio_mode_t phoneState = AudioSystem::getPhoneState(); - if (phoneState == AUDIO_MODE_IN_CALL || phoneState == AUDIO_MODE_IN_COMMUNICATION) { - mStreamType = AUDIO_STREAM_VOICE_CALL; - break; - } - } /// FALL THROUGH - case AUDIO_USAGE_MEDIA: - case AUDIO_USAGE_GAME: - case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: - mStreamType = AUDIO_STREAM_MUSIC; - return; - case AUDIO_USAGE_ASSISTANCE_SONIFICATION: - mStreamType = AUDIO_STREAM_SYSTEM; - return; - case AUDIO_USAGE_VOICE_COMMUNICATION: - mStreamType = AUDIO_STREAM_VOICE_CALL; - return; - - case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: - mStreamType = AUDIO_STREAM_DTMF; - return; - - case AUDIO_USAGE_ALARM: - mStreamType = AUDIO_STREAM_ALARM; - return; - case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: - mStreamType = AUDIO_STREAM_RING; - return; - - 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: - mStreamType = AUDIO_STREAM_NOTIFICATION; - return; - - case AUDIO_USAGE_UNKNOWN: - default: - mStreamType = AUDIO_STREAM_MUSIC; - } -} - -bool AudioTrack::isValidAttributes(const audio_attributes_t *paa) { - // has flags that map to a strategy? - if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO | AUDIO_FLAG_BEACON)) != 0) { - return true; - } - - // has known usage? - switch (paa->usage) { - case AUDIO_USAGE_UNKNOWN: - case AUDIO_USAGE_MEDIA: - case AUDIO_USAGE_VOICE_COMMUNICATION: - case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: - case AUDIO_USAGE_ALARM: - case AUDIO_USAGE_NOTIFICATION: - case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: - case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: - case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: - case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: - case AUDIO_USAGE_NOTIFICATION_EVENT: - case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: - case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: - case AUDIO_USAGE_ASSISTANCE_SONIFICATION: - case AUDIO_USAGE_GAME: - break; - default: - return false; - } - return true; -} // ========================================================================= void AudioTrack::DeathNotifier::binderDied(const wp<IBinder>& who __unused) diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 89178f1..5f83a0d 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -160,21 +160,45 @@ public: return static_cast <audio_io_handle_t> (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) + virtual status_t getOutputForAttr(const audio_attributes_t *attr, + audio_io_handle_t *output, + audio_session_t session, + 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) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); if (attr == NULL) { - ALOGE("Writing NULL audio attributes - shouldn't happen"); - return (audio_io_handle_t) 0; + if (stream == NULL) { + ALOGE("getOutputForAttr(): NULL audio attributes and stream type"); + return BAD_VALUE; + } + if (*stream == AUDIO_STREAM_DEFAULT) { + ALOGE("getOutputForAttr unspecified stream type"); + return BAD_VALUE; + } + } + if (output == NULL) { + ALOGE("getOutputForAttr NULL output - shouldn't happen"); + return BAD_VALUE; + } + if (attr == NULL) { + data.writeInt32(0); + } else { + data.writeInt32(1); + data.write(attr, sizeof(audio_attributes_t)); + } + data.writeInt32(session); + if (stream == NULL) { + data.writeInt32(0); + } else { + data.writeInt32(1); + data.writeInt32(*stream); } - data.write(attr, sizeof(audio_attributes_t)); data.writeInt32(samplingRate); data.writeInt32(static_cast <uint32_t>(format)); data.writeInt32(channelMask); @@ -186,41 +210,56 @@ public: data.writeInt32(1); data.write(offloadInfo, sizeof(audio_offload_info_t)); } - remote()->transact(GET_OUTPUT_FOR_ATTR, data, &reply); - return static_cast <audio_io_handle_t> (reply.readInt32()); + status_t status = remote()->transact(GET_OUTPUT_FOR_ATTR, data, &reply); + if (status != NO_ERROR) { + return status; + } + status = (status_t)reply.readInt32(); + if (status != NO_ERROR) { + return status; + } + *output = (audio_io_handle_t)reply.readInt32(); + if (stream != NULL) { + *stream = (audio_stream_type_t)reply.readInt32(); + } + return status; } virtual status_t startOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session) + audio_session_t session) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.writeInt32(output); data.writeInt32((int32_t) stream); - data.writeInt32(session); + data.writeInt32((int32_t)session); remote()->transact(START_OUTPUT, data, &reply); return static_cast <status_t> (reply.readInt32()); } virtual status_t stopOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session) + audio_session_t session) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.writeInt32(output); data.writeInt32((int32_t) stream); - data.writeInt32(session); + data.writeInt32((int32_t)session); remote()->transact(STOP_OUTPUT, data, &reply); return static_cast <status_t> (reply.readInt32()); } - virtual void releaseOutput(audio_io_handle_t output) + virtual void releaseOutput(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t session) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.writeInt32(output); + data.writeInt32((int32_t)stream); + data.writeInt32((int32_t)session); remote()->transact(RELEASE_OUTPUT, data, &reply); } @@ -229,7 +268,7 @@ public: uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - int audioSession, + audio_session_t audioSession, audio_input_flags_t flags) { Parcel data, reply; @@ -238,7 +277,7 @@ public: data.writeInt32(samplingRate); data.writeInt32(static_cast <uint32_t>(format)); data.writeInt32(channelMask); - data.writeInt32(audioSession); + data.writeInt32((int32_t)audioSession); data.writeInt32(flags); remote()->transact(GET_INPUT, data, &reply); return static_cast <audio_io_handle_t> (reply.readInt32()); @@ -706,7 +745,16 @@ status_t BnAudioPolicyService::onTransact( case GET_OUTPUT_FOR_ATTR: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_attributes_t attr; - data.read(&attr, sizeof(audio_attributes_t)); + bool hasAttributes = data.readInt32() != 0; + if (hasAttributes) { + data.read(&attr, sizeof(audio_attributes_t)); + } + audio_session_t session = (audio_session_t)data.readInt32(); + audio_stream_type_t stream = AUDIO_STREAM_DEFAULT; + bool hasStream = data.readInt32() != 0; + if (hasStream) { + stream = (audio_stream_type_t)data.readInt32(); + } uint32_t samplingRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); audio_channel_mask_t channelMask = data.readInt32(); @@ -717,13 +765,14 @@ status_t BnAudioPolicyService::onTransact( 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 <int>(output)); + audio_io_handle_t output; + status_t status = getOutputForAttr(hasAttributes ? &attr : NULL, + &output, session, &stream, + samplingRate, format, channelMask, + flags, hasOffloadInfo ? &offloadInfo : NULL); + reply->writeInt32(status); + reply->writeInt32(output); + reply->writeInt32(stream); return NO_ERROR; } break; @@ -732,7 +781,7 @@ status_t BnAudioPolicyService::onTransact( audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32()); audio_stream_type_t stream = static_cast <audio_stream_type_t>(data.readInt32()); - int session = data.readInt32(); + audio_session_t session = (audio_session_t)data.readInt32(); reply->writeInt32(static_cast <uint32_t>(startOutput(output, stream, session))); @@ -744,7 +793,7 @@ status_t BnAudioPolicyService::onTransact( audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32()); audio_stream_type_t stream = static_cast <audio_stream_type_t>(data.readInt32()); - int session = data.readInt32(); + audio_session_t session = (audio_session_t)data.readInt32(); reply->writeInt32(static_cast <uint32_t>(stopOutput(output, stream, session))); @@ -754,7 +803,9 @@ status_t BnAudioPolicyService::onTransact( case RELEASE_OUTPUT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32()); - releaseOutput(output); + audio_stream_type_t stream = (audio_stream_type_t)data.readInt32(); + audio_session_t session = (audio_session_t)data.readInt32(); + releaseOutput(output, stream, session); return NO_ERROR; } break; @@ -764,7 +815,7 @@ status_t BnAudioPolicyService::onTransact( uint32_t samplingRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); audio_channel_mask_t channelMask = data.readInt32(); - int audioSession = data.readInt32(); + audio_session_t audioSession = (audio_session_t)data.readInt32(); audio_input_flags_t flags = (audio_input_flags_t) data.readInt32(); audio_io_handle_t input = getInput(inputSource, samplingRate, diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 792419f..08d9eb1 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -1622,13 +1622,15 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) if (track->isExternalTrack()) { TrackBase::track_state state = track->mState; mLock.unlock(); - status = AudioSystem::startOutput(mId, track->streamType(), track->sessionId()); + status = AudioSystem::startOutput(mId, track->streamType(), + (audio_session_t)track->sessionId()); mLock.lock(); // abort track was stopped/paused while we released the lock if (state != track->mState) { if (status == NO_ERROR) { mLock.unlock(); - AudioSystem::stopOutput(mId, track->streamType(), track->sessionId()); + AudioSystem::stopOutput(mId, track->streamType(), + (audio_session_t)track->sessionId()); mLock.lock(); } return INVALID_OPERATION; @@ -2057,13 +2059,15 @@ void AudioFlinger::PlaybackThread::threadLoop_removeTracks( for (size_t i = 0 ; i < count ; i++) { const sp<Track>& track = tracksToRemove.itemAt(i); if (track->isExternalTrack()) { - AudioSystem::stopOutput(mId, track->streamType(), track->sessionId()); + AudioSystem::stopOutput(mId, track->streamType(), + (audio_session_t)track->sessionId()); #ifdef ADD_BATTERY_DATA // to track the speaker usage addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop); #endif if (track->isTerminated()) { - AudioSystem::releaseOutput(mId); + AudioSystem::releaseOutput(mId, track->streamType(), + (audio_session_t)track->sessionId()); } } } diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index aa708ec..fcbf8f8 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -491,7 +491,7 @@ void AudioFlinger::PlaybackThread::Track::destroy() wasActive = playbackThread->destroyTrack_l(this); } if (isExternalTrack() && !wasActive) { - AudioSystem::releaseOutput(mThreadIoHandle); + AudioSystem::releaseOutput(mThreadIoHandle, mStreamType, (audio_session_t)mSessionId); } } } diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h index 5524463..f7ffb6d 100644 --- a/services/audiopolicy/AudioPolicyInterface.h +++ b/services/audiopolicy/AudioPolicyInterface.h @@ -90,22 +90,27 @@ 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; + virtual status_t getOutputForAttr(const audio_attributes_t *attr, + audio_io_handle_t *output, + audio_session_t session, + 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) = 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, - int session = 0) = 0; + audio_session_t session) = 0; // indicates to the audio policy manager that the output stops being used by corresponding stream. virtual status_t stopOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session = 0) = 0; + audio_session_t session) = 0; // releases the output. - virtual void releaseOutput(audio_io_handle_t output) = 0; + virtual void releaseOutput(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t session) = 0; // request an input appropriate for record from the supplied device with supplied parameters. virtual audio_io_handle_t getInput(audio_source_t inputSource, diff --git a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp index 710a905..8b64d5b 100644 --- a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp @@ -141,25 +141,28 @@ 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) +status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr, + audio_io_handle_t *output, + audio_session_t session, + 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) { if (mAudioPolicyManager == NULL) { - return 0; + return NO_INIT; } ALOGV("getOutput()"); Mutex::Autolock _l(mLock); - return mAudioPolicyManager->getOutputForAttr(attr, samplingRate, + return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, samplingRate, format, channelMask, flags, offloadInfo); } status_t AudioPolicyService::startOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session) + audio_session_t session) { if (uint32_t(stream) >= AUDIO_STREAM_CNT) { return BAD_VALUE; @@ -186,7 +189,7 @@ status_t AudioPolicyService::startOutput(audio_io_handle_t output, status_t AudioPolicyService::stopOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session) + audio_session_t session) { if (uint32_t(stream) >= AUDIO_STREAM_CNT) { return BAD_VALUE; @@ -201,7 +204,7 @@ status_t AudioPolicyService::stopOutput(audio_io_handle_t output, status_t AudioPolicyService::doStopOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session) + audio_session_t session) { ALOGV("doStopOutput from tid %d", gettid()); sp<AudioPolicyEffects>audioPolicyEffects; @@ -220,27 +223,31 @@ status_t AudioPolicyService::doStopOutput(audio_io_handle_t output, return mAudioPolicyManager->stopOutput(output, stream, session); } -void AudioPolicyService::releaseOutput(audio_io_handle_t output) +void AudioPolicyService::releaseOutput(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t session) { if (mAudioPolicyManager == NULL) { return; } ALOGV("releaseOutput()"); - mOutputCommandThread->releaseOutputCommand(output); + mOutputCommandThread->releaseOutputCommand(output, stream, session); } -void AudioPolicyService::doReleaseOutput(audio_io_handle_t output) +void AudioPolicyService::doReleaseOutput(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t session) { ALOGV("doReleaseOutput from tid %d", gettid()); Mutex::Autolock _l(mLock); - mAudioPolicyManager->releaseOutput(output); + mAudioPolicyManager->releaseOutput(output, stream, session); } audio_io_handle_t AudioPolicyService::getInput(audio_source_t inputSource, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - int audioSession, + audio_session_t audioSession, audio_input_flags_t flags) { if (mAudioPolicyManager == NULL) { @@ -263,7 +270,7 @@ audio_io_handle_t AudioPolicyService::getInput(audio_source_t inputSource, // the audio_in_acoustics_t parameter is ignored by get_input() input = mAudioPolicyManager->getInput(inputSource, samplingRate, format, channelMask, - (audio_session_t)audioSession, flags); + audioSession, flags); audioPolicyEffects = mAudioPolicyEffects; } if (input == 0) { diff --git a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp index ac61cb2..694dea3 100644 --- a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp +++ b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp @@ -148,7 +148,7 @@ audio_io_handle_t AudioPolicyService::getOutput(audio_stream_type_t stream, status_t AudioPolicyService::startOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session) + audio_session_t session) { if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) { return BAD_VALUE; @@ -176,7 +176,7 @@ status_t AudioPolicyService::startOutput(audio_io_handle_t output, status_t AudioPolicyService::stopOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session) + audio_session_t session) { if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) { return BAD_VALUE; @@ -191,7 +191,7 @@ status_t AudioPolicyService::stopOutput(audio_io_handle_t output, status_t AudioPolicyService::doStopOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session) + audio_session_t session) { ALOGV("doStopOutput from tid %d", gettid()); // release audio processors from the stream @@ -210,16 +210,20 @@ status_t AudioPolicyService::doStopOutput(audio_io_handle_t output, return mpAudioPolicy->stop_output(mpAudioPolicy, output, stream, session); } -void AudioPolicyService::releaseOutput(audio_io_handle_t output) +void AudioPolicyService::releaseOutput(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t session) { if (mpAudioPolicy == NULL) { return; } ALOGV("releaseOutput()"); - mOutputCommandThread->releaseOutputCommand(output); + mOutputCommandThread->releaseOutputCommand(output, stream, session); } -void AudioPolicyService::doReleaseOutput(audio_io_handle_t output) +void AudioPolicyService::doReleaseOutput(audio_io_handle_t output, + audio_stream_type_t stream __unused, + audio_session_t session __unused) { ALOGV("doReleaseOutput from tid %d", gettid()); Mutex::Autolock _l(mLock); @@ -230,7 +234,7 @@ audio_io_handle_t AudioPolicyService::getInput(audio_source_t inputSource, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - int audioSession, + audio_session_t audioSession, audio_input_flags_t flags __unused) { if (mpAudioPolicy == NULL) { @@ -549,16 +553,29 @@ status_t AudioPolicyService::setAudioPortConfig(const struct audio_port_config * return INVALID_OPERATION; } -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) +status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr, + audio_io_handle_t *output, + audio_session_t session, + 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_stream_type_t stream = audio_attributes_to_stream_type(attr); - - return getOutput(stream, samplingRate, format, channelMask, flags, offloadInfo); + if (attr != NULL) { + *stream = audio_attributes_to_stream_type(attr); + } else { + if (*stream == AUDIO_STREAM_DEFAULT) { + return BAD_VALUE; + } + } + *output = getOutput(*stream, samplingRate, format, channelMask, + flags, offloadInfo); + if (*output == AUDIO_IO_HANDLE_NONE) { + return INVALID_OPERATION; + } + return NO_ERROR; } status_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session __unused, diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp index 1631d6c..8ca0b96 100644 --- a/services/audiopolicy/AudioPolicyManager.cpp +++ b/services/audiopolicy/AudioPolicyManager.cpp @@ -43,6 +43,7 @@ #include <hardware/audio.h> #include <hardware/audio_effect.h> #include <media/AudioParameter.h> +#include <media/AudioPolicyHelper.h> #include <soundtrigger/SoundTrigger.h> #include "AudioPolicyManager.h" #include "audio_policy_conf.h" @@ -841,42 +842,65 @@ audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream, 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; + return getOutputForDevice(device, AUDIO_SESSION_ALLOCATE, + stream, samplingRate,format, channelMask, + flags, offloadInfo); +} + +status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, + audio_io_handle_t *output, + audio_session_t session, + 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_attributes_t attributes; + if (attr != NULL) { + if (!isValidAttributes(attr)) { + ALOGE("getOutputForAttr() invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]", + attr->usage, attr->content_type, attr->flags, + attr->tags); + return BAD_VALUE; + } + attributes = *attr; + } else { + if (*stream < AUDIO_STREAM_MIN || *stream >= AUDIO_STREAM_PUBLIC_CNT) { + ALOGE("getOutputForAttr(): invalid stream type"); + return BAD_VALUE; + } + stream_type_to_audio_attributes(*stream, &attributes); } + ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s flags=%08x", - attr->usage, attr->content_type, attr->tags, attr->flags); + attributes.usage, attributes.content_type, attributes.tags, attributes.flags); // TODO this is where filtering for custom policies (rerouting, dynamic sources) will go - routing_strategy strategy = (routing_strategy) getStrategyForAttr(attr); + routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes); audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); - if ((attr->flags & AUDIO_FLAG_HW_AV_SYNC) != 0) { + if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) { flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC); } ALOGV("getOutputForAttr() device 0x%x, 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); + *stream = streamTypefromAttributesInt(&attributes); + *output = getOutputForDevice(device, session, *stream, + samplingRate, format, channelMask, + flags, offloadInfo); + if (*output == AUDIO_IO_HANDLE_NONE) { + return INVALID_OPERATION; + } + return NO_ERROR; } audio_io_handle_t AudioPolicyManager::getOutputForDevice( audio_devices_t device, + audio_session_t session, audio_stream_type_t stream, uint32_t samplingRate, audio_format_t format, @@ -939,6 +963,10 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice( if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) { flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT); } + // only allow deep buffering for music stream type + if (stream != AUDIO_STREAM_MUSIC) { + flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER); + } sp<IOProfile> profile; @@ -1123,7 +1151,7 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h status_t AudioPolicyManager::startOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session) + audio_session_t session) { ALOGV("startOutput() output %d, stream %d, session %d", output, stream, session); ssize_t index = mOutputs.indexOfKey(output); @@ -1207,7 +1235,7 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output, status_t AudioPolicyManager::stopOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session) + audio_session_t session) { ALOGV("stopOutput() output %d, stream %d, session %d", output, stream, session); ssize_t index = mOutputs.indexOfKey(output); @@ -1265,7 +1293,9 @@ status_t AudioPolicyManager::stopOutput(audio_io_handle_t output, } } -void AudioPolicyManager::releaseOutput(audio_io_handle_t output) +void AudioPolicyManager::releaseOutput(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t session) { ALOGV("releaseOutput() %d", output); ssize_t index = mOutputs.indexOfKey(output); @@ -7494,6 +7524,15 @@ audio_stream_type_t AudioPolicyManager::streamTypefromAttributesInt(const audio_ case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: return AUDIO_STREAM_MUSIC; case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: + if (isStreamActive(AUDIO_STREAM_ALARM)) { + return AUDIO_STREAM_ALARM; + } + if (isStreamActive(AUDIO_STREAM_RING)) { + return AUDIO_STREAM_RING; + } + if (isInCall()) { + return AUDIO_STREAM_VOICE_CALL; + } return AUDIO_STREAM_ACCESSIBILITY; case AUDIO_USAGE_ASSISTANCE_SONIFICATION: return AUDIO_STREAM_SYSTEM; @@ -7520,4 +7559,35 @@ audio_stream_type_t AudioPolicyManager::streamTypefromAttributesInt(const audio_ return AUDIO_STREAM_MUSIC; } } + +bool AudioPolicyManager::isValidAttributes(const audio_attributes_t *paa) { + // has flags that map to a strategy? + if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO | AUDIO_FLAG_BEACON)) != 0) { + return true; + } + + // has known usage? + switch (paa->usage) { + case AUDIO_USAGE_UNKNOWN: + case AUDIO_USAGE_MEDIA: + case AUDIO_USAGE_VOICE_COMMUNICATION: + case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: + case AUDIO_USAGE_ALARM: + case AUDIO_USAGE_NOTIFICATION: + case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: + case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: + case AUDIO_USAGE_NOTIFICATION_EVENT: + case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: + case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: + case AUDIO_USAGE_ASSISTANCE_SONIFICATION: + case AUDIO_USAGE_GAME: + break; + default: + return false; + } + return true; +} + }; // namespace android diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h index 7af6475..6eb2163 100644 --- a/services/audiopolicy/AudioPolicyManager.h +++ b/services/audiopolicy/AudioPolicyManager.h @@ -87,19 +87,24 @@ 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 getOutputForAttr(const audio_attributes_t *attr, + audio_io_handle_t *output, + audio_session_t session, + 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); virtual status_t startOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session = 0); + audio_session_t session); virtual status_t stopOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session = 0); - virtual void releaseOutput(audio_io_handle_t output); + audio_session_t session); + virtual void releaseOutput(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t session); virtual audio_io_handle_t getInput(audio_source_t inputSource, uint32_t samplingRate, audio_format_t format, @@ -862,6 +867,7 @@ private: // internal method to return the output handle for the given device and format audio_io_handle_t getOutputForDevice( audio_devices_t device, + audio_session_t session, audio_stream_type_t stream, uint32_t samplingRate, audio_format_t format, @@ -877,6 +883,7 @@ private: // the mute/unmute happened uint32_t handleEventForBeacon(int event); uint32_t setBeaconMute(bool mute); + bool isValidAttributes(const audio_attributes_t *paa); }; }; diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/AudioPolicyService.cpp index 6a4a669..8a9abc9 100644 --- a/services/audiopolicy/AudioPolicyService.cpp +++ b/services/audiopolicy/AudioPolicyService.cpp @@ -457,7 +457,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() break; } mLock.unlock(); - svc->doReleaseOutput(data->mIO); + svc->doReleaseOutput(data->mIO, data->mStream, data->mSession); mLock.lock(); }break; case CREATE_AUDIO_PATCH: { @@ -654,7 +654,7 @@ status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_io_handle_t output, audio_stream_type_t stream, - int session) + audio_session_t session) { sp<AudioCommand> command = new AudioCommand(); command->mCommand = STOP_OUTPUT; @@ -667,12 +667,16 @@ void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_io_handle_t sendCommand(command); } -void AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handle_t output) +void AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t session) { sp<AudioCommand> command = new AudioCommand(); command->mCommand = RELEASE_OUTPUT; sp<ReleaseOutputData> data = new ReleaseOutputData(); data->mIO = output; + data->mStream = stream; + data->mSession = session; command->mParam = data; ALOGV("AudioCommandThread() adding release output %d", output); sendCommand(command); diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h index f1db309..b8171d6 100644 --- a/services/audiopolicy/AudioPolicyService.h +++ b/services/audiopolicy/AudioPolicyService.h @@ -72,24 +72,29 @@ 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 getOutputForAttr(const audio_attributes_t *attr, + audio_io_handle_t *output, + audio_session_t session, + audio_stream_type_t *stream, + 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); + audio_session_t session); virtual status_t stopOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session = 0); - virtual void releaseOutput(audio_io_handle_t output); + audio_session_t session); + virtual void releaseOutput(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t session); virtual audio_io_handle_t getInput(audio_source_t inputSource, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - int audioSession, + audio_session_t audioSession, audio_input_flags_t flags); virtual status_t startInput(audio_io_handle_t input, audio_session_t session); @@ -181,8 +186,10 @@ public: status_t doStopOutput(audio_io_handle_t output, audio_stream_type_t stream, - int session = 0); - void doReleaseOutput(audio_io_handle_t output); + audio_session_t session); + void doReleaseOutput(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t session); status_t clientCreateAudioPatch(const struct audio_patch *patch, audio_patch_handle_t *handle, @@ -250,8 +257,10 @@ private: status_t voiceVolumeCommand(float volume, int delayMs = 0); void stopOutputCommand(audio_io_handle_t output, audio_stream_type_t stream, - int session); - void releaseOutputCommand(audio_io_handle_t output); + audio_session_t session); + void releaseOutputCommand(audio_io_handle_t output, + audio_stream_type_t stream, + audio_session_t session); status_t sendCommand(sp<AudioCommand>& command, int delayMs = 0); void insertCommand_l(sp<AudioCommand>& command, int delayMs = 0); status_t createAudioPatchCommand(const struct audio_patch *patch, @@ -321,12 +330,14 @@ private: public: audio_io_handle_t mIO; audio_stream_type_t mStream; - int mSession; + audio_session_t mSession; }; class ReleaseOutputData : public AudioCommandData { public: audio_io_handle_t mIO; + audio_stream_type_t mStream; + audio_session_t mSession; }; class CreateAudioPatchData : public AudioCommandData { |