예제 #1
0
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;
    }
}
예제 #2
0
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);
	}
}
예제 #5
0
파일: prefs.cpp 프로젝트: PKEv/YakaPhone
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
}
예제 #6
0
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;
       }
}
예제 #9
0
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);
    }
}
예제 #10
0
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;
		}
		
	
	}

}
예제 #11
0
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;
}
예제 #12
0
파일: audiooutput.cpp 프로젝트: Afreeca/qt
 bool AudioOutput::setOutputDevice(const AudioOutputDevice & newDevice)
 {
     //stub implementation
     return setOutputDevice(newDevice.index());
 }
예제 #13
0
//--------------------------------------------------------------
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;
	

	
	
}
예제 #14
0
bool AudioOutput::setOutputDevice(int newDevice)
{
    return setOutputDevice(AudioOutputDevice::fromIndex(newDevice));
}
예제 #15
0
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;
    }
}
예제 #17
0
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;
}
예제 #20
0
bool AudioOutput::setOutputDevice(const AudioOutputDevice &newDevice)
{
    return setOutputDevice(newDevice.index());
}
예제 #21
0
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;
    }
}