diff options
author | Arne Coucheron <arco68@gmail.com> | 2016-03-18 20:08:41 +0100 |
---|---|---|
committer | Ethan Chen <intervigil@gmail.com> | 2016-03-18 13:05:48 -0700 |
commit | ef63860862a1ea7225868158f5d8c8a8c70a9596 (patch) | |
tree | 1a1341c865c49fbed8f93d9e938de45aa5117cf9 | |
parent | fb3b822e3e5f044969629d75b43d4865943a35c9 (diff) | |
download | hardware_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.cpp | 184 | ||||
-rw-r--r-- | legacy/policy_hal/AudioPolicyManager.h | 13 |
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 |