1/* AudioHardwareALSA.cpp
2 **
3 ** Copyright 2008-2010 Wind River Systems
4 ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
5 **
6 ** Licensed under the Apache License, Version 2.0 (the "License");
7 ** you may not use this file except in compliance with the License.
8 ** You may obtain a copy of the License at
9 **
10 **     http://www.apache.org/licenses/LICENSE-2.0
11 **
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 */
18
19#include <errno.h>
20#include <stdarg.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <stdlib.h>
24#include <unistd.h>
25#include <dlfcn.h>
26#include <math.h>
27
28#define LOG_TAG "AudioHardwareALSA"
29//#define LOG_NDEBUG 0
30#define LOG_NDDEBUG 0
31#include <utils/Log.h>
32#include <utils/String8.h>
33#include <sys/prctl.h>
34#include <sys/resource.h>
35#include <sys/poll.h>
36#include <sys/ioctl.h>
37#include <cutils/properties.h>
38#include <media/AudioRecord.h>
39#include <hardware_legacy/power.h>
40
41#include "AudioHardwareALSA.h"
42#ifdef QCOM_USBAUDIO_ENABLED
43#include "AudioUsbALSA.h"
44#endif
45#include "AudioUtil.h"
46
47extern "C"
48{
49    //
50    // Function for dlsym() to look up for creating a new AudioHardwareInterface.
51    //
52    android_audio_legacy::AudioHardwareInterface *createAudioHardware(void) {
53        return android_audio_legacy::AudioHardwareALSA::create();
54    }
55#ifdef QCOM_ACDB_ENABLED
56    static int (*acdb_init)();
57    static void (*acdb_deallocate)();
58#endif
59#ifdef QCOM_CSDCLIENT_ENABLED
60    static int (*csd_client_init)();
61    static int (*csd_client_deinit)();
62    static int (*csd_start_playback)();
63    static int (*csd_stop_playback)();
64#endif
65}         // extern "C"
66
67namespace android_audio_legacy
68{
69
70// ----------------------------------------------------------------------------
71
72AudioHardwareInterface *AudioHardwareALSA::create() {
73    return new AudioHardwareALSA();
74}
75
76AudioHardwareALSA::AudioHardwareALSA() :
77    mALSADevice(0),mVoipStreamCount(0),mVoipBitRate(0)
78    ,mCallState(0),mAcdbHandle(NULL),mCsdHandle(NULL),mMicMute(0)
79{
80    FILE *fp;
81    char soundCardInfo[200];
82    hw_module_t *module;
83    char platform[128], baseband[128];
84    int err = hw_get_module(ALSA_HARDWARE_MODULE_ID,
85            (hw_module_t const**)&module);
86    int codec_rev = 2;
87    ALOGD("hw_get_module(ALSA_HARDWARE_MODULE_ID) returned err %d", err);
88    if (err == 0) {
89        hw_device_t* device;
90        err = module->methods->open(module, ALSA_HARDWARE_NAME, &device);
91        if (err == 0) {
92            mALSADevice = (alsa_device_t *)device;
93            mALSADevice->init(mALSADevice, mDeviceList);
94            mCSCallActive = 0;
95            mVolteCallActive = 0;
96            mIsFmActive = 0;
97            mDevSettingsFlag = 0;
98#ifdef QCOM_USBAUDIO_ENABLED
99            mAudioUsbALSA = new AudioUsbALSA();
100            musbPlaybackState = 0;
101            musbRecordingState = 0;
102#endif
103#ifdef USES_FLUENCE_INCALL
104            mDevSettingsFlag |= TTY_OFF | DMIC_FLAG;
105#else
106            mDevSettingsFlag |= TTY_OFF;
107#endif
108            mBluetoothVGS = false;
109            mFusion3Platform = false;
110
111#ifdef QCOM_ACDB_ENABLED
112            mAcdbHandle = ::dlopen("/system/lib/libacdbloader.so", RTLD_NOW);
113            if (mAcdbHandle == NULL) {
114                ALOGE("AudioHardware: DLOPEN not successful for ACDBLOADER");
115            } else {
116                ALOGD("AudioHardware: DLOPEN successful for ACDBLOADER");
117                acdb_init = (int (*)())::dlsym(mAcdbHandle,"acdb_loader_init_ACDB");
118                if (acdb_init == NULL) {
119                    ALOGE("dlsym:Error:%s Loading acdb_loader_init_ACDB", dlerror());
120                }else {
121                   acdb_init();
122                   acdb_deallocate = (void (*)())::dlsym(mAcdbHandle,"acdb_loader_deallocate_ACDB");
123                }
124            }
125#endif
126
127#ifdef QCOM_CSDCLIENT_ENABLED
128             mCsdHandle = ::dlopen("/system/lib/libcsd-client.so", RTLD_NOW);
129             if (mCsdHandle == NULL) {
130                 ALOGE("AudioHardware: DLOPEN not successful for CSD CLIENT");
131             } else {
132                 ALOGD("AudioHardware: DLOPEN successful for CSD CLIENT");
133                 csd_client_init = (int (*)())::dlsym(mCsdHandle,"csd_client_init");
134                 csd_client_deinit = (int (*)())::dlsym(mCsdHandle,"csd_client_deinit");
135                 csd_start_playback = (int (*)())::dlsym(mCsdHandle,"csd_client_start_playback");
136                 csd_stop_playback = (int (*)())::dlsym(mCsdHandle,"csd_client_stop_playback");
137
138                 if (csd_client_init == NULL) {
139                    ALOGE("dlsym: Error:%s Loading csd_client_init", dlerror());
140                 } else {
141                    csd_client_init();
142                 }
143             }
144             mALSADevice->setCsdHandle(mCsdHandle);
145#endif
146            if((fp = fopen("/proc/asound/cards","r")) == NULL) {
147                ALOGE("Cannot open /proc/asound/cards file to get sound card info");
148            } else {
149                while((fgets(soundCardInfo, sizeof(soundCardInfo), fp) != NULL)) {
150                    ALOGV("SoundCardInfo %s", soundCardInfo);
151                    if (strstr(soundCardInfo, "msm8960-tabla1x-snd-card")) {
152                        codec_rev = 1;
153                        break;
154                    } else if (strstr(soundCardInfo, "msm-snd-card")) {
155                        codec_rev = 2;
156                        break;
157                    } else if (strstr(soundCardInfo, "msm8930-sitar-snd-card")) {
158                        codec_rev = 3;
159                        break;
160                    }
161                }
162                fclose(fp);
163            }
164
165            if (codec_rev == 1) {
166                    ALOGV("Detected tabla 1.x sound card");
167                    snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm");
168            } else if (codec_rev == 3) {
169                    ALOGV("Detected sitar 1.x sound card");
170                    snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_Sitar");
171            } else {
172                    property_get("ro.board.platform", platform, "");
173                    property_get("ro.baseband", baseband, "");
174                    if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
175                        ALOGV("Detected Fusion tabla 2.x");
176                        mFusion3Platform = true;
177                        snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x_Fusion3");
178                    } else {
179                        ALOGV("Detected tabla 2.x sound card");
180                        snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x");
181                    }
182            }
183
184            if (mUcMgr < 0) {
185                ALOGE("Failed to open ucm instance: %d", errno);
186            } else {
187                ALOGI("ucm instance opened: %u", (unsigned)mUcMgr);
188                mUcMgr->acdb_handle = NULL;
189#ifdef QCOM_ACDB_ENABLED
190                if (mAcdbHandle) {
191                    mUcMgr->acdb_handle = static_cast<void*> (mAcdbHandle);
192                    if (mFusion3Platform)
193                        mUcMgr->isFusion3Platform = true;
194                    else
195                        mUcMgr->isFusion3Platform = false;
196                }
197#endif
198            }
199        } else {
200            ALOGE("ALSA Module could not be opened!!!");
201        }
202    } else {
203        ALOGE("ALSA Module not found!!!");
204    }
205}
206
207AudioHardwareALSA::~AudioHardwareALSA()
208{
209    if (mUcMgr != NULL) {
210        ALOGV("closing ucm instance: %u", (unsigned)mUcMgr);
211        snd_use_case_mgr_close(mUcMgr);
212    }
213    if (mALSADevice) {
214        mALSADevice->common.close(&mALSADevice->common);
215    }
216    for(ALSAHandleList::iterator it = mDeviceList.begin();
217            it != mDeviceList.end(); ++it) {
218        it->useCase[0] = 0;
219        mDeviceList.erase(it);
220    }
221#ifdef QCOM_ACDB_ENABLED
222     if (acdb_deallocate == NULL) {
223        ALOGE("dlsym: Error:%s Loading acdb_deallocate_ACDB", dlerror());
224     } else {
225        acdb_deallocate();
226     }
227     if (mAcdbHandle) {
228        ::dlclose(mAcdbHandle);
229        mAcdbHandle = NULL;
230     }
231#endif
232#ifdef QCOM_USBAUDIO_ENABLED
233    delete mAudioUsbALSA;
234#endif
235
236#ifdef QCOM_CSDCLEINT_ENABLED
237     if (mCsdHandle) {
238         if (csd_client_deinit == NULL) {
239             ALOGE("dlsym: Error:%s Loading csd_client_deinit", dlerror());
240         } else {
241             csd_client_deinit();
242         }
243         ::dlclose(mCsdHandle);
244         mCsdHandle = NULL;
245     }
246#endif
247}
248
249status_t AudioHardwareALSA::initCheck()
250{
251    if (!mALSADevice)
252        return NO_INIT;
253
254    return NO_ERROR;
255}
256
257status_t AudioHardwareALSA::setVoiceVolume(float v)
258{
259    ALOGV("setVoiceVolume(%f)\n", v);
260    if (v < 0.0) {
261        ALOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
262        v = 0.0;
263    } else if (v > 1.0) {
264        ALOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
265        v = 1.0;
266    }
267
268    int newMode = mode();
269    ALOGV("setVoiceVolume  newMode %d",newMode);
270    int vol = lrint(v * 100.0);
271
272    // Voice volume levels from android are mapped to driver volume levels as follows.
273    // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
274    // So adjust the volume to get the correct volume index in driver
275    vol = 100 - vol;
276
277    if (mALSADevice) {
278        if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
279            mALSADevice->setVoipVolume(vol);
280        } else if (newMode == AudioSystem::MODE_IN_CALL){
281               if (mCSCallActive == CS_ACTIVE)
282                   mALSADevice->setVoiceVolume(vol);
283               if (mVolteCallActive == IMS_ACTIVE)
284                   mALSADevice->setVoLTEVolume(vol);
285        }
286    }
287
288    return NO_ERROR;
289}
290
291#ifdef QCOM_FM_ENABLED
292status_t  AudioHardwareALSA::setFmVolume(float value)
293{
294    status_t status = NO_ERROR;
295
296    int vol;
297
298    if (value < 0.0) {
299        ALOGW("setFmVolume(%f) under 0.0, assuming 0.0\n", value);
300        value = 0.0;
301    } else if (value > 1.0) {
302        ALOGW("setFmVolume(%f) over 1.0, assuming 1.0\n", value);
303        value = 1.0;
304    }
305    vol  = lrint((value * 0x2000) + 0.5);
306
307    ALOGV("setFmVolume(%f)\n", value);
308    ALOGV("Setting FM volume to %d (available range is 0 to 0x2000)\n", vol);
309
310    mALSADevice->setFmVolume(vol);
311
312    return status;
313}
314#endif
315
316status_t AudioHardwareALSA::setMasterVolume(float volume)
317{
318    return NO_ERROR;
319}
320
321status_t AudioHardwareALSA::setMode(int mode)
322{
323    status_t status = NO_ERROR;
324
325    if (mode != mMode) {
326        status = AudioHardwareBase::setMode(mode);
327    }
328
329    if (mode == AudioSystem::MODE_IN_CALL) {
330        mCallState = CS_ACTIVE;
331    }else if (mode == AudioSystem::MODE_NORMAL) {
332        mCallState = 0;
333    }
334
335    return status;
336}
337
338status_t AudioHardwareALSA::setParameters(const String8& keyValuePairs)
339{
340    AudioParameter param = AudioParameter(keyValuePairs);
341    String8 key;
342    String8 value;
343    status_t status = NO_ERROR;
344    int device;
345    int btRate;
346    int state;
347    ALOGV("setParameters() %s", keyValuePairs.string());
348
349    key = String8(TTY_MODE_KEY);
350    if (param.get(key, value) == NO_ERROR) {
351        mDevSettingsFlag &= TTY_CLEAR;
352        if (value == "tty_full") {
353            mDevSettingsFlag |= TTY_FULL;
354        } else if (value == "tty_hco") {
355            mDevSettingsFlag |= TTY_HCO;
356        } else if (value == "tty_vco") {
357            mDevSettingsFlag |= TTY_VCO;
358        } else {
359            mDevSettingsFlag |= TTY_OFF;
360        }
361        ALOGI("Changed TTY Mode=%s", value.string());
362        mALSADevice->setFlags(mDevSettingsFlag);
363        if(mMode != AudioSystem::MODE_IN_CALL){
364           return NO_ERROR;
365        }
366        doRouting(0);
367    }
368
369    key = String8(FLUENCE_KEY);
370    if (param.get(key, value) == NO_ERROR) {
371        if (value == "quadmic") {
372            mDevSettingsFlag |= QMIC_FLAG;
373            mDevSettingsFlag &= (~DMIC_FLAG);
374            ALOGV("Fluence quadMic feature Enabled");
375        } else if (value == "dualmic") {
376            mDevSettingsFlag |= DMIC_FLAG;
377            mDevSettingsFlag &= (~QMIC_FLAG);
378            ALOGV("Fluence dualmic feature Enabled");
379        } else if (value == "none") {
380            mDevSettingsFlag &= (~DMIC_FLAG);
381            mDevSettingsFlag &= (~QMIC_FLAG);
382            ALOGV("Fluence feature Disabled");
383        }
384        mALSADevice->setFlags(mDevSettingsFlag);
385        doRouting(0);
386    }
387
388#ifdef QCOM_CSDCLIENT_ENABLED
389    if (mFusion3Platform) {
390        key = String8(INCALLMUSIC_KEY);
391        if (param.get(key, value) == NO_ERROR) {
392            if (value == "true") {
393                ALOGV("Enabling Incall Music setting in the setparameter\n");
394                if (csd_start_playback == NULL) {
395                    ALOGE("dlsym: Error:%s Loading csd_client_start_playback", dlerror());
396                } else {
397                    csd_start_playback();
398                }
399            } else {
400                ALOGV("Disabling Incall Music setting in the setparameter\n");
401                if (csd_stop_playback == NULL) {
402                    ALOGE("dlsym: Error:%s Loading csd_client_stop_playback", dlerror());
403                } else {
404                    csd_stop_playback();
405                }
406            }
407        }
408    }
409#endif
410
411    key = String8(ANC_KEY);
412    if (param.get(key, value) == NO_ERROR) {
413        if (value == "true") {
414            ALOGV("Enabling ANC setting in the setparameter\n");
415            mDevSettingsFlag |= ANC_FLAG;
416        } else {
417            ALOGV("Disabling ANC setting in the setparameter\n");
418            mDevSettingsFlag &= (~ANC_FLAG);
419        }
420        mALSADevice->setFlags(mDevSettingsFlag);
421        doRouting(0);
422    }
423
424    key = String8(AudioParameter::keyRouting);
425    if (param.getInt(key, device) == NO_ERROR) {
426        // Ignore routing if device is 0.
427        if(device) {
428            doRouting(device);
429        }
430        param.remove(key);
431    }
432
433    key = String8(BT_SAMPLERATE_KEY);
434    if (param.getInt(key, btRate) == NO_ERROR) {
435        mALSADevice->setBtscoRate(btRate);
436        param.remove(key);
437    }
438
439    key = String8(BTHEADSET_VGS);
440    if (param.get(key, value) == NO_ERROR) {
441        if (value == "on") {
442            mBluetoothVGS = true;
443        } else {
444            mBluetoothVGS = false;
445        }
446    }
447
448    key = String8(WIDEVOICE_KEY);
449    if (param.get(key, value) == NO_ERROR) {
450        bool flag = false;
451        if (value == "true") {
452            flag = true;
453        }
454        if(mALSADevice) {
455            mALSADevice->enableWideVoice(flag);
456        }
457        param.remove(key);
458    }
459
460    key = String8(VOIPRATE_KEY);
461    if (param.get(key, value) == NO_ERROR) {
462            mVoipBitRate = atoi(value);
463        param.remove(key);
464    }
465
466    key = String8(FENS_KEY);
467    if (param.get(key, value) == NO_ERROR) {
468        bool flag = false;
469        if (value == "true") {
470            flag = true;
471        }
472        if(mALSADevice) {
473            mALSADevice->enableFENS(flag);
474        }
475        param.remove(key);
476    }
477
478#ifdef QCOM_FM_ENABLED
479    key = String8(AudioParameter::keyHandleFm);
480    if (param.getInt(key, device) == NO_ERROR) {
481        // Ignore if device is 0
482        if(device) {
483            handleFm(device);
484        }
485        param.remove(key);
486    }
487#endif
488
489    key = String8(ST_KEY);
490    if (param.get(key, value) == NO_ERROR) {
491        bool flag = false;
492        if (value == "true") {
493            flag = true;
494        }
495        if(mALSADevice) {
496            mALSADevice->enableSlowTalk(flag);
497        }
498        param.remove(key);
499    }
500    key = String8(MODE_CALL_KEY);
501    if (param.getInt(key,state) == NO_ERROR) {
502        if (mCallState != state) {
503            mCallState = state;
504            doRouting(0);
505        }
506        mCallState = state;
507    }
508    if (param.size()) {
509        status = BAD_VALUE;
510    }
511    return status;
512}
513
514String8 AudioHardwareALSA::getParameters(const String8& keys)
515{
516    AudioParameter param = AudioParameter(keys);
517    String8 value;
518
519    String8 key = String8(DUALMIC_KEY);
520    if (param.get(key, value) == NO_ERROR) {
521        value = String8("false");
522        param.add(key, value);
523    }
524
525    key = String8(FLUENCE_KEY);
526    if (param.get(key, value) == NO_ERROR) {
527    if ((mDevSettingsFlag & QMIC_FLAG) &&
528                               (mDevSettingsFlag & ~DMIC_FLAG))
529            value = String8("quadmic");
530    else if ((mDevSettingsFlag & DMIC_FLAG) &&
531                                (mDevSettingsFlag & ~QMIC_FLAG))
532            value = String8("dualmic");
533    else if ((mDevSettingsFlag & ~DMIC_FLAG) &&
534                                (mDevSettingsFlag & ~QMIC_FLAG))
535            value = String8("none");
536        param.add(key, value);
537    }
538
539#ifdef QCOM_FM_ENABLED
540    key = String8("Fm-radio");
541    if ( param.get(key,value) == NO_ERROR ) {
542        if ( mIsFmActive ) {
543            param.addInt(String8("isFMON"), true );
544        }
545    }
546#endif
547
548    key = String8(BTHEADSET_VGS);
549    if (param.get(key, value) == NO_ERROR) {
550        if(mBluetoothVGS)
551           param.addInt(String8("isVGS"), true);
552    }
553
554    ALOGV("AudioHardwareALSA::getParameters() %s", param.toString().string());
555    return param.toString();
556}
557
558#ifdef QCOM_USBAUDIO_ENABLED
559void AudioHardwareALSA::closeUSBPlayback()
560{
561    ALOGV("closeUSBPlayback, musbPlaybackState: %d", musbPlaybackState);
562    musbPlaybackState = 0;
563    mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_KILLTHREAD);
564}
565
566void AudioHardwareALSA::closeUSBRecording()
567{
568    ALOGV("closeUSBRecording");
569    musbRecordingState = 0;
570    mAudioUsbALSA->exitRecordingThread(SIGNAL_EVENT_KILLTHREAD);
571}
572
573void AudioHardwareALSA::closeUsbPlaybackIfNothingActive(){
574    ALOGV("closeUsbPlaybackIfNothingActive, musbPlaybackState: %d", musbPlaybackState);
575    if(!musbPlaybackState && mAudioUsbALSA != NULL) {
576        mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_TIMEOUT);
577    }
578}
579
580void AudioHardwareALSA::closeUsbRecordingIfNothingActive(){
581    ALOGV("closeUsbRecordingIfNothingActive, musbRecordingState: %d", musbRecordingState);
582    if(!musbRecordingState && mAudioUsbALSA != NULL) {
583        ALOGD("Closing USB Recording Session as no stream is active");
584        mAudioUsbALSA->setkillUsbRecordingThread(true);
585    }
586}
587
588void AudioHardwareALSA::startUsbPlaybackIfNotStarted(){
589    ALOGV("Starting the USB playback %d kill %d", musbPlaybackState,
590             mAudioUsbALSA->getkillUsbPlaybackThread());
591    if((!musbPlaybackState) || (mAudioUsbALSA->getkillUsbPlaybackThread() == true)) {
592        mAudioUsbALSA->startPlayback();
593    }
594}
595
596void AudioHardwareALSA::startUsbRecordingIfNotStarted(){
597    ALOGV("Starting the recording musbRecordingState: %d killUsbRecordingThread %d",
598          musbRecordingState, mAudioUsbALSA->getkillUsbRecordingThread());
599    if((!musbRecordingState) || (mAudioUsbALSA->getkillUsbRecordingThread() == true)) {
600        mAudioUsbALSA->startRecording();
601    }
602}
603#endif
604
605void AudioHardwareALSA::doRouting(int device)
606{
607    Mutex::Autolock autoLock(mLock);
608    int newMode = mode();
609    bool isRouted = false;
610
611    if ((device == AudioSystem::DEVICE_IN_VOICE_CALL)
612#ifdef QCOM_FM_ENABLED
613        || (device == AudioSystem::DEVICE_IN_FM_RX)
614        || (device == AudioSystem::DEVICE_OUT_DIRECTOUTPUT)
615        || (device == AudioSystem::DEVICE_IN_FM_RX_A2DP)
616#endif
617        || (device == AudioSystem::DEVICE_IN_COMMUNICATION)
618        ) {
619        ALOGV("Ignoring routing for FM/INCALL/VOIP recording");
620        return;
621    }
622    if (device == 0)
623        device = mCurDevice;
624    ALOGV("doRouting: device %d newMode %d mCSCallActive %d mVolteCallActive %d"
625         "mIsFmActive %d", device, newMode, mCSCallActive, mVolteCallActive,
626         mIsFmActive);
627
628    isRouted = routeVoLTECall(device, newMode);
629    isRouted |= routeVoiceCall(device, newMode);
630
631    if(!isRouted) {
632#ifdef QCOM_USBAUDIO_ENABLED
633        if(!(device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) &&
634            !(device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET) &&
635            !(device & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) &&
636             (musbPlaybackState)){
637                //USB unplugged
638                device &= ~ AudioSystem::DEVICE_OUT_PROXY;
639                device &= ~ AudioSystem::DEVICE_IN_PROXY;
640                ALSAHandleList::iterator it = mDeviceList.end();
641                it--;
642                mALSADevice->route(&(*it), (uint32_t)device, newMode);
643                ALOGD("USB UNPLUGGED, setting musbPlaybackState to 0");
644                musbPlaybackState = 0;
645                musbRecordingState = 0;
646                closeUSBRecording();
647                closeUSBPlayback();
648        } else if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
649                  (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
650                    ALOGD("Routing everything to prox now");
651                    ALSAHandleList::iterator it = mDeviceList.end();
652                    it--;
653                    mALSADevice->route(&(*it), AudioSystem::DEVICE_OUT_PROXY,
654                                       newMode);
655                    for(it = mDeviceList.begin(); it != mDeviceList.end(); ++it) {
656                         if((!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
657                            (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_LPA))) {
658                                 ALOGV("doRouting: LPA device switch to proxy");
659                                 startUsbPlaybackIfNotStarted();
660                                 musbPlaybackState |= USBPLAYBACKBIT_LPA;
661                                 break;
662                         } else if((!strcmp(it->useCase, SND_USE_CASE_VERB_VOICECALL)) ||
663                                   (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOICE))) {
664                                    ALOGV("doRouting: VOICE device switch to proxy");
665                                    startUsbRecordingIfNotStarted();
666                                    startUsbPlaybackIfNotStarted();
667                                    musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
668                                    musbRecordingState |= USBPLAYBACKBIT_VOICECALL;
669                                    break;
670                        }else if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
671                                 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
672                                    ALOGV("doRouting: FM device switch to proxy");
673                                    startUsbPlaybackIfNotStarted();
674                                    musbPlaybackState |= USBPLAYBACKBIT_FM;
675                                    break;
676                         }
677                    }
678        } else
679#endif
680        {
681             ALSAHandleList::iterator it = mDeviceList.end();
682             it--;
683             mALSADevice->route(&(*it), (uint32_t)device, newMode);
684        }
685    }
686    mCurDevice = device;
687}
688
689uint32_t AudioHardwareALSA::getVoipMode(int format)
690{
691    switch(format) {
692    case AudioSystem::PCM_16_BIT:
693               return MODE_PCM;
694         break;
695    case AudioSystem::AMR_NB:
696               return MODE_AMR;
697         break;
698    case AudioSystem::AMR_WB:
699               return MODE_AMR_WB;
700         break;
701
702#ifdef QCOM_QCHAT_ENABLED
703    case AudioSystem::EVRC:
704               return MODE_IS127;
705         break;
706
707    case AudioSystem::EVRCB:
708               return MODE_4GV_NB;
709         break;
710    case AudioSystem::EVRCWB:
711               return MODE_4GV_WB;
712         break;
713#endif
714
715    default:
716               return MODE_PCM;
717    }
718}
719
720AudioStreamOut *
721AudioHardwareALSA::openOutputStream(uint32_t devices,
722                                    int *format,
723                                    uint32_t *channels,
724                                    uint32_t *sampleRate,
725                                    status_t *status)
726{
727    Mutex::Autolock autoLock(mLock);
728    ALOGV("openOutputStream: devices 0x%x channels %d sampleRate %d",
729         devices, *channels, *sampleRate);
730
731    audio_output_flags_t flag = static_cast<audio_output_flags_t> (*status);
732
733    status_t err = BAD_VALUE;
734    *status = NO_ERROR;
735    AudioStreamOutALSA *out = 0;
736    ALSAHandleList::iterator it;
737
738    if (devices & (devices - 1)) {
739        if (status) *status = err;
740        ALOGE("openOutputStream called with bad devices");
741        return out;
742    }
743
744
745# if 0
746    if((devices == AudioSystem::DEVICE_OUT_DIRECTOUTPUT) &&
747       ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
748        bool voipstream_active = false;
749        for(it = mDeviceList.begin();
750            it != mDeviceList.end(); ++it) {
751                if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
752                   (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
753                    ALOGD("openOutput:  it->rxHandle %d it->handle %d",it->rxHandle,it->handle);
754                    voipstream_active = true;
755                    break;
756                }
757        }
758      if(voipstream_active == false) {
759         mVoipStreamCount = 0;
760         alsa_handle_t alsa_handle;
761         unsigned long bufferSize;
762         if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
763             bufferSize = VOIP_BUFFER_SIZE_8K;
764         }
765         else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
766             bufferSize = VOIP_BUFFER_SIZE_16K;
767         }
768         else {
769             ALOGE("unsupported samplerate %d for voip",*sampleRate);
770             if (status) *status = err;
771                 return out;
772          }
773          alsa_handle.module = mALSADevice;
774          alsa_handle.bufferSize = bufferSize;
775          alsa_handle.devices = devices;
776          alsa_handle.handle = 0;
777          if(*format == AudioSystem::PCM_16_BIT)
778              alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
779          else
780              alsa_handle.format = *format;
781          alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
782          alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
783          alsa_handle.sampleRate = *sampleRate;
784          alsa_handle.latency = VOIP_PLAYBACK_LATENCY;
785          alsa_handle.rxHandle = 0;
786          alsa_handle.ucMgr = mUcMgr;
787          mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
788          char *use_case;
789          snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
790          if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
791              strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
792          } else {
793              strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
794          }
795          free(use_case);
796          mDeviceList.push_back(alsa_handle);
797          it = mDeviceList.end();
798          it--;
799          ALOGV("openoutput: mALSADevice->route useCase %s mCurDevice %d mVoipStreamCount %d mode %d", it->useCase,mCurDevice,mVoipStreamCount, mode());
800          if((mCurDevice & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
801             (mCurDevice & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)||
802             (mCurDevice & AudioSystem::DEVICE_OUT_PROXY)){
803              ALOGD("Routing to proxy for normal voip call in openOutputStream");
804              mCurDevice |= AudioSystem::DEVICE_OUT_PROXY;
805              alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
806              mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
807              ALOGD("enabling VOIP in openoutputstream, musbPlaybackState: %d", musbPlaybackState);
808              startUsbPlaybackIfNotStarted();
809              musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
810              ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
811              startUsbRecordingIfNotStarted();
812              musbRecordingState |= USBRECBIT_VOIPCALL;
813          } else{
814              mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
815          }
816          if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
817              snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
818          } else {
819              snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
820          }
821          err = mALSADevice->startVoipCall(&(*it));
822          if (err) {
823              ALOGE("Device open failed");
824              return NULL;
825          }
826      }
827      out = new AudioStreamOutALSA(this, &(*it));
828      err = out->set(format, channels, sampleRate, devices);
829      if(err == NO_ERROR) {
830          mVoipStreamCount++;   //increment VoipstreamCount only if success
831          ALOGD("openoutput mVoipStreamCount %d",mVoipStreamCount);
832      }
833      if (status) *status = err;
834      return out;
835    } else
836#endif
837    if ((flag & AUDIO_OUTPUT_FLAG_DIRECT) &&
838        (devices == AudioSystem::DEVICE_OUT_AUX_DIGITAL)) {
839        ALOGD("Multi channel PCM");
840        alsa_handle_t alsa_handle;
841        EDID_AUDIO_INFO info = { 0 };
842
843        alsa_handle.module = mALSADevice;
844        alsa_handle.devices = devices;
845        alsa_handle.handle = 0;
846        alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
847
848        if (!AudioUtil::getHDMIAudioSinkCaps(&info)) {
849            ALOGE("openOutputStream: Failed to get HDMI sink capabilities");
850            return NULL;
851        }
852        if (0 == *channels) {
853            alsa_handle.channels = info.AudioBlocksArray[info.nAudioBlocks-1].nChannels;
854            if (alsa_handle.channels > 6) {
855                alsa_handle.channels = 6;
856            }
857            *channels = audio_channel_out_mask_from_count(alsa_handle.channels);
858        } else {
859            alsa_handle.channels = AudioSystem::popCount(*channels);
860        }
861        alsa_handle.channelMask = *channels;
862
863        if (6 == alsa_handle.channels) {
864            alsa_handle.bufferSize = DEFAULT_MULTI_CHANNEL_BUF_SIZE;
865        } else {
866            alsa_handle.bufferSize = DEFAULT_BUFFER_SIZE;
867        }
868        if (0 == *sampleRate) {
869            alsa_handle.sampleRate = info.AudioBlocksArray[info.nAudioBlocks-1].nSamplingFreq;
870            *sampleRate = alsa_handle.sampleRate;
871        } else {
872            alsa_handle.sampleRate = *sampleRate;
873        }
874        alsa_handle.latency = PLAYBACK_LATENCY;
875        alsa_handle.rxHandle = 0;
876        alsa_handle.ucMgr = mUcMgr;
877        ALOGD("alsa_handle.channels %d alsa_handle.sampleRate %d",alsa_handle.channels,alsa_handle.sampleRate);
878
879        char *use_case;
880        snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
881        if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
882            strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI2 , sizeof(alsa_handle.useCase));
883        } else {
884            strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC2, sizeof(alsa_handle.useCase));
885        }
886        free(use_case);
887        mDeviceList.push_back(alsa_handle);
888        ALSAHandleList::iterator it = mDeviceList.end();
889        it--;
890        ALOGD("it->useCase %s", it->useCase);
891        mALSADevice->route(&(*it), devices, mode());
892        if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI2)) {
893            snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI2 );
894        } else {
895            snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC2);
896        }
897        ALOGD("channels: %d", AudioSystem::popCount(*channels));
898        err = mALSADevice->open(&(*it));
899
900        if (err) {
901            ALOGE("Device open failed err:%d",err);
902        } else {
903            out = new AudioStreamOutALSA(this, &(*it));
904            err = out->set(format, channels, sampleRate, devices);
905        }
906        if (status) *status = err;
907        return out;
908    } else {
909
910      alsa_handle_t alsa_handle;
911      unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
912
913      for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
914          bufferSize &= ~b;
915
916      alsa_handle.module = mALSADevice;
917      alsa_handle.bufferSize = bufferSize;
918      alsa_handle.devices = devices;
919      alsa_handle.handle = 0;
920      alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
921      alsa_handle.channels = DEFAULT_CHANNEL_MODE;
922      alsa_handle.channelMask = AUDIO_CHANNEL_OUT_STEREO;
923      alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
924      alsa_handle.latency = PLAYBACK_LATENCY;
925      alsa_handle.rxHandle = 0;
926      alsa_handle.ucMgr = mUcMgr;
927      alsa_handle.isDeepbufferOutput = false;
928
929      char *use_case;
930      snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
931
932      if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
933      ALOGD("openOutputStream: DeepBuffer Output");
934          alsa_handle.isDeepbufferOutput = true;
935          if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
936               strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI, sizeof(alsa_handle.useCase));
937          } else {
938               strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC, sizeof(alsa_handle.useCase));
939          }
940      } else {
941      ALOGD("openOutputStream: Lowlatency Output");
942          alsa_handle.bufferSize = PLAYBACK_LOW_LATENCY_BUFFER_SIZE;
943          alsa_handle.latency = PLAYBACK_LOW_LATENCY_MEASURED;
944          if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
945               strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
946          } else {
947               strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
948          }
949      }
950      free(use_case);
951      mDeviceList.push_back(alsa_handle);
952      ALSAHandleList::iterator it = mDeviceList.end();
953      it--;
954      ALOGV("useCase %s", it->useCase);
955#ifdef QCOM_USBAUDIO_ENABLED
956      if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
957         (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
958          ALOGD("Routing to proxy for normal playback in openOutputStream");
959          devices |= AudioSystem::DEVICE_OUT_PROXY;
960      }
961#endif
962      mALSADevice->route(&(*it), devices, mode());
963      if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
964          if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI)) {
965             snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI);
966          } else {
967             snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC);
968          }
969      } else {
970          if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) {
971             snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC);
972          } else {
973             snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC);
974          }
975      }
976      err = mALSADevice->open(&(*it));
977      if (err) {
978          ALOGE("Device open failed");
979      } else {
980          out = new AudioStreamOutALSA(this, &(*it));
981          err = out->set(format, channels, sampleRate, devices);
982      }
983
984      if (status) *status = err;
985      return out;
986    }
987}
988
989void
990AudioHardwareALSA::closeOutputStream(AudioStreamOut* out)
991{
992    delete out;
993}
994
995#ifdef QCOM_TUNNEL_LPA_ENABLED
996AudioStreamOut *
997AudioHardwareALSA::openOutputSession(uint32_t devices,
998                                     int *format,
999                                     status_t *status,
1000                                     int sessionId,
1001                                     uint32_t samplingRate,
1002                                     uint32_t channels)
1003{
1004    Mutex::Autolock autoLock(mLock);
1005    ALOGD("openOutputSession = %d" ,sessionId);
1006    AudioStreamOutALSA *out = 0;
1007    status_t err = BAD_VALUE;
1008
1009    alsa_handle_t alsa_handle;
1010    unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
1011
1012    for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1013        bufferSize &= ~b;
1014
1015    alsa_handle.module = mALSADevice;
1016    alsa_handle.bufferSize = bufferSize;
1017    alsa_handle.devices = devices;
1018    alsa_handle.handle = 0;
1019    alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1020    alsa_handle.channels = DEFAULT_CHANNEL_MODE;
1021    alsa_handle.channelMask = AUDIO_CHANNEL_OUT_STEREO;
1022    alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
1023    alsa_handle.latency = VOICE_LATENCY;
1024    alsa_handle.rxHandle = 0;
1025    alsa_handle.ucMgr = mUcMgr;
1026
1027    char *use_case;
1028    if(sessionId == TUNNEL_SESSION_ID) {
1029        snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1030        if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1031            strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_TUNNEL, sizeof(alsa_handle.useCase));
1032        } else {
1033            strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_TUNNEL, sizeof(alsa_handle.useCase));
1034        }
1035    } else {
1036        snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1037        if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1038            strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER, sizeof(alsa_handle.useCase));
1039        } else {
1040            strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LPA, sizeof(alsa_handle.useCase));
1041        }
1042    }
1043    free(use_case);
1044    mDeviceList.push_back(alsa_handle);
1045    ALSAHandleList::iterator it = mDeviceList.end();
1046    it--;
1047    ALOGD("useCase %s", it->useCase);
1048#ifdef QCOM_USBAUDIO_ENABLED
1049    if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1050       (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1051        ALOGD("Routing to proxy for LPA in openOutputSession");
1052        devices |= AudioSystem::DEVICE_OUT_PROXY;
1053        mALSADevice->route(&(*it), devices, mode());
1054        devices = AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
1055        ALOGD("Starting USBPlayback for LPA");
1056        startUsbPlaybackIfNotStarted();
1057        musbPlaybackState |= USBPLAYBACKBIT_LPA;
1058    } else
1059#endif
1060    {
1061        mALSADevice->route(&(*it), devices, mode());
1062    }
1063    if(sessionId == TUNNEL_SESSION_ID) {
1064        if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) {
1065            snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_TUNNEL);
1066        } else {
1067            snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_TUNNEL);
1068        }
1069    }
1070    else {
1071        if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) {
1072            snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOW_POWER);
1073        } else {
1074            snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LPA);
1075        }
1076    }
1077    err = mALSADevice->open(&(*it));
1078    out = new AudioStreamOutALSA(this, &(*it));
1079
1080    if (status) *status = err;
1081       return out;
1082}
1083
1084void
1085AudioHardwareALSA::closeOutputSession(AudioStreamOut* out)
1086{
1087    delete out;
1088}
1089#endif
1090
1091AudioStreamIn *
1092AudioHardwareALSA::openInputStream(uint32_t devices,
1093                                   int *format,
1094                                   uint32_t *channels,
1095                                   uint32_t *sampleRate,
1096                                   status_t *status,
1097                                   AudioSystem::audio_in_acoustics acoustics)
1098{
1099    Mutex::Autolock autoLock(mLock);
1100    char *use_case;
1101    int newMode = mode();
1102    uint32_t route_devices;
1103
1104    status_t err = BAD_VALUE;
1105    AudioStreamInALSA *in = 0;
1106    ALSAHandleList::iterator it;
1107
1108    ALOGD("openInputStream: devices 0x%x channels %d sampleRate %d", devices, *channels, *sampleRate);
1109    if (devices & (devices - 1)) {
1110        if (status) *status = err;
1111        return in;
1112    }
1113
1114    if((devices == AudioSystem::DEVICE_IN_COMMUNICATION) &&
1115       ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
1116        bool voipstream_active = false;
1117        for(it = mDeviceList.begin();
1118            it != mDeviceList.end(); ++it) {
1119                if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
1120                   (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
1121                    ALOGD("openInput:  it->rxHandle %p it->handle %p",it->rxHandle,it->handle);
1122                    voipstream_active = true;
1123                    break;
1124                }
1125        }
1126        if(voipstream_active == false) {
1127           mVoipStreamCount = 0;
1128           alsa_handle_t alsa_handle;
1129           unsigned long bufferSize;
1130           if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
1131               bufferSize = VOIP_BUFFER_SIZE_8K;
1132           }
1133           else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
1134               bufferSize = VOIP_BUFFER_SIZE_16K;
1135           }
1136           else {
1137               ALOGE("unsupported samplerate %d for voip",*sampleRate);
1138               if (status) *status = err;
1139               return in;
1140           }
1141           alsa_handle.module = mALSADevice;
1142           alsa_handle.bufferSize = bufferSize;
1143           alsa_handle.devices = devices;
1144           alsa_handle.handle = 0;
1145          if(*format == AudioSystem::PCM_16_BIT)
1146              alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1147          else
1148              alsa_handle.format = *format;
1149           alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
1150           alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
1151           alsa_handle.sampleRate = *sampleRate;
1152           alsa_handle.latency = VOIP_RECORD_LATENCY;
1153           alsa_handle.rxHandle = 0;
1154           alsa_handle.ucMgr = mUcMgr;
1155          mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
1156           snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1157           if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1158                strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
1159           } else {
1160                strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
1161           }
1162           free(use_case);
1163           mDeviceList.push_back(alsa_handle);
1164           it = mDeviceList.end();
1165           it--;
1166           ALOGD("mCurrDevice: %d", mCurDevice);
1167#ifdef QCOM_USBAUDIO_ENABLED
1168           if((mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1169              (mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1170              ALOGD("Routing everything from proxy for voipcall");
1171              mALSADevice->route(&(*it), AudioSystem::DEVICE_IN_PROXY, AudioSystem::MODE_IN_COMMUNICATION);
1172              ALOGD("enabling VOIP in openInputstream, musbPlaybackState: %d", musbPlaybackState);
1173              startUsbPlaybackIfNotStarted();
1174              musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
1175              ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
1176              startUsbRecordingIfNotStarted();
1177              musbRecordingState |= USBRECBIT_VOIPCALL;
1178           } else
1179#endif
1180           {
1181               mALSADevice->route(&(*it),mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
1182           }
1183           if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
1184               snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
1185           } else {
1186               snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
1187           }
1188           if(sampleRate) {
1189               it->sampleRate = *sampleRate;
1190           }
1191           if(channels)
1192               it->channels = AudioSystem::popCount(*channels);
1193           err = mALSADevice->startVoipCall(&(*it));
1194           if (err) {
1195               ALOGE("Error opening pcm input device");
1196               return NULL;
1197           }
1198        }
1199        in = new AudioStreamInALSA(this, &(*it), acoustics);
1200        err = in->set(format, channels, sampleRate, devices);
1201        if(err == NO_ERROR) {
1202            mVoipStreamCount++;   //increment VoipstreamCount only if success
1203            ALOGD("OpenInput mVoipStreamCount %d",mVoipStreamCount);
1204        }
1205        ALOGD("openInput: After Get alsahandle");
1206        if (status) *status = err;
1207        return in;
1208      } else {
1209        alsa_handle_t alsa_handle;
1210        unsigned long bufferSize = MIN_CAPTURE_BUFFER_SIZE_PER_CH;
1211
1212        alsa_handle.module = mALSADevice;
1213        alsa_handle.bufferSize = bufferSize;
1214        alsa_handle.devices = devices;
1215        alsa_handle.handle = 0;
1216        alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1217        alsa_handle.channels = VOICE_CHANNEL_MODE;
1218        alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
1219        alsa_handle.sampleRate = android::AudioRecord::DEFAULT_SAMPLE_RATE;
1220        alsa_handle.latency = RECORD_LATENCY;
1221        alsa_handle.rxHandle = 0;
1222        alsa_handle.ucMgr = mUcMgr;
1223        snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1224        if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1225            if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
1226                (newMode == AudioSystem::MODE_IN_CALL)) {
1227                ALOGD("openInputStream: into incall recording, channels %d", *channels);
1228                mIncallMode = *channels;
1229                if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
1230                    (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
1231                    if (mFusion3Platform) {
1232                        mALSADevice->setVocRecMode(INCALL_REC_STEREO);
1233                        strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1234                                sizeof(alsa_handle.useCase));
1235                    } else {
1236                        strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
1237                                sizeof(alsa_handle.useCase));
1238                    }
1239                } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
1240                    if (mFusion3Platform) {
1241                        mALSADevice->setVocRecMode(INCALL_REC_MONO);
1242                        strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1243                                sizeof(alsa_handle.useCase));
1244                    } else {
1245                        strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
1246                                sizeof(alsa_handle.useCase));
1247                    }
1248                }
1249#ifdef QCOM_FM_ENABLED
1250            } else if((devices == AudioSystem::DEVICE_IN_FM_RX)) {
1251                strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_FM, sizeof(alsa_handle.useCase));
1252            } else if(devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
1253                strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, sizeof(alsa_handle.useCase));
1254#endif
1255            } else {
1256        char value[128];
1257        property_get("persist.audio.lowlatency.rec",value,"0");
1258                if (!strcmp("true", value)) {
1259                    strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
1260                } else {
1261                    strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, sizeof(alsa_handle.useCase));
1262                }
1263            }
1264        } else {
1265            if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
1266                (newMode == AudioSystem::MODE_IN_CALL)) {
1267                ALOGD("openInputStream: incall recording, channels %d", *channels);
1268                mIncallMode = *channels;
1269                if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
1270                    (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
1271                    if (mFusion3Platform) {
1272                        mALSADevice->setVocRecMode(INCALL_REC_STEREO);
1273                        strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
1274                                sizeof(alsa_handle.useCase));
1275                    } else {
1276                        strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_UL_DL_REC,
1277                                sizeof(alsa_handle.useCase));
1278                    }
1279                } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
1280                    if (mFusion3Platform) {
1281                        mALSADevice->setVocRecMode(INCALL_REC_MONO);
1282                        strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
1283                                sizeof(alsa_handle.useCase));
1284                    } else {
1285                       strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DL_REC,
1286                               sizeof(alsa_handle.useCase));
1287                    }
1288                }
1289#ifdef QCOM_FM_ENABLED
1290            } else if(devices == AudioSystem::DEVICE_IN_FM_RX) {
1291                strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_REC, sizeof(alsa_handle.useCase));
1292            } else if (devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
1293                strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_A2DP_REC, sizeof(alsa_handle.useCase));
1294#endif
1295            } else {
1296                char value[128];
1297                property_get("persist.audio.lowlatency.rec",value,"0");
1298                if (!strcmp("true", value)) {
1299                    strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, sizeof(alsa_handle.useCase));
1300                } else {
1301                    strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_REC, sizeof(alsa_handle.useCase));
1302                }
1303            }
1304        }
1305        free(use_case);
1306        mDeviceList.push_back(alsa_handle);
1307        ALSAHandleList::iterator it = mDeviceList.end();
1308        it--;
1309        //update channel info before do routing
1310        if(channels) {
1311            it->channels = AudioSystem::popCount((*channels) &
1312                      (AudioSystem::CHANNEL_IN_STEREO
1313                       | AudioSystem::CHANNEL_IN_MONO
1314#ifdef QCOM_SSR_ENABLED
1315                       | AudioSystem::CHANNEL_IN_5POINT1
1316#endif
1317                       | AUDIO_CHANNEL_IN_FRONT_BACK));
1318            it->channelMask = *channels;
1319            ALOGV("updated channel info: channels=%d channelMask %08x",
1320                  it->channels, it->channelMask);
1321        }
1322        if (devices == AudioSystem::DEVICE_IN_VOICE_CALL){
1323           /* Add current devices info to devices to do route */
1324#ifdef QCOM_USBAUDIO_ENABLED
1325            if(mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET ||
1326               mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET){
1327                ALOGD("Routing everything from proxy for VOIP call");
1328                route_devices = devices | AudioSystem::DEVICE_IN_PROXY;
1329            } else
1330#endif
1331            {
1332            route_devices = devices | mCurDevice;
1333            }
1334            mALSADevice->route(&(*it), route_devices, mode());
1335        } else {
1336#ifdef QCOM_USBAUDIO_ENABLED
1337            if(devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET ||
1338               devices & AudioSystem::DEVICE_IN_PROXY) {
1339                devices |= AudioSystem::DEVICE_IN_PROXY;
1340                ALOGD("routing everything from proxy");
1341            mALSADevice->route(&(*it), devices, mode());
1342            } else
1343#endif
1344            {
1345                mALSADevice->route(&(*it), devices, mode());
1346            }
1347        }
1348        if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC) ||
1349           !strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC) ||
1350#ifdef QCOM_FM_ENABLED
1351           !strcmp(it->useCase, SND_USE_CASE_VERB_FM_REC) ||
1352           !strcmp(it->useCase, SND_USE_CASE_VERB_FM_A2DP_REC) ||
1353#endif
1354           !strcmp(it->useCase, SND_USE_CASE_VERB_DL_REC) ||
1355           !strcmp(it->useCase, SND_USE_CASE_VERB_UL_DL_REC) ||
1356           !strcmp(it->useCase, SND_USE_CASE_VERB_INCALL_REC)) {
1357            snd_use_case_set(mUcMgr, "_verb", it->useCase);
1358        } else {
1359            snd_use_case_set(mUcMgr, "_enamod", it->useCase);
1360        }
1361        if(sampleRate) {
1362            it->sampleRate = *sampleRate;
1363        }
1364        if (!strncmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
1365            || !strncmp(it->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
1366            ALOGV("OpenInoutStream: Use larger buffer size for 5.1(%s) recording ", it->useCase);
1367            it->bufferSize = getInputBufferSize(it->sampleRate,*format,it->channels);
1368        }
1369        err = mALSADevice->open(&(*it));
1370        if (err) {
1371           ALOGE("Error opening pcm input device");
1372        } else {
1373           in = new AudioStreamInALSA(this, &(*it), acoustics);
1374           err = in->set(format, channels, sampleRate, devices);
1375        }
1376        if (status) *status = err;
1377        return in;
1378      }
1379}
1380
1381void
1382AudioHardwareALSA::closeInputStream(AudioStreamIn* in)
1383{
1384    delete in;
1385}
1386
1387status_t AudioHardwareALSA::setMicMute(bool state)
1388{
1389    if (mMicMute != state) {
1390        mMicMute = state;
1391        ALOGD("setMicMute: mMicMute %d", mMicMute);
1392        if(mALSADevice) {
1393            mALSADevice->setMicMute(state);
1394        }
1395    }
1396    return NO_ERROR;
1397}
1398
1399status_t AudioHardwareALSA::getMicMute(bool *state)
1400{
1401    *state = mMicMute;
1402    return NO_ERROR;
1403}
1404
1405status_t AudioHardwareALSA::dump(int fd, const Vector<String16>& args)
1406{
1407    return NO_ERROR;
1408}
1409
1410size_t AudioHardwareALSA::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
1411{
1412    size_t bufferSize = 0;
1413    if (format == AudioSystem::PCM_16_BIT) {
1414        if(sampleRate == 8000 || sampleRate == 16000 || sampleRate == 32000) {
1415            bufferSize = (sampleRate * channelCount * 20 * sizeof(int16_t)) / 1000;
1416        } else if (sampleRate == 11025 || sampleRate == 12000) {
1417            bufferSize = 256 * sizeof(int16_t)  * channelCount;
1418        } else if (sampleRate == 22050 || sampleRate == 24000) {
1419            bufferSize = 512 * sizeof(int16_t)  * channelCount;
1420        } else if (sampleRate == 44100 || sampleRate == 48000) {
1421            bufferSize = 1024 * sizeof(int16_t) * channelCount;
1422        }
1423    } else {
1424        ALOGE("getInputBufferSize bad format: %d", format);
1425    }
1426    return bufferSize;
1427}
1428
1429#ifdef QCOM_FM_ENABLED
1430void AudioHardwareALSA::handleFm(int device)
1431{
1432int newMode = mode();
1433    if(device & AudioSystem::DEVICE_OUT_FM && mIsFmActive == 0) {
1434        // Start FM Radio on current active device
1435        unsigned long bufferSize = FM_BUFFER_SIZE;
1436        alsa_handle_t alsa_handle;
1437        char *use_case;
1438        ALOGV("Start FM");
1439        snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1440        if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1441            strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DIGITAL_RADIO, sizeof(alsa_handle.useCase));
1442        } else {
1443            strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_FM, sizeof(alsa_handle.useCase));
1444        }
1445        free(use_case);
1446
1447        for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1448        bufferSize &= ~b;
1449        alsa_handle.module = mALSADevice;
1450        alsa_handle.bufferSize = bufferSize;
1451        alsa_handle.devices = device;
1452        alsa_handle.handle = 0;
1453        alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1454        alsa_handle.channels = DEFAULT_CHANNEL_MODE;
1455        alsa_handle.channelMask = AUDIO_CHANNEL_OUT_STEREO;
1456        alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
1457        alsa_handle.latency = VOICE_LATENCY;
1458        alsa_handle.rxHandle = 0;
1459        alsa_handle.ucMgr = mUcMgr;
1460        mIsFmActive = 1;
1461        mDeviceList.push_back(alsa_handle);
1462        ALSAHandleList::iterator it = mDeviceList.end();
1463        it--;
1464        if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1465           (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1466            device |= AudioSystem::DEVICE_OUT_PROXY;
1467            alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
1468            ALOGD("Routing to proxy for FM case");
1469        }
1470        mALSADevice->route(&(*it), (uint32_t)device, newMode);
1471        if(!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) {
1472            snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_DIGITAL_RADIO);
1473        } else {
1474            snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_FM);
1475        }
1476        mALSADevice->startFm(&(*it));
1477        if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1478           (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1479            ALOGD("Starting FM, musbPlaybackState %d", musbPlaybackState);
1480            startUsbPlaybackIfNotStarted();
1481            musbPlaybackState |= USBPLAYBACKBIT_FM;
1482        }
1483    } else if (!(device & AudioSystem::DEVICE_OUT_FM) && mIsFmActive == 1) {
1484        //i Stop FM Radio
1485        ALOGV("Stop FM");
1486        for(ALSAHandleList::iterator it = mDeviceList.begin();
1487            it != mDeviceList.end(); ++it) {
1488            if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
1489              (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
1490                mALSADevice->close(&(*it));
1491                //mALSADevice->route(&(*it), (uint32_t)device, newMode);
1492                mDeviceList.erase(it);
1493                break;
1494            }
1495        }
1496        mIsFmActive = 0;
1497        musbPlaybackState &= ~USBPLAYBACKBIT_FM;
1498        if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1499           (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1500            closeUsbPlaybackIfNothingActive();
1501        }
1502    }
1503}
1504#endif
1505
1506void AudioHardwareALSA::disableVoiceCall(char* verb, char* modifier, int mode, int device)
1507{
1508    for(ALSAHandleList::iterator it = mDeviceList.begin();
1509         it != mDeviceList.end(); ++it) {
1510        if((!strcmp(it->useCase, verb)) ||
1511           (!strcmp(it->useCase, modifier))) {
1512            ALOGV("Disabling voice call");
1513            mALSADevice->close(&(*it));
1514            mALSADevice->route(&(*it), (uint32_t)device, mode);
1515            mDeviceList.erase(it);
1516            break;
1517        }
1518    }
1519#ifdef QCOM_USBAUDIO_ENABLED
1520   if(musbPlaybackState & USBPLAYBACKBIT_VOICECALL) {
1521          ALOGD("Voice call ended on USB");
1522          musbPlaybackState &= ~USBPLAYBACKBIT_VOICECALL;
1523          musbRecordingState &= ~USBRECBIT_VOICECALL;
1524          closeUsbRecordingIfNothingActive();
1525          closeUsbPlaybackIfNothingActive();
1526   }
1527#endif
1528}
1529void AudioHardwareALSA::enableVoiceCall(char* verb, char* modifier, int mode, int device)
1530{
1531// Start voice call
1532unsigned long bufferSize = DEFAULT_VOICE_BUFFER_SIZE;
1533alsa_handle_t alsa_handle;
1534char *use_case;
1535    snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1536    if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1537        strlcpy(alsa_handle.useCase, verb, sizeof(alsa_handle.useCase));
1538    } else {
1539        strlcpy(alsa_handle.useCase, modifier, sizeof(alsa_handle.useCase));
1540    }
1541    free(use_case);
1542
1543    for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1544    bufferSize &= ~b;
1545    alsa_handle.module = mALSADevice;
1546    alsa_handle.bufferSize = bufferSize;
1547    alsa_handle.devices = device;
1548    alsa_handle.handle = 0;
1549    alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1550    alsa_handle.channels = VOICE_CHANNEL_MODE;
1551    alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
1552    alsa_handle.sampleRate = VOICE_SAMPLING_RATE;
1553    alsa_handle.latency = VOICE_LATENCY;
1554    alsa_handle.rxHandle = 0;
1555    alsa_handle.ucMgr = mUcMgr;
1556    mDeviceList.push_back(alsa_handle);
1557    ALSAHandleList::iterator it = mDeviceList.end();
1558    it--;
1559#ifdef QCOM_USBAUDIO_ENABLED
1560    if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1561       (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1562        device |= AudioSystem::DEVICE_OUT_PROXY;
1563        alsa_handle.devices = device;
1564    }
1565#endif
1566    mALSADevice->route(&(*it), (uint32_t)device, mode);
1567    if (!strcmp(it->useCase, verb)) {
1568        snd_use_case_set(mUcMgr, "_verb", verb);
1569    } else {
1570        snd_use_case_set(mUcMgr, "_enamod", modifier);
1571    }
1572    mALSADevice->startVoiceCall(&(*it));
1573#ifdef QCOM_USBAUDIO_ENABLED
1574    if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1575       (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1576       startUsbRecordingIfNotStarted();
1577       startUsbPlaybackIfNotStarted();
1578       musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
1579       musbRecordingState |= USBRECBIT_VOICECALL;
1580    }
1581#endif
1582}
1583
1584bool AudioHardwareALSA::routeVoiceCall(int device, int newMode)
1585{
1586int csCallState = mCallState&0xF;
1587 bool isRouted = false;
1588 switch (csCallState) {
1589    case CS_INACTIVE:
1590        if (mCSCallActive != CS_INACTIVE) {
1591            ALOGD("doRouting: Disabling voice call");
1592            disableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
1593                (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
1594            isRouted = true;
1595            mCSCallActive = CS_INACTIVE;
1596        }
1597    break;
1598    case CS_ACTIVE:
1599        if (mCSCallActive == CS_INACTIVE) {
1600            ALOGD("doRouting: Enabling CS voice call ");
1601            enableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
1602                (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
1603            isRouted = true;
1604            mCSCallActive = CS_ACTIVE;
1605        } else if (mCSCallActive == CS_HOLD) {
1606             ALOGD("doRouting: Resume voice call from hold state");
1607             ALSAHandleList::iterator vt_it;
1608             for(vt_it = mDeviceList.begin();
1609                 vt_it != mDeviceList.end(); ++vt_it) {
1610                 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
1611                     strlen(SND_USE_CASE_VERB_VOICECALL))) ||
1612                     (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1613                     strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
1614                     alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1615                     mCSCallActive = CS_ACTIVE;
1616                     if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
1617                                   ALOGE("VoLTE resume failed");
1618                     break;
1619                 }
1620             }
1621        }
1622    break;
1623    case CS_HOLD:
1624        if (mCSCallActive == CS_ACTIVE) {
1625            ALOGD("doRouting: Voice call going to Hold");
1626             ALSAHandleList::iterator vt_it;
1627             for(vt_it = mDeviceList.begin();
1628                 vt_it != mDeviceList.end(); ++vt_it) {
1629                 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
1630                     strlen(SND_USE_CASE_VERB_VOICECALL))) ||
1631                     (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1632                         strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
1633                         mCSCallActive = CS_HOLD;
1634                         alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1635                         if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
1636                                   ALOGE("Voice pause failed");
1637                         break;
1638                }
1639            }
1640        }
1641    break;
1642    }
1643    return isRouted;
1644}
1645bool AudioHardwareALSA::routeVoLTECall(int device, int newMode)
1646{
1647int volteCallState = mCallState&0xF0;
1648bool isRouted = false;
1649switch (volteCallState) {
1650    case IMS_INACTIVE:
1651        if (mVolteCallActive != IMS_INACTIVE) {
1652            ALOGD("doRouting: Disabling IMS call");
1653            disableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
1654                (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
1655            isRouted = true;
1656            mVolteCallActive = IMS_INACTIVE;
1657        }
1658    break;
1659    case IMS_ACTIVE:
1660        if (mVolteCallActive == IMS_INACTIVE) {
1661            ALOGD("doRouting: Enabling IMS voice call ");
1662            enableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
1663                (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
1664            isRouted = true;
1665            mVolteCallActive = IMS_ACTIVE;
1666        } else if (mVolteCallActive == IMS_HOLD) {
1667             ALOGD("doRouting: Resume IMS call from hold state");
1668             ALSAHandleList::iterator vt_it;
1669             for(vt_it = mDeviceList.begin();
1670                 vt_it != mDeviceList.end(); ++vt_it) {
1671                 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
1672                     strlen(SND_USE_CASE_VERB_VOLTE))) ||
1673                     (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1674                     strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
1675                     alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1676                     mVolteCallActive = IMS_ACTIVE;
1677                     if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
1678                                   ALOGE("VoLTE resume failed");
1679                     break;
1680                 }
1681             }
1682        }
1683    break;
1684    case IMS_HOLD:
1685        if (mVolteCallActive == IMS_ACTIVE) {
1686             ALOGD("doRouting: IMS ACTIVE going to HOLD");
1687             ALSAHandleList::iterator vt_it;
1688             for(vt_it = mDeviceList.begin();
1689                 vt_it != mDeviceList.end(); ++vt_it) {
1690                 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
1691                     strlen(SND_USE_CASE_VERB_VOLTE))) ||
1692                     (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1693                         strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
1694                          mVolteCallActive = IMS_HOLD;
1695                         alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1696                         if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
1697                                   ALOGE("VoLTE Pause failed");
1698                    break;
1699                }
1700            }
1701        }
1702    break;
1703    }
1704    return isRouted;
1705}
1706
1707}       // namespace android_audio_legacy
1708