14765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev/* AudioHardwareALSA.cpp
24765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev **
34765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** Copyright 2008-2010 Wind River Systems
44765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
54765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev **
64765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** Licensed under the Apache License, Version 2.0 (the "License");
74765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** you may not use this file except in compliance with the License.
84765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** You may obtain a copy of the License at
94765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev **
104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev **     http://www.apache.org/licenses/LICENSE-2.0
114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev **
124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** Unless required by applicable law or agreed to in writing, software
134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** distributed under the License is distributed on an "AS IS" BASIS,
144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** See the License for the specific language governing permissions and
164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ** limitations under the License.
174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev */
184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <errno.h>
204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <stdarg.h>
214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <sys/stat.h>
224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <fcntl.h>
234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <stdlib.h>
244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <unistd.h>
254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <dlfcn.h>
264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <math.h>
274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
289746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#define LOG_TAG "AudioHardwareALSA"
294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev//#define LOG_NDEBUG 0
309746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#define LOG_NDDEBUG 0
314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <utils/Log.h>
324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <utils/String8.h>
334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <sys/prctl.h>
344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <sys/resource.h>
354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <sys/poll.h>
364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <sys/ioctl.h>
374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <cutils/properties.h>
384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <media/AudioRecord.h>
394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <hardware_legacy/power.h>
404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include "AudioHardwareALSA.h"
429746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED
434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include "AudioUsbALSA.h"
449746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif
45bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani#include "AudioUtil.h"
464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevextern "C"
484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    //
504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    // Function for dlsym() to look up for creating a new AudioHardwareInterface.
514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    //
524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    android_audio_legacy::AudioHardwareInterface *createAudioHardware(void) {
534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        return android_audio_legacy::AudioHardwareALSA::create();
544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
555ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani#ifdef QCOM_ACDB_ENABLED
565ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani    static int (*acdb_init)();
575ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani    static void (*acdb_deallocate)();
585ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani#endif
595ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani#ifdef QCOM_CSDCLIENT_ENABLED
60295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani    static int (*csd_client_init)();
61295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani    static int (*csd_client_deinit)();
625ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani    static int (*csd_start_playback)();
635ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani    static int (*csd_stop_playback)();
645ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani#endif
654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}         // extern "C"
664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevnamespace android_audio_legacy
684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// ----------------------------------------------------------------------------
714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
724765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareInterface *AudioHardwareALSA::create() {
734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return new AudioHardwareALSA();
744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
764765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::AudioHardwareALSA() :
776ccde10fdc6591e5cd21ed32c2b5817aaeb1a208SathishKumar Mani    mALSADevice(0),mVoipStreamCount(0),mVoipBitRate(0)
786ccde10fdc6591e5cd21ed32c2b5817aaeb1a208SathishKumar Mani    ,mCallState(0),mAcdbHandle(NULL),mCsdHandle(NULL),mMicMute(0)
794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    FILE *fp;
814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    char soundCardInfo[200];
824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    hw_module_t *module;
834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    char platform[128], baseband[128];
844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    int err = hw_get_module(ALSA_HARDWARE_MODULE_ID,
854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            (hw_module_t const**)&module);
864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    int codec_rev = 2;
874113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGD("hw_get_module(ALSA_HARDWARE_MODULE_ID) returned err %d", err);
884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (err == 0) {
894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        hw_device_t* device;
904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        err = module->methods->open(module, ALSA_HARDWARE_NAME, &device);
914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (err == 0) {
924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mALSADevice = (alsa_device_t *)device;
934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mALSADevice->init(mALSADevice, mDeviceList);
944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mCSCallActive = 0;
954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mVolteCallActive = 0;
964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mIsFmActive = 0;
974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDevSettingsFlag = 0;
989746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED
994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mAudioUsbALSA = new AudioUsbALSA();
1009746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani            musbPlaybackState = 0;
1019746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani            musbRecordingState = 0;
1029746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif
103924f79851aaa4eebe593a456203d1c39d3c53d73ty.lee#ifdef USES_FLUENCE_INCALL
104924f79851aaa4eebe593a456203d1c39d3c53d73ty.lee            mDevSettingsFlag |= TTY_OFF | DMIC_FLAG;
105924f79851aaa4eebe593a456203d1c39d3c53d73ty.lee#else
1064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDevSettingsFlag |= TTY_OFF;
107924f79851aaa4eebe593a456203d1c39d3c53d73ty.lee#endif
1084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mBluetoothVGS = false;
1094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mFusion3Platform = false;
1109746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani
1119746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_ACDB_ENABLED
1125ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani            mAcdbHandle = ::dlopen("/system/lib/libacdbloader.so", RTLD_NOW);
1135ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani            if (mAcdbHandle == NULL) {
1145ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                ALOGE("AudioHardware: DLOPEN not successful for ACDBLOADER");
1155ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani            } else {
1165ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                ALOGD("AudioHardware: DLOPEN successful for ACDBLOADER");
1175ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                acdb_init = (int (*)())::dlsym(mAcdbHandle,"acdb_loader_init_ACDB");
1185ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                if (acdb_init == NULL) {
1195ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                    ALOGE("dlsym:Error:%s Loading acdb_loader_init_ACDB", dlerror());
1205ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                }else {
1215ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                   acdb_init();
1225ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                   acdb_deallocate = (void (*)())::dlsym(mAcdbHandle,"acdb_loader_deallocate_ACDB");
1235ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                }
1249746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani            }
1259746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif
1264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
1275ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani#ifdef QCOM_CSDCLIENT_ENABLED
1285ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani             mCsdHandle = ::dlopen("/system/lib/libcsd-client.so", RTLD_NOW);
1295ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani             if (mCsdHandle == NULL) {
1305ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                 ALOGE("AudioHardware: DLOPEN not successful for CSD CLIENT");
1315ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani             } else {
1325ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                 ALOGD("AudioHardware: DLOPEN successful for CSD CLIENT");
133295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani                 csd_client_init = (int (*)())::dlsym(mCsdHandle,"csd_client_init");
134295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani                 csd_client_deinit = (int (*)())::dlsym(mCsdHandle,"csd_client_deinit");
1355ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                 csd_start_playback = (int (*)())::dlsym(mCsdHandle,"csd_client_start_playback");
1365ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                 csd_stop_playback = (int (*)())::dlsym(mCsdHandle,"csd_client_stop_playback");
137295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani
138295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani                 if (csd_client_init == NULL) {
139295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani                    ALOGE("dlsym: Error:%s Loading csd_client_init", dlerror());
140295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani                 } else {
141295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani                    csd_client_init();
142295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani                 }
1435ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani             }
1445ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani             mALSADevice->setCsdHandle(mCsdHandle);
1455ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani#endif
1464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            if((fp = fopen("/proc/asound/cards","r")) == NULL) {
1474113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                ALOGE("Cannot open /proc/asound/cards file to get sound card info");
1484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            } else {
1494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                while((fgets(soundCardInfo, sizeof(soundCardInfo), fp) != NULL)) {
1504113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                    ALOGV("SoundCardInfo %s", soundCardInfo);
1514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    if (strstr(soundCardInfo, "msm8960-tabla1x-snd-card")) {
1524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        codec_rev = 1;
1534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        break;
1544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    } else if (strstr(soundCardInfo, "msm-snd-card")) {
1554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        codec_rev = 2;
1564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        break;
1574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    } else if (strstr(soundCardInfo, "msm8930-sitar-snd-card")) {
1584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        codec_rev = 3;
1594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        break;
1604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    }
1614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                }
1624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                fclose(fp);
1634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            }
1644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
1654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            if (codec_rev == 1) {
1664113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                    ALOGV("Detected tabla 1.x sound card");
1674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm");
1684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            } else if (codec_rev == 3) {
1694113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                    ALOGV("Detected sitar 1.x sound card");
1704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_Sitar");
1714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            } else {
1724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    property_get("ro.board.platform", platform, "");
1734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    property_get("ro.baseband", baseband, "");
1744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
1754113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                        ALOGV("Detected Fusion tabla 2.x");
1764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        mFusion3Platform = true;
1774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x_Fusion3");
1784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    } else {
1794113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                        ALOGV("Detected tabla 2.x sound card");
1804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x");
1814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    }
1824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            }
1834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
1844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            if (mUcMgr < 0) {
1854113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                ALOGE("Failed to open ucm instance: %d", errno);
1864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            } else {
1874113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                ALOGI("ucm instance opened: %u", (unsigned)mUcMgr);
1885ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                mUcMgr->acdb_handle = NULL;
1895ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani#ifdef QCOM_ACDB_ENABLED
1905ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                if (mAcdbHandle) {
1915ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                    mUcMgr->acdb_handle = static_cast<void*> (mAcdbHandle);
192295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani                    if (mFusion3Platform)
193295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani                        mUcMgr->isFusion3Platform = true;
194295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani                    else
195295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani                        mUcMgr->isFusion3Platform = false;
1965ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                }
1975ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani#endif
1984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            }
1994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else {
2004113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev            ALOGE("ALSA Module could not be opened!!!");
2014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
2024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    } else {
2034113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev        ALOGE("ALSA Module not found!!!");
2044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
2054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2074765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::~AudioHardwareALSA()
2084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
2094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (mUcMgr != NULL) {
2109efed76df6b7c75d170e8f900f875f4329587719SathishKumar Mani        ALOGV("closing ucm instance: %u", (unsigned)mUcMgr);
2114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        snd_use_case_mgr_close(mUcMgr);
2124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
2134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (mALSADevice) {
2144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mALSADevice->common.close(&mALSADevice->common);
2154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
2164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    for(ALSAHandleList::iterator it = mDeviceList.begin();
2174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            it != mDeviceList.end(); ++it) {
2184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        it->useCase[0] = 0;
2194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mDeviceList.erase(it);
2204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
2219746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_ACDB_ENABLED
2225ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani     if (acdb_deallocate == NULL) {
2235ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani        ALOGE("dlsym: Error:%s Loading acdb_deallocate_ACDB", dlerror());
2245ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani     } else {
2255ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani        acdb_deallocate();
2265ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani     }
2275ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani     if (mAcdbHandle) {
2285ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani        ::dlclose(mAcdbHandle);
2295ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani        mAcdbHandle = NULL;
2305ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani     }
2319746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif
2329746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED
2334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    delete mAudioUsbALSA;
2349746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif
2355ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani
2365ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani#ifdef QCOM_CSDCLEINT_ENABLED
2375ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani     if (mCsdHandle) {
238295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani         if (csd_client_deinit == NULL) {
239295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani             ALOGE("dlsym: Error:%s Loading csd_client_deinit", dlerror());
240295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani         } else {
241295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani             csd_client_deinit();
242295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani         }
243295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani         ::dlclose(mCsdHandle);
244295559398bf12612fb208ab3dd24ac08b6f04f2aSathishKumar Mani         mCsdHandle = NULL;
2455ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani     }
2465ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani#endif
2474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::initCheck()
2504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
2514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (!mALSADevice)
2524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        return NO_INIT;
2534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return NO_ERROR;
2554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::setVoiceVolume(float v)
2584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
2598a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani    ALOGV("setVoiceVolume(%f)\n", v);
2604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (v < 0.0) {
2614113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev        ALOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
2624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        v = 0.0;
2634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    } else if (v > 1.0) {
2644113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev        ALOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
2654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        v = 1.0;
2664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
2674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    int newMode = mode();
2698a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani    ALOGV("setVoiceVolume  newMode %d",newMode);
2704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    int vol = lrint(v * 100.0);
2714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    // Voice volume levels from android are mapped to driver volume levels as follows.
2734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
2744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    // So adjust the volume to get the correct volume index in driver
2754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    vol = 100 - vol;
2764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (mALSADevice) {
2784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
2794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mALSADevice->setVoipVolume(vol);
2804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else if (newMode == AudioSystem::MODE_IN_CALL){
2819746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani               if (mCSCallActive == CS_ACTIVE)
2824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                   mALSADevice->setVoiceVolume(vol);
2839746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani               if (mVolteCallActive == IMS_ACTIVE)
2844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                   mALSADevice->setVoLTEVolume(vol);
2854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
2864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
2874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return NO_ERROR;
2894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2919746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED
2924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t  AudioHardwareALSA::setFmVolume(float value)
2934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
2944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    status_t status = NO_ERROR;
2954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    int vol;
2974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (value < 0.0) {
2994113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev        ALOGW("setFmVolume(%f) under 0.0, assuming 0.0\n", value);
3004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        value = 0.0;
3014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    } else if (value > 1.0) {
3024113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev        ALOGW("setFmVolume(%f) over 1.0, assuming 1.0\n", value);
3034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        value = 1.0;
3044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
3054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    vol  = lrint((value * 0x2000) + 0.5);
3064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3079efed76df6b7c75d170e8f900f875f4329587719SathishKumar Mani    ALOGV("setFmVolume(%f)\n", value);
3089efed76df6b7c75d170e8f900f875f4329587719SathishKumar Mani    ALOGV("Setting FM volume to %d (available range is 0 to 0x2000)\n", vol);
3094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    mALSADevice->setFmVolume(vol);
3114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return status;
3134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
3144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
3154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::setMasterVolume(float volume)
3174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
3184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return NO_ERROR;
3194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
3204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::setMode(int mode)
3224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
3234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    status_t status = NO_ERROR;
3244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (mode != mMode) {
3264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        status = AudioHardwareBase::setMode(mode);
3274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
3284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (mode == AudioSystem::MODE_IN_CALL) {
3309746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        mCallState = CS_ACTIVE;
3314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }else if (mode == AudioSystem::MODE_NORMAL) {
3324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mCallState = 0;
3334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
3344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return status;
3364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
3374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::setParameters(const String8& keyValuePairs)
3394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
3404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    AudioParameter param = AudioParameter(keyValuePairs);
3414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    String8 key;
3424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    String8 value;
3434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    status_t status = NO_ERROR;
3444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    int device;
3454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    int btRate;
3464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    int state;
3479efed76df6b7c75d170e8f900f875f4329587719SathishKumar Mani    ALOGV("setParameters() %s", keyValuePairs.string());
3484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8(TTY_MODE_KEY);
3504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.get(key, value) == NO_ERROR) {
3514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mDevSettingsFlag &= TTY_CLEAR;
352a97e6f657522513449514a677f19a0ff28df0059ty.lee        if (value == "tty_full") {
3534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDevSettingsFlag |= TTY_FULL;
354a97e6f657522513449514a677f19a0ff28df0059ty.lee        } else if (value == "tty_hco") {
3554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDevSettingsFlag |= TTY_HCO;
356a97e6f657522513449514a677f19a0ff28df0059ty.lee        } else if (value == "tty_vco") {
3574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDevSettingsFlag |= TTY_VCO;
3584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else {
3594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDevSettingsFlag |= TTY_OFF;
3604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
3614113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev        ALOGI("Changed TTY Mode=%s", value.string());
3624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mALSADevice->setFlags(mDevSettingsFlag);
3634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(mMode != AudioSystem::MODE_IN_CALL){
3644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           return NO_ERROR;
3654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
3664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        doRouting(0);
3674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
3684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8(FLUENCE_KEY);
3704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.get(key, value) == NO_ERROR) {
3714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (value == "quadmic") {
3724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDevSettingsFlag |= QMIC_FLAG;
3734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDevSettingsFlag &= (~DMIC_FLAG);
3744113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev            ALOGV("Fluence quadMic feature Enabled");
3754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else if (value == "dualmic") {
3764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDevSettingsFlag |= DMIC_FLAG;
3774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDevSettingsFlag &= (~QMIC_FLAG);
3784113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev            ALOGV("Fluence dualmic feature Enabled");
3794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else if (value == "none") {
3804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDevSettingsFlag &= (~DMIC_FLAG);
3814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDevSettingsFlag &= (~QMIC_FLAG);
3824113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev            ALOGV("Fluence feature Disabled");
3834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
3844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mALSADevice->setFlags(mDevSettingsFlag);
3854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        doRouting(0);
3864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
3874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3889746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_CSDCLIENT_ENABLED
3894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (mFusion3Platform) {
3904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        key = String8(INCALLMUSIC_KEY);
3914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (param.get(key, value) == NO_ERROR) {
3924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            if (value == "true") {
3934113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                ALOGV("Enabling Incall Music setting in the setparameter\n");
3945ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                if (csd_start_playback == NULL) {
3955ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                    ALOGE("dlsym: Error:%s Loading csd_client_start_playback", dlerror());
3965ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                } else {
3975ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                    csd_start_playback();
3985ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                }
3994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            } else {
4004113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                ALOGV("Disabling Incall Music setting in the setparameter\n");
4015ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                if (csd_stop_playback == NULL) {
4025ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                    ALOGE("dlsym: Error:%s Loading csd_client_stop_playback", dlerror());
4035ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                } else {
4045ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                    csd_stop_playback();
4055ff7a02ca497656b711919b81a783e6a10cdcc76SathishKumar Mani                }
4064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            }
4074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
4084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
4099746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif
4104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8(ANC_KEY);
4124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.get(key, value) == NO_ERROR) {
4134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (value == "true") {
4144113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev            ALOGV("Enabling ANC setting in the setparameter\n");
4154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDevSettingsFlag |= ANC_FLAG;
4164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else {
4174113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev            ALOGV("Disabling ANC setting in the setparameter\n");
4184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDevSettingsFlag &= (~ANC_FLAG);
4194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
4204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mALSADevice->setFlags(mDevSettingsFlag);
4214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        doRouting(0);
4224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
4234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8(AudioParameter::keyRouting);
4254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.getInt(key, device) == NO_ERROR) {
4264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        // Ignore routing if device is 0.
4274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(device) {
4284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            doRouting(device);
4294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
4304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        param.remove(key);
4314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
4324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8(BT_SAMPLERATE_KEY);
4344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.getInt(key, btRate) == NO_ERROR) {
4354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mALSADevice->setBtscoRate(btRate);
4364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        param.remove(key);
4374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
4384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8(BTHEADSET_VGS);
4404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.get(key, value) == NO_ERROR) {
4414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (value == "on") {
4424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mBluetoothVGS = true;
4434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else {
4444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mBluetoothVGS = false;
4454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
4464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
4474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8(WIDEVOICE_KEY);
4494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.get(key, value) == NO_ERROR) {
4504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        bool flag = false;
4514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (value == "true") {
4524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            flag = true;
4534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
4544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(mALSADevice) {
4554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mALSADevice->enableWideVoice(flag);
4564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
4574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        param.remove(key);
4584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
4594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8(VOIPRATE_KEY);
4614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.get(key, value) == NO_ERROR) {
4624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mVoipBitRate = atoi(value);
4634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        param.remove(key);
4644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
4654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8(FENS_KEY);
4674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.get(key, value) == NO_ERROR) {
4684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        bool flag = false;
4694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (value == "true") {
4704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            flag = true;
4714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
4724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(mALSADevice) {
4734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mALSADevice->enableFENS(flag);
4744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
4754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        param.remove(key);
4764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
4774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4789746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED
4794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8(AudioParameter::keyHandleFm);
4804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.getInt(key, device) == NO_ERROR) {
4814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        // Ignore if device is 0
4824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(device) {
4834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            handleFm(device);
4844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
4854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        param.remove(key);
4864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
4874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
4884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8(ST_KEY);
4904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.get(key, value) == NO_ERROR) {
4914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        bool flag = false;
4924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (value == "true") {
4934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            flag = true;
4944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
4954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(mALSADevice) {
4964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mALSADevice->enableSlowTalk(flag);
4974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
4984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        param.remove(key);
4994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
5004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8(MODE_CALL_KEY);
5014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.getInt(key,state) == NO_ERROR) {
5024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (mCallState != state) {
5034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mCallState = state;
5044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            doRouting(0);
5054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
5064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mCallState = state;
5074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
5084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.size()) {
5094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        status = BAD_VALUE;
5104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
5114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return status;
5124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
5134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5144765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevString8 AudioHardwareALSA::getParameters(const String8& keys)
5154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
5164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    AudioParameter param = AudioParameter(keys);
5174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    String8 value;
5184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    String8 key = String8(DUALMIC_KEY);
5204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.get(key, value) == NO_ERROR) {
5214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        value = String8("false");
5224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        param.add(key, value);
5234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
5244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8(FLUENCE_KEY);
5264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.get(key, value) == NO_ERROR) {
5274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if ((mDevSettingsFlag & QMIC_FLAG) &&
5284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                               (mDevSettingsFlag & ~DMIC_FLAG))
5294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            value = String8("quadmic");
5304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    else if ((mDevSettingsFlag & DMIC_FLAG) &&
5314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                (mDevSettingsFlag & ~QMIC_FLAG))
5324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            value = String8("dualmic");
5334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    else if ((mDevSettingsFlag & ~DMIC_FLAG) &&
5344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                (mDevSettingsFlag & ~QMIC_FLAG))
5354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            value = String8("none");
5364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        param.add(key, value);
5374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
5384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5399746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED
5404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8("Fm-radio");
5414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if ( param.get(key,value) == NO_ERROR ) {
5424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if ( mIsFmActive ) {
5434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            param.addInt(String8("isFMON"), true );
5444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
5454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
5464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
5474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    key = String8(BTHEADSET_VGS);
5494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (param.get(key, value) == NO_ERROR) {
5504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(mBluetoothVGS)
5514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           param.addInt(String8("isVGS"), true);
5524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
5534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5544113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGV("AudioHardwareALSA::getParameters() %s", param.toString().string());
5554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return param.toString();
5564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
5574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5589746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED
5594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::closeUSBPlayback()
5604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
5614113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGV("closeUSBPlayback, musbPlaybackState: %d", musbPlaybackState);
5624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    musbPlaybackState = 0;
5634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_KILLTHREAD);
5644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
5654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::closeUSBRecording()
5674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
5684113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGV("closeUSBRecording");
5694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    musbRecordingState = 0;
5704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    mAudioUsbALSA->exitRecordingThread(SIGNAL_EVENT_KILLTHREAD);
5714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
5724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::closeUsbPlaybackIfNothingActive(){
5744113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGV("closeUsbPlaybackIfNothingActive, musbPlaybackState: %d", musbPlaybackState);
5754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if(!musbPlaybackState && mAudioUsbALSA != NULL) {
5764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_TIMEOUT);
5774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
5784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
5794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::closeUsbRecordingIfNothingActive(){
5814113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGV("closeUsbRecordingIfNothingActive, musbRecordingState: %d", musbRecordingState);
5824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if(!musbRecordingState && mAudioUsbALSA != NULL) {
5834113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev        ALOGD("Closing USB Recording Session as no stream is active");
5844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mAudioUsbALSA->setkillUsbRecordingThread(true);
5854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
5864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
5874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::startUsbPlaybackIfNotStarted(){
5894113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGV("Starting the USB playback %d kill %d", musbPlaybackState,
5904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             mAudioUsbALSA->getkillUsbPlaybackThread());
5914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if((!musbPlaybackState) || (mAudioUsbALSA->getkillUsbPlaybackThread() == true)) {
5924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mAudioUsbALSA->startPlayback();
5934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
5944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
5954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::startUsbRecordingIfNotStarted(){
5974113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGV("Starting the recording musbRecordingState: %d killUsbRecordingThread %d",
5984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          musbRecordingState, mAudioUsbALSA->getkillUsbRecordingThread());
5994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if((!musbRecordingState) || (mAudioUsbALSA->getkillUsbRecordingThread() == true)) {
6004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mAudioUsbALSA->startRecording();
6014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
6024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
6039746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif
6044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::doRouting(int device)
6064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
6074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    Mutex::Autolock autoLock(mLock);
6084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    int newMode = mode();
6094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    bool isRouted = false;
6104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6119746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani    if ((device == AudioSystem::DEVICE_IN_VOICE_CALL)
6129746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED
6139746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        || (device == AudioSystem::DEVICE_IN_FM_RX)
6149746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        || (device == AudioSystem::DEVICE_OUT_DIRECTOUTPUT)
6159746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        || (device == AudioSystem::DEVICE_IN_FM_RX_A2DP)
6164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
6179746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        || (device == AudioSystem::DEVICE_IN_COMMUNICATION)
6189746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        ) {
6194113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev        ALOGV("Ignoring routing for FM/INCALL/VOIP recording");
6204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        return;
6214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
6224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (device == 0)
6234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        device = mCurDevice;
6244113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGV("doRouting: device %d newMode %d mCSCallActive %d mVolteCallActive %d"
6254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         "mIsFmActive %d", device, newMode, mCSCallActive, mVolteCallActive,
6264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         mIsFmActive);
6274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    isRouted = routeVoLTECall(device, newMode);
6294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    isRouted |= routeVoiceCall(device, newMode);
6304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if(!isRouted) {
6329746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED
6334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(!(device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) &&
6344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            !(device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET) &&
6354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            !(device & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) &&
6364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             (musbPlaybackState)){
6374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                //USB unplugged
6384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                device &= ~ AudioSystem::DEVICE_OUT_PROXY;
6394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                device &= ~ AudioSystem::DEVICE_IN_PROXY;
6404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                ALSAHandleList::iterator it = mDeviceList.end();
6414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                it--;
6424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                mALSADevice->route(&(*it), (uint32_t)device, newMode);
6430a019914794cc27f5dacddf4e5dbc019dbe21788SathishKumar Mani                ALOGD("USB UNPLUGGED, setting musbPlaybackState to 0");
6444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                musbPlaybackState = 0;
6454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                musbRecordingState = 0;
6464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                closeUSBRecording();
6474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                closeUSBPlayback();
6484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
6494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                  (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
6500a019914794cc27f5dacddf4e5dbc019dbe21788SathishKumar Mani                    ALOGD("Routing everything to prox now");
6514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    ALSAHandleList::iterator it = mDeviceList.end();
6524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    it--;
6534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    mALSADevice->route(&(*it), AudioSystem::DEVICE_OUT_PROXY,
6544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                       newMode);
6554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    for(it = mDeviceList.begin(); it != mDeviceList.end(); ++it) {
6564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                         if((!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
6574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                            (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_LPA))) {
6588a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani                                 ALOGV("doRouting: LPA device switch to proxy");
6594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                 startUsbPlaybackIfNotStarted();
6604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                 musbPlaybackState |= USBPLAYBACKBIT_LPA;
6614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                 break;
6624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                         } else if((!strcmp(it->useCase, SND_USE_CASE_VERB_VOICECALL)) ||
6634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOICE))) {
6648a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani                                    ALOGV("doRouting: VOICE device switch to proxy");
6654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                    startUsbRecordingIfNotStarted();
6664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                    startUsbPlaybackIfNotStarted();
6674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                    musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
6684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                    musbRecordingState |= USBPLAYBACKBIT_VOICECALL;
6694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                    break;
6704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        }else if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
6714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
6728a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani                                    ALOGV("doRouting: FM device switch to proxy");
6734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                    startUsbPlaybackIfNotStarted();
6744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                    musbPlaybackState |= USBPLAYBACKBIT_FM;
6754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                    break;
6764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                         }
6774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    }
678e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani        } else
6794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
680e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani        {
6814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             ALSAHandleList::iterator it = mDeviceList.end();
6824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             it--;
6834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             mALSADevice->route(&(*it), (uint32_t)device, newMode);
6844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
6854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
6864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    mCurDevice = device;
6874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
6884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevuint32_t AudioHardwareALSA::getVoipMode(int format)
6904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
6914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    switch(format) {
6924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    case AudioSystem::PCM_16_BIT:
6934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               return MODE_PCM;
6944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         break;
6954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    case AudioSystem::AMR_NB:
6964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               return MODE_AMR;
6974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         break;
6984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    case AudioSystem::AMR_WB:
6994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               return MODE_AMR_WB;
7004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         break;
7014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7029746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_QCHAT_ENABLED
7034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    case AudioSystem::EVRC:
7044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               return MODE_IS127;
7054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         break;
7064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    case AudioSystem::EVRCB:
7084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               return MODE_4GV_NB;
7094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         break;
7104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    case AudioSystem::EVRCWB:
7114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               return MODE_4GV_WB;
7124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         break;
7139746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif
7144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    default:
7164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               return MODE_PCM;
7174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
7184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
7194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7204765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioStreamOut *
7214765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::openOutputStream(uint32_t devices,
7224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                    int *format,
7234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                    uint32_t *channels,
7244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                    uint32_t *sampleRate,
7254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                    status_t *status)
7264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
7274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    Mutex::Autolock autoLock(mLock);
7288a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani    ALOGV("openOutputStream: devices 0x%x channels %d sampleRate %d",
7294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         devices, *channels, *sampleRate);
7304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7318861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani    audio_output_flags_t flag = static_cast<audio_output_flags_t> (*status);
7328861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani
7334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    status_t err = BAD_VALUE;
7348861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani    *status = NO_ERROR;
7354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    AudioStreamOutALSA *out = 0;
7364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    ALSAHandleList::iterator it;
7374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (devices & (devices - 1)) {
7394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (status) *status = err;
7404113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev        ALOGE("openOutputStream called with bad devices");
7414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        return out;
7424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
7438861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani
7448861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani
7454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev# if 0
7464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if((devices == AudioSystem::DEVICE_OUT_DIRECTOUTPUT) &&
7474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev       ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
7484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        bool voipstream_active = false;
7494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        for(it = mDeviceList.begin();
7504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            it != mDeviceList.end(); ++it) {
7514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
7524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                   (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
7534113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                    ALOGD("openOutput:  it->rxHandle %d it->handle %d",it->rxHandle,it->handle);
7544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    voipstream_active = true;
7554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    break;
7564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                }
7574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
7584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      if(voipstream_active == false) {
7594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         mVoipStreamCount = 0;
7604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         alsa_handle_t alsa_handle;
7614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         unsigned long bufferSize;
7624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
7634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             bufferSize = VOIP_BUFFER_SIZE_8K;
7644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         }
7654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
7664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             bufferSize = VOIP_BUFFER_SIZE_16K;
7674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         }
7684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         else {
7694113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev             ALOGE("unsupported samplerate %d for voip",*sampleRate);
7704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             if (status) *status = err;
7714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                 return out;
7724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          }
7734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          alsa_handle.module = mALSADevice;
7744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          alsa_handle.bufferSize = bufferSize;
7754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          alsa_handle.devices = devices;
7764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          alsa_handle.handle = 0;
7774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          if(*format == AudioSystem::PCM_16_BIT)
7784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
7794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          else
7804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              alsa_handle.format = *format;
7814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
78261f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent          alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
7834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          alsa_handle.sampleRate = *sampleRate;
7844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          alsa_handle.latency = VOIP_PLAYBACK_LATENCY;
7854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          alsa_handle.rxHandle = 0;
7864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          alsa_handle.ucMgr = mUcMgr;
7874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
7884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          char *use_case;
7894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
7904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
7914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
7924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          } else {
7934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
7944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          }
7954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          free(use_case);
7964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          mDeviceList.push_back(alsa_handle);
7974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          it = mDeviceList.end();
7984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          it--;
7994113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev          ALOGV("openoutput: mALSADevice->route useCase %s mCurDevice %d mVoipStreamCount %d mode %d", it->useCase,mCurDevice,mVoipStreamCount, mode());
8004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          if((mCurDevice & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
8014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             (mCurDevice & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)||
8024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             (mCurDevice & AudioSystem::DEVICE_OUT_PROXY)){
8034113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev              ALOGD("Routing to proxy for normal voip call in openOutputStream");
8044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              mCurDevice |= AudioSystem::DEVICE_OUT_PROXY;
8054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
8064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
8074113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev              ALOGD("enabling VOIP in openoutputstream, musbPlaybackState: %d", musbPlaybackState);
8084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              startUsbPlaybackIfNotStarted();
8094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
8104113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev              ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
8114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              startUsbRecordingIfNotStarted();
8124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              musbRecordingState |= USBRECBIT_VOIPCALL;
8134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          } else{
8144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
8154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          }
8164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
8174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
8184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          } else {
8194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
8204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          }
8214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          err = mALSADevice->startVoipCall(&(*it));
8224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          if (err) {
8234113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev              ALOGE("Device open failed");
8244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              return NULL;
8254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          }
8264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      }
8274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      out = new AudioStreamOutALSA(this, &(*it));
8284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      err = out->set(format, channels, sampleRate, devices);
8294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      if(err == NO_ERROR) {
8304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          mVoipStreamCount++;   //increment VoipstreamCount only if success
8314113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev          ALOGD("openoutput mVoipStreamCount %d",mVoipStreamCount);
8324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      }
8334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      if (status) *status = err;
8344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      return out;
8354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    } else
8364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
837bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani    if ((flag & AUDIO_OUTPUT_FLAG_DIRECT) &&
838bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        (devices == AudioSystem::DEVICE_OUT_AUX_DIGITAL)) {
839bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        ALOGD("Multi channel PCM");
840bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        alsa_handle_t alsa_handle;
841bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        EDID_AUDIO_INFO info = { 0 };
842bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani
843bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        alsa_handle.module = mALSADevice;
844bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        alsa_handle.devices = devices;
845bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        alsa_handle.handle = 0;
846bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
847bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani
848bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        if (!AudioUtil::getHDMIAudioSinkCaps(&info)) {
849bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            ALOGE("openOutputStream: Failed to get HDMI sink capabilities");
850bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            return NULL;
851bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        }
852bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        if (0 == *channels) {
853bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            alsa_handle.channels = info.AudioBlocksArray[info.nAudioBlocks-1].nChannels;
854bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            if (alsa_handle.channels > 6) {
855bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani                alsa_handle.channels = 6;
856bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            }
857bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            *channels = audio_channel_out_mask_from_count(alsa_handle.channels);
858bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        } else {
859bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            alsa_handle.channels = AudioSystem::popCount(*channels);
860bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        }
86161f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent        alsa_handle.channelMask = *channels;
86261f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent
863bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        if (6 == alsa_handle.channels) {
864bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            alsa_handle.bufferSize = DEFAULT_MULTI_CHANNEL_BUF_SIZE;
865bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        } else {
866bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            alsa_handle.bufferSize = DEFAULT_BUFFER_SIZE;
867bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        }
868bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        if (0 == *sampleRate) {
869bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            alsa_handle.sampleRate = info.AudioBlocksArray[info.nAudioBlocks-1].nSamplingFreq;
870bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            *sampleRate = alsa_handle.sampleRate;
871bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        } else {
872bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            alsa_handle.sampleRate = *sampleRate;
873bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        }
874bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        alsa_handle.latency = PLAYBACK_LATENCY;
875bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        alsa_handle.rxHandle = 0;
876bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        alsa_handle.ucMgr = mUcMgr;
877bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        ALOGD("alsa_handle.channels %d alsa_handle.sampleRate %d",alsa_handle.channels,alsa_handle.sampleRate);
878bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani
879bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        char *use_case;
880bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
881bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
882bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI2 , sizeof(alsa_handle.useCase));
883bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        } else {
884bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC2, sizeof(alsa_handle.useCase));
885bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        }
886bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        free(use_case);
887bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        mDeviceList.push_back(alsa_handle);
888bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        ALSAHandleList::iterator it = mDeviceList.end();
889bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        it--;
890bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        ALOGD("it->useCase %s", it->useCase);
891bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        mALSADevice->route(&(*it), devices, mode());
892bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI2)) {
893bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI2 );
894bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        } else {
895bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC2);
896bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        }
897bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        ALOGD("channels: %d", AudioSystem::popCount(*channels));
898bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        err = mALSADevice->open(&(*it));
899bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani
900bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        if (err) {
901bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            ALOGE("Device open failed err:%d",err);
902bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        } else {
903bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            out = new AudioStreamOutALSA(this, &(*it));
904bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani            err = out->set(format, channels, sampleRate, devices);
905bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        }
906bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        if (status) *status = err;
907bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani        return out;
908bf1c87481d62736cab8832e9085c121fbafdbb6bSathishKumar Mani    } else {
9094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
9104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      alsa_handle_t alsa_handle;
9114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
9124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
9134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
9144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          bufferSize &= ~b;
9154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
9164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      alsa_handle.module = mALSADevice;
9174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      alsa_handle.bufferSize = bufferSize;
9184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      alsa_handle.devices = devices;
9194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      alsa_handle.handle = 0;
9204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
9214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      alsa_handle.channels = DEFAULT_CHANNEL_MODE;
92261f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent      alsa_handle.channelMask = AUDIO_CHANNEL_OUT_STEREO;
9234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
9244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      alsa_handle.latency = PLAYBACK_LATENCY;
9254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      alsa_handle.rxHandle = 0;
9264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      alsa_handle.ucMgr = mUcMgr;
9278861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani      alsa_handle.isDeepbufferOutput = false;
9284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
9294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      char *use_case;
9304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
9318861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani
9328861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani      if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
9339efed76df6b7c75d170e8f900f875f4329587719SathishKumar Mani      ALOGD("openOutputStream: DeepBuffer Output");
9348861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani          alsa_handle.isDeepbufferOutput = true;
9358861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani          if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
9368861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani               strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI, sizeof(alsa_handle.useCase));
9378861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani          } else {
9388861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani               strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC, sizeof(alsa_handle.useCase));
9398861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani          }
9404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      } else {
9419efed76df6b7c75d170e8f900f875f4329587719SathishKumar Mani      ALOGD("openOutputStream: Lowlatency Output");
9428861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani          alsa_handle.bufferSize = PLAYBACK_LOW_LATENCY_BUFFER_SIZE;
94377780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani          alsa_handle.latency = PLAYBACK_LOW_LATENCY_MEASURED;
9448861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani          if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
9458861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani               strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
9468861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani          } else {
9478861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani               strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
9488861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani          }
9494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      }
9504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      free(use_case);
9514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      mDeviceList.push_back(alsa_handle);
9524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      ALSAHandleList::iterator it = mDeviceList.end();
9534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      it--;
9548a9785b5e6a199a6c64ac671afc2e8036c7ec13fAjay Dudani      ALOGV("useCase %s", it->useCase);
9559746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED
9564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
9574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
9580a019914794cc27f5dacddf4e5dbc019dbe21788SathishKumar Mani          ALOGD("Routing to proxy for normal playback in openOutputStream");
9594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          devices |= AudioSystem::DEVICE_OUT_PROXY;
9604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      }
9614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
9624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      mALSADevice->route(&(*it), devices, mode());
9638861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani      if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
9648861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani          if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI)) {
9658861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani             snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI);
9668861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani          } else {
9678861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani             snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC);
9688861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani          }
9694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      } else {
9708861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani          if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) {
9718861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani             snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC);
9728861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani          } else {
9738861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani             snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC);
9748861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani          }
9754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      }
9764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      err = mALSADevice->open(&(*it));
9774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      if (err) {
9784113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev          ALOGE("Device open failed");
9794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      } else {
9804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          out = new AudioStreamOutALSA(this, &(*it));
9814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          err = out->set(format, channels, sampleRate, devices);
9824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      }
9834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
9844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      if (status) *status = err;
9854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      return out;
9864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
9874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
9884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
9894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid
9904765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::closeOutputStream(AudioStreamOut* out)
9914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
9924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    delete out;
9934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
9944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
9959746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_TUNNEL_LPA_ENABLED
9964765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioStreamOut *
9974765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::openOutputSession(uint32_t devices,
9984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                     int *format,
9994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                     status_t *status,
10004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                     int sessionId,
10014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                     uint32_t samplingRate,
10024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                     uint32_t channels)
10034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
10044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    Mutex::Autolock autoLock(mLock);
10054113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGD("openOutputSession = %d" ,sessionId);
10064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    AudioStreamOutALSA *out = 0;
10074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    status_t err = BAD_VALUE;
10084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
10094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle_t alsa_handle;
10104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
10114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
10124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
10134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        bufferSize &= ~b;
10144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
10154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.module = mALSADevice;
10164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.bufferSize = bufferSize;
10174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.devices = devices;
10184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.handle = 0;
10194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
10204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.channels = DEFAULT_CHANNEL_MODE;
102161f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent    alsa_handle.channelMask = AUDIO_CHANNEL_OUT_STEREO;
10224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
10234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.latency = VOICE_LATENCY;
10244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.rxHandle = 0;
10254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.ucMgr = mUcMgr;
10264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
10274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    char *use_case;
10284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if(sessionId == TUNNEL_SESSION_ID) {
10294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
10304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
10314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_TUNNEL, sizeof(alsa_handle.useCase));
10324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else {
10334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_TUNNEL, sizeof(alsa_handle.useCase));
10344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
10354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    } else {
10364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
10374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
10384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER, sizeof(alsa_handle.useCase));
10394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else {
10404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LPA, sizeof(alsa_handle.useCase));
10414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
10424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
10434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    free(use_case);
10444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    mDeviceList.push_back(alsa_handle);
10454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    ALSAHandleList::iterator it = mDeviceList.end();
10464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    it--;
10474113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGD("useCase %s", it->useCase);
10489746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED
10494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
10504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev       (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
10510a019914794cc27f5dacddf4e5dbc019dbe21788SathishKumar Mani        ALOGD("Routing to proxy for LPA in openOutputSession");
10524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        devices |= AudioSystem::DEVICE_OUT_PROXY;
10534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mALSADevice->route(&(*it), devices, mode());
10544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        devices = AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
10554113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev        ALOGD("Starting USBPlayback for LPA");
10564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        startUsbPlaybackIfNotStarted();
10574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        musbPlaybackState |= USBPLAYBACKBIT_LPA;
10584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    } else
10594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
10604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    {
10614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mALSADevice->route(&(*it), devices, mode());
10624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
10634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if(sessionId == TUNNEL_SESSION_ID) {
10644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) {
10654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_TUNNEL);
10664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else {
10674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_TUNNEL);
10684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
10694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
10704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    else {
10714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) {
10724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOW_POWER);
10734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else {
10744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LPA);
10754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
10764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
10774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    err = mALSADevice->open(&(*it));
10784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out = new AudioStreamOutALSA(this, &(*it));
10794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
10804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (status) *status = err;
10814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev       return out;
10824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
10834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
10844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid
10854765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::closeOutputSession(AudioStreamOut* out)
10864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
10874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    delete out;
10884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
10899746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif
10904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
10914765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioStreamIn *
10924765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::openInputStream(uint32_t devices,
10934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   int *format,
10944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   uint32_t *channels,
10954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   uint32_t *sampleRate,
10964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   status_t *status,
10974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   AudioSystem::audio_in_acoustics acoustics)
10984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
10994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    Mutex::Autolock autoLock(mLock);
11004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    char *use_case;
11014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    int newMode = mode();
11024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    uint32_t route_devices;
11034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
11044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    status_t err = BAD_VALUE;
11054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    AudioStreamInALSA *in = 0;
11064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    ALSAHandleList::iterator it;
11074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
11084113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGD("openInputStream: devices 0x%x channels %d sampleRate %d", devices, *channels, *sampleRate);
11094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (devices & (devices - 1)) {
11104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (status) *status = err;
11114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        return in;
11124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
11134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
11144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if((devices == AudioSystem::DEVICE_IN_COMMUNICATION) &&
11154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev       ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
11164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        bool voipstream_active = false;
11174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        for(it = mDeviceList.begin();
11184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            it != mDeviceList.end(); ++it) {
11194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
11204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                   (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
11219746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani                    ALOGD("openInput:  it->rxHandle %p it->handle %p",it->rxHandle,it->handle);
11224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    voipstream_active = true;
11234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    break;
11244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                }
11254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
11264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(voipstream_active == false) {
11274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           mVoipStreamCount = 0;
11284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           alsa_handle_t alsa_handle;
11294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           unsigned long bufferSize;
11304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
11314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               bufferSize = VOIP_BUFFER_SIZE_8K;
11324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           }
11334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
11344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               bufferSize = VOIP_BUFFER_SIZE_16K;
11354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           }
11364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           else {
11374113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev               ALOGE("unsupported samplerate %d for voip",*sampleRate);
11384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               if (status) *status = err;
11394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               return in;
11404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           }
11414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           alsa_handle.module = mALSADevice;
11424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           alsa_handle.bufferSize = bufferSize;
11434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           alsa_handle.devices = devices;
11444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           alsa_handle.handle = 0;
11454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          if(*format == AudioSystem::PCM_16_BIT)
11464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
11474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          else
11484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              alsa_handle.format = *format;
11494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
115061f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent           alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
11514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           alsa_handle.sampleRate = *sampleRate;
11524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           alsa_handle.latency = VOIP_RECORD_LATENCY;
11534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           alsa_handle.rxHandle = 0;
11544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           alsa_handle.ucMgr = mUcMgr;
11554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
11564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
11574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
11584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
11594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           } else {
11604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
11614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           }
11624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           free(use_case);
11634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           mDeviceList.push_back(alsa_handle);
11644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           it = mDeviceList.end();
11654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           it--;
11660a019914794cc27f5dacddf4e5dbc019dbe21788SathishKumar Mani           ALOGD("mCurrDevice: %d", mCurDevice);
11679746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED
11684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           if((mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
11694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              (mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
11700a019914794cc27f5dacddf4e5dbc019dbe21788SathishKumar Mani              ALOGD("Routing everything from proxy for voipcall");
11714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              mALSADevice->route(&(*it), AudioSystem::DEVICE_IN_PROXY, AudioSystem::MODE_IN_COMMUNICATION);
11724113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev              ALOGD("enabling VOIP in openInputstream, musbPlaybackState: %d", musbPlaybackState);
11734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              startUsbPlaybackIfNotStarted();
11744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
11754113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev              ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
11764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              startUsbRecordingIfNotStarted();
11774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              musbRecordingState |= USBRECBIT_VOIPCALL;
1178e42406e02e32dbb398a2fa0c452e52526b763c8dSathishKumar Mani           } else
11794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
11804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           {
11814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               mALSADevice->route(&(*it),mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
11824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           }
11834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
11844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
11854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           } else {
11864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
11874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           }
11884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           if(sampleRate) {
11894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               it->sampleRate = *sampleRate;
11904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           }
11914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           if(channels)
11924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               it->channels = AudioSystem::popCount(*channels);
11934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           err = mALSADevice->startVoipCall(&(*it));
11944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           if (err) {
11954113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev               ALOGE("Error opening pcm input device");
11964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               return NULL;
11974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           }
11984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
11994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        in = new AudioStreamInALSA(this, &(*it), acoustics);
12004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        err = in->set(format, channels, sampleRate, devices);
12014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(err == NO_ERROR) {
12024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mVoipStreamCount++;   //increment VoipstreamCount only if success
12034113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev            ALOGD("OpenInput mVoipStreamCount %d",mVoipStreamCount);
12044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
12050a019914794cc27f5dacddf4e5dbc019dbe21788SathishKumar Mani        ALOGD("openInput: After Get alsahandle");
12064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (status) *status = err;
12074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        return in;
1208ed3c0fdecb72890240d52a8ba3b5ecd05331736aSathishKumar Mani      } else {
12094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle_t alsa_handle;
121077780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani        unsigned long bufferSize = MIN_CAPTURE_BUFFER_SIZE_PER_CH;
12114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
12124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.module = mALSADevice;
12134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.bufferSize = bufferSize;
12144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.devices = devices;
12154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.handle = 0;
12164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
12174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.channels = VOICE_CHANNEL_MODE;
121861f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent        alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
12194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.sampleRate = android::AudioRecord::DEFAULT_SAMPLE_RATE;
12204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.latency = RECORD_LATENCY;
12214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.rxHandle = 0;
12224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.ucMgr = mUcMgr;
12234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
12244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
12254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
12264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                (newMode == AudioSystem::MODE_IN_CALL)) {
12274113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                ALOGD("openInputStream: into incall recording, channels %d", *channels);
12284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                mIncallMode = *channels;
12294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
12304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
12314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    if (mFusion3Platform) {
12324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        mALSADevice->setVocRecMode(INCALL_REC_STEREO);
12334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
12344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                sizeof(alsa_handle.useCase));
12354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    } else {
12364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
12374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                sizeof(alsa_handle.useCase));
12384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    }
12394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
12404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    if (mFusion3Platform) {
12414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        mALSADevice->setVocRecMode(INCALL_REC_MONO);
12424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
12434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                sizeof(alsa_handle.useCase));
12444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    } else {
12454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
12464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                sizeof(alsa_handle.useCase));
12474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    }
12484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                }
12499746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED
12504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            } else if((devices == AudioSystem::DEVICE_IN_FM_RX)) {
12514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_FM, sizeof(alsa_handle.useCase));
12524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            } else if(devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
12534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, sizeof(alsa_handle.useCase));
12544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
12554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            } else {
12569efed76df6b7c75d170e8f900f875f4329587719SathishKumar Mani        char value[128];
12579efed76df6b7c75d170e8f900f875f4329587719SathishKumar Mani        property_get("persist.audio.lowlatency.rec",value,"0");
12588861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani                if (!strcmp("true", value)) {
12598861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani                    strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
12608861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani                } else {
12618861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani                    strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, sizeof(alsa_handle.useCase));
12628861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani                }
12634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            }
12644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else {
12654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
12664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                (newMode == AudioSystem::MODE_IN_CALL)) {
12674113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                ALOGD("openInputStream: incall recording, channels %d", *channels);
12684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                mIncallMode = *channels;
12694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
12704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
12714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    if (mFusion3Platform) {
12724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        mALSADevice->setVocRecMode(INCALL_REC_STEREO);
12734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
12744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                sizeof(alsa_handle.useCase));
12754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    } else {
12764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_UL_DL_REC,
12774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                sizeof(alsa_handle.useCase));
12784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    }
12794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
12804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    if (mFusion3Platform) {
12814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        mALSADevice->setVocRecMode(INCALL_REC_MONO);
12824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
12834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                sizeof(alsa_handle.useCase));
12844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    } else {
12854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                       strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DL_REC,
12864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                               sizeof(alsa_handle.useCase));
12874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    }
12884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                }
12899746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED
12904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            } else if(devices == AudioSystem::DEVICE_IN_FM_RX) {
12914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_REC, sizeof(alsa_handle.useCase));
12924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            } else if (devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
12934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_A2DP_REC, sizeof(alsa_handle.useCase));
12944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
12954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            } else {
12968861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani                char value[128];
12978861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani                property_get("persist.audio.lowlatency.rec",value,"0");
12988861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani                if (!strcmp("true", value)) {
12998861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani                    strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, sizeof(alsa_handle.useCase));
13008861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani                } else {
13018861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani                    strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_REC, sizeof(alsa_handle.useCase));
13028861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani                }
13034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            }
13044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
13054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        free(use_case);
13064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mDeviceList.push_back(alsa_handle);
13074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        ALSAHandleList::iterator it = mDeviceList.end();
13084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        it--;
13094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        //update channel info before do routing
13104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(channels) {
13114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            it->channels = AudioSystem::popCount((*channels) &
13129746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani                      (AudioSystem::CHANNEL_IN_STEREO
13139746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani                       | AudioSystem::CHANNEL_IN_MONO
13149746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_SSR_ENABLED
13154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                       | AudioSystem::CHANNEL_IN_5POINT1
13164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
131761f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent                       | AUDIO_CHANNEL_IN_FRONT_BACK));
131861f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent            it->channelMask = *channels;
131961f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent            ALOGV("updated channel info: channels=%d channelMask %08x",
132061f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent                  it->channels, it->channelMask);
13214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
13224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (devices == AudioSystem::DEVICE_IN_VOICE_CALL){
13234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           /* Add current devices info to devices to do route */
13249746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED
13254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            if(mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET ||
13264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET){
13274113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                ALOGD("Routing everything from proxy for VOIP call");
13284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                route_devices = devices | AudioSystem::DEVICE_IN_PROXY;
13294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            } else
13304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
13314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            {
13324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            route_devices = devices | mCurDevice;
13334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            }
13344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mALSADevice->route(&(*it), route_devices, mode());
13354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else {
13369746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED
13374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            if(devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET ||
13384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev               devices & AudioSystem::DEVICE_IN_PROXY) {
13394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                devices |= AudioSystem::DEVICE_IN_PROXY;
13400a019914794cc27f5dacddf4e5dbc019dbe21788SathishKumar Mani                ALOGD("routing everything from proxy");
13414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mALSADevice->route(&(*it), devices, mode());
13424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            } else
13434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
13444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            {
13454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                mALSADevice->route(&(*it), devices, mode());
13464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            }
13474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
13484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC) ||
13498861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani           !strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC) ||
13509746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED
13514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           !strcmp(it->useCase, SND_USE_CASE_VERB_FM_REC) ||
13524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           !strcmp(it->useCase, SND_USE_CASE_VERB_FM_A2DP_REC) ||
13534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
13544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           !strcmp(it->useCase, SND_USE_CASE_VERB_DL_REC) ||
13554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           !strcmp(it->useCase, SND_USE_CASE_VERB_UL_DL_REC) ||
13564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           !strcmp(it->useCase, SND_USE_CASE_VERB_INCALL_REC)) {
13574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            snd_use_case_set(mUcMgr, "_verb", it->useCase);
13584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else {
13594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            snd_use_case_set(mUcMgr, "_enamod", it->useCase);
13604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
13614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(sampleRate) {
13624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            it->sampleRate = *sampleRate;
13634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
136477780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani        if (!strncmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
136577780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani            || !strncmp(it->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
136677780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani            ALOGV("OpenInoutStream: Use larger buffer size for 5.1(%s) recording ", it->useCase);
136777780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani            it->bufferSize = getInputBufferSize(it->sampleRate,*format,it->channels);
13684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
13694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        err = mALSADevice->open(&(*it));
13704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (err) {
13714113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev           ALOGE("Error opening pcm input device");
13724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else {
13734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           in = new AudioStreamInALSA(this, &(*it), acoustics);
13744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           err = in->set(format, channels, sampleRate, devices);
13754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
13764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if (status) *status = err;
13774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        return in;
13784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev      }
13794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
13804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
13814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid
13824765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::closeInputStream(AudioStreamIn* in)
13834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
13844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    delete in;
13854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
13864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
13874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::setMicMute(bool state)
13884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
13896ccde10fdc6591e5cd21ed32c2b5817aaeb1a208SathishKumar Mani    if (mMicMute != state) {
13906ccde10fdc6591e5cd21ed32c2b5817aaeb1a208SathishKumar Mani        mMicMute = state;
13916ccde10fdc6591e5cd21ed32c2b5817aaeb1a208SathishKumar Mani        ALOGD("setMicMute: mMicMute %d", mMicMute);
13926ccde10fdc6591e5cd21ed32c2b5817aaeb1a208SathishKumar Mani        if(mALSADevice) {
13936ccde10fdc6591e5cd21ed32c2b5817aaeb1a208SathishKumar Mani            mALSADevice->setMicMute(state);
13944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
13954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
13964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return NO_ERROR;
13974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
13984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
13994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::getMicMute(bool *state)
14004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
14016ccde10fdc6591e5cd21ed32c2b5817aaeb1a208SathishKumar Mani    *state = mMicMute;
14024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return NO_ERROR;
14034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
14044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
14054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::dump(int fd, const Vector<String16>& args)
14064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
14074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return NO_ERROR;
14084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
14094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
14104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevsize_t AudioHardwareALSA::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
14114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
141277780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani    size_t bufferSize = 0;
141377780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani    if (format == AudioSystem::PCM_16_BIT) {
141477780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani        if(sampleRate == 8000 || sampleRate == 16000 || sampleRate == 32000) {
141577780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani            bufferSize = (sampleRate * channelCount * 20 * sizeof(int16_t)) / 1000;
141677780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani        } else if (sampleRate == 11025 || sampleRate == 12000) {
141777780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani            bufferSize = 256 * sizeof(int16_t)  * channelCount;
141877780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani        } else if (sampleRate == 22050 || sampleRate == 24000) {
141977780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani            bufferSize = 512 * sizeof(int16_t)  * channelCount;
142077780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani        } else if (sampleRate == 44100 || sampleRate == 48000) {
142177780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani            bufferSize = 1024 * sizeof(int16_t) * channelCount;
142277780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani        }
14234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    } else {
142477780382b45794eb5bc0e8589d9b7c96bb406772SathishKumar Mani        ALOGE("getInputBufferSize bad format: %d", format);
14254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
14264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return bufferSize;
14274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
14284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
14299746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED
14304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::handleFm(int device)
14314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
14324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevint newMode = mode();
14334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if(device & AudioSystem::DEVICE_OUT_FM && mIsFmActive == 0) {
14344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        // Start FM Radio on current active device
14354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        unsigned long bufferSize = FM_BUFFER_SIZE;
14364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle_t alsa_handle;
14374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        char *use_case;
14384113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev        ALOGV("Start FM");
14394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
14404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
14414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DIGITAL_RADIO, sizeof(alsa_handle.useCase));
14424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else {
14434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_FM, sizeof(alsa_handle.useCase));
14444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
14454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        free(use_case);
14464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
14474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
14484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        bufferSize &= ~b;
14494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.module = mALSADevice;
14504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.bufferSize = bufferSize;
14514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.devices = device;
14524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.handle = 0;
14534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
14544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.channels = DEFAULT_CHANNEL_MODE;
145561f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent        alsa_handle.channelMask = AUDIO_CHANNEL_OUT_STEREO;
14564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
14574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.latency = VOICE_LATENCY;
14584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.rxHandle = 0;
14594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.ucMgr = mUcMgr;
14604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mIsFmActive = 1;
14614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mDeviceList.push_back(alsa_handle);
14624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        ALSAHandleList::iterator it = mDeviceList.end();
14634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        it--;
14644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
14654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
14664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            device |= AudioSystem::DEVICE_OUT_PROXY;
14674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
14680a019914794cc27f5dacddf4e5dbc019dbe21788SathishKumar Mani            ALOGD("Routing to proxy for FM case");
14694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
14704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mALSADevice->route(&(*it), (uint32_t)device, newMode);
14714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if(!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) {
14724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_DIGITAL_RADIO);
14734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        } else {
14744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_FM);
14754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
14764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mALSADevice->startFm(&(*it));
14774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
14784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
14790a019914794cc27f5dacddf4e5dbc019dbe21788SathishKumar Mani            ALOGD("Starting FM, musbPlaybackState %d", musbPlaybackState);
14804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            startUsbPlaybackIfNotStarted();
14814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            musbPlaybackState |= USBPLAYBACKBIT_FM;
14824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
14834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    } else if (!(device & AudioSystem::DEVICE_OUT_FM) && mIsFmActive == 1) {
14844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        //i Stop FM Radio
14854113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev        ALOGV("Stop FM");
14864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        for(ALSAHandleList::iterator it = mDeviceList.begin();
14874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            it != mDeviceList.end(); ++it) {
14884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
14894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev              (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
14904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                mALSADevice->close(&(*it));
14914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                //mALSADevice->route(&(*it), (uint32_t)device, newMode);
14924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                mDeviceList.erase(it);
14934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                break;
14944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            }
14954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
14964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        mIsFmActive = 0;
14974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        musbPlaybackState &= ~USBPLAYBACKBIT_FM;
14984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
14994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
15004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            closeUsbPlaybackIfNothingActive();
15014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
15024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
15034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
15044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
15054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
15064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::disableVoiceCall(char* verb, char* modifier, int mode, int device)
15074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
15084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    for(ALSAHandleList::iterator it = mDeviceList.begin();
15094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev         it != mDeviceList.end(); ++it) {
15104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        if((!strcmp(it->useCase, verb)) ||
15114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev           (!strcmp(it->useCase, modifier))) {
15124113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev            ALOGV("Disabling voice call");
15134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mALSADevice->close(&(*it));
15144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mALSADevice->route(&(*it), (uint32_t)device, mode);
15154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            mDeviceList.erase(it);
15164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            break;
15174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
15184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
15199746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED
15204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev   if(musbPlaybackState & USBPLAYBACKBIT_VOICECALL) {
15210a019914794cc27f5dacddf4e5dbc019dbe21788SathishKumar Mani          ALOGD("Voice call ended on USB");
15224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          musbPlaybackState &= ~USBPLAYBACKBIT_VOICECALL;
15234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          musbRecordingState &= ~USBRECBIT_VOICECALL;
15244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          closeUsbRecordingIfNothingActive();
15254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev          closeUsbPlaybackIfNothingActive();
15264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev   }
15279746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif
15284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
15294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::enableVoiceCall(char* verb, char* modifier, int mode, int device)
15304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
15314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// Start voice call
1532018d1c5b5746dc189b2d7b86a87f1d2fd219994aSathishKumar Maniunsigned long bufferSize = DEFAULT_VOICE_BUFFER_SIZE;
15334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevalsa_handle_t alsa_handle;
15344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevchar *use_case;
15354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
15364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
15374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        strlcpy(alsa_handle.useCase, verb, sizeof(alsa_handle.useCase));
15384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    } else {
15394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        strlcpy(alsa_handle.useCase, modifier, sizeof(alsa_handle.useCase));
15404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
15414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    free(use_case);
15424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
15434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
15444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    bufferSize &= ~b;
15454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.module = mALSADevice;
15464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.bufferSize = bufferSize;
15474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.devices = device;
15484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.handle = 0;
15494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
15504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.channels = VOICE_CHANNEL_MODE;
155161f449827974e117406693ef2cc6bdfdaf1fc00bEric Laurent    alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
15524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.sampleRate = VOICE_SAMPLING_RATE;
15534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.latency = VOICE_LATENCY;
15544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.rxHandle = 0;
15554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    alsa_handle.ucMgr = mUcMgr;
15564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    mDeviceList.push_back(alsa_handle);
15574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    ALSAHandleList::iterator it = mDeviceList.end();
15584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    it--;
15599746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED
15604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
15614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev       (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
15624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        device |= AudioSystem::DEVICE_OUT_PROXY;
15634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        alsa_handle.devices = device;
15644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
15654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
15664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    mALSADevice->route(&(*it), (uint32_t)device, mode);
15674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (!strcmp(it->useCase, verb)) {
15684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        snd_use_case_set(mUcMgr, "_verb", verb);
15694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    } else {
15704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        snd_use_case_set(mUcMgr, "_enamod", modifier);
15714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
15724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    mALSADevice->startVoiceCall(&(*it));
15739746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED
15744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
15754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev       (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
15764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev       startUsbRecordingIfNotStarted();
15774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev       startUsbPlaybackIfNotStarted();
15784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev       musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
15794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev       musbRecordingState |= USBRECBIT_VOICECALL;
15804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
15819746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif
15824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
15834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
15844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevbool AudioHardwareALSA::routeVoiceCall(int device, int newMode)
15854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
15864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevint csCallState = mCallState&0xF;
15874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bool isRouted = false;
15884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch (csCallState) {
15899746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani    case CS_INACTIVE:
15909746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        if (mCSCallActive != CS_INACTIVE) {
15914113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev            ALOGD("doRouting: Disabling voice call");
15924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            disableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
15934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
15944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            isRouted = true;
15959746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani            mCSCallActive = CS_INACTIVE;
15964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
15974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    break;
15989746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani    case CS_ACTIVE:
15999746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        if (mCSCallActive == CS_INACTIVE) {
16004113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev            ALOGD("doRouting: Enabling CS voice call ");
16014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            enableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
16024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
16034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            isRouted = true;
16049746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani            mCSCallActive = CS_ACTIVE;
16059746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        } else if (mCSCallActive == CS_HOLD) {
16064113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev             ALOGD("doRouting: Resume voice call from hold state");
16074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             ALSAHandleList::iterator vt_it;
16084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             for(vt_it = mDeviceList.begin();
16094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                 vt_it != mDeviceList.end(); ++vt_it) {
16104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
16114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     strlen(SND_USE_CASE_VERB_VOICECALL))) ||
16124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
16134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
16144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
16159746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani                     mCSCallActive = CS_ACTIVE;
16164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
16174113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                                   ALOGE("VoLTE resume failed");
16184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     break;
16194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                 }
16204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             }
16214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
16224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    break;
16239746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani    case CS_HOLD:
16249746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        if (mCSCallActive == CS_ACTIVE) {
16254113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev            ALOGD("doRouting: Voice call going to Hold");
16264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             ALSAHandleList::iterator vt_it;
16274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             for(vt_it = mDeviceList.begin();
16284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                 vt_it != mDeviceList.end(); ++vt_it) {
16294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
16304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     strlen(SND_USE_CASE_VERB_VOICECALL))) ||
16314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
16324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                         strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
16339746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani                         mCSCallActive = CS_HOLD;
16344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                         alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
16354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                         if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
16364113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                                   ALOGE("Voice pause failed");
16374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                         break;
16384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                }
16394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            }
16404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
16414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    break;
16424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
16434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return isRouted;
16444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
16454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevbool AudioHardwareALSA::routeVoLTECall(int device, int newMode)
16464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
16474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevint volteCallState = mCallState&0xF0;
16484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevbool isRouted = false;
16494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevswitch (volteCallState) {
16509746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani    case IMS_INACTIVE:
16519746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        if (mVolteCallActive != IMS_INACTIVE) {
16524113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev            ALOGD("doRouting: Disabling IMS call");
16534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            disableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
16544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
16554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            isRouted = true;
16569746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani            mVolteCallActive = IMS_INACTIVE;
16574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
16584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    break;
16599746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani    case IMS_ACTIVE:
16609746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        if (mVolteCallActive == IMS_INACTIVE) {
16614113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev            ALOGD("doRouting: Enabling IMS voice call ");
16624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            enableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
16634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
16644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            isRouted = true;
16659746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani            mVolteCallActive = IMS_ACTIVE;
16669746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        } else if (mVolteCallActive == IMS_HOLD) {
16674113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev             ALOGD("doRouting: Resume IMS call from hold state");
16684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             ALSAHandleList::iterator vt_it;
16694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             for(vt_it = mDeviceList.begin();
16704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                 vt_it != mDeviceList.end(); ++vt_it) {
16714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
16724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     strlen(SND_USE_CASE_VERB_VOLTE))) ||
16734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
16744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
16754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
16769746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani                     mVolteCallActive = IMS_ACTIVE;
16774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
16784113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                                   ALOGE("VoLTE resume failed");
16794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     break;
16804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                 }
16814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             }
16824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
16834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    break;
16849746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani    case IMS_HOLD:
16859746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        if (mVolteCallActive == IMS_ACTIVE) {
16864113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev             ALOGD("doRouting: IMS ACTIVE going to HOLD");
16874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             ALSAHandleList::iterator vt_it;
16884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev             for(vt_it = mDeviceList.begin();
16894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                 vt_it != mDeviceList.end(); ++vt_it) {
16904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
16914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     strlen(SND_USE_CASE_VERB_VOLTE))) ||
16924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                     (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
16934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                         strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
16949746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani                          mVolteCallActive = IMS_HOLD;
16954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                         alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
16964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                         if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
16974113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                                   ALOGE("VoLTE Pause failed");
16984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                    break;
16994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                }
17004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            }
17014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        }
17024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    break;
17034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
17044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return isRouted;
17054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
17064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
17074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}       // namespace android_audio_legacy
1708