summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArne Coucheron <arco68@gmail.com>2016-03-18 20:08:41 +0100
committerEthan Chen <intervigil@gmail.com>2016-03-18 13:05:48 -0700
commitef63860862a1ea7225868158f5d8c8a8c70a9596 (patch)
tree1a1341c865c49fbed8f93d9e938de45aa5117cf9
parentfb3b822e3e5f044969629d75b43d4865943a35c9 (diff)
downloadhardware_qcom_audio-stable/cm-13.0-caf-8960-ZNH2KB.tar.gz
hardware_qcom_audio-stable/cm-13.0-caf-8960-ZNH2KB.tar.bz2
hardware_qcom_audio-stable/cm-13.0-caf-8960-ZNH2KB.zip
policy_hal: Always call local implementation of updateCallRoutingstable/cm-13.0-caf-8960-ZNH2KBstable/cm-13.0-caf-8960-ZNH2K
* updateCallRouting is not a virtual function, so any calls to the local implementation from the superclass will call the superclass's version instead of correctly calling the local version. * Override implementations of virtual functions that DO call updateCallRouting (setDeviceConnectionState, setPhoneState, setForceUse) to ensure the local version of the function is called. Change-Id: I071e2bf1ce4bf36f691c4808bf63610bcbb93227
-rw-r--r--legacy/policy_hal/AudioPolicyManager.cpp184
-rw-r--r--legacy/policy_hal/AudioPolicyManager.h13
2 files changed, 191 insertions, 6 deletions
diff --git a/legacy/policy_hal/AudioPolicyManager.cpp b/legacy/policy_hal/AudioPolicyManager.cpp
index 7090ac19..4fb745d3 100644
--- a/legacy/policy_hal/AudioPolicyManager.cpp
+++ b/legacy/policy_hal/AudioPolicyManager.cpp
@@ -94,10 +94,24 @@ void AudioPolicyManagerCustom::checkA2dpSuspend()
}
}
+status_t AudioPolicyManagerCustom::setDeviceConnectionState(audio_devices_t device,
+ audio_policy_dev_state_t state,
+ const char *device_address,
+ const char *device_name)
+{
+ return setDeviceConnectionStateInt(device, state, device_address, device_name);
+}
+
+/* NOTE: setDeviceConnectionStateInt is also called by
+ * unregisterPolicyMixes
+ * registerPolicyMixes
+ * stopInput
+ * startInput
+ */
status_t AudioPolicyManagerCustom::setDeviceConnectionStateInt(audio_devices_t device,
- audio_policy_dev_state_t state,
- const char *device_address,
- const char *device_name)
+ audio_policy_dev_state_t state,
+ const char *device_address,
+ const char *device_name)
{
ALOGV("setDeviceConnectionStateInt() device: 0x%X, state %d, address %s name %s",
device, state, device_address, device_name);
@@ -360,6 +374,11 @@ status_t AudioPolicyManagerCustom::setDeviceConnectionStateInt(audio_devices_t d
return BAD_VALUE;
}
+/* NOTE: updateCallRouting is called by:
+ * setForceUse
+ * setPhoneState
+ * setDeviceConnectionStateInt
+ */
void AudioPolicyManagerCustom::updateCallRouting(audio_devices_t rxDevice, int delayMs)
{
bool createTxPatch = false;
@@ -689,6 +708,165 @@ status_t AudioPolicyManagerCustom::getInputForAttr(const audio_attributes_t *att
return NO_ERROR;
}
+void AudioPolicyManagerCustom::setPhoneState(audio_mode_t state)
+{
+ ALOGV("setPhoneState() state %d", state);
+ // store previous phone state for management of sonification strategy below
+ int oldState = mEngine->getPhoneState();
+
+ if (mEngine->setPhoneState(state) != NO_ERROR) {
+ ALOGW("setPhoneState() invalid or same state %d", state);
+ return;
+ }
+ /// Opens: can these line be executed after the switch of volume curves???
+ // if leaving call state, handle special case of active streams
+ // pertaining to sonification strategy see handleIncallSonification()
+ if (isStateInCall(oldState)) {
+ ALOGV("setPhoneState() in call state management: new state is %d", state);
+ for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
+ if (stream == AUDIO_STREAM_PATCH) {
+ continue;
+ }
+ handleIncallSonification((audio_stream_type_t)stream, false, true);
+ }
+
+ // force reevaluating accessibility routing when call stops
+ mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY);
+ }
+
+ /**
+ * Switching to or from incall state or switching between telephony and VoIP lead to force
+ * routing command.
+ */
+ bool force = ((is_state_in_call(oldState) != is_state_in_call(state))
+ || (is_state_in_call(state) && (state != oldState)));
+
+ // check for device and output changes triggered by new phone state
+ checkA2dpSuspend();
+ checkOutputForAllStrategies();
+ updateDevicesAndOutputs();
+
+ int delayMs = 0;
+ if (isStateInCall(state)) {
+ nsecs_t sysTime = systemTime();
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ // mute media and sonification strategies and delay device switch by the largest
+ // latency of any output where either strategy is active.
+ // This avoid sending the ring tone or music tail into the earpiece or headset.
+ if ((isStrategyActive(desc, STRATEGY_MEDIA,
+ SONIFICATION_HEADSET_MUSIC_DELAY,
+ sysTime) ||
+ isStrategyActive(desc, STRATEGY_SONIFICATION,
+ SONIFICATION_HEADSET_MUSIC_DELAY,
+ sysTime)) &&
+ (delayMs < (int)desc->latency()*2)) {
+ delayMs = desc->latency()*2;
+ }
+ setStrategyMute(STRATEGY_MEDIA, true, desc);
+ setStrategyMute(STRATEGY_MEDIA, false, desc, MUTE_TIME_MS,
+ getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/));
+ setStrategyMute(STRATEGY_SONIFICATION, true, desc);
+ setStrategyMute(STRATEGY_SONIFICATION, false, desc, MUTE_TIME_MS,
+ getDeviceForStrategy(STRATEGY_SONIFICATION, true /*fromCache*/));
+ }
+ }
+
+ if (hasPrimaryOutput()) {
+ // Note that despite the fact that getNewOutputDevice() is called on the primary output,
+ // the device returned is not necessarily reachable via this output
+ audio_devices_t rxDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/);
+ // force routing command to audio hardware when ending call
+ // even if no device change is needed
+ if (isStateInCall(oldState) && rxDevice == AUDIO_DEVICE_NONE) {
+ rxDevice = mPrimaryOutput->device();
+ }
+
+ if (state == AUDIO_MODE_IN_CALL) {
+ updateCallRouting(rxDevice, delayMs);
+ } else if (oldState == AUDIO_MODE_IN_CALL) {
+ if (mCallRxPatch != 0) {
+ mpClientInterface->releaseAudioPatch(mCallRxPatch->mAfPatchHandle, 0);
+ mCallRxPatch.clear();
+ }
+ if (mCallTxPatch != 0) {
+ mpClientInterface->releaseAudioPatch(mCallTxPatch->mAfPatchHandle, 0);
+ mCallTxPatch.clear();
+ }
+ setOutputDevice(mPrimaryOutput, rxDevice, force, 0);
+ } else {
+ setOutputDevice(mPrimaryOutput, rxDevice, force, 0);
+ }
+ }
+ // if entering in call state, handle special case of active streams
+ // pertaining to sonification strategy see handleIncallSonification()
+ if (isStateInCall(state)) {
+ ALOGV("setPhoneState() in call state management: new state is %d", state);
+ for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
+ if (stream == AUDIO_STREAM_PATCH) {
+ continue;
+ }
+ handleIncallSonification((audio_stream_type_t)stream, true, true);
+ }
+
+ // force reevaluating accessibility routing when call starts
+ mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY);
+ }
+
+ // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE
+ if (state == AUDIO_MODE_RINGTONE &&
+ isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) {
+ mLimitRingtoneVolume = true;
+ } else {
+ mLimitRingtoneVolume = false;
+ }
+}
+
+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());
+
+ if (mEngine->setForceUse(usage, config) != NO_ERROR) {
+ ALOGW("setForceUse() could not set force cfg %d for usage %d", config, usage);
+ return;
+ }
+ bool forceVolumeReeval = (usage == AUDIO_POLICY_FORCE_FOR_COMMUNICATION) ||
+ (usage == AUDIO_POLICY_FORCE_FOR_DOCK) ||
+ (usage == AUDIO_POLICY_FORCE_FOR_SYSTEM);
+
+ // check for device and output changes triggered by new force usage
+ checkA2dpSuspend();
+ checkOutputForAllStrategies();
+ updateDevicesAndOutputs();
+ if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
+ audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, true /*fromCache*/);
+ updateCallRouting(newDevice);
+ }
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
+ audio_devices_t newDevice = getNewOutputDevice(outputDesc, true /*fromCache*/);
+ if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (outputDesc != mPrimaryOutput)) {
+ setOutputDevice(outputDesc, newDevice, (newDevice != AUDIO_DEVICE_NONE));
+ }
+ if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) {
+ applyStreamVolumes(outputDesc, newDevice, 0, true);
+ }
+ }
+
+ audio_io_handle_t activeInput = mInputs.getActiveInput();
+ if (activeInput != 0) {
+ 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->mSupportedDevices.types() & (newDevice & ~AUDIO_DEVICE_BIT_IN)) {
+ setInputDevice(activeInput, newDevice);
+ } else {
+ closeInput(activeInput);
+ }
+ }
+}
+
status_t AudioPolicyManagerCustom::checkAndSetVolume(audio_stream_type_t stream,
int index,
const sp<AudioOutputDescriptor>& outputDesc,
diff --git a/legacy/policy_hal/AudioPolicyManager.h b/legacy/policy_hal/AudioPolicyManager.h
index 1818b2b4..1b2420e5 100644
--- a/legacy/policy_hal/AudioPolicyManager.h
+++ b/legacy/policy_hal/AudioPolicyManager.h
@@ -35,10 +35,14 @@ public:
virtual ~AudioPolicyManagerCustom() {}
+ virtual status_t setDeviceConnectionState(audio_devices_t device,
+ audio_policy_dev_state_t state,
+ const char *device_address,
+ const char *device_name);
status_t setDeviceConnectionStateInt(audio_devices_t device,
- audio_policy_dev_state_t state,
- const char *device_address,
- const char *device_name);
+ audio_policy_dev_state_t state,
+ const char *device_address,
+ const char *device_name);
virtual status_t getInputForAttr(const audio_attributes_t *attr,
audio_io_handle_t *input,
audio_session_t session,
@@ -49,6 +53,9 @@ public:
audio_input_flags_t flags,
audio_port_handle_t selectedDeviceId,
input_type_t *inputType);
+ virtual void setPhoneState(audio_mode_t state);
+ virtual void setForceUse(audio_policy_force_use_t usage,
+ audio_policy_forced_cfg_t config);
protected:
// manages A2DP output suspend/restore according to phone state and BT SCO usage