Esempio n. 1
0
void AudioOffloadPlayer::SendMetaDataToHal(sp<AudioSink>& aSink,
                                           const sp<MetaData>& aMeta)
{
  int32_t sampleRate = 0;
  int32_t bitRate = 0;
  int32_t channelMask = 0;
  int32_t delaySamples = 0;
  int32_t paddingSamples = 0;
  CHECK(aSink.get());

  AudioParameter param = AudioParameter();

  if (aMeta->findInt32(kKeySampleRate, &sampleRate)) {
    param.addInt(String8(AUDIO_OFFLOAD_CODEC_SAMPLE_RATE), sampleRate);
  }
  if (aMeta->findInt32(kKeyChannelMask, &channelMask)) {
    param.addInt(String8(AUDIO_OFFLOAD_CODEC_NUM_CHANNEL), channelMask);
  }
  if (aMeta->findInt32(kKeyBitRate, &bitRate)) {
    param.addInt(String8(AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE), bitRate);
  }
  if (aMeta->findInt32(kKeyEncoderDelay, &delaySamples)) {
    param.addInt(String8(AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES), delaySamples);
  }
  if (aMeta->findInt32(kKeyEncoderPadding, &paddingSamples)) {
    param.addInt(String8(AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES), paddingSamples);
  }

  AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("SendMetaDataToHal: bitRate %d,"
      " sampleRate %d, chanMask %d, delaySample %d, paddingSample %d", bitRate,
      sampleRate, channelMask, delaySamples, paddingSamples));

  aSink->SetParameters(param.toString());
  return;
}
Esempio n. 2
0
/*
Overwriting this function from base class to allow 2 acitve AudioRecord clients in case of FM.
One for FM A2DP playbck and other for FM recording.
*/
status_t AudioPolicyManager::startInput(audio_io_handle_t input)
{
    LOGV("startInput() input %d", input);
    ssize_t index = mInputs.indexOfKey(input);
    if (index < 0) {
        LOGW("startInput() unknow input %d", input);
        return BAD_VALUE;
    }
    AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
    AudioParameter param = AudioParameter();
    param.addInt(String8(AudioParameter::keyRouting), (int)inputDesc->mDevice);
    // use Voice Recognition mode or not for this input based on input source
    int vr_enabled = inputDesc->mInputSource == AUDIO_SOURCE_VOICE_RECOGNITION ? 1 : 0;
    param.addInt(String8("vr_mode"), vr_enabled);
    LOGV("AudioPolicyManager::startInput(%d), setting vr_mode to %d", inputDesc->mInputSource, vr_enabled);
    mpClientInterface->setParameters(input, param.toString());
    inputDesc->mRefCount = 1;
    return NO_ERROR;
}
char* AudioHardwareOutput::getParameters(const char* keys) {
    Settings s;

    // Explicit scope for auto-lock pattern.
    {
        // Snapshot the current settings so we don't have to hold the settings
        // lock while formatting the results.
        Mutex::Autolock _l(mSettingsLock);
        s = mSettings;
    }

    AudioParameter param = AudioParameter(String8(keys));
    String8 tmp;

    /***************************************************************
     *                     HDMI Audio Options                      *
     ***************************************************************/
    if (param.get(kHDMIAllowedParamKey, tmp) == NO_ERROR)
        param.addInt(kHDMIAllowedParamKey, s.hdmi.allowed ? 1 : 0);

    if (param.get(kHDMIDelayCompParamKey, tmp) == NO_ERROR)
        param.addFloat(kHDMIDelayCompParamKey,
                       static_cast<float>(s.hdmi.delayCompUsec) / 1000.0);

    if (param.get(kFixedHDMIOutputParamKey, tmp) == NO_ERROR)
        param.addInt(kFixedHDMIOutputParamKey, s.hdmi.isFixed ? 1 : 0);

    if (param.get(kFixedHDMIOutputLevelParamKey, tmp) == NO_ERROR)
        param.addFloat(kFixedHDMIOutputLevelParamKey, s.hdmi.fixedLvl);

    /***************************************************************
     *                       Other Options                         *
     ***************************************************************/
    if (param.get(kVideoDelayCompParamKey, tmp) == NO_ERROR)
        param.addFloat(kVideoDelayCompParamKey,
                       static_cast<float>(s.videoDelayCompUsec) / 1000.0);

    return strdup(param.toString().string());
}
String8 AudioAACStreamIn::getParameters(const String8& keys)
{
    AudioParameter param = AudioParameter(keys);
    String8 value;
    String8 key = String8(AudioParameter::keyRouting);

    if (param.get(key, value) == NO_ERROR) {
        param.addInt(key, (int)mDevice);
    }

    ALOGV("getParameters() %s", param.toString().string());
    return param.toString();
}
String8 AudioStreamInMotorola::getParameters(const String8& keys)
{
    AudioParameter param = AudioParameter(keys);
    String8 value;
    String8 key = String8(AudioParameter::keyRouting);

    if (param.get(key, value) == NO_ERROR) {
        param.addInt(key, (int)mDevices);
    }

    LOGD("getParameters(%s)", param.toString().string());
    return param.toString();
}
Esempio n. 6
0
String8 AudioHardware::AudioStreamOutMSM72xx::getParameters(const String8& keys)
{
    AudioParameter param = AudioParameter(keys);
    String8 value;
    String8 key = String8(AudioParameter::keyRouting);

    if (param.get(key, value) == NO_ERROR) {
        LOGV("get routing %x", mDevices);
        param.addInt(key, (int)mDevices);
    }

    LOGV("AudioStreamOutMSM72xx::getParameters() %s", param.toString().string());
    return param.toString();
}
String8 AudioStreamInWrapper::getParameters(const String8& keys)
{
        LOGV("AudioStreamInWrapper::getParameters(\"%s\")", keys.string());

	AudioParameter param = AudioParameter(keys);
	String8 value;
	String8 key = String8(AudioParameter::keyRouting);

	if (param.get(key, value) == NO_ERROR) {
		LOGV("get routing %x", mDevices);
		param.addInt(key, (int)mDevices);
	}

	LOGV("AudioStreamInWrapper::getParameters() %s", param.toString().string());
	return param.toString();
}
String8 A2dpAudioInterface::A2dpAudioStreamOut::getParameters(const String8& keys)
{
    AudioParameter param = AudioParameter(keys);
    String8 value;
    String8 key = String8("a2dp_sink_address");

    if (param.get(key, value) == NO_ERROR) {
        value = mA2dpAddress;
        param.add(key, value);
    }
    key = AudioParameter::keyRouting;
    if (param.get(key, value) == NO_ERROR) {
        param.addInt(key, (int)mDevice);
    }

    LOGV("A2dpAudioStreamOut::getParameters() %s", param.toString().string());
    return param.toString();
}
Esempio n. 9
0
int AudioFtm::Audio_FM_I2S_Play(char bEnable)
{
    ALOGD("%s()", __FUNCTION__);

    const float kMaxFmVolume = 1.0;

    if (mStreamOut == NULL)
    {
        if (mStreamManager->getStreamOutVectorSize() == 0) // Factory mode
        {
            uint32_t devices = 0x2;
            int format = 0x1;
            uint32_t channels = 0x3;
            uint32_t sampleRate = 44100;
            status_t status = 0;

            mStreamManager->openOutputStream(devices, &format, &channels, &sampleRate, &status);
        }

        mStreamOut = mStreamManager->getStreamOut(0);
    }

    if (bEnable == true)
    {
        // force assigned earphone
        AudioParameter paramRouting = AudioParameter();
        paramRouting.addInt(String8(AudioParameter::keyRouting), AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
        mStreamOut->setParameters(paramRouting.toString());

        // enable
        mStreamManager->setFmVolume(0);
        mStreamManager->setFmEnable(true);
        mStreamManager->setFmVolume(kMaxFmVolume);
    }
    else
    {
        // disable
        mStreamManager->setFmVolume(0);
        mStreamManager->setFmEnable(false);
    }

    return true;
}
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;
}
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;
}
Esempio n. 12
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);
        }
    }
}