From 466dc8ed6ca6b7f585104806c48613dd34e608c9 Mon Sep 17 00:00:00 2001 From: Paul McLean Date: Fri, 17 Apr 2015 13:15:36 -0600 Subject: Explicit routing in AudioRecord Change-Id: I9cc5d54883a3e5c75d553fabb619fc8e49f4f9e5 --- services/audiopolicy/AudioPolicyInterface.h | 1 + .../managerdefault/AudioPolicyManager.cpp | 96 +++++++++++++++------- .../managerdefault/AudioPolicyManager.h | 78 +++++++++++++----- .../service/AudioPolicyInterfaceImpl.cpp | 9 +- .../service/AudioPolicyInterfaceImplLegacy.cpp | 5 +- services/audiopolicy/service/AudioPolicyService.h | 5 +- 6 files changed, 139 insertions(+), 55 deletions(-) (limited to 'services') diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h index 58c65fa..9230750 100644 --- a/services/audiopolicy/AudioPolicyInterface.h +++ b/services/audiopolicy/AudioPolicyInterface.h @@ -133,6 +133,7 @@ public: audio_format_t format, audio_channel_mask_t channelMask, audio_input_flags_t flags, + audio_port_handle_t selectedDeviceId, input_type_t *inputType) = 0; // indicates to the audio policy manager that the input starts being used. virtual status_t startInput(audio_io_handle_t input, diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index ba3fcaf..7de72de 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -689,7 +689,7 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, break; } } - mOutputRoutes.addRoute(session, *stream, deviceDesc); + mOutputRoutes.addRoute(session, *stream, SessionRoute::SOURCE_TYPE_NA, deviceDesc); return NO_ERROR; } @@ -1226,6 +1226,7 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, audio_format_t format, audio_channel_mask_t channelMask, audio_input_flags_t flags, + audio_port_handle_t selectedDeviceId, input_type_t *inputType) { ALOGV("getInputForAttr() source %d, samplingRate %d, format %d, channelMask %x," @@ -1247,6 +1248,16 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, } halInputSource = inputSource; + // Explicit routing? + sp deviceDesc; + for (size_t i = 0; i < mAvailableInputDevices.size(); i++) { + if (mAvailableInputDevices[i]->getId() == selectedDeviceId) { + deviceDesc = mAvailableInputDevices[i]; + break; + } + } + mInputRoutes.addRoute(session, SessionRoute::STREAM_TYPE_NA, inputSource, deviceDesc); + if (inputSource == AUDIO_SOURCE_REMOTE_SUBMIX && strncmp(attr->tags, "addr=", strlen("addr=")) == 0) { status_t ret = mPolicyMixes.getInputMixForAttr(*attr, &policyMix); @@ -1378,6 +1389,7 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, addInput(*input, inputDesc); mpClientInterface->onAudioPortListUpdate(); + return NO_ERROR; } @@ -1419,7 +1431,7 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input, } } - if (inputDesc->mRefCount == 0) { + if (inputDesc->mRefCount == 0 || mInputRoutes.hasRouteChanged(session)) { // if input maps to a dynamic policy with an activity listener, notify of state change if ((inputDesc->mPolicyMix != NULL) && ((inputDesc->mPolicyMix->mFlags & MIX_FLAG_NOTIFY_ACTIVITY) != 0)) { @@ -1427,6 +1439,9 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input, MIX_STATE_MIXING); } + // Routing? + mInputRoutes.incRouteActivity(session); + if (mInputs.activeInputsCount() == 0) { SoundTrigger::setCaptureState(true); } @@ -1479,6 +1494,10 @@ status_t AudioPolicyManager::stopInput(audio_io_handle_t input, } inputDesc->mRefCount--; + + // Routing? + mInputRoutes.decRouteActivity(session); + if (inputDesc->mRefCount == 0) { // if input maps to a dynamic policy with an activity listener, notify of state change if ((inputDesc->mPolicyMix != NULL) @@ -1521,6 +1540,10 @@ void AudioPolicyManager::releaseInput(audio_io_handle_t input, ALOGW("releaseInput() releasing unknown input %d", input); return; } + + // Routing + mInputRoutes.removeRoute(session); + sp inputDesc = mInputs.valueAt(index); ALOG_ASSERT(inputDesc != 0); @@ -3771,7 +3794,6 @@ audio_devices_t AudioPolicyManager::getNewInputDevice(audio_io_handle_t input) audio_devices_t device = getDeviceAndMixForInputSource(inputDesc->mInputSource); - ALOGV("getNewInputDevice() selected device %x", device); return device; } @@ -4291,7 +4313,15 @@ audio_devices_t AudioPolicyManager::getDeviceAndMixForInputSource(audio_source_t audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource) { - return mEngine->getDeviceForInputSource(inputSource); + for (size_t routeIndex = 0; routeIndex < mInputRoutes.size(); routeIndex++) { + sp route = mInputRoutes.valueAt(routeIndex); + if (inputSource == route->mSource && route->mDeviceDescriptor != 0 + /*&& route->mActivityCount != 0*/) { + return route->mDeviceDescriptor->type(); + } + } + + return mEngine->getDeviceForInputSource(inputSource); } float AudioPolicyManager::computeVolume(audio_stream_type_t stream, @@ -4514,8 +4544,8 @@ void AudioPolicyManager::handleIncallSonification(audio_stream_type_t stream, // --- SessionRoute class implementation void AudioPolicyManager::SessionRoute::log(const char* prefix) { - ALOGI("%s[SessionRoute strm:0x%X, sess:0x%X, dev:0x%X refs:%d act:%d", - prefix, mStreamType, mSession, + ALOGI("%s[SessionRoute strm:0x%X, src:%d, sess:0x%X, dev:0x%X refs:%d act:%d", + prefix, mStreamType, mSource, mSession, mDeviceDescriptor != 0 ? mDeviceDescriptor->type() : AUDIO_DEVICE_NONE, mRefCount, mActivityCount); } @@ -4537,28 +4567,6 @@ bool AudioPolicyManager::SessionRouteMap::hasRouteChanged(audio_session_t sessio return false; } -void AudioPolicyManager::SessionRouteMap::addRoute(audio_session_t session, - audio_stream_type_t streamType, - sp deviceDescriptor) -{ - sp route = indexOfKey(session) >= 0 ? valueFor(session) : 0; - if (route != NULL) { - if ((route->mDeviceDescriptor == 0 && deviceDescriptor != 0) || - (!route->mDeviceDescriptor->equals(deviceDescriptor))) { - route->mChanged = true; - } - route->mRefCount++; - route->mDeviceDescriptor = deviceDescriptor; - } else { - route = new AudioPolicyManager::SessionRoute(session, streamType, deviceDescriptor); - route->mRefCount++; - add(session, route); - if (deviceDescriptor != 0) { - route->mChanged = true; - } - } -} - void AudioPolicyManager::SessionRouteMap::removeRoute(audio_session_t session) { sp route = indexOfKey(session) >= 0 ? valueFor(session) : 0; @@ -4594,6 +4602,38 @@ void AudioPolicyManager::SessionRouteMap::log(const char* caption) { } } +void AudioPolicyManager::SessionRouteMap::addRoute(audio_session_t session, + audio_stream_type_t streamType, + audio_source_t source, + sp descriptor) +{ + if (mMapType == MAPTYPE_INPUT && streamType != SessionRoute::STREAM_TYPE_NA) { + ALOGE("Adding Output Route to InputRouteMap"); + return; + } else if (mMapType == MAPTYPE_OUTPUT && source != SessionRoute::SOURCE_TYPE_NA) { + ALOGE("Adding Input Route to OutputRouteMap"); + return; + } + + sp route = indexOfKey(session) >= 0 ? valueFor(session) : 0; + + if (route != 0) { + if ((route->mDeviceDescriptor == 0 && descriptor != 0) || + (!route->mDeviceDescriptor->equals(descriptor))) { + route->mChanged = true; + } + route->mRefCount++; + route->mDeviceDescriptor = descriptor; + } else { + route = new AudioPolicyManager::SessionRoute(session, streamType, source, descriptor); + route->mRefCount++; + add(session, route); + if (descriptor != 0) { + route->mChanged = true; + } + } +} + void AudioPolicyManager::defaultAudioPolicyConfig(void) { sp module; diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h index 521f6c4..b965411 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.h +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h @@ -131,6 +131,7 @@ public: audio_format_t format, audio_channel_mask_t channelMask, audio_input_flags_t flags, + audio_port_handle_t selectedDeviceId, input_type_t *inputType); // indicates to the audio policy manager that the input starts being used. @@ -233,45 +234,84 @@ public: routing_strategy getStrategy(audio_stream_type_t stream) const; protected: - class SessionRoute : public RefBase - { + class SessionRoute : public RefBase { public: - friend class SessionRouteMap; + // For Input (Source) routes, use STREAM_TYPE_NA ("NA" = "not applicable)for the + // streamType argument + static const audio_stream_type_t STREAM_TYPE_NA = AUDIO_STREAM_DEFAULT; + + // For Output (Sink) routes, use SOURCE_TYPE_NA ("NA" = "not applicable") for the + // source argument + + static const audio_source_t SOURCE_TYPE_NA = AUDIO_SOURCE_DEFAULT; + SessionRoute(audio_session_t session, audio_stream_type_t streamType, + audio_source_t source, sp deviceDescriptor) - : mSession(session), - mStreamType(streamType), - mDeviceDescriptor(deviceDescriptor), - mRefCount(0), - mActivityCount(0), - mChanged(false) {} - - void log(const char* prefix); + : mSession(session), + mDeviceDescriptor(deviceDescriptor), + mRefCount(0), + mActivityCount(0), + mChanged(false), + mStreamType(streamType), + mSource(source) {} audio_session_t mSession; - audio_stream_type_t mStreamType; sp mDeviceDescriptor; + void log(const char* prefix); + // "reference" counting int mRefCount; // +/- on references int mActivityCount; // +/- on start/stop bool mChanged; + + // for outputs + const audio_stream_type_t mStreamType; + + // for inputs + const audio_source_t mSource; }; - class SessionRouteMap: public KeyedVector> - { - public: + class SessionRouteMap: public KeyedVector> { + public: + // These constants identify the SessionRoutMap as holding EITHER input routes, + // or output routes. An error will occur if an attempt is made to add a SessionRoute + // object with mStreamType == STREAM_TYPE_NA (i.e. an input SessionRoute) to a + // SessionRoutMap that is marked for output (i.e. mMapType == SESSION_ROUTE_MAP_OUTPUT) + // and similarly for output SessionRoutes and Input SessionRouteMaps. + typedef enum { + MAPTYPE_INPUT = 0, + MAPTYPE_OUTPUT = 1 + } session_route_map_type_t; + + SessionRouteMap(session_route_map_type_t mapType) : + mMapType(mapType) { + } + bool hasRoute(audio_session_t session); - void addRoute(audio_session_t session, audio_stream_type_t streamType, - sp deviceDescriptor); void removeRoute(audio_session_t session); int incRouteActivity(audio_session_t session); int decRouteActivity(audio_session_t session); bool hasRouteChanged(audio_session_t session); // also clears the changed flag void log(const char* caption); + + // Specify an Output(Sink) route by passing SessionRoute::SOURCE_TYPE_NA in the + // source argument. + // Specify an Input(Source) rout by passing SessionRoute::AUDIO_STREAM_DEFAULT + // in the streamType argument. + void addRoute(audio_session_t session, + audio_stream_type_t streamType, + audio_source_t source, + sp deviceDescriptor); + + private: + // Used to mark a SessionRoute as for either inputs (mMapType == kSessionRouteMap_Input) + // or outputs (mMapType == kSessionRouteMap_Output) + const session_route_map_type_t mMapType; }; // From AudioPolicyManagerObserver @@ -535,8 +575,8 @@ protected: DeviceVector mAvailableOutputDevices; // all available output devices DeviceVector mAvailableInputDevices; // all available input devices - SessionRouteMap mOutputRoutes; - SessionRouteMap mInputRoutes; + SessionRouteMap mOutputRoutes = SessionRouteMap(SessionRouteMap::MAPTYPE_OUTPUT); + SessionRouteMap mInputRoutes = SessionRouteMap(SessionRouteMap::MAPTYPE_INPUT); StreamDescriptorCollection mStreams; // stream descriptors for volume control bool mLimitRingtoneVolume; // limit ringtone volume to music volume if headset connected diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index e764eda..5ceb1cf 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -150,7 +150,7 @@ status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr, audio_format_t format, audio_channel_mask_t channelMask, audio_output_flags_t flags, - int mSelectedDeviceId, + audio_port_handle_t selectedDeviceId, const audio_offload_info_t *offloadInfo) { if (mAudioPolicyManager == NULL) { @@ -159,7 +159,7 @@ status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr, ALOGV("getOutput()"); Mutex::Autolock _l(mLock); return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, samplingRate, - format, channelMask, flags, mSelectedDeviceId, offloadInfo); + format, channelMask, flags, selectedDeviceId, offloadInfo); } status_t AudioPolicyService::startOutput(audio_io_handle_t output, @@ -251,7 +251,8 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - audio_input_flags_t flags) + audio_input_flags_t flags, + audio_port_handle_t selectedDeviceId) { if (mAudioPolicyManager == NULL) { return NO_INIT; @@ -273,7 +274,7 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr, // the audio_in_acoustics_t parameter is ignored by get_input() status = mAudioPolicyManager->getInputForAttr(attr, input, session, samplingRate, format, channelMask, - flags, &inputType); + flags, selectedDeviceId, &inputType); audioPolicyEffects = mAudioPolicyEffects; if (status == NO_ERROR) { diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp index f783437..433e712 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp @@ -237,7 +237,8 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - audio_input_flags_t flags __unused) + audio_input_flags_t flags __unused, + audio_port_handle_t selectedDeviceId __unused) { if (mpAudioPolicy == NULL) { return NO_INIT; @@ -568,7 +569,7 @@ status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr, audio_format_t format, audio_channel_mask_t channelMask, audio_output_flags_t flags, - int selectedDeviceId __unused, + audio_port_handle_t selectedDeviceId __unused, const audio_offload_info_t *offloadInfo) { if (attr != NULL) { diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h index 4e25d33..07ea96b 100644 --- a/services/audiopolicy/service/AudioPolicyService.h +++ b/services/audiopolicy/service/AudioPolicyService.h @@ -84,7 +84,7 @@ public: audio_format_t format = AUDIO_FORMAT_DEFAULT, audio_channel_mask_t channelMask = 0, audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, - int selectedDeviceId = AUDIO_PORT_HANDLE_NONE, + audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE, const audio_offload_info_t *offloadInfo = NULL); virtual status_t startOutput(audio_io_handle_t output, audio_stream_type_t stream, @@ -101,7 +101,8 @@ public: uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - audio_input_flags_t flags); + audio_input_flags_t flags, + audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE); virtual status_t startInput(audio_io_handle_t input, audio_session_t session); virtual status_t stopInput(audio_io_handle_t input, -- cgit v1.1