audiopolicy: align custom APM with AOSP.
Change-Id: Ic5112352c5aa1bcc9e889cca76048b6b27b2c4c6
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 3aff1d0..3885491 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -265,10 +265,11 @@
&& strncmp(device_address, "0", AUDIO_DEVICE_MAX_ADDRESS_LEN) != 0) {
for (audio_io_handle_t output : outputs) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
- if (desc->mPolicyMix != nullptr
- && desc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS
+ sp<AudioPolicyMix> policyMix = desc->mPolicyMix.promote();
+ if (policyMix != nullptr
+ && policyMix->mMixType == MIX_TYPE_RECORDERS
&& strncmp(device_address,
- desc->mPolicyMix->mDeviceAddress.string(),
+ policyMix->mDeviceAddress.string(),
AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
doCheckForDeviceAndOutputChanges = false;
break;
@@ -1040,12 +1041,13 @@
if (outputDesc->getActivityCount(clientVolSrc) == 1) {
// Automatically disable the remote submix input when output is stopped on a
// re routing mix of type MIX_TYPE_RECORDERS
+ sp<AudioPolicyMix> policyMix = outputDesc->mPolicyMix.promote();
if (audio_is_remote_submix_device(outputDesc->devices().types()) &&
- outputDesc->mPolicyMix != NULL &&
- outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
+ policyMix != NULL &&
+ policyMix->mMixType == MIX_TYPE_RECORDERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- outputDesc->mPolicyMix->mDeviceAddress,
+ policyMix->mDeviceAddress,
"remote-submix", AUDIO_FORMAT_DEFAULT);
}
}
@@ -1153,10 +1155,9 @@
(outputDesc->getPatchHandle() == AUDIO_PATCH_HANDLE_NONE);
DeviceVector devices;
- AudioMix *policyMix = NULL;
+ sp<AudioPolicyMix> policyMix = outputDesc->mPolicyMix.promote();
const char *address = NULL;
- if (outputDesc->mPolicyMix != NULL) {
- policyMix = outputDesc->mPolicyMix;
+ if (policyMix != NULL) {
audio_devices_t newDeviceType;
address = policyMix->mDeviceAddress.string();
if ((policyMix->mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) {
@@ -1244,7 +1245,8 @@
setOutputDevices(outputDesc, devices, force, 0, NULL, requiresMuteCheck);
// apply volume rules for current stream and device if necessary
- checkAndSetVolume(stream,
+ auto &curves = getVolumeCurves(client->attributes());
+ checkAndSetVolume(curves, client->volumeSource(),
getVolumeCurves(stream).getVolumeIndex(outputDesc->devices().types()),
outputDesc,
outputDesc->devices().types());
@@ -1282,29 +1284,34 @@
return NO_ERROR;
}
-status_t AudioPolicyManagerCustom::checkAndSetVolume(audio_stream_type_t stream,
- int index,
- const sp<AudioOutputDescriptor>& outputDesc,
- audio_devices_t device,
- int delayMs,
- bool force)
+status_t AudioPolicyManagerCustom::checkAndSetVolume(IVolumeCurves &curves,
+ VolumeSource volumeSource,
+ int index,
+ const sp<AudioOutputDescriptor>& outputDesc,
+ audio_devices_t device,
+ int delayMs,
+ bool force)
{
- if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
- ALOGW("checkAndSetVolume() invalid stream %d", stream);
- return INVALID_OPERATION;
- }
// do not change actual stream volume if the stream is muted
- if (outputDesc->isMuted(streamToVolumeSource(stream))) {
- ALOGVV("%s() stream %d muted count %d", __func__, stream, outputDesc->getMuteCount(stream));
+ if (outputDesc->isMuted(volumeSource)) {
+ ALOGVV("%s: volume source %d muted count %d active=%d", __func__, volumeSource,
+ outputDesc->getMuteCount(volumeSource), outputDesc->isActive(volumeSource));
return NO_ERROR;
}
+
+ VolumeSource callVolSrc = toVolumeSource(AUDIO_STREAM_VOICE_CALL);
+ VolumeSource btScoVolSrc = toVolumeSource(AUDIO_STREAM_BLUETOOTH_SCO);
+ bool isVoiceVolSrc = callVolSrc == volumeSource;
+ bool isBtScoVolSrc = btScoVolSrc == volumeSource;
+
audio_policy_forced_cfg_t forceUseForComm =
mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION);
// do not change in call volume if bluetooth is connected and vice versa
- if ((stream == AUDIO_STREAM_VOICE_CALL && forceUseForComm == AUDIO_POLICY_FORCE_BT_SCO) ||
- (stream == AUDIO_STREAM_BLUETOOTH_SCO && forceUseForComm != AUDIO_POLICY_FORCE_BT_SCO)) {
+ if ((callVolSrc != btScoVolSrc) &&
+ ((isVoiceVolSrc && forceUseForComm == AUDIO_POLICY_FORCE_BT_SCO) ||
+ (isBtScoVolSrc && forceUseForComm != AUDIO_POLICY_FORCE_BT_SCO))) {
ALOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm",
- stream, forceUseForComm);
+ volumeSource, forceUseForComm);
return INVALID_OPERATION;
}
@@ -1312,19 +1319,18 @@
device = outputDesc->devices().types();
}
- float volumeDb = computeVolume(stream, index, device);
+ float volumeDb = computeVolume(curves, volumeSource, index, device);
if (outputDesc->isFixedVolume(device)) {
volumeDb = 0.0f;
}
- outputDesc->setVolume(volumeDb, stream, device, delayMs, force);
+ outputDesc->setVolume(volumeDb, volumeSource, curves.getStreamTypes(), device, delayMs, force);
- if (stream == AUDIO_STREAM_VOICE_CALL ||
- stream == AUDIO_STREAM_BLUETOOTH_SCO) {
+ if (isVoiceVolSrc || isBtScoVolSrc) {
float voiceVolume;
// Force voice volume to max for bluetooth SCO as volume is managed by the headset
- if (stream == AUDIO_STREAM_VOICE_CALL) {
- voiceVolume = (float)index/(float)getVolumeCurves(stream).getVolumeIndexMax();
+ if (isVoiceVolSrc) {
+ voiceVolume = (float)index/(float)curves.getVolumeIndexMax();
} else {
voiceVolume = 1.0;
}
@@ -1389,15 +1395,20 @@
}
audio_io_handle_t AudioPolicyManagerCustom::getOutputForDevices(
- const DeviceVector &devices,
- audio_session_t session,
- audio_stream_type_t stream,
- const audio_config_t *config,
- audio_output_flags_t *flags)
+ const DeviceVector &devices,
+ audio_session_t session,
+ audio_stream_type_t stream,
+ const audio_config_t *config,
+ audio_output_flags_t *flags,
+ bool forceMutingHaptic)
{
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
status_t status;
+ // Discard haptic channel mask when forcing muting haptic channels.
+ audio_channel_mask_t channelMask = forceMutingHaptic
+ ? (config->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL) : config->channel_mask;
+
if (stream < AUDIO_STREAM_MIN || stream >= AUDIO_STREAM_CNT) {
ALOGE("%s: invalid stream %d", __func__, stream);
return AUDIO_IO_HANDLE_NONE;
@@ -1417,7 +1428,7 @@
// in case direct voip is bypassed
bool use_primary_out = true;
- if ((config->channel_mask == 1) &&
+ if ((channelMask == 1) &&
(config->sample_rate == 8000 || config->sample_rate == 16000 ||
config->sample_rate == 32000 || config->sample_rate == 48000)) {
// Allow Voip direct output only if:
@@ -1695,7 +1706,7 @@
// and not explicitly requested
if (((*flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
audio_is_linear_pcm(config->format) && config->sample_rate <= SAMPLE_RATE_HZ_MAX &&
- audio_channel_count_from_out_mask(config->channel_mask) <= 2) {
+ audio_channel_count_from_out_mask(channelMask) <= 2) {
goto non_direct_output;
}
@@ -1718,7 +1729,7 @@
profile = getProfileForOutput(devices,
config->sample_rate,
config->format,
- config->channel_mask,
+ channelMask,
(audio_output_flags_t)*flags,
true /* directOnly */);
@@ -1746,7 +1757,7 @@
// and configured with same parameters
if ((config->sample_rate == desc->mSamplingRate) &&
audio_formats_match(config->format, desc->mFormat) &&
- (config->channel_mask == desc->mChannelMask) &&
+ (channelMask == desc->mChannelMask) &&
(session == desc->mDirectClientSession)) {
desc->mDirectOpenCount++;
ALOGV("getOutputForDevice() reusing direct output %d for session %d",
@@ -1782,11 +1793,11 @@
(config->sample_rate != 0 && config->sample_rate != outputDesc->mSamplingRate) ||
(config->format != AUDIO_FORMAT_DEFAULT &&
!audio_formats_match(config->format, outputDesc->mFormat)) ||
- (config->channel_mask != 0 && config->channel_mask != outputDesc->mChannelMask)) {
+ (channelMask != 0 && channelMask != outputDesc->mChannelMask)) {
ALOGV("getOutputForDevice() failed opening direct output: output %d sample rate %d %d,"
"format %d %d, channel mask %04x %04x", output, config->sample_rate,
outputDesc->mSamplingRate, config->format, outputDesc->mFormat,
- config->channel_mask, outputDesc->mChannelMask);
+ channelMask, outputDesc->mChannelMask);
if (output != AUDIO_IO_HANDLE_NONE) {
outputDesc->close();
}
@@ -1843,7 +1854,7 @@
ALOGW_IF((output == 0), "getOutputForDevice() could not find output for stream %d, "
"sampling rate %d, format %#x, channels %#x, flags %#x",
- stream, config->sample_rate, config->format, config->channel_mask, *flags);
+ stream, config->sample_rate, config->format, channelMask, *flags);
ALOGV("getOutputForDevice() returns output %d", output);
@@ -2029,10 +2040,11 @@
setInputDevice(input, device, true /* force */);
if (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 ((inputDesc->mPolicyMix != NULL)
- && ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
- mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
+ if ((policyMix != NULL)
+ && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
+ mpClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress,
MIX_STATE_MIXING);
}
@@ -2050,10 +2062,10 @@
// 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 (inputDesc->mPolicyMix == NULL) {
+ if (policyMix == NULL) {
address = String8("0");
- } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
- address = inputDesc->mPolicyMix->mDeviceAddress;
+ } else if (policyMix->mMixType == MIX_TYPE_PLAYERS) {
+ address = policyMix->mDeviceAddress;
}
if (address != "") {
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index 96d7dcb..5a8a907 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -115,11 +115,12 @@
static sp<APMConfigHelper> mApmConfigs;
protected:
- status_t checkAndSetVolume(audio_stream_type_t stream,
- int index,
- const sp<AudioOutputDescriptor>& outputDesc,
- audio_devices_t device,
- int delayMs = 0, bool force = false);
+ // check that volume change is permitted, compute and send new volume to audio hardware
+ virtual status_t checkAndSetVolume(IVolumeCurves &curves,
+ VolumeSource volumeSource, int index,
+ const sp<AudioOutputDescriptor>& outputDesc,
+ audio_devices_t device,
+ int delayMs = 0, bool force = false);
// avoid invalidation for active music stream on previous outputs
// which is supported on the new device.
@@ -156,8 +157,8 @@
audio_session_t session,
audio_stream_type_t stream,
const audio_config_t *config,
- audio_output_flags_t *flags);
-
+ audio_output_flags_t *flags,
+ bool forceMutingHaptic = false);
// internal method to fill offload info in case of Direct PCM
status_t getOutputForAttr(const audio_attributes_t *attr,