From f41599b115c9b3fc13a5fe00186067885a31c3ba Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Tue, 7 Jan 2020 14:22:08 -0800 Subject: [PATCH] APM: support querying of audio playback routing Add support for querying the audio devices used for playback routing for the given audio attributes. Take into account registered dynamic policies but disregard secondary output descriptors as they are used for playback capture. Bug: 144440677 Test: atest AudioServiceHostTest Change-Id: I102c57b432b044dc6b0ead49e0a30d8e9094411d --- media/libaudioclient/AudioSystem.cpp | 10 +++ media/libaudioclient/IAudioPolicyService.cpp | 70 ++++++++++++++++++- .../include/media/AudioSystem.h | 2 + .../include/media/IAudioPolicyService.h | 2 + services/audiopolicy/AudioPolicyInterface.h | 4 ++ .../managerdefinitions/src/AudioPolicyMix.cpp | 4 +- .../managerdefault/AudioPolicyManager.cpp | 65 ++++++++++++----- .../managerdefault/AudioPolicyManager.h | 4 ++ .../service/AudioPolicyInterfaceImpl.cpp | 11 +++ .../audiopolicy/service/AudioPolicyService.h | 2 + 10 files changed, 155 insertions(+), 19 deletions(-) diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp index 941cf54d8d..074209158f 100644 --- a/media/libaudioclient/AudioSystem.cpp +++ b/media/libaudioclient/AudioSystem.cpp @@ -1017,6 +1017,16 @@ audio_devices_t AudioSystem::getDevicesForStream(audio_stream_type_t stream) return aps->getDevicesForStream(stream); } +status_t AudioSystem::getDevicesForAttributes(const AudioAttributes &aa, + AudioDeviceTypeAddrVector *devices) { + if (devices == nullptr) { + return BAD_VALUE; + } + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->getDevicesForAttributes(aa, devices); +} + audio_io_handle_t AudioSystem::getOutputForEffect(const effect_descriptor_t *desc) { const sp& aps = AudioSystem::get_audio_policy_service(); diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp index b9e6e33ee3..87802a190f 100644 --- a/media/libaudioclient/IAudioPolicyService.cpp +++ b/media/libaudioclient/IAudioPolicyService.cpp @@ -109,6 +109,7 @@ enum { SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY, REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY, GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY, + GET_DEVICES_FOR_ATTRIBUTES, }; #define MAX_ITEMS_PER_LIST 1024 @@ -1348,6 +1349,41 @@ public: } return static_cast(reply.readInt32()); } + + virtual status_t getDevicesForAttributes(const AudioAttributes &aa, + AudioDeviceTypeAddrVector *devices) const + { + if (devices == nullptr) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + status_t status = aa.writeToParcel(&data); + if (status != NO_ERROR) { + return status; + } + status = remote()->transact(GET_DEVICES_FOR_ATTRIBUTES, data, &reply); + if (status != NO_ERROR) { + // transaction failed, return error + return status; + } + status = static_cast(reply.readInt32()); + if (status != NO_ERROR) { + // APM method call failed, return error + return status; + } + + const size_t numberOfDevices = (size_t)reply.readInt32(); + for (size_t i = 0; i < numberOfDevices; i++) { + AudioDeviceTypeAddr device; + if (device.readFromParcel((Parcel*)&reply) == NO_ERROR) { + devices->push_back(device); + } else { + return FAILED_TRANSACTION; + } + } + return NO_ERROR; + } }; IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService"); @@ -1414,7 +1450,8 @@ status_t BnAudioPolicyService::onTransact( case IS_CALL_SCREEN_MODE_SUPPORTED: case SET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY: case REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY: - case GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY: { + case GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY: + case GET_DEVICES_FOR_ATTRIBUTES: { if (!isServiceUid(IPCThreadState::self()->getCallingUid())) { ALOGW("%s: transaction %d received from PID %d unauthorized UID %d", __func__, code, IPCThreadState::self()->getCallingPid(), @@ -2473,6 +2510,37 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } + case GET_DEVICES_FOR_ATTRIBUTES: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + AudioAttributes attributes; + status_t status = attributes.readFromParcel(&data); + if (status != NO_ERROR) { + return status; + } + AudioDeviceTypeAddrVector devices; + status = getDevicesForAttributes(attributes.getAttributes(), &devices); + // reply data formatted as: + // - (int32) method call result from APM + // - (int32) number of devices (n) if method call returned NO_ERROR + // - n AudioDeviceTypeAddr if method call returned NO_ERROR + reply->writeInt32(status); + if (status != NO_ERROR) { + return NO_ERROR; + } + status = reply->writeInt32(devices.size()); + if (status != NO_ERROR) { + return status; + } + for (const auto& device : devices) { + status = device.writeToParcel(reply); + if (status != NO_ERROR) { + return status; + } + } + + return NO_ERROR; + } + default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h index c4b528e959..ae8b59cb72 100644 --- a/media/libaudioclient/include/media/AudioSystem.h +++ b/media/libaudioclient/include/media/AudioSystem.h @@ -279,6 +279,8 @@ public: static uint32_t getStrategyForStream(audio_stream_type_t stream); static audio_devices_t getDevicesForStream(audio_stream_type_t stream); + static status_t getDevicesForAttributes(const AudioAttributes &aa, + AudioDeviceTypeAddrVector *devices); static audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc); static status_t registerEffect(const effect_descriptor_t *desc, diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h index 6623061893..742762da10 100644 --- a/media/libaudioclient/include/media/IAudioPolicyService.h +++ b/media/libaudioclient/include/media/IAudioPolicyService.h @@ -108,6 +108,8 @@ public: virtual uint32_t getStrategyForStream(audio_stream_type_t stream) = 0; virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream) = 0; + virtual status_t getDevicesForAttributes(const AudioAttributes &aa, + AudioDeviceTypeAddrVector *devices) const = 0; virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc) = 0; virtual status_t registerEffect(const effect_descriptor_t *desc, audio_io_handle_t io, diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h index c5cdc2571c..dd0cd9bf8c 100644 --- a/services/audiopolicy/AudioPolicyInterface.h +++ b/services/audiopolicy/AudioPolicyInterface.h @@ -192,6 +192,10 @@ public: // return the enabled output devices for the given stream type virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream) = 0; + // retrieves the list of enabled output devices for the given audio attributes + virtual status_t getDevicesForAttributes(const audio_attributes_t &attr, + AudioDeviceTypeAddrVector *devices) = 0; + // Audio effect management virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc) = 0; virtual status_t registerEffect(const effect_descriptor_t *desc, diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp index 20c0a240cf..b1103ab2f1 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp @@ -197,7 +197,9 @@ status_t AudioPolicyMixCollection::getOutputForAttr( ALOGV("%s: Mix %zu ignored as secondaryOutput because not opened yet", __func__, i); } else { ALOGV("%s: Add a secondary desc %zu", __func__, i); - secondaryDescs->push_back(policyDesc); + if (secondaryDescs != nullptr) { + secondaryDescs->push_back(policyDesc); + } } } } diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index d4d59d6c96..23cd5c37f0 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -971,19 +971,21 @@ status_t AudioPolicyManager::getOutputForAttrInt( if (usePrimaryOutputFromPolicyMixes) { *output = policyDesc->mIoHandle; sp mix = policyDesc->mPolicyMix.promote(); - sp deviceDesc = - mAvailableOutputDevices.getDevice(mix->mDeviceType, - mix->mDeviceAddress, - AUDIO_FORMAT_DEFAULT); - *selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE; + if (mix != nullptr) { + sp deviceDesc = + mAvailableOutputDevices.getDevice(mix->mDeviceType, + mix->mDeviceAddress, + AUDIO_FORMAT_DEFAULT); + *selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE; - ALOGV("getOutputForAttr() returns output %d", *output); - if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) { - *outputType = API_OUT_MIX_PLAYBACK; - } else { - *outputType = API_OUTPUT_LEGACY; + ALOGV("getOutputForAttr() returns output %d", *output); + if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) { + *outputType = API_OUT_MIX_PLAYBACK; + } else { + *outputType = API_OUTPUT_LEGACY; + } + return NO_ERROR; } - return NO_ERROR; } // Virtual sources must always be dynamicaly or explicitly routed if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) { @@ -1638,7 +1640,7 @@ status_t AudioPolicyManager::startSource(const sp& outp DeviceVector devices; sp policyMix = outputDesc->mPolicyMix.promote(); const char *address = NULL; - if (policyMix != NULL) { + if (policyMix != nullptr) { audio_devices_t newDeviceType; address = policyMix->mDeviceAddress.string(); if ((policyMix->mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) { @@ -1820,7 +1822,7 @@ status_t AudioPolicyManager::stopSource(const sp& outpu sp policyMix = outputDesc->mPolicyMix.promote(); if (isSingleDeviceType( outputDesc->devices().types(), &audio_is_remote_submix_device) && - policyMix != NULL && + policyMix != nullptr && policyMix->mMixType == MIX_TYPE_RECORDERS) { setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, @@ -2267,7 +2269,7 @@ status_t AudioPolicyManager::startInput(audio_port_handle_t portId) if (status == NO_ERROR && inputDesc->activeCount() == 1) { sp policyMix = inputDesc->mPolicyMix.promote(); // if input maps to a dynamic policy with an activity listener, notify of state change - if ((policyMix != NULL) + if ((policyMix != nullptr) && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) { mpClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress, MIX_STATE_MIXING); @@ -2284,7 +2286,7 @@ status_t AudioPolicyManager::startInput(audio_port_handle_t portId) // For remote submix (a virtual device), we open only one input per capture request. if (audio_is_remote_submix_device(inputDesc->getDeviceType())) { String8 address = String8(""); - if (policyMix == NULL) { + if (policyMix == nullptr) { address = String8("0"); } else if (policyMix->mMixType == MIX_TYPE_PLAYERS) { address = policyMix->mDeviceAddress; @@ -2331,7 +2333,7 @@ status_t AudioPolicyManager::stopInput(audio_port_handle_t portId) } else { sp policyMix = inputDesc->mPolicyMix.promote(); // if input maps to a dynamic policy with an activity listener, notify of state change - if ((policyMix != NULL) + if ((policyMix != nullptr) && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) { mpClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress, MIX_STATE_IDLE); @@ -2341,7 +2343,7 @@ status_t AudioPolicyManager::stopInput(audio_port_handle_t portId) // used by a policy mix of type MIX_TYPE_RECORDERS if (audio_is_remote_submix_device(inputDesc->getDeviceType())) { String8 address = String8(""); - if (policyMix == NULL) { + if (policyMix == nullptr) { address = String8("0"); } else if (policyMix->mMixType == MIX_TYPE_PLAYERS) { address = policyMix->mDeviceAddress; @@ -5426,6 +5428,35 @@ audio_devices_t AudioPolicyManager::getDevicesForStream(audio_stream_type_t stre return deviceTypesToBitMask(devices.types()); } +status_t AudioPolicyManager::getDevicesForAttributes( + const audio_attributes_t &attr, AudioDeviceTypeAddrVector *devices) { + if (devices == nullptr) { + return BAD_VALUE; + } + // check dynamic policies but only for primary descriptors (secondary not used for audible + // audio routing, only used for duplication for playback capture) + sp policyDesc; + status_t status = mPolicyMixes.getOutputForAttr(attr, 0 /*uid unknown here*/, + AUDIO_OUTPUT_FLAG_NONE, policyDesc, nullptr); + if (status != OK) { + return status; + } + if (policyDesc != nullptr) { + sp mix = policyDesc->mPolicyMix.promote(); + if (mix != nullptr) { + AudioDeviceTypeAddr device(mix->mDeviceType, mix->mDeviceAddress.c_str()); + devices->push_back(device); + return NO_ERROR; + } + } + + DeviceVector curDevices = mEngine->getOutputDevicesForAttributes(attr, nullptr, false); + for (const auto& device : curDevices) { + devices->push_back(device->getDeviceTypeAddr()); + } + return NO_ERROR; +} + void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t stream) { switch(stream) { case AUDIO_STREAM_MUSIC: diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h index d6c1016fff..7e0e16f73e 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.h +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h @@ -193,6 +193,10 @@ public: // return the enabled output devices for the given stream type virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream); + virtual status_t getDevicesForAttributes( + const audio_attributes_t &attributes, + AudioDeviceTypeAddrVector *devices); + virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc = NULL); virtual status_t registerEffect(const effect_descriptor_t *desc, audio_io_handle_t io, diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index 44c1d09f92..01614ceb8c 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -801,6 +801,17 @@ audio_devices_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stre return mAudioPolicyManager->getDevicesForStream(stream); } +status_t AudioPolicyService::getDevicesForAttributes(const AudioAttributes &aa, + AudioDeviceTypeAddrVector *devices) const +{ + if (mAudioPolicyManager == NULL) { + return NO_INIT; + } + Mutex::Autolock _l(mLock); + AutoCallerClear acc; + return mAudioPolicyManager->getDevicesForAttributes(aa.getAttributes(), devices); +} + audio_io_handle_t AudioPolicyService::getOutputForEffect(const effect_descriptor_t *desc) { // FIXME change return type to status_t, and return NO_INIT here diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h index 135b3ac227..84adcc2de5 100644 --- a/services/audiopolicy/service/AudioPolicyService.h +++ b/services/audiopolicy/service/AudioPolicyService.h @@ -127,6 +127,8 @@ public: virtual uint32_t getStrategyForStream(audio_stream_type_t stream); virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream); + virtual status_t getDevicesForAttributes(const AudioAttributes &aa, + AudioDeviceTypeAddrVector *devices) const; virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc); virtual status_t registerEffect(const effect_descriptor_t *desc,