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 d1b85c81ff..75c89aa16e 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) { @@ -1646,7 +1648,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) { @@ -1828,7 +1830,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, @@ -2275,7 +2277,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); @@ -2292,7 +2294,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; @@ -2339,7 +2341,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); @@ -2349,7 +2351,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; @@ -5437,6 +5439,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 d245231b2c..68a2a8cf19 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -806,6 +806,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,