Merge "APM: support querying of audio playback routing"

gugelfrei
TreeHugger Robot 5 years ago committed by Android (Google) Code Review
commit 2623d36522

@ -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<IAudioPolicyService>& 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<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();

@ -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<status_t>(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<status_t>(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);
}

@ -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,

@ -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,

@ -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,

@ -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);
}
}
}
}

@ -971,19 +971,21 @@ status_t AudioPolicyManager::getOutputForAttrInt(
if (usePrimaryOutputFromPolicyMixes) {
*output = policyDesc->mIoHandle;
sp<AudioPolicyMix> mix = policyDesc->mPolicyMix.promote();
sp<DeviceDescriptor> deviceDesc =
mAvailableOutputDevices.getDevice(mix->mDeviceType,
mix->mDeviceAddress,
AUDIO_FORMAT_DEFAULT);
*selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
if (mix != nullptr) {
sp<DeviceDescriptor> 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<SwAudioOutputDescriptor>& outp
DeviceVector devices;
sp<AudioPolicyMix> 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<SwAudioOutputDescriptor>& outpu
sp<AudioPolicyMix> 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<AudioPolicyMix> 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<AudioPolicyMix> 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<SwAudioOutputDescriptor> 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<AudioPolicyMix> 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:

@ -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,

@ -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

@ -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,

Loading…
Cancel
Save