From 223fd5c9738e9665e495904d37d4632414b68c1e Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Tue, 11 Nov 2014 13:43:36 -0800 Subject: audio: new routing strategies and stream types Added new routing strategies and stream type for internal use by audio policy manager and audio flinger: - One for accessibility to allow different routing than media - One for re-routing (remote submix) in preparation of dynamic policies - Added stream type for "internal" audio flinger tracks used for audio patches and duplication. Bug: 18067208. Change-Id: I88f884b552e51e4a49c29125e5a1204cf58ff434 --- services/audioflinger/AudioFlinger.cpp | 37 ++++++-- services/audioflinger/AudioFlinger.h | 2 + services/audioflinger/Threads.cpp | 7 +- services/audioflinger/Threads.h | 4 +- services/audioflinger/Tracks.cpp | 8 +- services/audiopolicy/AudioPolicyEffects.cpp | 13 ++- services/audiopolicy/AudioPolicyEffects.h | 2 +- services/audiopolicy/AudioPolicyInterfaceImpl.cpp | 16 ++-- .../audiopolicy/AudioPolicyInterfaceImplLegacy.cpp | 28 +++--- services/audiopolicy/AudioPolicyManager.cpp | 103 +++++++++++++++++++-- services/audiopolicy/AudioPolicyManager.h | 3 + 11 files changed, 170 insertions(+), 53 deletions(-) (limited to 'services') 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 @@ bool AudioFlinger::masterMute_l() const 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 @@ status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value, 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 @@ status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted) 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 @@ status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted) 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 @@ float AudioFlinger::streamVolume(audio_stream_type_t stream, audio_io_handle_t o 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 @@ private: void closeInputInternal_l(sp 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 mRecordTeeSink; diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 0f11b34..792419f 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -1224,15 +1224,12 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp& audioFlinge 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() @@ -4746,7 +4743,7 @@ void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread) 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 @@ private: void dumpTracks(int fd, const Vector& args); SortedVector< sp > 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..aa708ec 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -1657,8 +1657,9 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack( 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 @@ AudioFlinger::PlaybackThread::PatchTrack::PatchTrack(PlaybackThread *playbackThr 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 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output, 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 @@ void AudioPolicyEffects::EffectVector::setProcessorEnabled(bool enabled) 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 @@ const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_CNT+1] = { }; // 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 @@ status_t AudioPolicyEffects::loadStreamEffectConfigurations(cnode *root, 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 @@ private: 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/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp index c06ca72..710a905 100644 --- a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp @@ -129,7 +129,7 @@ audio_io_handle_t AudioPolicyService::getOutput(audio_stream_type_t stream, 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) { @@ -332,7 +332,7 @@ status_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream, 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 +350,7 @@ status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream, 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 +366,7 @@ status_t AudioPolicyService::getStreamVolumeIndex(audio_stream_type_t stream, 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 +377,7 @@ status_t AudioPolicyService::getStreamVolumeIndex(audio_stream_type_t stream, 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 +390,7 @@ uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream) 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 +439,7 @@ status_t AudioPolicyService::setEffectEnabled(int id, bool enabled) 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 +451,7 @@ bool AudioPolicyService::isStreamActive(audio_stream_type_t stream, uint32_t inP 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..ac61cb2 100644 --- a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp +++ b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp @@ -134,7 +134,7 @@ audio_io_handle_t AudioPolicyService::getOutput(audio_stream_type_t stream, 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) { @@ -150,7 +150,7 @@ status_t AudioPolicyService::startOutput(audio_io_handle_t output, audio_stream_type_t stream, int session) { - if (uint32_t(stream) >= AUDIO_STREAM_CNT) { + if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) { return BAD_VALUE; } if (mpAudioPolicy == NULL) { @@ -178,7 +178,7 @@ status_t AudioPolicyService::stopOutput(audio_io_handle_t output, audio_stream_type_t stream, int session) { - if (uint32_t(stream) >= AUDIO_STREAM_CNT) { + if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) { return BAD_VALUE; } if (mpAudioPolicy == NULL) { @@ -324,7 +324,7 @@ status_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream, 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 +342,7 @@ status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream, 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 +363,7 @@ status_t AudioPolicyService::getStreamVolumeIndex(audio_stream_type_t stream, 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 +379,7 @@ status_t AudioPolicyService::getStreamVolumeIndex(audio_stream_type_t stream, 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 +392,7 @@ uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream) 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 +441,7 @@ status_t AudioPolicyService::setEffectEnabled(int id, bool enabled) 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 +453,7 @@ bool AudioPolicyService::isStreamActive(audio_stream_type_t stream, uint32_t inP 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) { @@ -561,14 +561,14 @@ audio_io_handle_t AudioPolicyService::getOutputForAttr(const audio_attributes_t return getOutput(stream, samplingRate, format, channelMask, flags, offloadInfo); } -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..78ba23d 100644 --- a/services/audiopolicy/AudioPolicyManager.cpp +++ b/services/audiopolicy/AudioPolicyManager.cpp @@ -584,6 +584,9 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state) 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 +684,9 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state) 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,7 +836,6 @@ audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream, 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", @@ -1587,6 +1592,11 @@ void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream, } 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 +1627,16 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream, // 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 +1649,10 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream, 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 +3778,9 @@ void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy) } // 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 +3797,10 @@ void AudioPolicyManager::checkOutputForAllStrategies() 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 +3889,13 @@ audio_devices_t AudioPolicyManager::getNewOutputDevice(audio_io_handle_t output, // 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 +3909,16 @@ audio_devices_t AudioPolicyManager::getNewOutputDevice(audio_io_handle_t output, 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 +3953,7 @@ audio_devices_t AudioPolicyManager::getDevicesForStream(audio_stream_type_t stre // 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 +3980,9 @@ audio_devices_t AudioPolicyManager::getDevicesForStream(audio_stream_type_t stre 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 +3996,7 @@ AudioPolicyManager::routing_strategy AudioPolicyManager::getStrategy( 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 +4006,10 @@ AudioPolicyManager::routing_strategy AudioPolicyManager::getStrategy( 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; } } @@ -4015,6 +4056,13 @@ uint32_t AudioPolicyManager::getStrategyForAttr(const audio_attributes_t *attr) case AUDIO_USAGE_NOTIFICATION_EVENT: return (uint32_t) STRATEGY_SONIFICATION_RESPECTFUL; + case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: + if (isStreamActive(AUDIO_STREAM_RING, 0) || + isStreamActive(AUDIO_STREAM_ALARM, 0)) { + return (uint32_t) STRATEGY_SONIFICATION; + } + return (uint32_t) STRATEGY_ACCESSIBILITY; + case AUDIO_USAGE_UNKNOWN: default: return (uint32_t) STRATEGY_MEDIA; @@ -4282,6 +4330,9 @@ audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strate // 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: + case STRATEGY_REROUTING: case STRATEGY_MEDIA: { uint32_t device2 = AUDIO_DEVICE_NONE; if (strategy != STRATEGY_SONIFICATION) { @@ -4933,6 +4984,7 @@ AudioPolicyManager::device_category AudioPolicyManager::getDeviceCategory(audio_ } } +/* static */ float AudioPolicyManager::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc, int indexInUi) { @@ -5056,6 +5108,11 @@ const AudioPolicyManager::VolumeCurvePoint }; 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 +5176,24 @@ const AudioPolicyManager::VolumeCurvePoint 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 +5217,8 @@ void AudioPolicyManager::initializeVolumeCurves() sSpeakerSonificationVolumeCurveDrc; mStreams[AUDIO_STREAM_MUSIC].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = sSpeakerMediaVolumeCurveDrc; + mStreams[AUDIO_STREAM_ACCESSIBILITY].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = + sSpeakerMediaVolumeCurveDrc; } } @@ -5267,6 +5344,9 @@ void AudioPolicyManager::applyStreamVolumes(audio_io_handle_t output, 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 +5364,9 @@ void AudioPolicyManager::setStrategyMute(routing_strategy strategy, { 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 +5578,9 @@ bool AudioPolicyManager::AudioOutputDescriptor::isStrategyActive(routing_strateg 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 +7498,10 @@ audio_stream_type_t AudioPolicyManager::streamTypefromAttributesInt(const audio_ 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: + return AUDIO_STREAM_ACCESSIBILITY; case AUDIO_USAGE_ASSISTANCE_SONIFICATION: return AUDIO_STREAM_SYSTEM; case AUDIO_USAGE_VOICE_COMMUNICATION: diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h index 50d7831..7af6475 100644 --- a/services/audiopolicy/AudioPolicyManager.h +++ b/services/audiopolicy/AudioPolicyManager.h @@ -188,6 +188,8 @@ protected: STRATEGY_DTMF, STRATEGY_ENFORCED_AUDIBLE, STRATEGY_TRANSMITTED_THROUGH_SPEAKER, + STRATEGY_ACCESSIBILITY, + STRATEGY_REROUTING, NUM_STRATEGIES }; @@ -437,6 +439,7 @@ protected: 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]; -- cgit v1.1