policy-hal: enable custom audio policy
-This change enable custom audio policy and also includes
the fixes that went in to audio policy manager.
audio policy: add support for external audio sources
Change-Id: If5805d58a4356b2f681f1aabf54375f62b55b98a
Add setMasterMono and getMasterMono
Change-Id: I32dc1fcecf285967a61bd508af3bb299595db57d
AudioPolicy: AudioOutputDescriptor set/get for patch handle
Change-Id: I5bffecf7a157ec042d749064208bc6c279008542
AudioPolicyManager: force encoded surround setting
Change-Id: I0f7a486bf1aa7a27f15cf220e2c75ef23f8f8536
audio: several fixes in audio routing callbacks
Change-Id: Ieb0d9f92f563a40552eb31bc0499c8ac65f78ce4
audio policy: move volume table to XML file
Change-Id: I78c91bc3378b6c47202abe7b5c1c1e011ff62eed
AudioPolicy: capture sample rate 0 is route-specific default
Change-Id: I7d193640572c08ab5e5f1ecfc8ad6d31635967dd
audio policy: remove deserialization from policy objects
Change-Id: I1ce798848f4657b37e47446c9fbdc63f7ed0390e
DO NOT MERGE - audio policy: disable concurrent capture
Change-Id: I9085918f1f7b12e28430958cceb768bb29c12bdb
audio policy: select output with best sample format match
Change-Id: I31981940be5d1c06d713d52187cfb0a7bf355773
audio policy: audio sessions on input descriptors
Change-Id: I915a65989a7fd0d3cbe2fcf5a0aee2ea0df5f4f5
Call SoundTrigger::setCaptureState in AudioPoilcyManager::closeAllInputs
Change-Id: I613434ecacce3ef03a657008fd94c314948ba2b8
Change-Id: Iee8ef2647691fe1167b95f19357f17c28f54bf0e
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index cbebf42..2f657d5 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -116,7 +116,7 @@
const char *device_address,
const char *device_name)
{
- ALOGV("setDeviceConnectionStateInt() device: 0x%X, state %d, address %s name %s",
+ ALOGD("setDeviceConnectionStateInt() device: 0x%X, state %d, address %s name %s",
device, state, device_address, device_name);
// connect/disconnect only 1 device at a time
@@ -314,6 +314,10 @@
}
}
+ if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
+ cleanUpForDevice(devDesc);
+ }
+
mpClientInterface->onAudioPortListUpdate();
return NO_ERROR;
} // end if is output device
@@ -390,6 +394,10 @@
updateCallRouting(newDevice);
}
+ if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
+ cleanUpForDevice(devDesc);
+ }
+
mpClientInterface->onAudioPortListUpdate();
return NO_ERROR;
} // end if is input device
@@ -409,6 +417,11 @@
offloadInfo.format,
offloadInfo.stream_type, offloadInfo.bit_rate, offloadInfo.duration_us,
offloadInfo.has_video);
+
+ if (mMasterMono) {
+ return false; // no offloading if mono is set.
+ }
+
#ifdef VOICE_CONCURRENCY
char concpropValue[PROPERTY_VALUE_MAX];
if (property_get("voice.playback.conc.disabled", concpropValue, NULL)) {
@@ -584,12 +597,12 @@
{
audio_devices_t device = AUDIO_DEVICE_NONE;
- ssize_t index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle);
+ ssize_t index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
if (patchDesc->mUid != mUidCached) {
ALOGV("getNewOutputDevice() device %08x forced by patch %d",
- outputDesc->device(), outputDesc->mPatchHandle);
+ outputDesc->device(), outputDesc->getPatchHandle());
return outputDesc->device();
}
}
@@ -647,7 +660,7 @@
void AudioPolicyManagerCustom::setPhoneState(audio_mode_t state)
{
- ALOGV("setPhoneState() state %d", state);
+ ALOGD("setPhoneState() state %d", state);
// store previous phone state for management of sonification strategy below
audio_devices_t newDevice = AUDIO_DEVICE_NONE;
int oldState = mEngine->getPhoneState();
@@ -961,8 +974,9 @@
void AudioPolicyManagerCustom::setForceUse(audio_policy_force_use_t usage,
audio_policy_forced_cfg_t config)
{
- ALOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mEngine->getPhoneState());
+ ALOGD("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mEngine->getPhoneState());
+ audio_policy_forced_cfg_t originalConfig = mEngine->getForceUse(usage);
if (mEngine->setForceUse(usage, config) != NO_ERROR) {
ALOGW("setForceUse() could not set force cfg %d for usage %d", config, usage);
return;
@@ -975,6 +989,33 @@
checkA2dpSuspend();
checkOutputForAllStrategies();
updateDevicesAndOutputs();
+
+ // Did surround forced use change?
+ if ((usage == AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND)
+ && (originalConfig != config)) {
+ const char *device_address = "";
+ // Is it currently connected? If so then cycle the connection
+ // so that the supported surround formats will be reloaded.
+ //
+ // FIXME As S/PDIF is not a removable device we have to handle this differently.
+ // Probably by updating the device descriptor directly and manually
+ // tearing down active playback on S/PDIF
+ if (getDeviceConnectionState(AUDIO_DEVICE_OUT_HDMI, device_address) ==
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+ // Disconnect and reconnect output devices so that the surround
+ // encodings can be updated.
+ const char *device_name = "";
+ // disconnect
+ setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ device_address, device_name);
+ // reconnect
+ setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ device_address, device_name);
+ }
+ }
+
if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, true /*fromCache*/);
updateCallRouting(newDevice);
@@ -999,9 +1040,15 @@
audio_io_handle_t activeInput = mInputs.getActiveInput();
if (activeInput != 0) {
- setInputDevice(activeInput, getNewInputDevice(activeInput));
+ sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
+ audio_devices_t newDevice = getNewInputDevice(activeInput);
+ // Force new input selection if the new device can not be reached via current input
+ if (activeDesc->mProfile->getSupportedDevices().types() & (newDevice & ~AUDIO_DEVICE_BIT_IN)) {
+ setInputDevice(activeInput, newDevice);
+ } else {
+ closeInput(activeInput);
+ }
}
-
}
status_t AudioPolicyManagerCustom::stopSource(sp<AudioOutputDescriptor> outputDesc,
@@ -1088,7 +1135,7 @@
*delayMs = 0;
if (stream == AUDIO_STREAM_TTS) {
ALOGV("\t found BEACON stream");
- if (mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
+ if (!mTtsOutputAvailable && mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
return INVALID_OPERATION;
} else {
beaconMuteLatency = handleEventForBeacon(STARTING_BEACON);
@@ -1098,6 +1145,9 @@
beaconMuteLatency = handleEventForBeacon(STARTING_OUTPUT);
}
+ // check active before incrementing usage count
+ bool force = !outputDesc->isActive();
+
// increment usage count for this stream on the requested output:
// NOTE that the usage count is the same for duplicated output and hardware output which is
// necessary for a correct control of hardware output routing by startOutput() and stopOutput()
@@ -1113,7 +1163,6 @@
(strategy == STRATEGY_SONIFICATION_RESPECTFUL) ||
(beaconMuteLatency > 0);
uint32_t waitMs = beaconMuteLatency;
- bool force = false;
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i);
if (desc != outputDesc) {
@@ -1134,7 +1183,8 @@
}
}
}
- uint32_t muteWaitMs = setOutputDevice(outputDesc, device, force);
+ uint32_t muteWaitMs;
+ muteWaitMs = setOutputDevice(outputDesc, device, force);
// handle special case for sonification while in call
if (isInCall()) {
@@ -1143,7 +1193,7 @@
// apply volume rules for current stream and device if necessary
checkAndSetVolume(stream,
- mStreams.valueFor(stream).getVolumeIndex(device),
+ mVolumeCurves->getVolumeIndex(stream, device),
outputDesc,
device);
@@ -1271,7 +1321,7 @@
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)mStreams.valueFor(stream).getVolumeIndexMax();
+ voiceVolume = (float)index/(float)mVolumeCurves->getVolumeIndexMax(stream);
} else {
voiceVolume = 1.0;
}
@@ -1369,7 +1419,6 @@
const audio_offload_info_t *offloadInfo)
{
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- uint32_t latency = 0;
status_t status;
#ifdef AUDIO_POLICY_TEST
@@ -1614,7 +1663,7 @@
// skip direct output selection if the request can obviously be attached to a mixed output
// and not explicitly requested
if (((flags & (AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_DIRECT_PCM)) == 0) &&
- audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE &&
+ audio_is_linear_pcm(format) && samplingRate <= SAMPLE_RATE_HZ_MAX &&
audio_channel_count_from_out_mask(channelMask) <= 2) {
goto non_direct_output;
}
@@ -1627,7 +1676,7 @@
// in the background.
if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
- !mEffects.isNonOffloadableEffectEnabled()) {
+ !(mEffects.isNonOffloadableEffectEnabled() || mMasterMono)) {
profile = getProfileForDirectOutput(device,
samplingRate,
format,
@@ -1638,7 +1687,7 @@
if (profile != 0) {
if (!(flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
- (profile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
+ (profile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
ALOGI("got Direct_PCM without requesting ... reject ");
profile = NULL;
goto non_direct_output;
@@ -1657,7 +1706,7 @@
outputDesc = desc;
// reuse direct output if currently open and configured with same parameters
if ((samplingRate == outputDesc->mSamplingRate) &&
- (format == outputDesc->mFormat) &&
+ audio_formats_match(format, outputDesc->mFormat) &&
(channelMask == outputDesc->mChannelMask)) {
outputDesc->mDirectOpenCount++;
ALOGV("getOutput() reusing direct output %d", mOutputs.keyAt(i));
@@ -1674,7 +1723,7 @@
// if the selected profile is offloaded and no offload info was specified,
// create a default one
audio_offload_info_t defaultOffloadInfo = AUDIO_INFO_INITIALIZER;
- if ((profile->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && !offloadInfo) {
+ if ((profile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && !offloadInfo) {
flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
defaultOffloadInfo.sample_rate = samplingRate;
defaultOffloadInfo.channel_mask = channelMask;
@@ -1709,7 +1758,7 @@
// only accept an output with the requested parameters
if (status != NO_ERROR ||
(samplingRate != 0 && samplingRate != config.sample_rate) ||
- (format != AUDIO_FORMAT_DEFAULT && format != config.format) ||
+ (format != AUDIO_FORMAT_DEFAULT && !audio_formats_match(format, config.format)) ||
(channelMask != 0 && channelMask != config.channel_mask)) {
ALOGV("getOutput() failed opening direct output: output %d samplingRate %d %d,"
"format %d %d, channelMask %04x %04x", output, samplingRate,
@@ -1719,7 +1768,7 @@
mpClientInterface->closeOutput(output);
}
// fall back to mixer output if possible when the direct output could not be open
- if (audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE) {
+ if (audio_is_linear_pcm(format) && samplingRate <= SAMPLE_RATE_HZ_MAX) {
goto non_direct_output;
}
return AUDIO_IO_HANDLE_NONE;
@@ -1797,7 +1846,8 @@
audio_port_handle_t selectedDeviceId,
input_type_t *inputType)
{
- audio_source_t inputSource = attr->source;
+ audio_source_t inputSource;
+ inputSource = attr->source;
#ifdef VOICE_CONCURRENCY
char propValue[PROPERTY_VALUE_MAX];
@@ -1881,8 +1931,8 @@
}
sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index);
- index = inputDesc->mSessions.indexOf(session);
- if (index < 0) {
+ sp<AudioSession> audioSession = inputDesc->getAudioSession(session);
+ if (audioSession == 0) {
ALOGW("startInput() unknown session %d on input %d", session, input);
return BAD_VALUE;
}
@@ -1897,15 +1947,31 @@
// If the already active input uses AUDIO_SOURCE_HOTWORD then it is closed,
// otherwise the active input continues and the new input cannot be started.
sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
- if (activeDesc->mInputSource == AUDIO_SOURCE_HOTWORD) {
+ if ((activeDesc->inputSource() == AUDIO_SOURCE_HOTWORD) &&
+ !activeDesc->hasPreemptedSession(session)) {
ALOGW("startInput(%d) preempting low-priority input %d", input, activeInput);
- stopInput(activeInput, activeDesc->mSessions.itemAt(0));
- releaseInput(activeInput, activeDesc->mSessions.itemAt(0));
+ //FIXME: consider all active sessions
+ AudioSessionCollection activeSessions = activeDesc->getActiveAudioSessions();
+ audio_session_t activeSession = activeSessions.keyAt(0);
+ SortedVector<audio_session_t> sessions =
+ activeDesc->getPreemptedSessions();
+ sessions.add(activeSession);
+ inputDesc->setPreemptedSessions(sessions);
+ stopInput(activeInput, activeSession);
+ releaseInput(activeInput, activeSession);
} else {
ALOGE("startInput(%d) failed: other input %d already started", input, activeInput);
return INVALID_OPERATION;
}
}
+ // Do not allow capture if an active voice call is using a software patch and
+ // the call TX source device is on the same HW module.
+ // FIXME: would be better to refine to only inputs whose profile connects to the
+ // call TX device but this information is not in the audio patch
+ if (mCallTxPatch != 0 &&
+ inputDesc->getModuleHandle() == mCallTxPatch->mPatch.sources[0].ext.device.hw_module) {
+ return INVALID_OPERATION;
+ }
}
// Routing?
@@ -1954,7 +2020,7 @@
}
#endif
- if (inputDesc->mRefCount == 0 || mInputRoutes.hasRouteChanged(session)) {
+ if (!inputDesc->isActive() || mInputRoutes.hasRouteChanged(session)) {
// 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)) {
@@ -1985,9 +2051,9 @@
}
}
- ALOGV("AudioPolicyManager::startInput() input source = %d", inputDesc->mInputSource);
+ ALOGV("AudioPolicyManager::startInput() input source = %d", audioSession->inputSource());
- inputDesc->mRefCount++;
+ audioSession->changeActiveCount(1);
#ifdef RECORD_PLAY_CONCURRENCY
mIsInputRequestOnProgress = false;
#endif
@@ -2034,20 +2100,24 @@
for(size_t input_index = mInputs.size(); input_index > 0; input_index--) {
sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(input_index-1);
- ssize_t patch_index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+ ssize_t patch_index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
if (patch_index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(patch_index);
- status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
+ status_t status;
+ status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
mAudioPatches.removeItemsAt(patch_index);
patchRemoved = true;
}
- if ((inputDesc->mIsSoundTrigger) && (mInputs.size() == 1)) {
+ if ((inputDesc->getOpenRefCount() > 0) && inputDesc->isSoundTrigger()
+ && (mInputs.size() == 1)) {
ALOGD("Do not close sound trigger input handle");
} else {
mpClientInterface->closeInput(mInputs.keyAt(input_index-1));
mInputs.removeItem(mInputs.keyAt(input_index-1));
}
}
+ mInputs.clear();
+ SoundTrigger::setCaptureState(false);
nextAudioPortGeneration();
if (patchRemoved) {
@@ -2063,6 +2133,9 @@
mPrevFMVolumeDb(0.0f),
mFMIsActive(false)
{
+
+ //TODO: Check the new logic to parse policy conf and update the below code
+ // Need this when SSR encoding is enabled
char ssr_enabled[PROPERTY_VALUE_MAX] = {0};
bool prop_ssr_enabled = false;
@@ -2071,29 +2144,30 @@
}
for (size_t i = 0; i < mHwModules.size(); i++) {
- ALOGV("Hw module %d", i);
+ ALOGV("Hw module %zu", i);
for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) {
const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j];
- ALOGV("Input profile ", j);
- for (size_t k = 0; k < inProfile->mChannelMasks.size(); k++) {
- audio_channel_mask_t channelMask =
- inProfile->mChannelMasks.itemAt(k);
- ALOGV("Channel Mask %x size %d", channelMask,
- inProfile->mChannelMasks.size());
- if (AUDIO_CHANNEL_IN_5POINT1 == channelMask) {
- if (!prop_ssr_enabled) {
- ALOGI("removing AUDIO_CHANNEL_IN_5POINT1 from"
- " input profile as SSR(surround sound record)"
- " is not supported on this chipset variant");
- inProfile->mChannelMasks.removeItemsAt(k, 1);
- ALOGV("Channel Mask size now %d",
- inProfile->mChannelMasks.size());
+ AudioProfileVector profiles = inProfile->getAudioProfiles();
+ for (size_t k = 0; k < profiles.size(); k++){
+ ChannelsVector channels = profiles[k]->getChannels();
+ for (size_t x = 0; x < channels.size(); x++) {
+ audio_channel_mask_t channelMask = channels[x];
+ ALOGV("Channel Mask %x size %zu", channelMask,
+ channels.size());
+ if (AUDIO_CHANNEL_IN_5POINT1 == channelMask) {
+ if (!prop_ssr_enabled) {
+ ALOGI("removing AUDIO_CHANNEL_IN_5POINT1 from"
+ " input profile as SSR(surround sound record)"
+ " is not supported on this chipset variant");
+ channels.removeItemsAt(x, 1);
+ ALOGV("Channel Mask size now %zu",
+ channels.size());
+ }
}
}
}
}
}
-
#ifdef RECORD_PLAY_CONCURRENCY
mIsInputRequestOnProgress = false;
#endif
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index af8c2a8..160fabc 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2009 The Android Open Source Project
@@ -149,7 +149,9 @@
const audio_offload_info_t *offloadInfo);
// Used for voip + voice concurrency usecase
int mPrevPhoneState;
+#ifdef VOICE_CONCURRENCY
int mvoice_call_state;
+#endif
#ifdef RECORD_PLAY_CONCURRENCY
// Used for record + playback concurrency
bool mIsInputRequestOnProgress;