status_t AudioPolicyManager::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session) { LOGV("stopOutput() output %d, stream %d", output, stream); ssize_t index = mOutputs.indexOfKey(output); if (index < 0) { LOGW("stopOutput() unknow output %d", output); return BAD_VALUE; } AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index); routing_strategy strategy = AudioPolicyManagerBase::getStrategy((AudioSystem::stream_type)stream); // handle special case for sonification while in call if (isInCall()) { AudioPolicyManagerBase::handleIncallSonification(stream, false, false); } if (outputDesc->mRefCount[stream] > 0) { // decrement usage count of this stream on the output outputDesc->changeRefCount(stream, -1); // store time at which the last music track was stopped - see computeVolume() if (stream == AudioSystem::MUSIC) { outputDesc->mStopTime[stream] = systemTime(); // mMusicStopTime = systemTime(); } #ifdef WITH_QCOM_LPA uint32_t newDevice = AudioPolicyManagerBase::getNewDevice(mHardwareOutput, false); if(newDevice == 0 && mLPADecodeOutput != -1) { newDevice = AudioPolicyManagerBase::getNewDevice(mLPADecodeOutput, false); } setOutputDevice(output, newDevice); #else setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output)); #endif #ifdef WITH_A2DP if (mA2dpOutput != 0 && !a2dpUsedForSonification() && (strategy == STRATEGY_SONIFICATION || strategy == STRATEGY_ENFORCED_AUDIBLE)) { setStrategyMute(STRATEGY_MEDIA, false, mA2dpOutput, mOutputs.valueFor(mHardwareOutput)->mLatency*2); } #endif if (output != mHardwareOutput) { setOutputDevice(mHardwareOutput, AudioPolicyManagerBase::getNewDevice(mHardwareOutput), true); } return NO_ERROR; } else { LOGW("stopOutput() refcount is already 0 for output %d", output); return INVALID_OPERATION; } }
HidController::HidController(const hid_device_info deviceInfo) : m_pHidDevice(NULL) { // Copy required variables from deviceInfo, which will be freed after // this class is initialized by caller. hid_vendor_id = deviceInfo.vendor_id; hid_product_id = deviceInfo.product_id; hid_interface_number = deviceInfo.interface_number; if (hid_interface_number == -1) { // OS/X and windows don't use interface numbers, but usage_page/usage hid_usage_page = deviceInfo.usage_page; hid_usage = deviceInfo.usage; } else { // Linux hidapi does not set value for usage_page or usage and uses // interface number to identify subdevices hid_usage_page = 0; hid_usage = 0; } // Don't trust path to be null terminated. hid_path = new char[PATH_MAX + 1]; strncpy(hid_path, deviceInfo.path, PATH_MAX); hid_path[PATH_MAX] = 0; hid_serial_raw = NULL; if (deviceInfo.serial_number != NULL) { size_t serial_max_length = 512; hid_serial_raw = new wchar_t[serial_max_length+1]; wcsncpy(hid_serial_raw, deviceInfo.serial_number, serial_max_length); hid_serial_raw[serial_max_length] = 0; } hid_serial = safeDecodeWideString(deviceInfo.serial_number, 512); hid_manufacturer = safeDecodeWideString(deviceInfo.manufacturer_string, 512); hid_product = safeDecodeWideString(deviceInfo.product_string, 512); guessDeviceCategory(); // Set the Unique Identifier to the serial_number m_sUID = hid_serial; //Note: We include the last 4 digits of the serial number and the // interface number to allow the user (and Mixxx!) to keep track of // which is which if (hid_interface_number < 0) { setDeviceName( QString("%1 %2").arg(hid_product) .arg(hid_serial.right(4))); } else { setDeviceName( QString("%1 %2_%3").arg(hid_product) .arg(hid_serial.right(4)) .arg(QString::number(hid_interface_number))); m_sUID.append(QString::number(hid_interface_number)); } // All HID devices are full-duplex setInputDevice(true); setOutputDevice(true); m_pReader = NULL; }
void MIDIDeviceParameter::midiDeviceOutAdded(MIDIOutputDevice * o) { if (outputDevice == nullptr&& o->name == ghostDeviceOut) { setOutputDevice(o); } }
void MIDIDeviceParameter::midiDeviceOutRemoved(MIDIOutputDevice * o) { if (o == outputDevice) { if(o != nullptr) ghostDeviceOut = o->name; setOutputDevice(nullptr); } }
Prefs::Prefs(QObject *parent, const char *name) : QObject(parent) { this->setObjectName(name); setInputDevice(0); setOutputDevice(0); setRingDevice(0); setFilterFlag(IAXC_FILTER_AAGC|IAXC_FILTER_ECHO|IAXC_FILTER_DENOISE|IAXC_FILTER_CN); silenceThreshold = -99; // default }
status_t AudioPolicyManager::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session) { LOGV("startOutput() output %d, stream %d", output, stream); ssize_t index = mOutputs.indexOfKey(output); if (index < 0) { LOGW("startOutput() unknow output %d", output); return BAD_VALUE; } AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index); routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream); #ifdef WITH_A2DP if (mA2dpOutput != 0 && !a2dpUsedForSonification() && (strategy == STRATEGY_SONIFICATION || strategy == STRATEGY_ENFORCED_AUDIBLE)) { setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput); } #endif // incremenent 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 // necassary for a correct control of hardware output routing by startOutput() and stopOutput() outputDesc->changeRefCount(stream, 1); #ifdef FM_RADIO #ifdef WITH_QCOM_LPA if ((stream == AudioSystem::FM && output == mA2dpOutput) || output == mLPADecodeOutput) setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output), true); else setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output)); #else if (stream == AudioSystem::FM && output == mA2dpOutput) setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output), true); else setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output)); #endif #else #ifdef WITH_QCOM_LPA if (output == mLPADecodeOutput) setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output), true); else setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output)); #else setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output)); #endif #endif // handle special case for sonification while in call if (isInCall()) { AudioPolicyManagerBase::handleIncallSonification(stream, true, false); } // apply volume rules for current stream and device if necessary checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, outputDesc->device()); return NO_ERROR; }
void MIDIDeviceParameter::loadJSONDataInternal(var data) { Parameter::loadJSONDataInternal(data); setInputDevice(MIDIManager::getInstance()->getInputDeviceWithName(value[0])); if (inputDevice == nullptr) ghostDeviceIn = data.getProperty("value", var())[0]; setOutputDevice(MIDIManager::getInstance()->getOutputDeviceWithName(value[1])); if (outputDevice == nullptr) ghostDeviceOut = data.getProperty("value", var())[1]; }
/* LGE_CHANGE_E [email protected] 2010.01.27 */ status_t AudioPolicyManagerALSA::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream) { LOGV("stopOutput() output %d, stream %d", output, stream); ssize_t index = mOutputs.indexOfKey(output); if (index < 0) { LOGW("stopOutput() unknow output %d", output); return BAD_VALUE; } AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index); routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream); // handle special case for sonification while in call if (mPhoneState == AudioSystem::MODE_IN_CALL) { handleIncallSonification(stream, false, false); } if (outputDesc->isUsedByStrategy(strategy)) { // decrement usage count of this stream on the output outputDesc->changeRefCount(stream, -1); if (!outputDesc->isUsedByStrategy(strategy)) { // if the stream is the last of its strategy to use this output, change routing // in the following order or priority: // PHONE > SONIFICATION > MEDIA > DTMF uint32_t newDevice = 0; if (outputDesc->isUsedByStrategy(STRATEGY_PHONE)) { newDevice = getDeviceForStrategy(STRATEGY_PHONE); } else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) { newDevice = getDeviceForStrategy(STRATEGY_SONIFICATION); } else if (mPhoneState == AudioSystem::MODE_IN_CALL) { newDevice = getDeviceForStrategy(STRATEGY_PHONE); } else if (outputDesc->isUsedByStrategy(STRATEGY_MEDIA)) { newDevice = getDeviceForStrategy(STRATEGY_MEDIA); } else if (outputDesc->isUsedByStrategy(STRATEGY_DTMF)) { newDevice = getDeviceForStrategy(STRATEGY_DTMF); } // apply routing change if necessary. // insert a delay of 2 times the audio hardware latency to ensure PCM // buffers in audio flinger and audio hardware are emptied before the // routing change is executed. setOutputDevice(mHardwareOutput, newDevice, false, mOutputs.valueFor(mHardwareOutput)->mLatency*2); } // store time at which the last music track was stopped - see computeVolume() if (stream == AudioSystem::MUSIC) { mMusicStopTime = systemTime(); } return NO_ERROR; } else { LOGW("stopOutput() refcount is already 0 for output %d", output); return INVALID_OPERATION; } }
bool AudioOutput::event(QEvent *ev) { switch (ev->type()) { case Event::AudioDeviceFailed: { ev->accept(); // we don't know for sure which AudioPort failed. We also can't know from the // information libxine makes available. So we have to just try the old device again if (setOutputDevice(m_device)) { return true; } // we really need a different output device QMetaObject::invokeMethod(this, "audioDeviceFailed", Qt::QueuedConnection); } return true; default: return AbstractAudioOutput::event(ev); } }
void testApp::checkPressOnDeviceList(int x, int y){ if (mouseX > ofGetWidth() - 360){ //check height float deviceNumber = y - deviceListHeightOffset/2; deviceNumber /= deviceListHeightDistance; int deviceInt = (int) round( deviceNumber)-1; if (showingInputDevices && inputSoundStream.deviceList[deviceInt].maxNumberOfInputs > 0){ setInputDevice(deviceInt); showingInputDevices = false; } if (showingOutputDevices && outputSoundStream.deviceList[deviceInt].maxNumberOfOutputs > 0){ setOutputDevice(deviceInt); showingOutputDevices = false; } } }
BulkController::BulkController(libusb_context* context, libusb_device_handle *handle, struct libusb_device_descriptor *desc) : m_context(context), m_phandle(handle), in_epaddr(0), out_epaddr(0) { vendor_id = desc->idVendor; product_id = desc->idProduct; manufacturer = get_string(handle, desc->iManufacturer); product = get_string(handle, desc->iProduct); m_sUID = get_string(handle, desc->iSerialNumber); setDeviceCategory(tr("USB Controller")); setDeviceName(QString("%1 %2").arg(product).arg(m_sUID)); setInputDevice(true); setOutputDevice(true); m_pReader = NULL; }
bool AudioOutput::setOutputDevice(const AudioOutputDevice & newDevice) { //stub implementation return setOutputDevice(newDevice.index()); }
//-------------------------------------------------------------- void testApp::setup(){ /* soundStream.setup(this, 0, 2, 44100, bufferSize, 4); */ screenToDraw = 1; aubioOnsetDetect = new ofxAubioOnsetDetection(); sampleIndex = 0; outputIsSameAsInput = true; infoString = "this shows two sound streams being used\npress 's' to unpause the audio\n'e' to pause the audio\n"; infoString += "'i' to switch from using input and using sine wave for output stream"; volHistory.assign(400, 0.0); bufferCounter = 0; drawCounter = 0; smoothedVol = 0.0; scaledVol = 0.0; setupFinished = false; ofBackground(255,255,255); bufferSize = 512;//important for the beat tracker analysis - this could be improved. leftAudioIn.assign(bufferSize, 0.0); rightAudioIn.assign(bufferSize, 0.0); leftAudioOut.assign(bufferSize, 0.0); rightAudioOut.assign(bufferSize, 0.0); //setting up input and output streams // inputSoundStream.listDevices(); usePortaudioClass = true; //ofxSoundStream - class version cout << "Input process setting up input with instance of ofxPortaudioSoundstream ..." << endl; inputDeviceID = 1;//the mic(0)/line input(1) of a mac book pro outputDeviceID = 2;//the headphones out of a macbook pro setInputDevice(inputDeviceID);//includes calling the setup routine etc ofAddListener(inputSoundStream.audioReceivedEvent, this, &testApp::audioInputListener); cout << "Output process, setting up output with instance of ofxPortaudioSoundstream ..." << endl; setOutputDevice(outputDeviceID); ofAddListener(outputSoundStream.audioRequestedEvent, this, &testApp::audioOutputListener); bufferCounter = 0; ofSetFrameRate(40); //loading audio file for click sound const char *clickfilename = "cow2.wav"; clickSound.loadSound(clickfilename); clickSound.setVolume(0.1); verdana30.loadFont("verdana.ttf", 30, true, true); verdana30.setLineHeight(34.0f); verdana30.setLetterSpacing(1.035); verdana14.loadFont("verdana.ttf", 14, true, true); verdana14.setLineHeight(14.0f); verdana14.setLetterSpacing(1.035); setupFinished = true; showingInputDevices = false; showingOutputDevices = false; deviceListHeightDistance = 30; deviceListHeightOffset = 20; }
bool AudioOutput::setOutputDevice(int newDevice) { return setOutputDevice(AudioOutputDevice::fromIndex(newDevice)); }
void AudioPolicyManager::setOutputDevice(audio_io_handle_t output, uint32_t device, bool force, int delayMs) { LOGV("setOutputDevice() output %d device %x delayMs %d", output, device, delayMs); AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output); if (outputDesc->isDuplicated()) { setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs); setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs); return; } #ifdef WITH_A2DP // filter devices according to output selected if (output == mA2dpOutput) { device &= AudioSystem::DEVICE_OUT_ALL_A2DP; } else { device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP; } #endif uint32_t prevDevice = (uint32_t)outputDesc->device(); // Do not change the routing if: // - the requestede device is 0 // - the requested device is the same as current device and force is not specified. // Doing this check here allows the caller to call setOutputDevice() without conditions if ((device == 0 || device == prevDevice) && !force) { LOGV("setOutputDevice() setting same device %x or null device for output %d", device, output); return; } outputDesc->mDevice = device; // mute media streams if both speaker and headset are selected if (device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADSET) #ifdef QCOM_ANC || device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_ANC_HEADSET) || device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_ANC_HEADPHONE) #endif || device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) #ifdef FM_RADIO || device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADSET | AudioSystem::DEVICE_OUT_FM) || device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADPHONE | AudioSystem::DEVICE_OUT_FM) || device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_FM_TX) #endif ) { setStrategyMute(STRATEGY_MEDIA, true, output); #ifdef WITH_QCOM_LPA // Mute LPA output also if it belongs to STRATEGY_MEDIA if(((mLPADecodeOutput != -1) && (mLPADecodeOutput != output) && mOutputs.valueFor(mLPADecodeOutput)->isUsedByStrategy(STRATEGY_MEDIA))) { LOGV("setOutputDevice: Muting mLPADecodeOutput:%d",mLPADecodeOutput); setStrategyMute(STRATEGY_MEDIA, true, mLPADecodeOutput); } #endif // Mute hardware output also if it belongs to STRATEGY_MEDIA if(((mHardwareOutput != -1) && (mHardwareOutput != output) && mOutputs.valueFor(mHardwareOutput)->isUsedByStrategy(STRATEGY_MEDIA))) { LOGV("setOutputDevice: Muting mHardwareOutput:%d",mHardwareOutput); setStrategyMute(STRATEGY_MEDIA, true, mHardwareOutput); } // wait for the PCM output buffers to empty before proceeding with the rest of the command usleep(outputDesc->mLatency*2*1000); } #ifdef WITH_A2DP // suspend A2DP output if SCO device is selected if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)device)) { if ((mA2dpOutput != 0) && (output == mHardwareOutput)) { mpClientInterface->suspendOutput(mA2dpOutput); } } #endif // wait for output buffers to be played on the HDMI device before routing to new device if(prevDevice == AudioSystem::DEVICE_OUT_AUX_DIGITAL) { #ifdef WITH_QCOM_LPA if((mLPADecodeOutput != -1 && output == mLPADecodeOutput && mOutputs.valueFor(mLPADecodeOutput)->isUsedByStrategy(STRATEGY_MEDIA))) { AudioPolicyManagerBase::checkAndSetVolume(AudioSystem::MUSIC, mStreams[AudioSystem::MUSIC].mIndexCur, mLPADecodeOutput, device, delayMs, force); usleep(75*1000); } else { #endif AudioPolicyManagerBase::checkAndSetVolume(AudioSystem::MUSIC, mStreams[AudioSystem::MUSIC].mIndexCur, output, device, delayMs, force); usleep(outputDesc->mLatency*3*1000); #ifdef WITH_QCOM_LPA } #endif } // do the routing AudioParameter param = AudioParameter(); param.addInt(String8(AudioParameter::keyRouting), (int)device); mpClientInterface->setParameters(mHardwareOutput, param.toString(), delayMs); // update stream volumes according to new device AudioPolicyManagerBase::applyStreamVolumes(output, device, delayMs); #ifdef WITH_QCOM_LPA if((mLPADecodeOutput != -1 && mOutputs.valueFor(mLPADecodeOutput)->isUsedByStrategy(STRATEGY_MEDIA))) { AudioPolicyManagerBase::applyStreamVolumes(mLPADecodeOutput, device, delayMs); } #endif #ifdef WITH_A2DP // if disconnecting SCO device, restore A2DP output if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)prevDevice)) { if (mA2dpOutput != 0) { LOGV("restore A2DP output"); mpClientInterface->restoreOutput(mA2dpOutput); } } #endif // if changing from a combined headset + speaker route, unmute media streams if (prevDevice == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADSET) #ifdef QCOM_ANC || prevDevice == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_ANC_HEADSET) || prevDevice == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_ANC_HEADPHONE) #endif || prevDevice == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) #ifdef FM_RADIO || prevDevice == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADSET | AudioSystem::DEVICE_OUT_FM) || prevDevice == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADPHONE | AudioSystem::DEVICE_OUT_FM) || prevDevice == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_FM_TX) #endif ) { setStrategyMute(STRATEGY_MEDIA, false, output, delayMs); #ifdef WITH_QCOM_LPA // Unmute LPA output also if it belongs to STRATEGY_MEDIA if(((mLPADecodeOutput != -1) && (mLPADecodeOutput != output) && mOutputs.valueFor(mLPADecodeOutput)->isUsedByStrategy(STRATEGY_MEDIA))) { LOGV("setOutputDevice: Unmuting mLPADecodeOutput:%d delayMs:%d",mLPADecodeOutput,delayMs); setStrategyMute(STRATEGY_MEDIA, false, mLPADecodeOutput, delayMs); } #endif // Unmute hardware output also if it belongs to STRATEGY_MEDIA if(((mHardwareOutput != -1) && (mHardwareOutput != output) && mOutputs.valueFor(mHardwareOutput)->isUsedByStrategy(STRATEGY_MEDIA))) { LOGV("setOutputDevice: Unmuting mHardwareOutput:%d delayMs:%d",mHardwareOutput,delayMs); setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, delayMs); } } }
void AudioPolicyManager::setPhoneState(int state) { ALOGV("setPhoneState() state %d", state); audio_devices_t newDevice = AUDIO_DEVICE_NONE; if (state < 0 || state >= AudioSystem::NUM_MODES) { ALOGW("setPhoneState() invalid state %d", state); return; } if (state == mPhoneState) { ALOGW("setPhoneState() setting same state %d", state); return; } // if leaving call state, handle special case of active streams // pertaining to sonification strategy see handleIncallSonification() if (isInCall()) { ALOGV("setPhoneState() in call state management: new state is %d", state); for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { handleIncallSonification(stream, false, true); } } // store previous phone state for management of sonification strategy below int oldState = mPhoneState; mPhoneState = state; bool force = false; // are we entering or starting a call if (!isStateInCall(oldState) && isStateInCall(state)) { ALOGV(" Entering call in setPhoneState()"); // force routing command to audio hardware when starting a call // even if no device change is needed force = true; } else if (isStateInCall(oldState) && !isStateInCall(state)) { ALOGV(" Exiting call in setPhoneState()"); // force routing command to audio hardware when exiting a call // even if no device change is needed force = true; } else if (isStateInCall(state) && (state != oldState)) { ALOGV(" Switching between telephony and VoIP in setPhoneState()"); // force routing command to audio hardware when switching between telephony and VoIP // even if no device change is needed force = true; } // check for device and output changes triggered by new phone state newDevice = getNewDevice(mPrimaryOutput, false /*fromCache*/); checkA2dpSuspend(); checkOutputForAllStrategies(); updateDevicesAndOutputs(); AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mPrimaryOutput); // force routing command to audio hardware when ending call // even if no device change is needed if (isStateInCall(oldState) && newDevice == AUDIO_DEVICE_NONE) { newDevice = hwOutputDesc->device(); } // when changing from ring tone to in call mode, mute the ringing tone // immediately and delay the route change to avoid sending the ring tone // tail into the earpiece or headset. int delayMs = 0; if (isStateInCall(state) && oldState == AudioSystem::MODE_RINGTONE) { // delay the device change command by twice the output latency to have some margin // and be sure that audio buffers not yet affected by the mute are out when // we actually apply the route change delayMs = hwOutputDesc->mLatency*2; setStreamMute(AudioSystem::RING, true, mPrimaryOutput); } if (isStateInCall(state)) { for (size_t i = 0; i < mOutputs.size(); i++) { AudioOutputDescriptor *desc = mOutputs.valueAt(i); //take the biggest latency for all outputs if (delayMs < desc->mLatency*2) { delayMs = desc->mLatency*2; } //mute STRATEGY_MEDIA on all outputs if (desc->strategyRefCount(STRATEGY_MEDIA) != 0) { setStrategyMute(STRATEGY_MEDIA, true, mOutputs.keyAt(i)); setStrategyMute(STRATEGY_MEDIA, false, mOutputs.keyAt(i), MUTE_TIME_MS, getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/)); } } } // Ignore the delay to enable voice call on this target as the enabling the // voice call has enough delay to make sure the ringtone audio completely // played out if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) { delayMs = 40; } // change routing is necessary setOutputDevice(mPrimaryOutput, newDevice, force, delayMs); // 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); // unmute the ringing tone after a sufficient delay if it was muted before // setting output device above if (oldState == AudioSystem::MODE_RINGTONE) { setStreamMute(AudioSystem::RING, false, mPrimaryOutput, MUTE_TIME_MS); } for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { handleIncallSonification(stream, true, true); } } // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE if (state == AudioSystem::MODE_RINGTONE && isStreamActive(AudioSystem::MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) { mLimitRingtoneVolume = true; } else { mLimitRingtoneVolume = false; } }
status_t AudioPolicyManager::checkAndSetVolume(int stream, int index, audio_io_handle_t output, uint32_t device, int delayMs, bool force) { #ifdef WITH_QCOM_LPA // do not change actual stream volume if the stream is muted if ((mOutputs.valueFor(output)->mMuteCount[stream] != 0 && output != mLPADecodeOutput) || (output == mLPADecodeOutput && stream == mLPAStreamType && mLPAMuted == true)) { #else if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) { #endif LOGV("checkAndSetVolume() stream %d muted count %d", stream, mOutputs.valueFor(output)->mMuteCount[stream]); return NO_ERROR; } // do not change in call volume if bluetooth is connected and vice versa if ((stream == AudioSystem::VOICE_CALL && mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) || (stream == AudioSystem::BLUETOOTH_SCO && mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO)) { LOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm", stream, mForceUse[AudioSystem::FOR_COMMUNICATION]); return INVALID_OPERATION; } float volume = computeVolume(stream, index, output, device); // do not set volume if the float value did not change if ((volume != mOutputs.valueFor(output)->mCurVolume[stream]) || (stream == AudioSystem::VOICE_CALL) #ifdef FM_RADIO || (stream == AudioSystem::FM) #endif || force) { mOutputs.valueFor(output)->mCurVolume[stream] = volume; LOGD("setStreamVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs); if (stream == AudioSystem::VOICE_CALL || stream == AudioSystem::DTMF || stream == AudioSystem::BLUETOOTH_SCO) { float voiceVolume = -1.0; // offset value to reflect actual hardware volume that never reaches 0 // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java) volume = 0.01 + 0.99 * volume; if (stream == AudioSystem::VOICE_CALL) { voiceVolume = (float)index/(float)mStreams[stream].mIndexMax; } else if (stream == AudioSystem::BLUETOOTH_SCO) { voiceVolume = 1.0; } if (voiceVolume >= 0 && output == mHardwareOutput) { mpClientInterface->setVoiceVolume(voiceVolume, delayMs); } #ifdef FM_RADIO } else if (stream == AudioSystem::FM) { float fmVolume = -1.0; fmVolume = computeVolume(stream, index, output, device); if (fmVolume >= 0) { if(output == mHardwareOutput) mpClientInterface->setFmVolume(fmVolume, delayMs); else if(output == mA2dpOutput) mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs); } return NO_ERROR; #endif } mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs); } return NO_ERROR; } void AudioPolicyManager::setStreamMute(int stream, bool on, audio_io_handle_t output, int delayMs) { StreamDescriptor &streamDesc = mStreams[stream]; AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output); LOGV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d", stream, on, output, outputDesc->mMuteCount[stream]); if (on) { #ifdef WITH_QCOM_LPA if ((outputDesc->mMuteCount[stream] == 0 && output != mLPADecodeOutput) || (output == mLPADecodeOutput && stream == mLPAStreamType && false == mLPAMuted)) { #else if (outputDesc->mMuteCount[stream] == 0) { #endif if (streamDesc.mCanBeMuted) { checkAndSetVolume(stream, 0, output, outputDesc->device(), delayMs); } } #ifdef WITH_QCOM_LPA // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored if(output == mLPADecodeOutput) { if(stream == mLPAStreamType && false == mLPAMuted) { mLPAMuted = true; } } else { #endif outputDesc->mMuteCount[stream]++; #ifdef WITH_QCOM_LPA } #endif } else { #ifdef WITH_QCOM_LPA if ((outputDesc->mMuteCount[stream] == 0 && output != mLPADecodeOutput) || (output == mLPADecodeOutput && stream == mLPAStreamType && false == mLPAMuted)) { #else if (outputDesc->mMuteCount[stream] == 0) { #endif LOGW("setStreamMute() unmuting non muted stream!"); return; } #ifdef WITH_QCOM_LPA if(output == mLPADecodeOutput) { if(stream == mLPAStreamType && true == mLPAMuted) { mLPAMuted = false; checkAndSetVolume(stream, streamDesc.mIndexCur, output, outputDesc->device(), delayMs); } } else { if(--outputDesc->mMuteCount[stream] == 0){ checkAndSetVolume(stream, streamDesc.mIndexCur, output, outputDesc->device(), delayMs); } } #else if(--outputDesc->mMuteCount[stream] == 0){ checkAndSetVolume(stream, streamDesc.mIndexCur, output, outputDesc->device(), delayMs); } #endif } } void AudioPolicyManager::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config) { LOGD("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState); bool forceVolumeReeval = false; switch(usage) { case AudioSystem::FOR_COMMUNICATION: if (config != AudioSystem::FORCE_SPEAKER && config != AudioSystem::FORCE_BT_SCO && config != AudioSystem::FORCE_NONE) { LOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config); return; } mForceUse[usage] = config; break; case AudioSystem::FOR_MEDIA: if (config != AudioSystem::FORCE_HEADPHONES && config != AudioSystem::FORCE_BT_A2DP && config != AudioSystem::FORCE_WIRED_ACCESSORY && config != AudioSystem::FORCE_NONE && config != AudioSystem::FORCE_SPEAKER) { LOGW("setForceUse() invalid config %d for FOR_MEDIA", config); return; } mForceUse[usage] = config; { uint32_t device = getDeviceForStrategy(STRATEGY_MEDIA); setOutputDevice(mHardwareOutput, device); } break; case AudioSystem::FOR_RECORD: if (config != AudioSystem::FORCE_BT_SCO && config != AudioSystem::FORCE_WIRED_ACCESSORY && config != AudioSystem::FORCE_NONE) { LOGW("setForceUse() invalid config %d for FOR_RECORD", config); return; } mForceUse[usage] = config; break; case AudioSystem::FOR_DOCK: if (config != AudioSystem::FORCE_NONE && config != AudioSystem::FORCE_BT_CAR_DOCK && config != AudioSystem::FORCE_BT_DESK_DOCK && config != AudioSystem::FORCE_WIRED_ACCESSORY) { LOGW("setForceUse() invalid config %d for FOR_DOCK", config); } forceVolumeReeval = true; mForceUse[usage] = config; break; default: LOGW("setForceUse() invalid usage %d", usage); break; } // check for device and output changes triggered by new phone state uint32_t newDevice = getNewDevice(mHardwareOutput, false); #ifdef WITH_A2DP checkOutputForAllStrategies(); #endif updateDeviceForStrategy(); setOutputDevice(mHardwareOutput, newDevice); if (forceVolumeReeval) { applyStreamVolumes(mHardwareOutput, newDevice); } } uint32_t AudioPolicyManager::getDeviceForInputSource(int inputSource) { uint32_t device; switch(inputSource) { case AUDIO_SOURCE_DEFAULT: case AUDIO_SOURCE_MIC: case AUDIO_SOURCE_VOICE_RECOGNITION: if (mForceUse[AudioSystem::FOR_RECORD] == AudioSystem::FORCE_BT_SCO && mAvailableInputDevices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) { device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET; } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_WIRED_HEADSET) { device = AudioSystem::DEVICE_IN_WIRED_HEADSET; #ifdef QCOM_ANC } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_ANC_HEADSET) { device = AudioSystem::DEVICE_IN_ANC_HEADSET; #endif } else { device = AudioSystem::DEVICE_IN_BUILTIN_MIC; } break; case AUDIO_SOURCE_VOICE_COMMUNICATION: device = AudioSystem::DEVICE_IN_COMMUNICATION; break; case AUDIO_SOURCE_CAMCORDER: if (hasBackMicrophone()) { device = AudioSystem::DEVICE_IN_BACK_MIC; } else { device = AudioSystem::DEVICE_IN_BUILTIN_MIC; } break; case AUDIO_SOURCE_VOICE_UPLINK: case AUDIO_SOURCE_VOICE_DOWNLINK: case AUDIO_SOURCE_VOICE_CALL: device = AudioSystem::DEVICE_IN_VOICE_CALL; break; #ifdef FM_RADIO case AUDIO_SOURCE_FM_RX: device = AudioSystem::DEVICE_IN_FM_RX; break; case AUDIO_SOURCE_FM_RX_A2DP: device = AudioSystem::DEVICE_IN_FM_RX_A2DP; break; #endif default: LOGW("getInput() invalid input source %d", inputSource); device = 0; break; } LOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device); return device; }
status_t AudioPolicyManagerALSA::setDeviceConnectionState(AudioSystem::audio_devices device, AudioSystem::device_connection_state state, const char *device_address) { LOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address); // connect/disconnect only 1 device at a time if (AudioSystem::popCount(device) != 1) return BAD_VALUE; if (strlen(device_address) >= MAX_DEVICE_ADDRESS_LEN) { LOGE("setDeviceConnectionState() invalid address: %s", device_address); return BAD_VALUE; } // handle output devices if (AudioSystem::isOutputDevice(device)) { #ifndef WITH_A2DP if (AudioSystem::isA2dpDevice(device)) { LOGE("setDeviceConnectionState() invalid device: %x", device); return BAD_VALUE; } #endif switch (state) { // handle output device connection case AudioSystem::DEVICE_STATE_AVAILABLE: if (mAvailableOutputDevices & device) { LOGW("setDeviceConnectionState() device already connected: %x", device); return INVALID_OPERATION; } LOGV("setDeviceConnectionState() connecting device %x", device); // register new device as available mAvailableOutputDevices |= device; #ifdef WITH_A2DP // handle A2DP device connection if (AudioSystem::isA2dpDevice(device)) { status_t status = handleA2dpConnection(device, device_address); if (status != NO_ERROR) { mAvailableOutputDevices &= ~device; return status; } } else #endif { if (AudioSystem::isBluetoothScoDevice(device)) { LOGV("setDeviceConnectionState() BT SCO device, address %s", device_address); // keep track of SCO device address mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN); #ifdef WITH_A2DP if (mA2dpOutput != 0 && mPhoneState != AudioSystem::MODE_NORMAL) { mpClientInterface->suspendOutput(mA2dpOutput); } #endif } } break; // handle output device disconnection case AudioSystem::DEVICE_STATE_UNAVAILABLE: { if (!(mAvailableOutputDevices & device)) { LOGW("setDeviceConnectionState() device not connected: %x", device); return INVALID_OPERATION; } LOGV("setDeviceConnectionState() disconnecting device %x", device); // remove device from available output devices mAvailableOutputDevices &= ~device; #ifdef WITH_A2DP // handle A2DP device disconnection if (AudioSystem::isA2dpDevice(device)) { status_t status = handleA2dpDisconnection(device, device_address); if (status != NO_ERROR) { mAvailableOutputDevices |= device; return status; } } else #endif { if (AudioSystem::isBluetoothScoDevice(device)) { mScoDeviceAddress = ""; #ifdef WITH_A2DP if (mA2dpOutput != 0 && mPhoneState != AudioSystem::MODE_NORMAL) { mpClientInterface->restoreOutput(mA2dpOutput); } #endif } } } break; default: LOGE("setDeviceConnectionState() invalid state: %x", state); return BAD_VALUE; } // request routing change if necessary uint32_t newDevice = getNewDevice(mHardwareOutput, false); // force routing if device disconnection occurs when stream is stopped if ((newDevice == 0) && (state == AudioSystem::DEVICE_STATE_UNAVAILABLE)) newDevice = getDeviceForStrategy(STRATEGY_MEDIA, false); #ifdef WITH_A2DP //+++ KBNAM_PORTING /* org checkOutputForAllStrategies(newDevice); */ checkOutputForAllStrategies(); //--- // A2DP outputs must be closed after checkOutputForAllStrategies() is executed if (state == AudioSystem::DEVICE_STATE_UNAVAILABLE && AudioSystem::isA2dpDevice(device)) { closeA2dpOutputs(); } #endif updateDeviceForStrategy(); setOutputDevice(mHardwareOutput, newDevice); if (device == AudioSystem::DEVICE_OUT_WIRED_HEADSET) { device = AudioSystem::DEVICE_IN_WIRED_HEADSET; } else if (device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO || device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET || device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) { device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET; } else { return NO_ERROR; } } // handle input devices if (AudioSystem::isInputDevice(device)) { switch (state) { // handle input device connection case AudioSystem::DEVICE_STATE_AVAILABLE: { if (mAvailableInputDevices & device) { LOGW("setDeviceConnectionState() device already connected: %d", device); return INVALID_OPERATION; } mAvailableInputDevices |= device; } break; // handle input device disconnection case AudioSystem::DEVICE_STATE_UNAVAILABLE: { if (!(mAvailableInputDevices & device)) { LOGW("setDeviceConnectionState() device not connected: %d", device); return INVALID_OPERATION; } mAvailableInputDevices &= ~device; } break; default: LOGE("setDeviceConnectionState() invalid state: %x", state); return BAD_VALUE; } audio_io_handle_t activeInput = getActiveInput(); if (activeInput != 0) { AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput); uint32_t newDevice = getDeviceForInputSource(inputDesc->mInputSource); if (newDevice != inputDesc->mDevice) { LOGV("setDeviceConnectionState() changing device from %x to %x for input %d", inputDesc->mDevice, newDevice, activeInput); inputDesc->mDevice = newDevice; AudioParameter param = AudioParameter(); param.addInt(String8(AudioParameter::keyRouting), (int)newDevice); mpClientInterface->setParameters(activeInput, param.toString()); } } else { /* LGE_CHANGE_S [email protected] 2010.01.27 */ #ifdef SUPPORT_FM_ANALOG if (device == AudioSystem::DEVICE_IN_FM_ANALOG) { routing_strategy strategy = getStrategy((AudioSystem::stream_type)3); uint32_t curOutdevice = getDeviceForStrategy(strategy); /* If A2DP headset is connected then route FM to Headset */ if (curOutdevice == AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP || curOutdevice == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) { curOutdevice = AudioSystem::DEVICE_OUT_WIRED_HEADSET; } if (state) { // routing_strategy strategy = getStrategy((AudioSystem::stream_type)3); // uint32_t curOutdevice = getDeviceForStrategy(strategy); /* Get the new input descriptor for FM Rx In */ mfmInput = getFMInput(AUDIO_SOURCE_FM_ANALOG,8000,1, AudioSystem::CHANNEL_IN_MONO,(AudioSystem::audio_in_acoustics)7); /* Forcely open the current output device again for * FM Rx playback path to open */ LOGV("curOutdevice = %x",curOutdevice); setOutputDevice(mHardwareOutput, curOutdevice, true); /* Tell the audio flinger playback thread that * FM Rx is active */ mpClientInterface->setFMRxActive(true); } else { int newDevice=0; AudioParameter param = AudioParameter(); param.addInt(String8(AudioParameter::keyRouting), (int)newDevice); /* Change the input device from FM to default before releasing Input */ mpClientInterface->setParameters(mfmInput, param.toString()); param.addInt(String8("fm_off"), (int)newDevice); /* Close the capture handle */ mpClientInterface->setParameters(mfmInput, param.toString()); /* Release the input descriptor for FM Rx In */ releaseInput(mfmInput); /* Close the playback handle */ mpClientInterface->setParameters(mHardwareOutput, param.toString()); /* Tell the audio flinger playback thread that * FM Rx is not active now. */ mpClientInterface->setFMRxActive(false); } } #endif // SUPPORT_FM_ANALOG /* LGE_CHANGE_E [email protected] 2010.01.27 */ } return NO_ERROR; } LOGW("setDeviceConnectionState() invalid device: %x", device); return BAD_VALUE; }
status_t AudioPolicyManager::setDeviceConnectionState(AudioSystem::audio_devices device, AudioSystem::device_connection_state state, const char *device_address) { LOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address); // connect/disconnect only 1 device at a time if (AudioSystem::popCount(device) != 1) return BAD_VALUE; if (strlen(device_address) >= MAX_DEVICE_ADDRESS_LEN) { LOGE("setDeviceConnectionState() invalid address: %s", device_address); return BAD_VALUE; } // handle output devices if (AudioSystem::isOutputDevice(device)) { #ifndef WITH_A2DP if (AudioSystem::isA2dpDevice(device)) { LOGE("setDeviceConnectionState() invalid device: %x", device); return BAD_VALUE; } #endif switch (state) { // handle output device connection case AudioSystem::DEVICE_STATE_AVAILABLE: if (mAvailableOutputDevices & device) { LOGW("setDeviceConnectionState() device already connected: %x", device); return INVALID_OPERATION; } LOGV("setDeviceConnectionState() connecting device %x", device); // register new device as available mAvailableOutputDevices |= device; #ifdef WITH_A2DP // handle A2DP device connection if (AudioSystem::isA2dpDevice(device)) { status_t status = handleA2dpConnection(device, device_address); if (status != NO_ERROR) { mAvailableOutputDevices &= ~device; return status; } } else #endif { if (AudioSystem::isBluetoothScoDevice(device)) { LOGV("setDeviceConnectionState() BT SCO device, address %s", device_address); // keep track of SCO device address mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN); } } break; // handle output device disconnection case AudioSystem::DEVICE_STATE_UNAVAILABLE: { if (!(mAvailableOutputDevices & device)) { LOGW("setDeviceConnectionState() device not connected: %x", device); return INVALID_OPERATION; } LOGV("setDeviceConnectionState() disconnecting device %x", device); // remove device from available output devices mAvailableOutputDevices &= ~device; #ifdef WITH_A2DP // handle A2DP device disconnection if (AudioSystem::isA2dpDevice(device)) { status_t status = handleA2dpDisconnection(device, device_address); if (status != NO_ERROR) { mAvailableOutputDevices |= device; return status; } } else #endif { if (AudioSystem::isBluetoothScoDevice(device)) { mScoDeviceAddress = ""; } } } break; default: LOGE("setDeviceConnectionState() invalid state: %x", state); return BAD_VALUE; } #ifdef HAVE_FM_RADIO if (device == AudioSystem::DEVICE_OUT_FM) { AudioOutputDescriptor *out = mOutputs.valueFor(mHardwareOutput); if (state == AudioSystem::DEVICE_STATE_AVAILABLE) { out->changeRefCount(AudioSystem::FM, 1); if (out->mRefCount[AudioSystem::FM] > 0) mpClientInterface->setParameters(0, String8("fm_on=1")); } else { out->changeRefCount(AudioSystem::FM, -1); if (out->mRefCount[AudioSystem::FM] <= 0) mpClientInterface->setParameters(0, String8("fm_off=1")); } } #endif // request routing change if necessary uint32_t newDevice = getNewDevice(mHardwareOutput, false); #ifdef WITH_A2DP checkA2dpSuspend(); checkOutputForAllStrategies(); // A2DP outputs must be closed after checkOutputForAllStrategies() is executed if (state == AudioSystem::DEVICE_STATE_UNAVAILABLE && AudioSystem::isA2dpDevice(device)) { closeA2dpOutputs(); } #endif updateDeviceForStrategy(); setOutputDevice(mHardwareOutput, newDevice); if (device == AudioSystem::DEVICE_OUT_WIRED_HEADSET) { device = AudioSystem::DEVICE_IN_WIRED_HEADSET; } else if (device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO || device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET || device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) { device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET; } else { return NO_ERROR; } } // handle input devices if (AudioSystem::isInputDevice(device)) { switch (state) { // handle input device connection case AudioSystem::DEVICE_STATE_AVAILABLE: { if (mAvailableInputDevices & device) { LOGW("setDeviceConnectionState() device already connected: %d", device); return INVALID_OPERATION; } mAvailableInputDevices |= device; } break; // handle input device disconnection case AudioSystem::DEVICE_STATE_UNAVAILABLE: { if (!(mAvailableInputDevices & device)) { LOGW("setDeviceConnectionState() device not connected: %d", device); return INVALID_OPERATION; } mAvailableInputDevices &= ~device; } break; default: LOGE("setDeviceConnectionState() invalid state: %x", state); return BAD_VALUE; } audio_io_handle_t activeInput = getActiveInput(); if (activeInput != 0) { AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput); uint32_t newDevice = getDeviceForInputSource(inputDesc->mInputSource); if (newDevice != inputDesc->mDevice) { LOGV("setDeviceConnectionState() changing device from %x to %x for input %d", inputDesc->mDevice, newDevice, activeInput); inputDesc->mDevice = newDevice; AudioParameter param = AudioParameter(); param.addInt(String8(AudioParameter::keyRouting), (int)newDevice); mpClientInterface->setParameters(activeInput, param.toString()); } } return NO_ERROR; } LOGW("setDeviceConnectionState() invalid device: %x", device); return BAD_VALUE; }
bool AudioOutput::setOutputDevice(const AudioOutputDevice &newDevice) { return setOutputDevice(newDevice.index()); }
void AudioPolicyManager::setPhoneState(int state) { LOGD("setPhoneState() state %d", state); uint32_t newDevice = 0; if (state < 0 || state >= AudioSystem::NUM_MODES) { LOGW("setPhoneState() invalid state %d", state); return; } if (state == mPhoneState ) { LOGW("setPhoneState() setting same state %d", state); return; } // if leaving call state, handle special case of active streams // pertaining to sonification strategy see handleIncallSonification() if (isInCall()) { LOGV("setPhoneState() in call state management: new state is %d", state); for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { AudioPolicyManagerBase::handleIncallSonification(stream, false, true); } } // store previous phone state for management of sonification strategy below int oldState = mPhoneState; mPhoneState = state; // force routing command to audio hardware when starting call // even if no device change is needed bool force = (mPhoneState == AudioSystem::MODE_IN_CALL); // are we entering or starting a call if (!isStateInCall(oldState) && isStateInCall(state)) { LOGV(" Entering call in setPhoneState()"); // force routing command to audio hardware when starting a call // even if no device change is needed force = true; } else if (isStateInCall(oldState) && (state == AudioSystem::MODE_NORMAL)) { LOGV(" Exiting call in setPhoneState()"); // force routing command to audio hardware when exiting a call // even if no device change is needed force = true; } else if (isStateInCall(state) && (state != oldState)) { LOGV(" Switching between telephony and VoIP in setPhoneState()"); // force routing command to audio hardware when switching between telephony and VoIP // even if no device change is needed force = true; } // check for device and output changes triggered by new phone state newDevice = AudioPolicyManagerBase::getNewDevice(mHardwareOutput, false); #ifdef WITH_QCOM_LPA if (newDevice == 0 && (mLPADecodeOutput != -1 && mOutputs.valueFor(mLPADecodeOutput)->isUsedByStrategy(STRATEGY_MEDIA))) { newDevice = getDeviceForStrategy(STRATEGY_MEDIA, false); } #endif #ifdef WITH_A2DP AudioPolicyManagerBase::checkOutputForAllStrategies(); // suspend A2DP output if a SCO device is present. if (mA2dpOutput != 0 && mScoDeviceAddress != "") { if (oldState == AudioSystem::MODE_NORMAL) { mpClientInterface->suspendOutput(mA2dpOutput); } else if (state == AudioSystem::MODE_NORMAL) { mpClientInterface->restoreOutput(mA2dpOutput); } } #endif AudioPolicyManagerBase::updateDeviceForStrategy(); AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput); // force routing command to audio hardware when ending call // even if no device change is needed if (isStateInCall(oldState) && newDevice == 0) { newDevice = hwOutputDesc->device(); if(state == AudioSystem::MODE_NORMAL) { force = true; } } // when changing from ring tone to in call mode, mute the ringing tone // immediately and delay the route change to avoid sending the ring tone // tail into the earpiece or headset. int delayMs = 0; if (isStateInCall(state) && oldState == AudioSystem::MODE_RINGTONE) { // delay the device change command by twice the output latency to have some margin // and be sure that audio buffers not yet affected by the mute are out when // we actually apply the route change delayMs = hwOutputDesc->mLatency*2; setStreamMute(AudioSystem::RING, true, mHardwareOutput); } // change routing is necessary setOutputDevice(mHardwareOutput, newDevice, force, delayMs); // if entering in call state, handle special case of active streams // pertaining to sonification strategy see handleIncallSonification() if (isStateInCall(state)) { LOGV("setPhoneState() in call state management: new state is %d", state); // unmute the ringing tone after a sufficient delay if it was muted before // setting output device above if (oldState == AudioSystem::MODE_RINGTONE) { setStreamMute(AudioSystem::RING, false, mHardwareOutput, MUTE_TIME_MS); } for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { AudioPolicyManagerBase::handleIncallSonification(stream, true, true); } } // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE if (state == AudioSystem::MODE_RINGTONE && (hwOutputDesc->mRefCount[AudioSystem::MUSIC] || (systemTime() - hwOutputDesc->mStopTime[AudioSystem::MUSIC]) < seconds(SONIFICATION_HEADSET_MUSIC_DELAY))) { // (systemTime() - mMusicStopTime) < seconds(SONIFICATION_HEADSET_MUSIC_DELAY))) { mLimitRingtoneVolume = true; } else { mLimitRingtoneVolume = false; } }