Merge "notify seek complete upon first video output frame" into lmp-mr1-dev
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 @@
}
}
+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/AudioRecord.h b/include/media/AudioRecord.h
index 4edc1bf..f70d981 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -152,6 +152,7 @@
* transferType: How data is transferred from AudioRecord.
* flags: See comments on audio_input_flags_t in <system/audio.h>
* threadCanCallJava: Not present in parameter list, and so is fixed at false.
+ * pAttributes: if not NULL, supersedes inputSource for use case selection
*/
AudioRecord(audio_source_t inputSource,
@@ -164,7 +165,8 @@
uint32_t notificationFrames = 0,
int sessionId = AUDIO_SESSION_ALLOCATE,
transfer_type transferType = TRANSFER_DEFAULT,
- audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE);
+ audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
+ const audio_attributes_t* pAttributes = NULL);
/* Terminates the AudioRecord and unregisters it from AudioFlinger.
* Also destroys all resources associated with the AudioRecord.
@@ -198,7 +200,8 @@
bool threadCanCallJava = false,
int sessionId = AUDIO_SESSION_ALLOCATE,
transfer_type transferType = TRANSFER_DEFAULT,
- audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE);
+ audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
+ const audio_attributes_t* pAttributes = NULL);
/* Result of constructing the AudioRecord. This must be checked for successful initialization
* before using any AudioRecord API (except for set()), because using
@@ -219,7 +222,7 @@
uint32_t channelCount() const { return mChannelCount; }
size_t frameCount() const { return mFrameCount; }
size_t frameSize() const { return mFrameSize; }
- audio_source_t inputSource() const { return mInputSource; }
+ audio_source_t inputSource() const { return mAttributes.source; }
/* After it's created the track is not active. Call start() to
* make it active. If set, the callback will start being called.
@@ -489,7 +492,6 @@
audio_format_t mFormat;
uint32_t mChannelCount;
size_t mFrameSize; // app-level frame size == AudioFlinger frame size
- audio_source_t mInputSource;
uint32_t mLatency; // in ms
audio_channel_mask_t mChannelMask;
audio_input_flags_t mFlags;
@@ -529,6 +531,7 @@
sp<DeathNotifier> mDeathNotifier;
uint32_t mSequence; // incremented for each new IAudioRecord attempt
+ audio_attributes_t mAttributes;
};
}; // namespace android
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 1614525..bf1fc1c 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -215,7 +215,10 @@
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,20 +226,23 @@
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().
- static audio_io_handle_t getInput(audio_source_t inputSource,
+ static status_t getInputForAttr(const audio_attributes_t *attr,
+ audio_io_handle_t *input,
+ audio_session_t session,
uint32_t samplingRate,
audio_format_t format,
audio_channel_mask_t channelMask,
- int sessionId,
- audio_input_flags_t);
+ audio_input_flags_t flags);
static status_t startInput(audio_io_handle_t input,
audio_session_t session);
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 @@
* 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 @@
/* 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 @@
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 @@
// 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..3e4b873 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -56,25 +56,31 @@
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;
- 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_input_flags_t flags) = 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 status_t getInputForAttr(const audio_attributes_t *attr,
+ audio_io_handle_t *input,
+ audio_session_t session,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_input_flags_t flags) = 0;
virtual status_t startInput(audio_io_handle_t input,
audio_session_t session) = 0;
virtual status_t stopInput(audio_io_handle_t input,
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 9e7ba88..d9646d9 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -82,14 +82,16 @@
uint32_t notificationFrames,
int sessionId,
transfer_type transferType,
- audio_input_flags_t flags)
+ audio_input_flags_t flags,
+ const audio_attributes_t* pAttributes)
: mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
mProxy(NULL)
{
mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
- notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags);
+ notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
+ pAttributes);
}
AudioRecord::~AudioRecord()
@@ -126,7 +128,8 @@
bool threadCanCallJava,
int sessionId,
transfer_type transferType,
- audio_input_flags_t flags)
+ audio_input_flags_t flags,
+ const audio_attributes_t* pAttributes)
{
ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
"notificationFrames %u, sessionId %d, transferType %d, flags %#x",
@@ -168,7 +171,15 @@
if (inputSource == AUDIO_SOURCE_DEFAULT) {
inputSource = AUDIO_SOURCE_MIC;
}
- mInputSource = inputSource;
+ if (pAttributes == NULL) {
+ memset(&mAttributes, 0, sizeof(audio_attributes_t));
+ mAttributes.source = inputSource;
+ } else {
+ // stream type shouldn't be looked at, this track has audio attributes
+ memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
+ ALOGV("Building AudioRecord with attributes: source=%d flags=0x%x tags=[%s]",
+ mAttributes.source, mAttributes.flags, mAttributes.tags);
+ }
if (sampleRate == 0) {
ALOGE("Invalid sample rate %u", sampleRate);
@@ -444,12 +455,14 @@
}
}
- audio_io_handle_t input = AudioSystem::getInput(mInputSource, mSampleRate, mFormat,
- mChannelMask, mSessionId, mFlags);
- if (input == AUDIO_IO_HANDLE_NONE) {
+ audio_io_handle_t input;
+ status = AudioSystem::getInputForAttr(&mAttributes, &input, (audio_session_t)mSessionId,
+ mSampleRate, mFormat, mChannelMask, mFlags);
+
+ if (status != NO_ERROR) {
ALOGE("Could not get audio input for record source %d, sample rate %u, format %#x, "
"channel mask %#x, session %d, flags %#x",
- mInputSource, mSampleRate, mFormat, mChannelMask, mSessionId, mFlags);
+ mAttributes.source, mSampleRate, mFormat, mChannelMask, mSessionId, mFlags);
return BAD_VALUE;
}
{
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 1f8e9b6..96f1ade 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -649,22 +649,26 @@
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,30 +677,33 @@
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_input_flags_t flags)
+status_t AudioSystem::getInputForAttr(const audio_attributes_t *attr,
+ audio_io_handle_t *input,
+ audio_session_t session,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_input_flags_t flags)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
- if (aps == 0) return 0;
- return aps->getInput(inputSource, samplingRate, format, channelMask, sessionId, flags);
+ if (aps == 0) return NO_INIT;
+ return aps->getInputForAttr(attr, input, session, samplingRate, format, channelMask, flags);
}
status_t AudioSystem::startInput(audio_io_handle_t input,
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index c11050e..4a6df6d 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 @@
}
// 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_CNT) {
+ 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 @@
// 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)) {
@@ -385,7 +374,11 @@
mReqFrameCount = frameCount;
mNotificationFramesReq = notificationFrames;
mNotificationFramesAct = 0;
- mSessionId = sessionId;
+ if (sessionId == AUDIO_SESSION_ALLOCATE) {
+ mSessionId = AudioSystem::newAudioUniqueId();
+ } else {
+ mSessionId = sessionId;
+ }
int callingpid = IPCThreadState::self()->getCallingPid();
int mypid = getpid();
if (uid == -1 || (callingpid != mypid)) {
@@ -742,8 +735,7 @@
void AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount)
{
- // FIXME If setting a loop also sets position to start of loop, then
- // this is correct. Otherwise it should be removed.
+ // Setting the loop will reset next notification update period (like setPosition).
mNewPosition = updateAndGetPosition_l() + mUpdatePeriod;
mLoopPeriod = loopCount != 0 ? loopEnd - loopStart : 0;
mStaticProxy->setLoop(loopStart, loopEnd, loopCount);
@@ -915,24 +907,38 @@
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 +1092,7 @@
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 +1238,7 @@
}
release:
- AudioSystem::releaseOutput(output);
+ AudioSystem::releaseOutput(output, streamType, (audio_session_t)mSessionId);
if (status == NO_ERROR) {
status = NO_INIT;
}
@@ -2066,161 +2072,6 @@
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/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index 62362da..4a783b3 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -503,7 +503,11 @@
newState.mLoopStart = (uint32_t) loopStart;
newState.mLoopEnd = (uint32_t) loopEnd;
newState.mLoopCount = loopCount;
- mBufferPosition = loopStart;
+ size_t bufferPosition;
+ if (loopCount == 0 || (bufferPosition = getBufferPosition()) >= loopEnd) {
+ bufferPosition = loopStart;
+ }
+ mBufferPosition = bufferPosition; // snapshot buffer position until loop is acknowledged.
(void) mMutator.push(newState);
}
@@ -776,7 +780,9 @@
} else if (state.mLoopCount >= -1) {
if (loopStart < loopEnd && loopEnd <= mFrameCount &&
loopEnd - loopStart >= MIN_LOOP) {
- if (!(loopStart <= position && position < loopEnd)) {
+ // If the current position is greater than the end of the loop
+ // we "wrap" to the loop start. This might cause an audible pop.
+ if (position >= loopEnd) {
mPosition = position = loopStart;
}
if (state.mLoopCount == -1) {
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 89178f1..5873a30 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -41,7 +41,7 @@
START_OUTPUT,
STOP_OUTPUT,
RELEASE_OUTPUT,
- GET_INPUT,
+ GET_INPUT_FOR_ATTR,
START_INPUT,
STOP_INPUT,
RELEASE_INPUT,
@@ -160,21 +160,45 @@
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;
+ }
}
- data.write(attr, sizeof(audio_attributes_t));
+ 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.writeInt32(samplingRate);
data.writeInt32(static_cast <uint32_t>(format));
data.writeInt32(channelMask);
@@ -186,62 +210,93 @@
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);
}
- 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_input_flags_t flags)
+ virtual status_t getInputForAttr(const audio_attributes_t *attr,
+ audio_io_handle_t *input,
+ audio_session_t session,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_input_flags_t flags)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
- data.writeInt32((int32_t) inputSource);
+ if (attr == NULL) {
+ ALOGE("getInputForAttr NULL attr - shouldn't happen");
+ return BAD_VALUE;
+ }
+ if (input == NULL) {
+ ALOGE("getInputForAttr NULL input - shouldn't happen");
+ return BAD_VALUE;
+ }
+ data.write(attr, sizeof(audio_attributes_t));
+ data.writeInt32(session);
data.writeInt32(samplingRate);
data.writeInt32(static_cast <uint32_t>(format));
data.writeInt32(channelMask);
- data.writeInt32(audioSession);
data.writeInt32(flags);
- remote()->transact(GET_INPUT, data, &reply);
- return static_cast <audio_io_handle_t> (reply.readInt32());
+ status_t status = remote()->transact(GET_INPUT_FOR_ATTR, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = reply.readInt32();
+ if (status != NO_ERROR) {
+ return status;
+ }
+ *input = (audio_io_handle_t)reply.readInt32();
+ return NO_ERROR;
}
virtual status_t startInput(audio_io_handle_t input,
@@ -706,7 +761,16 @@
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 +781,14 @@
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 +797,7 @@
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 +809,7 @@
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,25 +819,29 @@
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;
- case GET_INPUT: {
+ case GET_INPUT_FOR_ATTR: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- audio_source_t inputSource = (audio_source_t) data.readInt32();
+ audio_attributes_t attr;
+ data.read(&attr, sizeof(audio_attributes_t));
+ audio_session_t session = (audio_session_t)data.readInt32();
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_input_flags_t flags = (audio_input_flags_t) data.readInt32();
- audio_io_handle_t input = getInput(inputSource,
- samplingRate,
- format,
- channelMask,
- audioSession,
- flags);
- reply->writeInt32(static_cast <int>(input));
+ audio_io_handle_t input;
+ status_t status = getInputForAttr(&attr, &input, session,
+ samplingRate, format, channelMask,
+ flags);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->writeInt32(input);
+ }
return NO_ERROR;
} break;
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 11069e4..e1c8a41 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1326,8 +1326,10 @@
CHECK(msg->senderAwaitsResponse(&replyID));
if (mState == FLUSHED) {
+ setState(STARTED);
mCodec->signalResume();
PostReplyWithError(replyID, OK);
+ break;
} else if (mState != CONFIGURED) {
PostReplyWithError(replyID, INVALID_OPERATION);
break;
diff --git a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
index 4999663..7f99dcd 100644
--- a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
+++ b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
@@ -152,28 +152,28 @@
OMX_PARAM_PORTDEFINITIONTYPE *defParams =
(OMX_PARAM_PORTDEFINITIONTYPE *)params;
- if (defParams->nPortIndex >= mPorts.size()
- || defParams->nSize
- != sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
- return OMX_ErrorUndefined;
+ if (defParams->nPortIndex >= mPorts.size()) {
+ return OMX_ErrorBadPortIndex;
+ }
+ if (defParams->nSize != sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
+ return OMX_ErrorUnsupportedSetting;
}
PortInfo *port =
&mPorts.editItemAt(defParams->nPortIndex);
- if (defParams->nBufferSize != port->mDef.nBufferSize) {
- CHECK_GE(defParams->nBufferSize, port->mDef.nBufferSize);
+ // default behavior is that we only allow buffer size to increase
+ if (defParams->nBufferSize > port->mDef.nBufferSize) {
port->mDef.nBufferSize = defParams->nBufferSize;
}
- if (defParams->nBufferCountActual
- != port->mDef.nBufferCountActual) {
- CHECK_GE(defParams->nBufferCountActual,
- port->mDef.nBufferCountMin);
-
- port->mDef.nBufferCountActual = defParams->nBufferCountActual;
+ if (defParams->nBufferCountActual < port->mDef.nBufferCountMin) {
+ ALOGW("component requires at least %u buffers (%u requested)",
+ port->mDef.nBufferCountMin, defParams->nBufferCountActual);
+ return OMX_ErrorUnsupportedSetting;
}
+ port->mDef.nBufferCountActual = defParams->nBufferCountActual;
return OMX_ErrorNone;
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index ea9d7d3..8acfc07 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -891,6 +891,21 @@
return mMasterMute;
}
+status_t AudioFlinger::checkStreamType(audio_stream_type_t stream) const
+{
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ ALOGW("setStreamVolume() invalid stream %d", stream);
+ return BAD_VALUE;
+ }
+ pid_t caller = IPCThreadState::self()->getCallingPid();
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT && caller != getpid_cached) {
+ ALOGW("setStreamVolume() pid %d cannot use internal stream type %d", caller, stream);
+ return PERMISSION_DENIED;
+ }
+
+ return NO_ERROR;
+}
+
status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
audio_io_handle_t output)
{
@@ -899,10 +914,11 @@
return PERMISSION_DENIED;
}
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
- ALOGE("setStreamVolume() invalid stream %d", stream);
- return BAD_VALUE;
+ status_t status = checkStreamType(stream);
+ if (status != NO_ERROR) {
+ return status;
}
+ ALOG_ASSERT(stream != AUDIO_STREAM_PATCH, "attempt to change AUDIO_STREAM_PATCH volume");
AutoMutex lock(mLock);
PlaybackThread *thread = NULL;
@@ -933,8 +949,13 @@
return PERMISSION_DENIED;
}
- if (uint32_t(stream) >= AUDIO_STREAM_CNT ||
- uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
+ status_t status = checkStreamType(stream);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ ALOG_ASSERT(stream != AUDIO_STREAM_PATCH, "attempt to mute AUDIO_STREAM_PATCH");
+
+ if (uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
ALOGE("setStreamMute() invalid stream %d", stream);
return BAD_VALUE;
}
@@ -949,7 +970,8 @@
float AudioFlinger::streamVolume(audio_stream_type_t stream, audio_io_handle_t output) const
{
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ status_t status = checkStreamType(stream);
+ if (status != NO_ERROR) {
return 0.0f;
}
@@ -970,7 +992,8 @@
bool AudioFlinger::streamMute(audio_stream_type_t stream) const
{
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ status_t status = checkStreamType(stream);
+ if (status != NO_ERROR) {
return true;
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 4fb372d..aa0af1f 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -745,6 +745,8 @@
void closeInputInternal_l(sp<RecordThread> thread);
void setAudioHwSyncForSession_l(PlaybackThread *thread, audio_session_t sessionId);
+ status_t checkStreamType(audio_stream_type_t stream) const;
+
#ifdef TEE_SINK
// all record threads serially share a common tee sink, which is re-created on format change
sp<NBAIO_Sink> mRecordTeeSink;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 0f11b34..08d9eb1 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1224,15 +1224,12 @@
readOutputParameters_l();
- // mStreamTypes[AUDIO_STREAM_CNT] is initialized by stream_type_t default constructor
- // There is no AUDIO_STREAM_MIN, and ++ operator does not compile
+ // ++ operator does not compile
for (audio_stream_type_t stream = AUDIO_STREAM_MIN; stream < AUDIO_STREAM_CNT;
stream = (audio_stream_type_t) (stream + 1)) {
mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream);
mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
}
- // mStreamTypes[AUDIO_STREAM_CNT] exists but isn't explicitly initialized here,
- // because mAudioFlinger doesn't have one to copy from
}
AudioFlinger::PlaybackThread::~PlaybackThread()
@@ -1625,13 +1622,15 @@
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;
@@ -2060,13 +2059,15 @@
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());
}
}
}
@@ -4746,7 +4747,7 @@
frameCount,
IPCThreadState::self()->getCallingUid());
if (outputTrack->cblk() != NULL) {
- thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
+ thread->setStreamVolume(AUDIO_STREAM_PATCH, 1.0f);
mOutputTracks.add(outputTrack);
ALOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
updateWaitTime_l();
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index bb9aa18..119e495 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -727,9 +727,7 @@
void dumpTracks(int fd, const Vector<String16>& args);
SortedVector< sp<Track> > mTracks;
- // mStreamTypes[] uses 1 additional stream type internally for the OutputTrack used by
- // DuplicatingThread
- stream_type_t mStreamTypes[AUDIO_STREAM_CNT + 1];
+ stream_type_t mStreamTypes[AUDIO_STREAM_CNT];
AudioStreamOut *mOutput;
float mMasterVolume;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 037c73b..fcbf8f8 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -491,7 +491,7 @@
wasActive = playbackThread->destroyTrack_l(this);
}
if (isExternalTrack() && !wasActive) {
- AudioSystem::releaseOutput(mThreadIoHandle);
+ AudioSystem::releaseOutput(mThreadIoHandle, mStreamType, (audio_session_t)mSessionId);
}
}
}
@@ -1657,8 +1657,9 @@
audio_channel_mask_t channelMask,
size_t frameCount,
int uid)
- : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount,
- NULL, 0, 0, uid, IAudioFlinger::TRACK_DEFAULT, TYPE_OUTPUT),
+ : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
+ sampleRate, format, channelMask, frameCount,
+ NULL, 0, 0, uid, IAudioFlinger::TRACK_DEFAULT, TYPE_OUTPUT),
mActive(false), mSourceThread(sourceThread), mClientProxy(NULL)
{
@@ -1873,7 +1874,8 @@
size_t frameCount,
void *buffer,
IAudioFlinger::track_flags_t flags)
- : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount,
+ : Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
+ sampleRate, format, channelMask, frameCount,
buffer, 0, 0, getuid(), flags, TYPE_PATCH),
mProxy(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true))
{
diff --git a/services/audiopolicy/AudioPolicyEffects.cpp b/services/audiopolicy/AudioPolicyEffects.cpp
index e7e1b36..4fbe042 100644
--- a/services/audiopolicy/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/AudioPolicyEffects.cpp
@@ -226,6 +226,11 @@
Mutex::Autolock _l(mLock);
// create audio processors according to stream
+ // FIXME: should we have specific post processing settings for internal streams?
+ // default to media for now.
+ if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
+ stream = AUDIO_STREAM_MUSIC;
+ }
ssize_t index = mOutputStreams.indexOfKey(stream);
if (index < 0) {
ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
@@ -335,7 +340,7 @@
return (audio_source_t)i;
}
-const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_CNT+1] = {
+const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1] = {
AUDIO_STREAM_DEFAULT_TAG,
AUDIO_STREAM_VOICE_CALL_TAG,
AUDIO_STREAM_SYSTEM_TAG,
@@ -350,11 +355,11 @@
};
// returns the audio_stream_t enum corresponding to the output stream name or
-// AUDIO_STREAM_CNT is no match found
+// AUDIO_STREAM_PUBLIC_CNT is no match found
audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
{
int i;
- for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_CNT; i++) {
+ for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
ALOGV("streamNameToEnum found stream %s %d", name, i);
break;
@@ -585,7 +590,7 @@
node = node->first_child;
while (node) {
audio_stream_type_t stream = streamNameToEnum(node->name);
- if (stream == AUDIO_STREAM_CNT) {
+ if (stream == AUDIO_STREAM_PUBLIC_CNT) {
ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
node = node->next;
continue;
diff --git a/services/audiopolicy/AudioPolicyEffects.h b/services/audiopolicy/AudioPolicyEffects.h
index 6b0d538..3dec437 100644
--- a/services/audiopolicy/AudioPolicyEffects.h
+++ b/services/audiopolicy/AudioPolicyEffects.h
@@ -151,7 +151,7 @@
static const char * const kInputSourceNames[AUDIO_SOURCE_CNT -1];
static audio_source_t inputSourceNameToEnum(const char *name);
- static const char *kStreamNames[AUDIO_STREAM_CNT+1]; //+1 required as streams start from -1
+ static const char *kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1]; //+1 required as streams start from -1
audio_stream_type_t streamNameToEnum(const char *name);
// Parse audio_effects.conf
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 5524463..5bcbca8 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -90,30 +90,36 @@
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,
- uint32_t samplingRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- audio_session_t session,
- audio_input_flags_t flags) = 0;
+ virtual status_t getInputForAttr(const audio_attributes_t *attr,
+ audio_io_handle_t *input,
+ audio_session_t session,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_input_flags_t flags) = 0;
// indicates to the audio policy manager that the input starts being used.
virtual status_t startInput(audio_io_handle_t input,
audio_session_t session) = 0;
diff --git a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
index c06ca72..abb1b21 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
@@ -129,7 +129,7 @@
audio_output_flags_t flags,
const audio_offload_info_t *offloadInfo)
{
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return AUDIO_IO_HANDLE_NONE;
}
if (mAudioPolicyManager == NULL) {
@@ -141,25 +141,28 @@
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::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::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,63 +223,68 @@
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_input_flags_t flags)
+status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
+ audio_io_handle_t *input,
+ audio_session_t session,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_input_flags_t flags)
{
if (mAudioPolicyManager == NULL) {
- return 0;
+ return NO_INIT;
}
// already checked by client, but double-check in case the client wrapper is bypassed
- if (inputSource >= AUDIO_SOURCE_CNT && inputSource != AUDIO_SOURCE_HOTWORD &&
- inputSource != AUDIO_SOURCE_FM_TUNER) {
- return 0;
+ if (attr->source >= AUDIO_SOURCE_CNT && attr->source != AUDIO_SOURCE_HOTWORD &&
+ attr->source != AUDIO_SOURCE_FM_TUNER) {
+ return BAD_VALUE;
}
- if (((inputSource == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) ||
- ((inputSource == AUDIO_SOURCE_FM_TUNER) && !captureFmTunerAllowed())) {
- return 0;
+ if (((attr->source == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) ||
+ ((attr->source == AUDIO_SOURCE_FM_TUNER) && !captureFmTunerAllowed())) {
+ return BAD_VALUE;
}
- audio_io_handle_t input;
sp<AudioPolicyEffects>audioPolicyEffects;
+ status_t status;
{
Mutex::Autolock _l(mLock);
// the audio_in_acoustics_t parameter is ignored by get_input()
- input = mAudioPolicyManager->getInput(inputSource, samplingRate,
- format, channelMask,
- (audio_session_t)audioSession, flags);
+ status = mAudioPolicyManager->getInputForAttr(attr, input, session,
+ samplingRate, format, channelMask,
+ flags);
audioPolicyEffects = mAudioPolicyEffects;
}
- if (input == 0) {
- return input;
+ if (status != NO_ERROR) {
+ return status;
}
if (audioPolicyEffects != 0) {
// create audio pre processors according to input source
- status_t status = audioPolicyEffects->addInputEffects(input, inputSource, audioSession);
+ status_t status = audioPolicyEffects->addInputEffects(*input, attr->source, session);
if (status != NO_ERROR && status != ALREADY_EXISTS) {
- ALOGW("Failed to add effects on input %d", input);
+ ALOGW("Failed to add effects on input %d", *input);
}
}
- return input;
+ return NO_ERROR;
}
status_t AudioPolicyService::startInput(audio_io_handle_t input,
@@ -332,7 +340,7 @@
if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
@@ -350,7 +358,7 @@
if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
@@ -366,7 +374,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
@@ -377,7 +385,7 @@
uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream)
{
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return 0;
}
if (mAudioPolicyManager == NULL) {
@@ -390,7 +398,7 @@
audio_devices_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stream)
{
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return AUDIO_DEVICE_NONE;
}
if (mAudioPolicyManager == NULL) {
@@ -439,7 +447,7 @@
bool AudioPolicyService::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
{
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return false;
}
if (mAudioPolicyManager == NULL) {
@@ -451,7 +459,7 @@
bool AudioPolicyService::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const
{
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return false;
}
if (mAudioPolicyManager == NULL) {
diff --git a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
index 09476c1..4e42b25 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
@@ -134,7 +134,7 @@
audio_output_flags_t flags,
const audio_offload_info_t *offloadInfo)
{
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return AUDIO_IO_HANDLE_NONE;
}
if (mpAudioPolicy == NULL) {
@@ -148,9 +148,9 @@
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) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return BAD_VALUE;
}
if (mpAudioPolicy == NULL) {
@@ -176,9 +176,9 @@
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) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return BAD_VALUE;
}
if (mpAudioPolicy == NULL) {
@@ -191,7 +191,7 @@
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,64 +210,68 @@
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);
mpAudioPolicy->release_output(mpAudioPolicy, output);
}
-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_input_flags_t flags __unused)
+status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
+ audio_io_handle_t *input,
+ audio_session_t session,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_input_flags_t flags __unused)
{
if (mpAudioPolicy == NULL) {
- return 0;
+ return NO_INIT;
}
// already checked by client, but double-check in case the client wrapper is bypassed
- if (inputSource >= AUDIO_SOURCE_CNT && inputSource != AUDIO_SOURCE_HOTWORD &&
- inputSource != AUDIO_SOURCE_FM_TUNER) {
- return 0;
+ if (attr->source >= AUDIO_SOURCE_CNT && attr->source != AUDIO_SOURCE_HOTWORD &&
+ attr->source != AUDIO_SOURCE_FM_TUNER) {
+ return BAD_VALUE;
}
- if (((inputSource == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) ||
- ((inputSource == AUDIO_SOURCE_FM_TUNER) && !captureFmTunerAllowed())) {
- return 0;
+ if (((attr->source == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) ||
+ ((attr->source == AUDIO_SOURCE_FM_TUNER) && !captureFmTunerAllowed())) {
+ return BAD_VALUE;
}
- audio_io_handle_t input;
sp<AudioPolicyEffects>audioPolicyEffects;
{
Mutex::Autolock _l(mLock);
// the audio_in_acoustics_t parameter is ignored by get_input()
- input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate,
+ *input = mpAudioPolicy->get_input(mpAudioPolicy, attr->source, samplingRate,
format, channelMask, (audio_in_acoustics_t) 0);
audioPolicyEffects = mAudioPolicyEffects;
}
- if (input == 0) {
- return input;
+ if (*input == AUDIO_IO_HANDLE_NONE) {
+ return INVALID_OPERATION;
}
if (audioPolicyEffects != 0) {
// create audio pre processors according to input source
- status_t status = audioPolicyEffects->addInputEffects(input, inputSource, audioSession);
+ status_t status = audioPolicyEffects->addInputEffects(*input, attr->source, session);
if (status != NO_ERROR && status != ALREADY_EXISTS) {
ALOGW("Failed to add effects on input %d", input);
}
}
- return input;
+ return NO_ERROR;
}
status_t AudioPolicyService::startInput(audio_io_handle_t input,
@@ -324,7 +328,7 @@
if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
@@ -342,7 +346,7 @@
if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
@@ -363,7 +367,7 @@
if (mpAudioPolicy == NULL) {
return NO_INIT;
}
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
@@ -379,7 +383,7 @@
uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream)
{
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return 0;
}
if (mpAudioPolicy == NULL) {
@@ -392,7 +396,7 @@
audio_devices_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stream)
{
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return AUDIO_DEVICE_NONE;
}
if (mpAudioPolicy == NULL) {
@@ -441,7 +445,7 @@
bool AudioPolicyService::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
{
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return false;
}
if (mpAudioPolicy == NULL) {
@@ -453,7 +457,7 @@
bool AudioPolicyService::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const
{
- if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return false;
}
if (mpAudioPolicy == NULL) {
@@ -549,26 +553,39 @@
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,
- audio_io_handle_t *ioHandle,
- audio_devices_t *device)
+status_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session __unused,
+ audio_io_handle_t *ioHandle __unused,
+ audio_devices_t *device __unused)
{
return INVALID_OPERATION;
}
-status_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session)
+status_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session __unused)
{
return INVALID_OPERATION;
}
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 20a72b0..b5a3d5b 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"
@@ -584,6 +585,9 @@
if (isInCall()) {
ALOGV("setPhoneState() in call state management: new state is %d", state);
for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
+ if (stream == AUDIO_STREAM_PATCH) {
+ continue;
+ }
handleIncallSonification((audio_stream_type_t)stream, false, true);
}
}
@@ -681,6 +685,9 @@
if (isStateInCall(state)) {
ALOGV("setPhoneState() in call state management: new state is %d", state);
for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
+ if (stream == AUDIO_STREAM_PATCH) {
+ continue;
+ }
handleIncallSonification((audio_stream_type_t)stream, true, true);
}
}
@@ -830,48 +837,70 @@
audio_output_flags_t flags,
const audio_offload_info_t *offloadInfo)
{
-
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);
+ return getOutputForDevice(device, AUDIO_SESSION_ALLOCATE,
+ 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)
+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)
{
- if (attr == NULL) {
- ALOGE("getOutputForAttr() called with NULL audio attributes");
- return 0;
+ 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 __unused,
audio_stream_type_t stream,
uint32_t samplingRate,
audio_format_t format,
@@ -934,6 +963,10 @@
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;
@@ -1118,7 +1151,7 @@
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);
@@ -1202,7 +1235,7 @@
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);
@@ -1260,7 +1293,9 @@
}
}
-void AudioPolicyManager::releaseOutput(audio_io_handle_t output)
+void AudioPolicyManager::releaseOutput(audio_io_handle_t output,
+ audio_stream_type_t stream __unused,
+ audio_session_t session __unused)
{
ALOGV("releaseOutput() %d", output);
ssize_t index = mOutputs.indexOfKey(output);
@@ -1303,26 +1338,27 @@
}
-audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource,
- uint32_t samplingRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- audio_session_t session,
- audio_input_flags_t flags)
+status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
+ audio_io_handle_t *input,
+ audio_session_t session,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_input_flags_t flags)
{
- ALOGV("getInput() inputSource %d, samplingRate %d, format %d, channelMask %x, session %d, "
- "flags %#x",
- inputSource, samplingRate, format, channelMask, session, flags);
+ ALOGV("getInputForAttr() source %d, samplingRate %d, format %d, channelMask %x,"
+ "session %d, flags %#x",
+ attr->source, samplingRate, format, channelMask, session, flags);
- audio_devices_t device = getDeviceForInputSource(inputSource);
+ audio_devices_t device = getDeviceForInputSource(attr->source);
if (device == AUDIO_DEVICE_NONE) {
- ALOGW("getInput() could not find device for inputSource %d", inputSource);
- return AUDIO_IO_HANDLE_NONE;
+ ALOGW("getInputForAttr() could not find device for source %d", attr->source);
+ return BAD_VALUE;
}
// adapt channel selection to input source
- switch (inputSource) {
+ switch (attr->source) {
case AUDIO_SOURCE_VOICE_UPLINK:
channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK;
break;
@@ -1336,16 +1372,16 @@
break;
}
- audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
+ *input = AUDIO_IO_HANDLE_NONE;
bool isSoundTrigger = false;
- audio_source_t halInputSource = inputSource;
- if (inputSource == AUDIO_SOURCE_HOTWORD) {
+ audio_source_t halInputSource = attr->source;
+ if (attr->source == AUDIO_SOURCE_HOTWORD) {
ssize_t index = mSoundTriggerSessions.indexOfKey(session);
if (index >= 0) {
- input = mSoundTriggerSessions.valueFor(session);
+ *input = mSoundTriggerSessions.valueFor(session);
isSoundTrigger = true;
flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_HW_HOTWORD);
- ALOGV("SoundTrigger capture on session %d input %d", session, input);
+ ALOGV("SoundTrigger capture on session %d input %d", session, *input);
} else {
halInputSource = AUDIO_SOURCE_VOICE_RECOGNITION;
}
@@ -1366,16 +1402,16 @@
channelMask,
flags);
if (profile == 0) {
- ALOGW("getInput() could not find profile for device 0x%X, samplingRate %u, format %#x, "
- "channelMask 0x%X, flags %#x",
+ ALOGW("getInputForAttr() could not find profile for device 0x%X, samplingRate %u,"
+ "format %#x, channelMask 0x%X, flags %#x",
device, samplingRate, format, channelMask, log_flags);
- return AUDIO_IO_HANDLE_NONE;
+ return BAD_VALUE;
}
}
if (profile->mModule->mHandle == 0) {
- ALOGE("getInput(): HW module %s not opened", profile->mModule->mName);
- return AUDIO_IO_HANDLE_NONE;
+ ALOGE("getInputForAttr(): HW module %s not opened", profile->mModule->mName);
+ return NO_INIT;
}
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
@@ -1387,7 +1423,7 @@
String8 address = deviceDistinguishesOnAddress(device) ? String8("0") : String8("");
status_t status = mpClientInterface->openInput(profile->mModule->mHandle,
- &input,
+ input,
&config,
&device,
address,
@@ -1395,20 +1431,20 @@
flags);
// only accept input with the exact requested set of parameters
- if (status != NO_ERROR ||
+ if (status != NO_ERROR || *input == AUDIO_IO_HANDLE_NONE ||
(samplingRate != config.sample_rate) ||
(format != config.format) ||
(channelMask != config.channel_mask)) {
- ALOGW("getInput() failed opening input: samplingRate %d, format %d, channelMask %x",
+ ALOGW("getInputForAttr() failed opening input: samplingRate %d, format %d, channelMask %x",
samplingRate, format, channelMask);
- if (input != AUDIO_IO_HANDLE_NONE) {
- mpClientInterface->closeInput(input);
+ if (*input != AUDIO_IO_HANDLE_NONE) {
+ mpClientInterface->closeInput(*input);
}
- return AUDIO_IO_HANDLE_NONE;
+ return BAD_VALUE;
}
sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(profile);
- inputDesc->mInputSource = inputSource;
+ inputDesc->mInputSource = attr->source;
inputDesc->mRefCount = 0;
inputDesc->mOpenRefCount = 1;
inputDesc->mSamplingRate = samplingRate;
@@ -1418,9 +1454,9 @@
inputDesc->mSessions.add(session);
inputDesc->mIsSoundTrigger = isSoundTrigger;
- addInput(input, inputDesc);
+ addInput(*input, inputDesc);
mpClientInterface->onAudioPortListUpdate();
- return input;
+ return NO_ERROR;
}
status_t AudioPolicyManager::startInput(audio_io_handle_t input,
@@ -1587,6 +1623,11 @@
}
mStreams[stream].mIndexMin = indexMin;
mStreams[stream].mIndexMax = indexMax;
+ //FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now
+ if (stream == AUDIO_STREAM_MUSIC) {
+ mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexMin = indexMin;
+ mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexMax = indexMax;
+ }
}
status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
@@ -1617,7 +1658,16 @@
// update volume on all outputs whose current device is also selected by the same
// strategy as the device specified by the caller
audio_devices_t strategyDevice = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/);
- if ((device != AUDIO_DEVICE_OUT_DEFAULT) && (device & strategyDevice) == 0) {
+
+
+ //FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now
+ audio_devices_t accessibilityDevice = AUDIO_DEVICE_NONE;
+ if (stream == AUDIO_STREAM_MUSIC) {
+ mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexCur.add(device, index);
+ accessibilityDevice = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, true /*fromCache*/);
+ }
+ if ((device != AUDIO_DEVICE_OUT_DEFAULT) &&
+ (device & (strategyDevice | accessibilityDevice)) == 0) {
return NO_ERROR;
}
status_t status = NO_ERROR;
@@ -1630,6 +1680,10 @@
status = volStatus;
}
}
+ if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & accessibilityDevice) != 0)) {
+ status_t volStatus = checkAndSetVolume(AUDIO_STREAM_ACCESSIBILITY,
+ index, mOutputs.keyAt(i), curDevice);
+ }
}
return status;
}
@@ -3755,6 +3809,9 @@
}
// Move tracks associated to this strategy from previous output to new output
for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
+ if (i == AUDIO_STREAM_PATCH) {
+ continue;
+ }
if (getStrategy((audio_stream_type_t)i) == strategy) {
mpClientInterface->invalidateStream((audio_stream_type_t)i);
}
@@ -3771,8 +3828,10 @@
checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE);
checkOutputForStrategy(STRATEGY_SONIFICATION);
checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL);
+ checkOutputForStrategy(STRATEGY_ACCESSIBILITY);
checkOutputForStrategy(STRATEGY_MEDIA);
checkOutputForStrategy(STRATEGY_DTMF);
+ checkOutputForStrategy(STRATEGY_REROUTING);
}
audio_io_handle_t AudioPolicyManager::getA2dpOutput()
@@ -3861,11 +3920,13 @@
// use device for strategy sonification
// 5: the strategy "respectful" sonification is active on the output:
// use device for strategy "respectful" sonification
- // 6: the strategy media is active on the output:
+ // 6: the strategy accessibility is active on the output:
+ // use device for strategy accessibility
+ // 7: the strategy media is active on the output:
// use device for strategy media
- // 7: the strategy DTMF is active on the output:
+ // 8: the strategy DTMF is active on the output:
// use device for strategy DTMF
- // 8: the strategy for beacon, a.k.a. "transmitted through speaker" is active on the output:
+ // 9: the strategy for beacon, a.k.a. "transmitted through speaker" is active on the output:
// use device for strategy t-t-s
if (outputDesc->isStrategyActive(STRATEGY_ENFORCED_AUDIBLE) &&
mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
@@ -3879,12 +3940,16 @@
device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
} else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION_RESPECTFUL)) {
device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache);
+ } else if (outputDesc->isStrategyActive(STRATEGY_ACCESSIBILITY)) {
+ device = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, fromCache);
} else if (outputDesc->isStrategyActive(STRATEGY_MEDIA)) {
device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);
} else if (outputDesc->isStrategyActive(STRATEGY_DTMF)) {
device = getDeviceForStrategy(STRATEGY_DTMF, fromCache);
} else if (outputDesc->isStrategyActive(STRATEGY_TRANSMITTED_THROUGH_SPEAKER)) {
device = getDeviceForStrategy(STRATEGY_TRANSMITTED_THROUGH_SPEAKER, fromCache);
+ } else if (outputDesc->isStrategyActive(STRATEGY_REROUTING)) {
+ device = getDeviceForStrategy(STRATEGY_REROUTING, fromCache);
}
ALOGV("getNewOutputDevice() selected device %x", device);
@@ -3919,7 +3984,7 @@
// By checking the range of stream before calling getStrategy, we avoid
// getStrategy's behavior for invalid streams. getStrategy would do a ALOGE
// and then return STRATEGY_MEDIA, but we want to return the empty set.
- if (stream < (audio_stream_type_t) 0 || stream >= AUDIO_STREAM_CNT) {
+ if (stream < (audio_stream_type_t) 0 || stream >= AUDIO_STREAM_PUBLIC_CNT) {
return AUDIO_DEVICE_NONE;
}
audio_devices_t devices;
@@ -3946,6 +4011,9 @@
AudioPolicyManager::routing_strategy AudioPolicyManager::getStrategy(
audio_stream_type_t stream) {
+
+ ALOG_ASSERT(stream != AUDIO_STREAM_PATCH,"getStrategy() called for AUDIO_STREAM_PATCH");
+
// stream to strategy mapping
switch (stream) {
case AUDIO_STREAM_VOICE_CALL:
@@ -3959,7 +4027,7 @@
case AUDIO_STREAM_DTMF:
return STRATEGY_DTMF;
default:
- ALOGE("unknown stream type");
+ ALOGE("unknown stream type %d", stream);
case AUDIO_STREAM_SYSTEM:
// NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
// while key clicks are played produces a poor result
@@ -3969,6 +4037,10 @@
return STRATEGY_ENFORCED_AUDIBLE;
case AUDIO_STREAM_TTS:
return STRATEGY_TRANSMITTED_THROUGH_SPEAKER;
+ case AUDIO_STREAM_ACCESSIBILITY:
+ return STRATEGY_ACCESSIBILITY;
+ case AUDIO_STREAM_REROUTING:
+ return STRATEGY_REROUTING;
}
}
@@ -3990,7 +4062,7 @@
if (isInCall()) {
return (uint32_t) STRATEGY_PHONE;
}
- // FALL THROUGH
+ return (uint32_t) STRATEGY_ACCESSIBILITY;
case AUDIO_USAGE_MEDIA:
case AUDIO_USAGE_GAME:
@@ -4282,6 +4354,24 @@
// The second device used for sonification is the same as the device used by media strategy
// FALL THROUGH
+ // FIXME: STRATEGY_ACCESSIBILITY and STRATEGY_REROUTING follow STRATEGY_MEDIA for now
+ case STRATEGY_ACCESSIBILITY:
+ if (strategy == STRATEGY_ACCESSIBILITY) {
+ // do not route accessibility prompts to a digital output currently configured with a
+ // compressed format as they would likely not be mixed and dropped.
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ audio_devices_t devices = desc->device() &
+ (AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_HDMI_ARC);
+ if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat) &&
+ devices != AUDIO_DEVICE_NONE) {
+ availableOutputDeviceTypes = availableOutputDeviceTypes & ~devices;
+ }
+ }
+ }
+ // FALL THROUGH
+
+ case STRATEGY_REROUTING:
case STRATEGY_MEDIA: {
uint32_t device2 = AUDIO_DEVICE_NONE;
if (strategy != STRATEGY_SONIFICATION) {
@@ -4933,6 +5023,7 @@
}
}
+/* static */
float AudioPolicyManager::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
int indexInUi)
{
@@ -5056,6 +5147,11 @@
};
const AudioPolicyManager::VolumeCurvePoint
+ AudioPolicyManager::sFullScaleVolumeCurve[AudioPolicyManager::VOLCNT] = {
+ {0, 0.0f}, {1, 0.0f}, {2, 0.0f}, {100, 0.0f}
+};
+
+const AudioPolicyManager::VolumeCurvePoint
*AudioPolicyManager::sVolumeProfiles[AUDIO_STREAM_CNT]
[AudioPolicyManager::DEVICE_CATEGORY_CNT] = {
{ // AUDIO_STREAM_VOICE_CALL
@@ -5119,6 +5215,24 @@
sSilentVolumeCurve, // DEVICE_CATEGORY_EARPIECE
sSilentVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
},
+ { // AUDIO_STREAM_ACCESSIBILITY
+ sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+ { // AUDIO_STREAM_REROUTING
+ sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ sFullScaleVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+ { // AUDIO_STREAM_PATCH
+ sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ sFullScaleVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
};
void AudioPolicyManager::initializeVolumeCurves()
@@ -5142,6 +5256,8 @@
sSpeakerSonificationVolumeCurveDrc;
mStreams[AUDIO_STREAM_MUSIC].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] =
sSpeakerMediaVolumeCurveDrc;
+ mStreams[AUDIO_STREAM_ACCESSIBILITY].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] =
+ sSpeakerMediaVolumeCurveDrc;
}
}
@@ -5267,6 +5383,9 @@
ALOGVV("applyStreamVolumes() for output %d and device %x", output, device);
for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
+ if (stream == AUDIO_STREAM_PATCH) {
+ continue;
+ }
checkAndSetVolume((audio_stream_type_t)stream,
mStreams[stream].getVolumeIndex(device),
output,
@@ -5284,6 +5403,9 @@
{
ALOGVV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output);
for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
+ if (stream == AUDIO_STREAM_PATCH) {
+ continue;
+ }
if (getStrategy((audio_stream_type_t)stream) == strategy) {
setStreamMute((audio_stream_type_t)stream, on, output, delayMs, device);
}
@@ -5495,6 +5617,9 @@
sysTime = systemTime();
}
for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
+ if (i == AUDIO_STREAM_PATCH) {
+ continue;
+ }
if (((getStrategy((audio_stream_type_t)i) == strategy) ||
(NUM_STRATEGIES == strategy)) &&
isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) {
@@ -7412,9 +7537,19 @@
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_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;
case AUDIO_USAGE_VOICE_COMMUNICATION:
@@ -7440,4 +7575,35 @@
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 50d7831..e2b6480 100644
--- a/services/audiopolicy/AudioPolicyManager.h
+++ b/services/audiopolicy/AudioPolicyManager.h
@@ -87,25 +87,31 @@
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);
- virtual audio_io_handle_t getInput(audio_source_t inputSource,
- uint32_t samplingRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- audio_session_t session,
- audio_input_flags_t flags);
+ audio_session_t session);
+ virtual void releaseOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ audio_session_t session);
+ virtual status_t getInputForAttr(const audio_attributes_t *attr,
+ audio_io_handle_t *input,
+ audio_session_t session,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_input_flags_t flags);
// indicates to the audio policy manager that the input starts being used.
virtual status_t startInput(audio_io_handle_t input,
@@ -188,6 +194,8 @@
STRATEGY_DTMF,
STRATEGY_ENFORCED_AUDIBLE,
STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
+ STRATEGY_ACCESSIBILITY,
+ STRATEGY_REROUTING,
NUM_STRATEGIES
};
@@ -437,6 +445,7 @@
static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[AudioPolicyManager::VOLCNT];
static const VolumeCurvePoint sLinearVolumeCurve[AudioPolicyManager::VOLCNT];
static const VolumeCurvePoint sSilentVolumeCurve[AudioPolicyManager::VOLCNT];
+ static const VolumeCurvePoint sFullScaleVolumeCurve[AudioPolicyManager::VOLCNT];
// default volume curves per stream and device category. See initializeVolumeCurves()
static const VolumeCurvePoint *sVolumeProfiles[AUDIO_STREAM_CNT][DEVICE_CATEGORY_CNT];
@@ -859,6 +868,7 @@
// 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,
@@ -874,6 +884,7 @@
// 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 @@
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 @@
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 @@
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..da17728 100644
--- a/services/audiopolicy/AudioPolicyService.h
+++ b/services/audiopolicy/AudioPolicyService.h
@@ -72,25 +72,31 @@
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);
- 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_input_flags_t flags);
+ audio_session_t session);
+ virtual void releaseOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ audio_session_t session);
+ virtual status_t getInputForAttr(const audio_attributes_t *attr,
+ audio_io_handle_t *input,
+ audio_session_t session,
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_input_flags_t flags);
virtual status_t startInput(audio_io_handle_t input,
audio_session_t session);
virtual status_t stopInput(audio_io_handle_t input,
@@ -181,8 +187,10 @@
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 +258,10 @@
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 +331,14 @@
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 {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 6a7f9e7..5281ea6 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2028,8 +2028,12 @@
// Check if everything has arrived for this result (buffers and metadata), remove it from
// InFlightMap if both arrived or HAL reports error for this request (i.e. during flush).
- if ((request.requestStatus != OK) ||
- (request.haveResultMetadata && request.numBuffersLeft == 0)) {
+ // For per-frame error notifications, camera3.h requirements state that all the
+ // buffer handles for a failed frame capture must be returned via process_capture_result()
+ // call(s). Hence, Camera3Device needs to ensure that the frame entry is not deleted from
+ // mInFlightMap until all buffers for that frame have been returned by HAL.
+ if ((request.numBuffersLeft == 0) &&
+ ((request.requestStatus != OK) || (request.haveResultMetadata))) {
ATRACE_ASYNC_END("frame capture", frameNumber);
mInFlightMap.removeItemsAt(idx, 1);
}