AudioHardwareALSA.cpp revision 9746c4758b161e26eec92b1ef1ff1bf0ba0bd268
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 454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevextern "C" { 479746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_CSDCLIENT_ENABLED 489746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#include "csd_client.h" 499746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 509746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_ACDB_ENABLED 519746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#include "acdb-loader.h" 529746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevextern "C" 564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // 584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Function for dlsym() to look up for creating a new AudioHardwareInterface. 594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // 604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev android_audio_legacy::AudioHardwareInterface *createAudioHardware(void) { 614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return android_audio_legacy::AudioHardwareALSA::create(); 624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} // extern "C" 644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevnamespace android_audio_legacy 664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// ---------------------------------------------------------------------------- 694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 704765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareInterface *AudioHardwareALSA::create() { 714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return new AudioHardwareALSA(); 724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 744765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::AudioHardwareALSA() : 754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice(0),mVoipStreamCount(0),mVoipMicMute(false),mVoipBitRate(0) 764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ,mCallState(0) 774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev FILE *fp; 794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev char soundCardInfo[200]; 804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hw_module_t *module; 814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev char platform[128], baseband[128]; 824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int err = hw_get_module(ALSA_HARDWARE_MODULE_ID, 834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (hw_module_t const**)&module); 844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int codec_rev = 2; 854113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("hw_get_module(ALSA_HARDWARE_MODULE_ID) returned err %d", err); 864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (err == 0) { 874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev hw_device_t* device; 884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev err = module->methods->open(module, ALSA_HARDWARE_NAME, &device); 894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (err == 0) { 904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice = (alsa_device_t *)device; 914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->init(mALSADevice, mDeviceList); 924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mCSCallActive = 0; 934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mVolteCallActive = 0; 944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mIsFmActive = 0; 954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag = 0; 969746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mAudioUsbALSA = new AudioUsbALSA(); 989746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani musbPlaybackState = 0; 999746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani musbRecordingState = 0; 1009746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 1014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag |= TTY_OFF; 1024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mBluetoothVGS = false; 1034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mFusion3Platform = false; 1049746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani 1059746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_ACDB_ENABLED 1069746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani if ((acdb_loader_init_ACDB()) < 0) { 1079746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani ALOGE("Failed to initialize ACDB"); 1089746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani } 1099746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 1104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((fp = fopen("/proc/asound/cards","r")) == NULL) { 1124113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Cannot open /proc/asound/cards file to get sound card info"); 1134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 1144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev while((fgets(soundCardInfo, sizeof(soundCardInfo), fp) != NULL)) { 1154113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("SoundCardInfo %s", soundCardInfo); 1164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (strstr(soundCardInfo, "msm8960-tabla1x-snd-card")) { 1174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev codec_rev = 1; 1184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (strstr(soundCardInfo, "msm-snd-card")) { 1204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev codec_rev = 2; 1214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (strstr(soundCardInfo, "msm8930-sitar-snd-card")) { 1234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev codec_rev = 3; 1244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 1254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev fclose(fp); 1284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (codec_rev == 1) { 1314113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Detected tabla 1.x sound card"); 1324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm"); 1334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (codec_rev == 3) { 1344113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Detected sitar 1.x sound card"); 1354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_Sitar"); 1364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 1374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev property_get("ro.board.platform", platform, ""); 1384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev property_get("ro.baseband", baseband, ""); 1394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) { 1404113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Detected Fusion tabla 2.x"); 1414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mFusion3Platform = true; 1424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x_Fusion3"); 1434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 1444113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Detected tabla 2.x sound card"); 1454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x"); 1464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mUcMgr < 0) { 1504113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Failed to open ucm instance: %d", errno); 1514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 1524113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGI("ucm instance opened: %u", (unsigned)mUcMgr); 1534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 1554113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("ALSA Module could not be opened!!!"); 1564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 1584113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("ALSA Module not found!!!"); 1594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 1614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1624765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::~AudioHardwareALSA() 1634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 1644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mUcMgr != NULL) { 1654113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("closing ucm instance: %u", (unsigned)mUcMgr); 1664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_mgr_close(mUcMgr); 1674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mALSADevice) { 1694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->common.close(&mALSADevice->common); 1704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for(ALSAHandleList::iterator it = mDeviceList.begin(); 1724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it != mDeviceList.end(); ++it) { 1734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it->useCase[0] = 0; 1744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDeviceList.erase(it); 1754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 1769746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_ACDB_ENABLED 1779746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani acdb_loader_deallocate_ACDB(); 1789746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 1799746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 1804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev delete mAudioUsbALSA; 1819746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 1824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 1834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::initCheck() 1854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 1864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!mALSADevice) 1874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_INIT; 1884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 1904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 1914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 1924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::setVoiceVolume(float v) 1934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 1944113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("setVoiceVolume(%f)\n", v); 1954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (v < 0.0) { 1964113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v); 1974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev v = 0.0; 1984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (v > 1.0) { 1994113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v); 2004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev v = 1.0; 2014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int newMode = mode(); 2044113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("setVoiceVolume newMode %d",newMode); 2054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int vol = lrint(v * 100.0); 2064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Voice volume levels from android are mapped to driver volume levels as follows. 2084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0 2094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // So adjust the volume to get the correct volume index in driver 2104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev vol = 100 - vol; 2114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mALSADevice) { 2134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(newMode == AudioSystem::MODE_IN_COMMUNICATION) { 2144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setVoipVolume(vol); 2154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (newMode == AudioSystem::MODE_IN_CALL){ 2169746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani if (mCSCallActive == CS_ACTIVE) 2174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setVoiceVolume(vol); 2189746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani if (mVolteCallActive == IMS_ACTIVE) 2194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setVoLTEVolume(vol); 2204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 2244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2269746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED 2274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::setFmVolume(float value) 2284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev status_t status = NO_ERROR; 2304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int vol; 2324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (value < 0.0) { 2344113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGW("setFmVolume(%f) under 0.0, assuming 0.0\n", value); 2354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev value = 0.0; 2364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (value > 1.0) { 2374113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGW("setFmVolume(%f) over 1.0, assuming 1.0\n", value); 2384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev value = 1.0; 2394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev vol = lrint((value * 0x2000) + 0.5); 2414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2424113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("setFmVolume(%f)\n", value); 2434113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("Setting FM volume to %d (available range is 0 to 0x2000)\n", vol); 2444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setFmVolume(vol); 2464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return status; 2484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 2504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::setMasterVolume(float volume) 2524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 2544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::setMode(int mode) 2574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev status_t status = NO_ERROR; 2594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mode != mMode) { 2614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev status = AudioHardwareBase::setMode(mode); 2624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mode == AudioSystem::MODE_IN_CALL) { 2659746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani mCallState = CS_ACTIVE; 2664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev }else if (mode == AudioSystem::MODE_NORMAL) { 2674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mCallState = 0; 2684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return status; 2714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 2724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::setParameters(const String8& keyValuePairs) 2744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 2754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev AudioParameter param = AudioParameter(keyValuePairs); 2764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev String8 key; 2774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev String8 value; 2784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev status_t status = NO_ERROR; 2794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int device; 2804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int btRate; 2814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int state; 2824113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("setParameters() %s", keyValuePairs.string()); 2834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 2844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(TTY_MODE_KEY); 2854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 2864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag &= TTY_CLEAR; 2874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (value == "full") { 2884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag |= TTY_FULL; 2894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (value == "hco") { 2904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag |= TTY_HCO; 2914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (value == "vco") { 2924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag |= TTY_VCO; 2934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 2944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag |= TTY_OFF; 2954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 2964113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGI("Changed TTY Mode=%s", value.string()); 2974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setFlags(mDevSettingsFlag); 2984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(mMode != AudioSystem::MODE_IN_CALL){ 2994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 3004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev doRouting(0); 3024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(FLUENCE_KEY); 3054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 3064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (value == "quadmic") { 3074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag |= QMIC_FLAG; 3084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag &= (~DMIC_FLAG); 3094113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Fluence quadMic feature Enabled"); 3104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (value == "dualmic") { 3114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag |= DMIC_FLAG; 3124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag &= (~QMIC_FLAG); 3134113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Fluence dualmic feature Enabled"); 3144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (value == "none") { 3154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag &= (~DMIC_FLAG); 3164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag &= (~QMIC_FLAG); 3174113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Fluence feature Disabled"); 3184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setFlags(mDevSettingsFlag); 3204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev doRouting(0); 3214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3239746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_CSDCLIENT_ENABLED 3244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mFusion3Platform) { 3254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(INCALLMUSIC_KEY); 3264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 3274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (value == "true") { 3284113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Enabling Incall Music setting in the setparameter\n"); 3299746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani csd_client_start_playback(); 3304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 3314113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Disabling Incall Music setting in the setparameter\n"); 3329746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani csd_client_stop_playback(); 3334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3369746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 3374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(ANC_KEY); 3394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 3404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (value == "true") { 3414113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Enabling ANC setting in the setparameter\n"); 3424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag |= ANC_FLAG; 3434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 3444113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Disabling ANC setting in the setparameter\n"); 3454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDevSettingsFlag &= (~ANC_FLAG); 3464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setFlags(mDevSettingsFlag); 3484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev doRouting(0); 3494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(AudioParameter::keyRouting); 3524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.getInt(key, device) == NO_ERROR) { 3534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Ignore routing if device is 0. 3544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(device) { 3554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev doRouting(device); 3564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.remove(key); 3584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(BT_SAMPLERATE_KEY); 3614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.getInt(key, btRate) == NO_ERROR) { 3624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setBtscoRate(btRate); 3634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.remove(key); 3644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(BTHEADSET_VGS); 3674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 3684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (value == "on") { 3694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mBluetoothVGS = true; 3704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 3714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mBluetoothVGS = false; 3724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(WIDEVOICE_KEY); 3764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 3774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bool flag = false; 3784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (value == "true") { 3794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev flag = true; 3804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(mALSADevice) { 3824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->enableWideVoice(flag); 3834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.remove(key); 3854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(VOIPRATE_KEY); 3884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 3894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mVoipBitRate = atoi(value); 3904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.remove(key); 3914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 3934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(FENS_KEY); 3944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 3954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bool flag = false; 3964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (value == "true") { 3974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev flag = true; 3984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 3994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(mALSADevice) { 4004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->enableFENS(flag); 4014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.remove(key); 4034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4059746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED 4064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(AudioParameter::keyHandleFm); 4074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.getInt(key, device) == NO_ERROR) { 4084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Ignore if device is 0 4094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(device) { 4104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev handleFm(device); 4114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.remove(key); 4134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 4154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(ST_KEY); 4174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 4184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bool flag = false; 4194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (value == "true") { 4204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev flag = true; 4214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(mALSADevice) { 4234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->enableSlowTalk(flag); 4244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.remove(key); 4264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(MODE_CALL_KEY); 4284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.getInt(key,state) == NO_ERROR) { 4294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mCallState != state) { 4304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mCallState = state; 4314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev doRouting(0); 4324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mCallState = state; 4344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.size()) { 4364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev status = BAD_VALUE; 4374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return status; 4394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 4404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4414765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevString8 AudioHardwareALSA::getParameters(const String8& keys) 4424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 4434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev AudioParameter param = AudioParameter(keys); 4444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev String8 value; 4454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev String8 key = String8(DUALMIC_KEY); 4474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 4484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev value = String8("false"); 4494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.add(key, value); 4504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(FLUENCE_KEY); 4534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 4544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((mDevSettingsFlag & QMIC_FLAG) && 4554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (mDevSettingsFlag & ~DMIC_FLAG)) 4564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev value = String8("quadmic"); 4574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else if ((mDevSettingsFlag & DMIC_FLAG) && 4584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (mDevSettingsFlag & ~QMIC_FLAG)) 4594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev value = String8("dualmic"); 4604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else if ((mDevSettingsFlag & ~DMIC_FLAG) && 4614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (mDevSettingsFlag & ~QMIC_FLAG)) 4624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev value = String8("none"); 4634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.add(key, value); 4644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4669746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED 4674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8("Fm-radio"); 4684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ( param.get(key,value) == NO_ERROR ) { 4694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ( mIsFmActive ) { 4704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.addInt(String8("isFMON"), true ); 4714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 4744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev key = String8(BTHEADSET_VGS); 4764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (param.get(key, value) == NO_ERROR) { 4774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(mBluetoothVGS) 4784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev param.addInt(String8("isVGS"), true); 4794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 4804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4814113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("AudioHardwareALSA::getParameters() %s", param.toString().string()); 4824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return param.toString(); 4834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 4844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4859746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 4864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::closeUSBPlayback() 4874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 4884113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("closeUSBPlayback, musbPlaybackState: %d", musbPlaybackState); 4894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbPlaybackState = 0; 4904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_KILLTHREAD); 4914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 4924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 4934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::closeUSBRecording() 4944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 4954113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("closeUSBRecording"); 4964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbRecordingState = 0; 4974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mAudioUsbALSA->exitRecordingThread(SIGNAL_EVENT_KILLTHREAD); 4984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 4994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 5004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::closeUsbPlaybackIfNothingActive(){ 5014113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("closeUsbPlaybackIfNothingActive, musbPlaybackState: %d", musbPlaybackState); 5024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(!musbPlaybackState && mAudioUsbALSA != NULL) { 5034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_TIMEOUT); 5044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 5054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 5064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 5074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::closeUsbRecordingIfNothingActive(){ 5084113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("closeUsbRecordingIfNothingActive, musbRecordingState: %d", musbRecordingState); 5094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(!musbRecordingState && mAudioUsbALSA != NULL) { 5104113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("Closing USB Recording Session as no stream is active"); 5114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mAudioUsbALSA->setkillUsbRecordingThread(true); 5124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 5134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 5144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 5154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::startUsbPlaybackIfNotStarted(){ 5164113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Starting the USB playback %d kill %d", musbPlaybackState, 5174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mAudioUsbALSA->getkillUsbPlaybackThread()); 5184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!musbPlaybackState) || (mAudioUsbALSA->getkillUsbPlaybackThread() == true)) { 5194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mAudioUsbALSA->startPlayback(); 5204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 5214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 5224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 5234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::startUsbRecordingIfNotStarted(){ 5244113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Starting the recording musbRecordingState: %d killUsbRecordingThread %d", 5254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbRecordingState, mAudioUsbALSA->getkillUsbRecordingThread()); 5264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!musbRecordingState) || (mAudioUsbALSA->getkillUsbRecordingThread() == true)) { 5274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mAudioUsbALSA->startRecording(); 5284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 5294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 5309746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 5314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 5324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::doRouting(int device) 5334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 5344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev Mutex::Autolock autoLock(mLock); 5354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int newMode = mode(); 5364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bool isRouted = false; 5374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 5389746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani if ((device == AudioSystem::DEVICE_IN_VOICE_CALL) 5399746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED 5409746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani || (device == AudioSystem::DEVICE_IN_FM_RX) 5419746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani || (device == AudioSystem::DEVICE_OUT_DIRECTOUTPUT) 5429746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani || (device == AudioSystem::DEVICE_IN_FM_RX_A2DP) 5434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 5449746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani || (device == AudioSystem::DEVICE_IN_COMMUNICATION) 5459746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani ) { 5464113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Ignoring routing for FM/INCALL/VOIP recording"); 5474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return; 5484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 5494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (device == 0) 5504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev device = mCurDevice; 5514113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("doRouting: device %d newMode %d mCSCallActive %d mVolteCallActive %d" 5524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev "mIsFmActive %d", device, newMode, mCSCallActive, mVolteCallActive, 5534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mIsFmActive); 5544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 5554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev isRouted = routeVoLTECall(device, newMode); 5564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev isRouted |= routeVoiceCall(device, newMode); 5574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 5584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(!isRouted) { 5599746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 5604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(!(device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) && 5614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev !(device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET) && 5624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev !(device & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) && 5634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (musbPlaybackState)){ 5644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev //USB unplugged 5654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev device &= ~ AudioSystem::DEVICE_OUT_PROXY; 5664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev device &= ~ AudioSystem::DEVICE_IN_PROXY; 5674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAHandleList::iterator it = mDeviceList.end(); 5684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it--; 5694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), (uint32_t)device, newMode); 5704113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("USB UNPLUGGED, setting musbPlaybackState to 0"); 5714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbPlaybackState = 0; 5724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbRecordingState = 0; 5734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev closeUSBRecording(); 5744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev closeUSBPlayback(); 5754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)|| 5764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){ 5774113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Routing everything to prox now"); 5784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAHandleList::iterator it = mDeviceList.end(); 5794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it--; 5804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), AudioSystem::DEVICE_OUT_PROXY, 5814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev newMode); 5824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for(it = mDeviceList.begin(); it != mDeviceList.end(); ++it) { 5834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) || 5844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_LPA))) { 5854113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("doRouting: LPA device switch to proxy"); 5864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev startUsbPlaybackIfNotStarted(); 5874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbPlaybackState |= USBPLAYBACKBIT_LPA; 5884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 5894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if((!strcmp(it->useCase, SND_USE_CASE_VERB_VOICECALL)) || 5904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOICE))) { 5914113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("doRouting: VOICE device switch to proxy"); 5924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev startUsbRecordingIfNotStarted(); 5934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev startUsbPlaybackIfNotStarted(); 5944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbPlaybackState |= USBPLAYBACKBIT_VOICECALL; 5954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbRecordingState |= USBPLAYBACKBIT_VOICECALL; 5964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 5974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev }else if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) || 5984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) { 5994113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("doRouting: FM device switch to proxy"); 6004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev startUsbPlaybackIfNotStarted(); 6014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbPlaybackState |= USBPLAYBACKBIT_FM; 6024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 6034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 6044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 6054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else 6064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 6074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((((mCurDevice & AudioSystem::DEVICE_OUT_WIRED_HEADSET) || 6084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (mCurDevice & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) && 6094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (mCurDevice & AudioSystem::DEVICE_OUT_SPEAKER) && 6104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ((device & AudioSystem::DEVICE_OUT_WIRED_HEADSET) || 6114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (device & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) || 6124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (((device & AudioSystem::DEVICE_OUT_WIRED_HEADSET) || 6134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (device & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) && 6144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (device & AudioSystem::DEVICE_OUT_SPEAKER) && 6154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ((mCurDevice & AudioSystem::DEVICE_OUT_WIRED_HEADSET) || 6164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (mCurDevice & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)))) { 6174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for(ALSAHandleList::iterator it = mDeviceList.begin(); 6184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it != mDeviceList.end(); ++it) { 6194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strncmp(it->useCase, SND_USE_CASE_VERB_HIFI, 6204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlen(SND_USE_CASE_VERB_HIFI))) || 6214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strncmp(it->useCase, SND_USE_CASE_MOD_PLAY_MUSIC, 6224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlen(SND_USE_CASE_MOD_PLAY_MUSIC)))) { 6234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it),(uint32_t)device, newMode); 6244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 6254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 6264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 6274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 6284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAHandleList::iterator it = mDeviceList.end(); 6294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it--; 6304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), (uint32_t)device, newMode); 6314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 6324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 6334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mCurDevice = device; 6344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 6354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 6364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevuint32_t AudioHardwareALSA::getVoipMode(int format) 6374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 6384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch(format) { 6394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::PCM_16_BIT: 6404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return MODE_PCM; 6414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 6424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::AMR_NB: 6434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return MODE_AMR; 6444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 6454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::AMR_WB: 6464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return MODE_AMR_WB; 6474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 6484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 6499746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_QCHAT_ENABLED 6504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRC: 6514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return MODE_IS127; 6524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 6534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 6544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRCB: 6554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return MODE_4GV_NB; 6564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 6574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev case AudioSystem::EVRCWB: 6584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return MODE_4GV_WB; 6594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 6609746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 6614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 6624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev default: 6634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return MODE_PCM; 6644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 6654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 6664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 6674765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioStreamOut * 6684765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::openOutputStream(uint32_t devices, 6694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int *format, 6704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t *channels, 6714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t *sampleRate, 6724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev status_t *status) 6734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 6744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev Mutex::Autolock autoLock(mLock); 6754113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("openOutputStream: devices 0x%x channels %d sampleRate %d", 6764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev devices, *channels, *sampleRate); 6774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 6784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev status_t err = BAD_VALUE; 6794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev AudioStreamOutALSA *out = 0; 6804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAHandleList::iterator it; 6814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 6824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (devices & (devices - 1)) { 6834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (status) *status = err; 6844113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("openOutputStream called with bad devices"); 6854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return out; 6864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 6874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev# if 0 6884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((devices == AudioSystem::DEVICE_OUT_DIRECTOUTPUT) && 6894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) { 6904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bool voipstream_active = false; 6914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for(it = mDeviceList.begin(); 6924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it != mDeviceList.end(); ++it) { 6934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) || 6944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) { 6954113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("openOutput: it->rxHandle %d it->handle %d",it->rxHandle,it->handle); 6964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev voipstream_active = true; 6974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 6984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 6994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 7004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(voipstream_active == false) { 7014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mVoipStreamCount = 0; 7024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mVoipMicMute = false; 7034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle_t alsa_handle; 7044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned long bufferSize; 7054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(*sampleRate == VOIP_SAMPLING_RATE_8K) { 7064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bufferSize = VOIP_BUFFER_SIZE_8K; 7074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 7084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else if(*sampleRate == VOIP_SAMPLING_RATE_16K) { 7094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bufferSize = VOIP_BUFFER_SIZE_16K; 7104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 7114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else { 7124113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("unsupported samplerate %d for voip",*sampleRate); 7134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (status) *status = err; 7144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return out; 7154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 7164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.module = mALSADevice; 7174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.bufferSize = bufferSize; 7184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.devices = devices; 7194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.handle = 0; 7204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(*format == AudioSystem::PCM_16_BIT) 7214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE; 7224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else 7234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.format = *format; 7244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE; 7254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.sampleRate = *sampleRate; 7264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.latency = VOIP_PLAYBACK_LATENCY; 7274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.rxHandle = 0; 7284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.ucMgr = mUcMgr; 7294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate); 7304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev char *use_case; 7314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case); 7324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) { 7334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase)); 7344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 7354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase)); 7364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 7374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev free(use_case); 7384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDeviceList.push_back(alsa_handle); 7394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it = mDeviceList.end(); 7404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it--; 7414113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("openoutput: mALSADevice->route useCase %s mCurDevice %d mVoipStreamCount %d mode %d", it->useCase,mCurDevice,mVoipStreamCount, mode()); 7424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((mCurDevice & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)|| 7434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (mCurDevice & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)|| 7444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (mCurDevice & AudioSystem::DEVICE_OUT_PROXY)){ 7454113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("Routing to proxy for normal voip call in openOutputStream"); 7464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mCurDevice |= AudioSystem::DEVICE_OUT_PROXY; 7474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY; 7484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION); 7494113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("enabling VOIP in openoutputstream, musbPlaybackState: %d", musbPlaybackState); 7504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev startUsbPlaybackIfNotStarted(); 7514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL; 7524113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState); 7534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev startUsbRecordingIfNotStarted(); 7544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbRecordingState |= USBRECBIT_VOIPCALL; 7554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else{ 7564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION); 7574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 7584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) { 7594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL); 7604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 7614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP); 7624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 7634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev err = mALSADevice->startVoipCall(&(*it)); 7644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (err) { 7654113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Device open failed"); 7664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NULL; 7674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 7684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 7694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev out = new AudioStreamOutALSA(this, &(*it)); 7704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev err = out->set(format, channels, sampleRate, devices); 7714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(err == NO_ERROR) { 7724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mVoipStreamCount++; //increment VoipstreamCount only if success 7734113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("openoutput mVoipStreamCount %d",mVoipStreamCount); 7744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 7754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (status) *status = err; 7764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return out; 7774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else 7784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 7794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev { 7804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 7814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle_t alsa_handle; 7824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned long bufferSize = DEFAULT_BUFFER_SIZE; 7834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 7844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1) 7854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bufferSize &= ~b; 7864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 7874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.module = mALSADevice; 7884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.bufferSize = bufferSize; 7894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.devices = devices; 7904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.handle = 0; 7914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE; 7924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.channels = DEFAULT_CHANNEL_MODE; 7934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE; 7944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.latency = PLAYBACK_LATENCY; 7954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.rxHandle = 0; 7964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.ucMgr = mUcMgr; 7974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 7984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev char *use_case; 7994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case); 8004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) { 8014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI, sizeof(alsa_handle.useCase)); 8024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 8034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC, sizeof(alsa_handle.useCase)); 8044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 8054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev free(use_case); 8064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDeviceList.push_back(alsa_handle); 8074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAHandleList::iterator it = mDeviceList.end(); 8084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it--; 8094113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("useCase %s", it->useCase); 8109746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 8114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)|| 8124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){ 8134113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Routing to proxy for normal playback in openOutputStream"); 8144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev devices |= AudioSystem::DEVICE_OUT_PROXY; 8154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 8164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 8174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), devices, mode()); 8184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI)) { 8194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI); 8204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 8214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC); 8224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 8234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev err = mALSADevice->open(&(*it)); 8244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (err) { 8254113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Device open failed"); 8264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 8274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev out = new AudioStreamOutALSA(this, &(*it)); 8284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev err = out->set(format, channels, sampleRate, devices); 8294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 8304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 8314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (status) *status = err; 8324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return out; 8334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 8344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 8354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 8364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid 8374765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::closeOutputStream(AudioStreamOut* out) 8384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 8394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev delete out; 8404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 8414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 8429746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_TUNNEL_LPA_ENABLED 8434765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioStreamOut * 8444765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::openOutputSession(uint32_t devices, 8454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int *format, 8464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev status_t *status, 8474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int sessionId, 8484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t samplingRate, 8494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t channels) 8504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 8514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev Mutex::Autolock autoLock(mLock); 8524113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("openOutputSession = %d" ,sessionId); 8534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev AudioStreamOutALSA *out = 0; 8544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev status_t err = BAD_VALUE; 8554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 8564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle_t alsa_handle; 8574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned long bufferSize = DEFAULT_BUFFER_SIZE; 8584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 8594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1) 8604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bufferSize &= ~b; 8614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 8624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.module = mALSADevice; 8634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.bufferSize = bufferSize; 8644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.devices = devices; 8654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.handle = 0; 8664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE; 8674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.channels = DEFAULT_CHANNEL_MODE; 8684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE; 8694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.latency = VOICE_LATENCY; 8704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.rxHandle = 0; 8714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.ucMgr = mUcMgr; 8724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 8734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev char *use_case; 8744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(sessionId == TUNNEL_SESSION_ID) { 8754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case); 8764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) { 8774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_TUNNEL, sizeof(alsa_handle.useCase)); 8784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 8794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_TUNNEL, sizeof(alsa_handle.useCase)); 8804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 8814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 8824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case); 8834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) { 8844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER, sizeof(alsa_handle.useCase)); 8854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 8864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LPA, sizeof(alsa_handle.useCase)); 8874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 8884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 8894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev free(use_case); 8904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDeviceList.push_back(alsa_handle); 8914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAHandleList::iterator it = mDeviceList.end(); 8924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it--; 8934113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("useCase %s", it->useCase); 8949746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 8954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)|| 8964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){ 8974113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Routing to proxy for LPA in openOutputSession"); 8984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev devices |= AudioSystem::DEVICE_OUT_PROXY; 8994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), devices, mode()); 9004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev devices = AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET; 9014113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("Starting USBPlayback for LPA"); 9024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev startUsbPlaybackIfNotStarted(); 9034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbPlaybackState |= USBPLAYBACKBIT_LPA; 9044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else 9054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 9064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev { 9074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), devices, mode()); 9084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 9094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(sessionId == TUNNEL_SESSION_ID) { 9104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) { 9114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_TUNNEL); 9124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 9134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_TUNNEL); 9144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 9154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 9164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else { 9174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) { 9184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOW_POWER); 9194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 9204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LPA); 9214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 9224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 9234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev err = mALSADevice->open(&(*it)); 9244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev out = new AudioStreamOutALSA(this, &(*it)); 9254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 9264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (status) *status = err; 9274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return out; 9284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 9294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 9304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid 9314765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::closeOutputSession(AudioStreamOut* out) 9324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 9334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev delete out; 9344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 9359746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 9364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 9374765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioStreamIn * 9384765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::openInputStream(uint32_t devices, 9394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int *format, 9404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t *channels, 9414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t *sampleRate, 9424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev status_t *status, 9434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev AudioSystem::audio_in_acoustics acoustics) 9444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 9454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev Mutex::Autolock autoLock(mLock); 9464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev char *use_case; 9474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int newMode = mode(); 9484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev uint32_t route_devices; 9494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 9504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev status_t err = BAD_VALUE; 9514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev AudioStreamInALSA *in = 0; 9524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAHandleList::iterator it; 9534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 9544113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("openInputStream: devices 0x%x channels %d sampleRate %d", devices, *channels, *sampleRate); 9554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (devices & (devices - 1)) { 9564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (status) *status = err; 9574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return in; 9584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 9594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 9604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((devices == AudioSystem::DEVICE_IN_COMMUNICATION) && 9614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) { 9624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bool voipstream_active = false; 9634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for(it = mDeviceList.begin(); 9644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it != mDeviceList.end(); ++it) { 9654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) || 9664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) { 9679746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani ALOGD("openInput: it->rxHandle %p it->handle %p",it->rxHandle,it->handle); 9684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev voipstream_active = true; 9694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 9704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 9714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 9724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(voipstream_active == false) { 9734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mVoipStreamCount = 0; 9744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mVoipMicMute = false; 9754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle_t alsa_handle; 9764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned long bufferSize; 9774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(*sampleRate == VOIP_SAMPLING_RATE_8K) { 9784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bufferSize = VOIP_BUFFER_SIZE_8K; 9794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 9804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else if(*sampleRate == VOIP_SAMPLING_RATE_16K) { 9814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bufferSize = VOIP_BUFFER_SIZE_16K; 9824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 9834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else { 9844113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("unsupported samplerate %d for voip",*sampleRate); 9854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (status) *status = err; 9864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return in; 9874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 9884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.module = mALSADevice; 9894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.bufferSize = bufferSize; 9904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.devices = devices; 9914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.handle = 0; 9924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(*format == AudioSystem::PCM_16_BIT) 9934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE; 9944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else 9954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.format = *format; 9964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE; 9974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.sampleRate = *sampleRate; 9984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.latency = VOIP_RECORD_LATENCY; 9994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.rxHandle = 0; 10004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.ucMgr = mUcMgr; 10014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate); 10024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case); 10034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) { 10044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase)); 10054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 10064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase)); 10074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 10084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev free(use_case); 10094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDeviceList.push_back(alsa_handle); 10104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it = mDeviceList.end(); 10114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it--; 10124113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("mCurrDevice: %d", mCurDevice); 10139746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 10144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)|| 10154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){ 10164113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Routing everything from proxy for voipcall"); 10174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), AudioSystem::DEVICE_IN_PROXY, AudioSystem::MODE_IN_COMMUNICATION); 10184113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("enabling VOIP in openInputstream, musbPlaybackState: %d", musbPlaybackState); 10194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev startUsbPlaybackIfNotStarted(); 10204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL; 10214113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState); 10224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev startUsbRecordingIfNotStarted(); 10234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbRecordingState |= USBRECBIT_VOIPCALL; 10244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev }else 10254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 10264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev { 10274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it),mCurDevice, AudioSystem::MODE_IN_COMMUNICATION); 10284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 10294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) { 10304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL); 10314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 10324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP); 10334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 10344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(sampleRate) { 10354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it->sampleRate = *sampleRate; 10364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 10374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(channels) 10384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it->channels = AudioSystem::popCount(*channels); 10394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev err = mALSADevice->startVoipCall(&(*it)); 10404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (err) { 10414113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Error opening pcm input device"); 10424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NULL; 10434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 10444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 10454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev in = new AudioStreamInALSA(this, &(*it), acoustics); 10464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev err = in->set(format, channels, sampleRate, devices); 10474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(err == NO_ERROR) { 10484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mVoipStreamCount++; //increment VoipstreamCount only if success 10494113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("OpenInput mVoipStreamCount %d",mVoipStreamCount); 10504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 10514113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("openInput: After Get alsahandle"); 10524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (status) *status = err; 10534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return in; 10544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else 10554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev { 10564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for(ALSAHandleList::iterator itDev = mDeviceList.begin(); 10574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev itDev != mDeviceList.end(); ++itDev) 10584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev { 10594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_HIFI_REC, MAX_UC_LEN)) 10604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, MAX_UC_LEN)) 10614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_FM, MAX_UC_LEN)) 10629746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED 10634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ||(0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_FM_REC, MAX_UC_LEN)) 10644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 10654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ) 10664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev { 10679746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED 10684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(!(devices == AudioSystem::DEVICE_IN_FM_RX_A2DP)){ 10694113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("Input stream already exists, new stream not permitted: useCase:%s, devices:0x%x, module:%p", 10704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev itDev->useCase, itDev->devices, itDev->module); 10714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return in; 10724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 10734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 10744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 10759746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED 10764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev else if ((0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_FM_A2DP_REC, MAX_UC_LEN)) 10774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, MAX_UC_LEN))) 10784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev { 10794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((devices == AudioSystem::DEVICE_IN_FM_RX_A2DP)){ 10804113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("Input stream already exists, new stream not permitted: useCase:%s, devices:0x%x, module:%p", 10814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev itDev->useCase, itDev->devices, itDev->module); 10824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return in; 10834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 10844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 10854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 10864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 10874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 10884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle_t alsa_handle; 10894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned long bufferSize = DEFAULT_IN_BUFFER_SIZE; 10904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 10914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.module = mALSADevice; 10924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.bufferSize = bufferSize; 10934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.devices = devices; 10944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.handle = 0; 10954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE; 10964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.channels = VOICE_CHANNEL_MODE; 10974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.sampleRate = android::AudioRecord::DEFAULT_SAMPLE_RATE; 10984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.latency = RECORD_LATENCY; 10994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.rxHandle = 0; 11004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.ucMgr = mUcMgr; 11014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case); 11024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) { 11034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) && 11044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (newMode == AudioSystem::MODE_IN_CALL)) { 11054113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("openInputStream: into incall recording, channels %d", *channels); 11064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mIncallMode = *channels; 11074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) && 11084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) { 11094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mFusion3Platform) { 11104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setVocRecMode(INCALL_REC_STEREO); 11114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE, 11124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sizeof(alsa_handle.useCase)); 11134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 11144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL, 11154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sizeof(alsa_handle.useCase)); 11164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 11174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) { 11184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mFusion3Platform) { 11194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setVocRecMode(INCALL_REC_MONO); 11204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE, 11214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sizeof(alsa_handle.useCase)); 11224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 11234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL, 11244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sizeof(alsa_handle.useCase)); 11254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 11264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 11279746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED 11284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if((devices == AudioSystem::DEVICE_IN_FM_RX)) { 11294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_FM, sizeof(alsa_handle.useCase)); 11304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if(devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) { 11314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, sizeof(alsa_handle.useCase)); 11324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 11334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 11344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, sizeof(alsa_handle.useCase)); 11354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 11364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 11374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) && 11384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (newMode == AudioSystem::MODE_IN_CALL)) { 11394113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("openInputStream: incall recording, channels %d", *channels); 11404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mIncallMode = *channels; 11414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) && 11424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) { 11434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mFusion3Platform) { 11444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setVocRecMode(INCALL_REC_STEREO); 11454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC, 11464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sizeof(alsa_handle.useCase)); 11474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 11484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_UL_DL_REC, 11494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sizeof(alsa_handle.useCase)); 11504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 11514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) { 11524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mFusion3Platform) { 11534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setVocRecMode(INCALL_REC_MONO); 11544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC, 11554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sizeof(alsa_handle.useCase)); 11564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 11574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DL_REC, 11584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev sizeof(alsa_handle.useCase)); 11594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 11604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 11619746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED 11624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if(devices == AudioSystem::DEVICE_IN_FM_RX) { 11634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_REC, sizeof(alsa_handle.useCase)); 11644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) { 11654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_A2DP_REC, sizeof(alsa_handle.useCase)); 11664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 11674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 11684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_REC, sizeof(alsa_handle.useCase)); 11694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 11704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 11714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev free(use_case); 11724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDeviceList.push_back(alsa_handle); 11734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAHandleList::iterator it = mDeviceList.end(); 11744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it--; 11754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev //update channel info before do routing 11764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(channels) { 11774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it->channels = AudioSystem::popCount((*channels) & 11789746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani (AudioSystem::CHANNEL_IN_STEREO 11799746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani | AudioSystem::CHANNEL_IN_MONO 11809746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_SSR_ENABLED 11814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev | AudioSystem::CHANNEL_IN_5POINT1 11824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 11834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev )); 11844113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("updated channel info: channels=%d", it->channels); 11854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 11864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (devices == AudioSystem::DEVICE_IN_VOICE_CALL){ 11874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev /* Add current devices info to devices to do route */ 11889746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 11894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET || 11904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET){ 11914113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("Routing everything from proxy for VOIP call"); 11924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev route_devices = devices | AudioSystem::DEVICE_IN_PROXY; 11934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else 11944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 11954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev { 11964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev route_devices = devices | mCurDevice; 11974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 11984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), route_devices, mode()); 11994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 12009746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 12014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET || 12024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev devices & AudioSystem::DEVICE_IN_PROXY) { 12034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev devices |= AudioSystem::DEVICE_IN_PROXY; 12044113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("routing everything from proxy"); 12054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), devices, mode()); 12064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else 12074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 12084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev { 12094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), devices, mode()); 12104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 12114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 12124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 12134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC) || 12149746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED 12154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev !strcmp(it->useCase, SND_USE_CASE_VERB_FM_REC) || 12164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev !strcmp(it->useCase, SND_USE_CASE_VERB_FM_A2DP_REC) || 12174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 12184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev !strcmp(it->useCase, SND_USE_CASE_VERB_DL_REC) || 12194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev !strcmp(it->useCase, SND_USE_CASE_VERB_UL_DL_REC) || 12204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev !strcmp(it->useCase, SND_USE_CASE_VERB_INCALL_REC)) { 12214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_verb", it->useCase); 12224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 12234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_enamod", it->useCase); 12244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 12254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(sampleRate) { 12264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it->sampleRate = *sampleRate; 12274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 12289746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_SSR_ENABLED 12294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (6 == it->channels) { 12304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!strncmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC)) 12314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev || !strncmp(it->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) { 12324113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("OpenInoutStream: Use larger buffer size for 5.1(%s) recording ", it->useCase); 12334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it->bufferSize = getInputBufferSize(it->sampleRate,*format,it->channels); 12344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 12354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 12364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 12374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev err = mALSADevice->open(&(*it)); 12384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (err) { 12394113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Error opening pcm input device"); 12404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 12414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev in = new AudioStreamInALSA(this, &(*it), acoustics); 12424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev err = in->set(format, channels, sampleRate, devices); 12434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 12444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (status) *status = err; 12454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return in; 12464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 12474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 12484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 12494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid 12504765c439491ddda3de658e62cc4a64d10e726b34Iliyan MalchevAudioHardwareALSA::closeInputStream(AudioStreamIn* in) 12514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 12524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev delete in; 12534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 12544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 12554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::setMicMute(bool state) 12564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 12574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int newMode = mode(); 12584113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("setMicMute newMode %d",newMode); 12594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(newMode == AudioSystem::MODE_IN_COMMUNICATION) { 12604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mVoipMicMute != state) { 12614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mVoipMicMute = state; 12624113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("setMicMute: mVoipMicMute %d", mVoipMicMute); 12634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(mALSADevice) { 12644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setVoipMicMute(state); 12654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 12664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 12674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 12684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (mMicMute != state) { 12694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mMicMute = state; 12704113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("setMicMute: mMicMute %d", mMicMute); 12714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(mALSADevice) { 12729746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani if(mCSCallActive == CS_ACTIVE) 12734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setMicMute(state); 12749746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani if(mVolteCallActive == IMS_ACTIVE) 12754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->setVoLTEMicMute(state); 12764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 12774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 12784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 12794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 12804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 12814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 12824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::getMicMute(bool *state) 12834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 12844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev int newMode = mode(); 12854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(newMode == AudioSystem::MODE_IN_COMMUNICATION) { 12864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *state = mVoipMicMute; 12874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 12884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *state = mMicMute; 12894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 12904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 12914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 12924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 12934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatus_t AudioHardwareALSA::dump(int fd, const Vector<String16>& args) 12944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 12954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return NO_ERROR; 12964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 12974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 12984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevsize_t AudioHardwareALSA::getInputBufferSize(uint32_t sampleRate, int format, int channelCount) 12994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 13004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev size_t bufferSize; 13014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (format != AudioSystem::PCM_16_BIT 13024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev && format != AudioSystem::AMR_NB 13034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev && format != AudioSystem::AMR_WB 13049746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_QCHAT_ENABLED 13054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev && format != AudioSystem::EVRC 13064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev && format != AudioSystem::EVRCB 13079746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani && format != AudioSystem::EVRCWB 13089746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 13099746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani ) { 13104113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGW("getInputBufferSize bad format: %d", format); 13114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return 0; 13124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 13134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(sampleRate == 16000) { 13144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bufferSize = DEFAULT_IN_BUFFER_SIZE * 2 * channelCount; 13154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if(sampleRate < 44100) { 13164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bufferSize = DEFAULT_IN_BUFFER_SIZE * channelCount; 13174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 13184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bufferSize = DEFAULT_IN_BUFFER_SIZE * 12; 13194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 13204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return bufferSize; 13214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 13224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 13239746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED 13244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::handleFm(int device) 13254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 13264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevint newMode = mode(); 13274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(device & AudioSystem::DEVICE_OUT_FM && mIsFmActive == 0) { 13284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev // Start FM Radio on current active device 13294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev unsigned long bufferSize = FM_BUFFER_SIZE; 13304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle_t alsa_handle; 13314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev char *use_case; 13324113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Start FM"); 13334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case); 13344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) { 13354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DIGITAL_RADIO, sizeof(alsa_handle.useCase)); 13364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 13374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_FM, sizeof(alsa_handle.useCase)); 13384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 13394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev free(use_case); 13404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 13414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1) 13424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bufferSize &= ~b; 13434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.module = mALSADevice; 13444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.bufferSize = bufferSize; 13454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.devices = device; 13464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.handle = 0; 13474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE; 13484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.channels = DEFAULT_CHANNEL_MODE; 13494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE; 13504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.latency = VOICE_LATENCY; 13514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.rxHandle = 0; 13524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.ucMgr = mUcMgr; 13534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mIsFmActive = 1; 13544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDeviceList.push_back(alsa_handle); 13554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAHandleList::iterator it = mDeviceList.end(); 13564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it--; 13574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)|| 13584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){ 13594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev device |= AudioSystem::DEVICE_OUT_PROXY; 13604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY; 13614113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Routing to proxy for FM case"); 13624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 13634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), (uint32_t)device, newMode); 13644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) { 13654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_DIGITAL_RADIO); 13664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 13674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_FM); 13684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 13694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->startFm(&(*it)); 13704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)|| 13714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){ 13724113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Starting FM, musbPlaybackState %d", musbPlaybackState); 13734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev startUsbPlaybackIfNotStarted(); 13744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbPlaybackState |= USBPLAYBACKBIT_FM; 13754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 13764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else if (!(device & AudioSystem::DEVICE_OUT_FM) && mIsFmActive == 1) { 13774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev //i Stop FM Radio 13784113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Stop FM"); 13794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for(ALSAHandleList::iterator it = mDeviceList.begin(); 13804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it != mDeviceList.end(); ++it) { 13814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) || 13824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) { 13834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->close(&(*it)); 13844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev //mALSADevice->route(&(*it), (uint32_t)device, newMode); 13854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDeviceList.erase(it); 13864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 13874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 13884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 13894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mIsFmActive = 0; 13904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbPlaybackState &= ~USBPLAYBACKBIT_FM; 13914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)|| 13924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){ 13934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev closeUsbPlaybackIfNothingActive(); 13944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 13954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 13964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 13974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 13984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 13994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::disableVoiceCall(char* verb, char* modifier, int mode, int device) 14004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 14014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for(ALSAHandleList::iterator it = mDeviceList.begin(); 14024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it != mDeviceList.end(); ++it) { 14034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strcmp(it->useCase, verb)) || 14044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strcmp(it->useCase, modifier))) { 14054113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGV("Disabling voice call"); 14064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->close(&(*it)); 14074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), (uint32_t)device, mode); 14084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDeviceList.erase(it); 14094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 14104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 14114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 14129746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 14134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(musbPlaybackState & USBPLAYBACKBIT_VOICECALL) { 14144113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Voice call ended on USB"); 14154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbPlaybackState &= ~USBPLAYBACKBIT_VOICECALL; 14164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbRecordingState &= ~USBRECBIT_VOICECALL; 14174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev closeUsbRecordingIfNothingActive(); 14184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev closeUsbPlaybackIfNothingActive(); 14194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 14209746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 14214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 14224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevvoid AudioHardwareALSA::enableVoiceCall(char* verb, char* modifier, int mode, int device) 14234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 14244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev// Start voice call 14254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevunsigned long bufferSize = DEFAULT_BUFFER_SIZE; 14264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevalsa_handle_t alsa_handle; 14274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevchar *use_case; 14284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case); 14294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) { 14304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, verb, sizeof(alsa_handle.useCase)); 14314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 14324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlcpy(alsa_handle.useCase, modifier, sizeof(alsa_handle.useCase)); 14334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 14344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev free(use_case); 14354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 14364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1) 14374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bufferSize &= ~b; 14384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.module = mALSADevice; 14394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.bufferSize = bufferSize; 14404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.devices = device; 14414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.handle = 0; 14424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE; 14434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.channels = VOICE_CHANNEL_MODE; 14444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.sampleRate = VOICE_SAMPLING_RATE; 14454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.latency = VOICE_LATENCY; 14464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.rxHandle = 0; 14474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.ucMgr = mUcMgr; 14484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mDeviceList.push_back(alsa_handle); 14494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAHandleList::iterator it = mDeviceList.end(); 14504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev it--; 14519746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 14524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)|| 14534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){ 14544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev device |= AudioSystem::DEVICE_OUT_PROXY; 14554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle.devices = device; 14564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 14574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif 14584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->route(&(*it), (uint32_t)device, mode); 14594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if (!strcmp(it->useCase, verb)) { 14604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_verb", verb); 14614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } else { 14624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev snd_use_case_set(mUcMgr, "_enamod", modifier); 14634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 14644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev mALSADevice->startVoiceCall(&(*it)); 14659746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_USBAUDIO_ENABLED 14664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)|| 14674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){ 14684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev startUsbRecordingIfNotStarted(); 14694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev startUsbPlaybackIfNotStarted(); 14704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbPlaybackState |= USBPLAYBACKBIT_VOICECALL; 14714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev musbRecordingState |= USBRECBIT_VOICECALL; 14724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 14739746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#endif 14744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 14754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 14764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevbool AudioHardwareALSA::routeVoiceCall(int device, int newMode) 14774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 14784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevint csCallState = mCallState&0xF; 14794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev bool isRouted = false; 14804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev switch (csCallState) { 14819746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani case CS_INACTIVE: 14829746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani if (mCSCallActive != CS_INACTIVE) { 14834113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("doRouting: Disabling voice call"); 14844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev disableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL, 14854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device); 14864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev isRouted = true; 14879746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani mCSCallActive = CS_INACTIVE; 14884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 14894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 14909746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani case CS_ACTIVE: 14919746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani if (mCSCallActive == CS_INACTIVE) { 14924113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("doRouting: Enabling CS voice call "); 14934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev enableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL, 14944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device); 14954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev isRouted = true; 14969746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani mCSCallActive = CS_ACTIVE; 14979746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani } else if (mCSCallActive == CS_HOLD) { 14984113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("doRouting: Resume voice call from hold state"); 14994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAHandleList::iterator vt_it; 15004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for(vt_it = mDeviceList.begin(); 15014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev vt_it != mDeviceList.end(); ++vt_it) { 15024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL, 15034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlen(SND_USE_CASE_VERB_VOICECALL))) || 15044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE, 15054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) { 15064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it)); 15079746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani mCSCallActive = CS_ACTIVE; 15084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0) 15094113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("VoLTE resume failed"); 15104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 15114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 15159746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani case CS_HOLD: 15169746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani if (mCSCallActive == CS_ACTIVE) { 15174113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("doRouting: Voice call going to Hold"); 15184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAHandleList::iterator vt_it; 15194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for(vt_it = mDeviceList.begin(); 15204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev vt_it != mDeviceList.end(); ++vt_it) { 15214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL, 15224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlen(SND_USE_CASE_VERB_VOICECALL))) || 15234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE, 15244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) { 15259746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani mCSCallActive = CS_HOLD; 15264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it)); 15274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0) 15284113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("Voice pause failed"); 15294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 15304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 15344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return isRouted; 15364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 15374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevbool AudioHardwareALSA::routeVoLTECall(int device, int newMode) 15384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{ 15394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevint volteCallState = mCallState&0xF0; 15404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevbool isRouted = false; 15414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevswitch (volteCallState) { 15429746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani case IMS_INACTIVE: 15439746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani if (mVolteCallActive != IMS_INACTIVE) { 15444113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("doRouting: Disabling IMS call"); 15454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev disableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE, 15464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device); 15474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev isRouted = true; 15489746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani mVolteCallActive = IMS_INACTIVE; 15494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 15519746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani case IMS_ACTIVE: 15529746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani if (mVolteCallActive == IMS_INACTIVE) { 15534113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("doRouting: Enabling IMS voice call "); 15544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev enableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE, 15554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device); 15564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev isRouted = true; 15579746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani mVolteCallActive = IMS_ACTIVE; 15589746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani } else if (mVolteCallActive == IMS_HOLD) { 15594113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("doRouting: Resume IMS call from hold state"); 15604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAHandleList::iterator vt_it; 15614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for(vt_it = mDeviceList.begin(); 15624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev vt_it != mDeviceList.end(); ++vt_it) { 15634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE, 15644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlen(SND_USE_CASE_VERB_VOLTE))) || 15654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE, 15664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) { 15674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it)); 15689746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani mVolteCallActive = IMS_ACTIVE; 15694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0) 15704113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("VoLTE resume failed"); 15714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 15724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 15769746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani case IMS_HOLD: 15779746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani if (mVolteCallActive == IMS_ACTIVE) { 15784113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGD("doRouting: IMS ACTIVE going to HOLD"); 15794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev ALSAHandleList::iterator vt_it; 15804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev for(vt_it = mDeviceList.begin(); 15814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev vt_it != mDeviceList.end(); ++vt_it) { 15824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE, 15834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlen(SND_USE_CASE_VERB_VOLTE))) || 15844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE, 15854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) { 15869746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani mVolteCallActive = IMS_HOLD; 15874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it)); 15884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0) 15894113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev ALOGE("VoLTE Pause failed"); 15904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 15914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev break; 15954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev } 15964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev return isRouted; 15974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} 15984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev 15994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev} // namespace android_audio_legacy 1600