blob: 54f386a87fcae9eecd23b75fb78028908ec18952 [file] [log] [blame]
Iliyan Malchev4765c432012-06-11 14:36:16 -07001/* AudioHardwareALSA.cpp
2 **
3 ** Copyright 2008-2010 Wind River Systems
4 ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
5 **
6 ** Licensed under the Apache License, Version 2.0 (the "License");
7 ** you may not use this file except in compliance with the License.
8 ** You may obtain a copy of the License at
9 **
10 ** http://www.apache.org/licenses/LICENSE-2.0
11 **
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 */
18
19#include <errno.h>
20#include <stdarg.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <stdlib.h>
24#include <unistd.h>
25#include <dlfcn.h>
26#include <math.h>
27
Ajay Dudani9746c472012-06-18 16:01:16 -070028#define LOG_TAG "AudioHardwareALSA"
Iliyan Malchev4765c432012-06-11 14:36:16 -070029//#define LOG_NDEBUG 0
Ajay Dudani9746c472012-06-18 16:01:16 -070030#define LOG_NDDEBUG 0
Iliyan Malchev4765c432012-06-11 14:36:16 -070031#include <utils/Log.h>
32#include <utils/String8.h>
33#include <sys/prctl.h>
34#include <sys/resource.h>
35#include <sys/poll.h>
36#include <sys/ioctl.h>
37#include <cutils/properties.h>
38#include <media/AudioRecord.h>
39#include <hardware_legacy/power.h>
40
41#include "AudioHardwareALSA.h"
Ajay Dudani9746c472012-06-18 16:01:16 -070042#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -070043#include "AudioUsbALSA.h"
Ajay Dudani9746c472012-06-18 16:01:16 -070044#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070045
46extern "C" {
Ajay Dudani9746c472012-06-18 16:01:16 -070047#ifdef QCOM_CSDCLIENT_ENABLED
48#include "csd_client.h"
49#endif
50#ifdef QCOM_ACDB_ENABLED
51#include "acdb-loader.h"
52#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070053}
54
55extern "C"
56{
57 //
58 // Function for dlsym() to look up for creating a new AudioHardwareInterface.
59 //
60 android_audio_legacy::AudioHardwareInterface *createAudioHardware(void) {
61 return android_audio_legacy::AudioHardwareALSA::create();
62 }
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070063#ifdef QCOM_ACDB_ENABLED
64 static int (*acdb_init)();
65 static void (*acdb_deallocate)();
66#endif
67#ifdef QCOM_CSDCLIENT_ENABLED
68 static int (*csd_start_playback)();
69 static int (*csd_stop_playback)();
70#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070071} // extern "C"
72
73namespace android_audio_legacy
74{
75
76// ----------------------------------------------------------------------------
77
78AudioHardwareInterface *AudioHardwareALSA::create() {
79 return new AudioHardwareALSA();
80}
81
82AudioHardwareALSA::AudioHardwareALSA() :
83 mALSADevice(0),mVoipStreamCount(0),mVoipMicMute(false),mVoipBitRate(0)
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070084 ,mCallState(0),mAcdbHandle(NULL),mCsdHandle(NULL)
Iliyan Malchev4765c432012-06-11 14:36:16 -070085{
86 FILE *fp;
87 char soundCardInfo[200];
88 hw_module_t *module;
89 char platform[128], baseband[128];
90 int err = hw_get_module(ALSA_HARDWARE_MODULE_ID,
91 (hw_module_t const**)&module);
92 int codec_rev = 2;
Iliyan Malchev4113f342012-06-11 14:39:47 -070093 ALOGD("hw_get_module(ALSA_HARDWARE_MODULE_ID) returned err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -070094 if (err == 0) {
95 hw_device_t* device;
96 err = module->methods->open(module, ALSA_HARDWARE_NAME, &device);
97 if (err == 0) {
98 mALSADevice = (alsa_device_t *)device;
99 mALSADevice->init(mALSADevice, mDeviceList);
100 mCSCallActive = 0;
101 mVolteCallActive = 0;
102 mIsFmActive = 0;
103 mDevSettingsFlag = 0;
Ajay Dudani9746c472012-06-18 16:01:16 -0700104#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700105 mAudioUsbALSA = new AudioUsbALSA();
Ajay Dudani9746c472012-06-18 16:01:16 -0700106 musbPlaybackState = 0;
107 musbRecordingState = 0;
108#endif
ty.lee924f7982012-08-01 23:15:30 +0900109#ifdef USES_FLUENCE_INCALL
110 mDevSettingsFlag |= TTY_OFF | DMIC_FLAG;
111#else
Iliyan Malchev4765c432012-06-11 14:36:16 -0700112 mDevSettingsFlag |= TTY_OFF;
ty.lee924f7982012-08-01 23:15:30 +0900113#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700114 mBluetoothVGS = false;
115 mFusion3Platform = false;
Ajay Dudani9746c472012-06-18 16:01:16 -0700116
117#ifdef QCOM_ACDB_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700118 mAcdbHandle = ::dlopen("/system/lib/libacdbloader.so", RTLD_NOW);
119 if (mAcdbHandle == NULL) {
120 ALOGE("AudioHardware: DLOPEN not successful for ACDBLOADER");
121 } else {
122 ALOGD("AudioHardware: DLOPEN successful for ACDBLOADER");
123 acdb_init = (int (*)())::dlsym(mAcdbHandle,"acdb_loader_init_ACDB");
124 if (acdb_init == NULL) {
125 ALOGE("dlsym:Error:%s Loading acdb_loader_init_ACDB", dlerror());
126 }else {
127 acdb_init();
128 acdb_deallocate = (void (*)())::dlsym(mAcdbHandle,"acdb_loader_deallocate_ACDB");
129 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700130 }
131#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700132
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700133#ifdef QCOM_CSDCLIENT_ENABLED
134 mCsdHandle = ::dlopen("/system/lib/libcsd-client.so", RTLD_NOW);
135 if (mCsdHandle == NULL) {
136 ALOGE("AudioHardware: DLOPEN not successful for CSD CLIENT");
137 } else {
138 ALOGD("AudioHardware: DLOPEN successful for CSD CLIENT");
139 csd_start_playback = (int (*)())::dlsym(mCsdHandle,"csd_client_start_playback");
140 csd_stop_playback = (int (*)())::dlsym(mCsdHandle,"csd_client_stop_playback");
141 }
142 mALSADevice->setCsdHandle(mCsdHandle);
143#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700144 if((fp = fopen("/proc/asound/cards","r")) == NULL) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700145 ALOGE("Cannot open /proc/asound/cards file to get sound card info");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700146 } else {
147 while((fgets(soundCardInfo, sizeof(soundCardInfo), fp) != NULL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700148 ALOGV("SoundCardInfo %s", soundCardInfo);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700149 if (strstr(soundCardInfo, "msm8960-tabla1x-snd-card")) {
150 codec_rev = 1;
151 break;
152 } else if (strstr(soundCardInfo, "msm-snd-card")) {
153 codec_rev = 2;
154 break;
155 } else if (strstr(soundCardInfo, "msm8930-sitar-snd-card")) {
156 codec_rev = 3;
157 break;
158 }
159 }
160 fclose(fp);
161 }
162
163 if (codec_rev == 1) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700164 ALOGV("Detected tabla 1.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700165 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm");
166 } else if (codec_rev == 3) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700167 ALOGV("Detected sitar 1.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700168 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_Sitar");
169 } else {
170 property_get("ro.board.platform", platform, "");
171 property_get("ro.baseband", baseband, "");
172 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700173 ALOGV("Detected Fusion tabla 2.x");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700174 mFusion3Platform = true;
175 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x_Fusion3");
176 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700177 ALOGV("Detected tabla 2.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700178 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x");
179 }
180 }
181
182 if (mUcMgr < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700183 ALOGE("Failed to open ucm instance: %d", errno);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700184 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700185 ALOGI("ucm instance opened: %u", (unsigned)mUcMgr);
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700186 mUcMgr->acdb_handle = NULL;
187#ifdef QCOM_ACDB_ENABLED
188 if (mAcdbHandle) {
189 mUcMgr->acdb_handle = static_cast<void*> (mAcdbHandle);
190 }
191#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700192 }
193 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700194 ALOGE("ALSA Module could not be opened!!!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700195 }
196 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700197 ALOGE("ALSA Module not found!!!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700198 }
199}
200
201AudioHardwareALSA::~AudioHardwareALSA()
202{
203 if (mUcMgr != NULL) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700204#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700205 ALOGD("closing ucm instance: %u", (unsigned)mUcMgr);
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700206#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700207 snd_use_case_mgr_close(mUcMgr);
208 }
209 if (mALSADevice) {
210 mALSADevice->common.close(&mALSADevice->common);
211 }
212 for(ALSAHandleList::iterator it = mDeviceList.begin();
213 it != mDeviceList.end(); ++it) {
214 it->useCase[0] = 0;
215 mDeviceList.erase(it);
216 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700217#ifdef QCOM_ACDB_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700218 if (acdb_deallocate == NULL) {
219 ALOGE("dlsym: Error:%s Loading acdb_deallocate_ACDB", dlerror());
220 } else {
221 acdb_deallocate();
222 }
223 if (mAcdbHandle) {
224 ::dlclose(mAcdbHandle);
225 mAcdbHandle = NULL;
226 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700227#endif
228#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700229 delete mAudioUsbALSA;
Ajay Dudani9746c472012-06-18 16:01:16 -0700230#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700231
232#ifdef QCOM_CSDCLEINT_ENABLED
233 if (mCsdHandle) {
234 ::dlclose(mCsdHandle);
235 mCsdHandle = NULL;
236 }
237#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700238}
239
240status_t AudioHardwareALSA::initCheck()
241{
242 if (!mALSADevice)
243 return NO_INIT;
244
245 return NO_ERROR;
246}
247
248status_t AudioHardwareALSA::setVoiceVolume(float v)
249{
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700250 ALOGV("setVoiceVolume(%f)\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700251 if (v < 0.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700252 ALOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700253 v = 0.0;
254 } else if (v > 1.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700255 ALOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700256 v = 1.0;
257 }
258
259 int newMode = mode();
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700260 ALOGV("setVoiceVolume newMode %d",newMode);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700261 int vol = lrint(v * 100.0);
262
263 // Voice volume levels from android are mapped to driver volume levels as follows.
264 // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
265 // So adjust the volume to get the correct volume index in driver
266 vol = 100 - vol;
267
268 if (mALSADevice) {
269 if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
270 mALSADevice->setVoipVolume(vol);
271 } else if (newMode == AudioSystem::MODE_IN_CALL){
Ajay Dudani9746c472012-06-18 16:01:16 -0700272 if (mCSCallActive == CS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700273 mALSADevice->setVoiceVolume(vol);
Ajay Dudani9746c472012-06-18 16:01:16 -0700274 if (mVolteCallActive == IMS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700275 mALSADevice->setVoLTEVolume(vol);
276 }
277 }
278
279 return NO_ERROR;
280}
281
Ajay Dudani9746c472012-06-18 16:01:16 -0700282#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700283status_t AudioHardwareALSA::setFmVolume(float value)
284{
285 status_t status = NO_ERROR;
286
287 int vol;
288
289 if (value < 0.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700290 ALOGW("setFmVolume(%f) under 0.0, assuming 0.0\n", value);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700291 value = 0.0;
292 } else if (value > 1.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700293 ALOGW("setFmVolume(%f) over 1.0, assuming 1.0\n", value);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700294 value = 1.0;
295 }
296 vol = lrint((value * 0x2000) + 0.5);
297
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700298#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700299 ALOGD("setFmVolume(%f)\n", value);
300 ALOGD("Setting FM volume to %d (available range is 0 to 0x2000)\n", vol);
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700301#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700302
303 mALSADevice->setFmVolume(vol);
304
305 return status;
306}
307#endif
308
309status_t AudioHardwareALSA::setMasterVolume(float volume)
310{
311 return NO_ERROR;
312}
313
314status_t AudioHardwareALSA::setMode(int mode)
315{
316 status_t status = NO_ERROR;
317
318 if (mode != mMode) {
319 status = AudioHardwareBase::setMode(mode);
320 }
321
322 if (mode == AudioSystem::MODE_IN_CALL) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700323 mCallState = CS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700324 }else if (mode == AudioSystem::MODE_NORMAL) {
325 mCallState = 0;
326 }
327
328 return status;
329}
330
331status_t AudioHardwareALSA::setParameters(const String8& keyValuePairs)
332{
333 AudioParameter param = AudioParameter(keyValuePairs);
334 String8 key;
335 String8 value;
336 status_t status = NO_ERROR;
337 int device;
338 int btRate;
339 int state;
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700340#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700341 ALOGD("setParameters() %s", keyValuePairs.string());
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700342#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700343
344 key = String8(TTY_MODE_KEY);
345 if (param.get(key, value) == NO_ERROR) {
346 mDevSettingsFlag &= TTY_CLEAR;
ty.leea97e6f62012-08-15 10:11:50 +0900347 if (value == "tty_full") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700348 mDevSettingsFlag |= TTY_FULL;
ty.leea97e6f62012-08-15 10:11:50 +0900349 } else if (value == "tty_hco") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700350 mDevSettingsFlag |= TTY_HCO;
ty.leea97e6f62012-08-15 10:11:50 +0900351 } else if (value == "tty_vco") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700352 mDevSettingsFlag |= TTY_VCO;
353 } else {
354 mDevSettingsFlag |= TTY_OFF;
355 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700356 ALOGI("Changed TTY Mode=%s", value.string());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700357 mALSADevice->setFlags(mDevSettingsFlag);
358 if(mMode != AudioSystem::MODE_IN_CALL){
359 return NO_ERROR;
360 }
361 doRouting(0);
362 }
363
364 key = String8(FLUENCE_KEY);
365 if (param.get(key, value) == NO_ERROR) {
366 if (value == "quadmic") {
367 mDevSettingsFlag |= QMIC_FLAG;
368 mDevSettingsFlag &= (~DMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700369 ALOGV("Fluence quadMic feature Enabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700370 } else if (value == "dualmic") {
371 mDevSettingsFlag |= DMIC_FLAG;
372 mDevSettingsFlag &= (~QMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700373 ALOGV("Fluence dualmic feature Enabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700374 } else if (value == "none") {
375 mDevSettingsFlag &= (~DMIC_FLAG);
376 mDevSettingsFlag &= (~QMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700377 ALOGV("Fluence feature Disabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700378 }
379 mALSADevice->setFlags(mDevSettingsFlag);
380 doRouting(0);
381 }
382
Ajay Dudani9746c472012-06-18 16:01:16 -0700383#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700384 if (mFusion3Platform) {
385 key = String8(INCALLMUSIC_KEY);
386 if (param.get(key, value) == NO_ERROR) {
387 if (value == "true") {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700388 ALOGV("Enabling Incall Music setting in the setparameter\n");
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700389 if (csd_start_playback == NULL) {
390 ALOGE("dlsym: Error:%s Loading csd_client_start_playback", dlerror());
391 } else {
392 csd_start_playback();
393 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700394 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700395 ALOGV("Disabling Incall Music setting in the setparameter\n");
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700396 if (csd_stop_playback == NULL) {
397 ALOGE("dlsym: Error:%s Loading csd_client_stop_playback", dlerror());
398 } else {
399 csd_stop_playback();
400 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700401 }
402 }
403 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700404#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700405
406 key = String8(ANC_KEY);
407 if (param.get(key, value) == NO_ERROR) {
408 if (value == "true") {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700409 ALOGV("Enabling ANC setting in the setparameter\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700410 mDevSettingsFlag |= ANC_FLAG;
411 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700412 ALOGV("Disabling ANC setting in the setparameter\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700413 mDevSettingsFlag &= (~ANC_FLAG);
414 }
415 mALSADevice->setFlags(mDevSettingsFlag);
416 doRouting(0);
417 }
418
419 key = String8(AudioParameter::keyRouting);
420 if (param.getInt(key, device) == NO_ERROR) {
421 // Ignore routing if device is 0.
422 if(device) {
423 doRouting(device);
424 }
425 param.remove(key);
426 }
427
428 key = String8(BT_SAMPLERATE_KEY);
429 if (param.getInt(key, btRate) == NO_ERROR) {
430 mALSADevice->setBtscoRate(btRate);
431 param.remove(key);
432 }
433
434 key = String8(BTHEADSET_VGS);
435 if (param.get(key, value) == NO_ERROR) {
436 if (value == "on") {
437 mBluetoothVGS = true;
438 } else {
439 mBluetoothVGS = false;
440 }
441 }
442
443 key = String8(WIDEVOICE_KEY);
444 if (param.get(key, value) == NO_ERROR) {
445 bool flag = false;
446 if (value == "true") {
447 flag = true;
448 }
449 if(mALSADevice) {
450 mALSADevice->enableWideVoice(flag);
451 }
452 param.remove(key);
453 }
454
455 key = String8(VOIPRATE_KEY);
456 if (param.get(key, value) == NO_ERROR) {
457 mVoipBitRate = atoi(value);
458 param.remove(key);
459 }
460
461 key = String8(FENS_KEY);
462 if (param.get(key, value) == NO_ERROR) {
463 bool flag = false;
464 if (value == "true") {
465 flag = true;
466 }
467 if(mALSADevice) {
468 mALSADevice->enableFENS(flag);
469 }
470 param.remove(key);
471 }
472
Ajay Dudani9746c472012-06-18 16:01:16 -0700473#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700474 key = String8(AudioParameter::keyHandleFm);
475 if (param.getInt(key, device) == NO_ERROR) {
476 // Ignore if device is 0
477 if(device) {
478 handleFm(device);
479 }
480 param.remove(key);
481 }
482#endif
483
484 key = String8(ST_KEY);
485 if (param.get(key, value) == NO_ERROR) {
486 bool flag = false;
487 if (value == "true") {
488 flag = true;
489 }
490 if(mALSADevice) {
491 mALSADevice->enableSlowTalk(flag);
492 }
493 param.remove(key);
494 }
495 key = String8(MODE_CALL_KEY);
496 if (param.getInt(key,state) == NO_ERROR) {
497 if (mCallState != state) {
498 mCallState = state;
499 doRouting(0);
500 }
501 mCallState = state;
502 }
503 if (param.size()) {
504 status = BAD_VALUE;
505 }
506 return status;
507}
508
509String8 AudioHardwareALSA::getParameters(const String8& keys)
510{
511 AudioParameter param = AudioParameter(keys);
512 String8 value;
513
514 String8 key = String8(DUALMIC_KEY);
515 if (param.get(key, value) == NO_ERROR) {
516 value = String8("false");
517 param.add(key, value);
518 }
519
520 key = String8(FLUENCE_KEY);
521 if (param.get(key, value) == NO_ERROR) {
522 if ((mDevSettingsFlag & QMIC_FLAG) &&
523 (mDevSettingsFlag & ~DMIC_FLAG))
524 value = String8("quadmic");
525 else if ((mDevSettingsFlag & DMIC_FLAG) &&
526 (mDevSettingsFlag & ~QMIC_FLAG))
527 value = String8("dualmic");
528 else if ((mDevSettingsFlag & ~DMIC_FLAG) &&
529 (mDevSettingsFlag & ~QMIC_FLAG))
530 value = String8("none");
531 param.add(key, value);
532 }
533
Ajay Dudani9746c472012-06-18 16:01:16 -0700534#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700535 key = String8("Fm-radio");
536 if ( param.get(key,value) == NO_ERROR ) {
537 if ( mIsFmActive ) {
538 param.addInt(String8("isFMON"), true );
539 }
540 }
541#endif
542
543 key = String8(BTHEADSET_VGS);
544 if (param.get(key, value) == NO_ERROR) {
545 if(mBluetoothVGS)
546 param.addInt(String8("isVGS"), true);
547 }
548
Iliyan Malchev4113f342012-06-11 14:39:47 -0700549 ALOGV("AudioHardwareALSA::getParameters() %s", param.toString().string());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700550 return param.toString();
551}
552
Ajay Dudani9746c472012-06-18 16:01:16 -0700553#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700554void AudioHardwareALSA::closeUSBPlayback()
555{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700556 ALOGV("closeUSBPlayback, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700557 musbPlaybackState = 0;
558 mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_KILLTHREAD);
559}
560
561void AudioHardwareALSA::closeUSBRecording()
562{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700563 ALOGV("closeUSBRecording");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700564 musbRecordingState = 0;
565 mAudioUsbALSA->exitRecordingThread(SIGNAL_EVENT_KILLTHREAD);
566}
567
568void AudioHardwareALSA::closeUsbPlaybackIfNothingActive(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700569 ALOGV("closeUsbPlaybackIfNothingActive, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700570 if(!musbPlaybackState && mAudioUsbALSA != NULL) {
571 mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_TIMEOUT);
572 }
573}
574
575void AudioHardwareALSA::closeUsbRecordingIfNothingActive(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700576 ALOGV("closeUsbRecordingIfNothingActive, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700577 if(!musbRecordingState && mAudioUsbALSA != NULL) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700578 ALOGD("Closing USB Recording Session as no stream is active");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700579 mAudioUsbALSA->setkillUsbRecordingThread(true);
580 }
581}
582
583void AudioHardwareALSA::startUsbPlaybackIfNotStarted(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700584 ALOGV("Starting the USB playback %d kill %d", musbPlaybackState,
Iliyan Malchev4765c432012-06-11 14:36:16 -0700585 mAudioUsbALSA->getkillUsbPlaybackThread());
586 if((!musbPlaybackState) || (mAudioUsbALSA->getkillUsbPlaybackThread() == true)) {
587 mAudioUsbALSA->startPlayback();
588 }
589}
590
591void AudioHardwareALSA::startUsbRecordingIfNotStarted(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700592 ALOGV("Starting the recording musbRecordingState: %d killUsbRecordingThread %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700593 musbRecordingState, mAudioUsbALSA->getkillUsbRecordingThread());
594 if((!musbRecordingState) || (mAudioUsbALSA->getkillUsbRecordingThread() == true)) {
595 mAudioUsbALSA->startRecording();
596 }
597}
Ajay Dudani9746c472012-06-18 16:01:16 -0700598#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700599
600void AudioHardwareALSA::doRouting(int device)
601{
602 Mutex::Autolock autoLock(mLock);
603 int newMode = mode();
604 bool isRouted = false;
605
Ajay Dudani9746c472012-06-18 16:01:16 -0700606 if ((device == AudioSystem::DEVICE_IN_VOICE_CALL)
607#ifdef QCOM_FM_ENABLED
608 || (device == AudioSystem::DEVICE_IN_FM_RX)
609 || (device == AudioSystem::DEVICE_OUT_DIRECTOUTPUT)
610 || (device == AudioSystem::DEVICE_IN_FM_RX_A2DP)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700611#endif
Ajay Dudani9746c472012-06-18 16:01:16 -0700612 || (device == AudioSystem::DEVICE_IN_COMMUNICATION)
613 ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700614 ALOGV("Ignoring routing for FM/INCALL/VOIP recording");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700615 return;
616 }
617 if (device == 0)
618 device = mCurDevice;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700619 ALOGV("doRouting: device %d newMode %d mCSCallActive %d mVolteCallActive %d"
Iliyan Malchev4765c432012-06-11 14:36:16 -0700620 "mIsFmActive %d", device, newMode, mCSCallActive, mVolteCallActive,
621 mIsFmActive);
622
623 isRouted = routeVoLTECall(device, newMode);
624 isRouted |= routeVoiceCall(device, newMode);
625
626 if(!isRouted) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700627#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700628 if(!(device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) &&
629 !(device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET) &&
630 !(device & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) &&
631 (musbPlaybackState)){
632 //USB unplugged
633 device &= ~ AudioSystem::DEVICE_OUT_PROXY;
634 device &= ~ AudioSystem::DEVICE_IN_PROXY;
635 ALSAHandleList::iterator it = mDeviceList.end();
636 it--;
637 mALSADevice->route(&(*it), (uint32_t)device, newMode);
SathishKumar Mani0a019912012-09-11 12:33:11 -0700638 ALOGD("USB UNPLUGGED, setting musbPlaybackState to 0");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700639 musbPlaybackState = 0;
640 musbRecordingState = 0;
641 closeUSBRecording();
642 closeUSBPlayback();
643 } else if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
644 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -0700645 ALOGD("Routing everything to prox now");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700646 ALSAHandleList::iterator it = mDeviceList.end();
647 it--;
648 mALSADevice->route(&(*it), AudioSystem::DEVICE_OUT_PROXY,
649 newMode);
650 for(it = mDeviceList.begin(); it != mDeviceList.end(); ++it) {
651 if((!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
652 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_LPA))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700653 ALOGV("doRouting: LPA device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700654 startUsbPlaybackIfNotStarted();
655 musbPlaybackState |= USBPLAYBACKBIT_LPA;
656 break;
657 } else if((!strcmp(it->useCase, SND_USE_CASE_VERB_VOICECALL)) ||
658 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOICE))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700659 ALOGV("doRouting: VOICE device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700660 startUsbRecordingIfNotStarted();
661 startUsbPlaybackIfNotStarted();
662 musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
663 musbRecordingState |= USBPLAYBACKBIT_VOICECALL;
664 break;
665 }else if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
666 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700667 ALOGV("doRouting: FM device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700668 startUsbPlaybackIfNotStarted();
669 musbPlaybackState |= USBPLAYBACKBIT_FM;
670 break;
671 }
672 }
SathishKumar Manie42406e2012-08-29 16:25:54 -0700673 } else
Iliyan Malchev4765c432012-06-11 14:36:16 -0700674#endif
SathishKumar Manie42406e2012-08-29 16:25:54 -0700675 {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700676 ALSAHandleList::iterator it = mDeviceList.end();
677 it--;
678 mALSADevice->route(&(*it), (uint32_t)device, newMode);
679 }
680 }
681 mCurDevice = device;
682}
683
684uint32_t AudioHardwareALSA::getVoipMode(int format)
685{
686 switch(format) {
687 case AudioSystem::PCM_16_BIT:
688 return MODE_PCM;
689 break;
690 case AudioSystem::AMR_NB:
691 return MODE_AMR;
692 break;
693 case AudioSystem::AMR_WB:
694 return MODE_AMR_WB;
695 break;
696
Ajay Dudani9746c472012-06-18 16:01:16 -0700697#ifdef QCOM_QCHAT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700698 case AudioSystem::EVRC:
699 return MODE_IS127;
700 break;
701
702 case AudioSystem::EVRCB:
703 return MODE_4GV_NB;
704 break;
705 case AudioSystem::EVRCWB:
706 return MODE_4GV_WB;
707 break;
Ajay Dudani9746c472012-06-18 16:01:16 -0700708#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700709
710 default:
711 return MODE_PCM;
712 }
713}
714
715AudioStreamOut *
716AudioHardwareALSA::openOutputStream(uint32_t devices,
717 int *format,
718 uint32_t *channels,
719 uint32_t *sampleRate,
720 status_t *status)
721{
722 Mutex::Autolock autoLock(mLock);
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700723 ALOGV("openOutputStream: devices 0x%x channels %d sampleRate %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700724 devices, *channels, *sampleRate);
725
SathishKumar Mani88613382012-08-13 18:40:18 -0700726 audio_output_flags_t flag = static_cast<audio_output_flags_t> (*status);
727
Iliyan Malchev4765c432012-06-11 14:36:16 -0700728 status_t err = BAD_VALUE;
SathishKumar Mani88613382012-08-13 18:40:18 -0700729 *status = NO_ERROR;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700730 AudioStreamOutALSA *out = 0;
731 ALSAHandleList::iterator it;
732
733 if (devices & (devices - 1)) {
734 if (status) *status = err;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700735 ALOGE("openOutputStream called with bad devices");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700736 return out;
737 }
SathishKumar Mani88613382012-08-13 18:40:18 -0700738
739
Iliyan Malchev4765c432012-06-11 14:36:16 -0700740# if 0
741 if((devices == AudioSystem::DEVICE_OUT_DIRECTOUTPUT) &&
742 ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
743 bool voipstream_active = false;
744 for(it = mDeviceList.begin();
745 it != mDeviceList.end(); ++it) {
746 if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
747 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700748 ALOGD("openOutput: it->rxHandle %d it->handle %d",it->rxHandle,it->handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700749 voipstream_active = true;
750 break;
751 }
752 }
753 if(voipstream_active == false) {
754 mVoipStreamCount = 0;
755 mVoipMicMute = false;
756 alsa_handle_t alsa_handle;
757 unsigned long bufferSize;
758 if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
759 bufferSize = VOIP_BUFFER_SIZE_8K;
760 }
761 else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
762 bufferSize = VOIP_BUFFER_SIZE_16K;
763 }
764 else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700765 ALOGE("unsupported samplerate %d for voip",*sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700766 if (status) *status = err;
767 return out;
768 }
769 alsa_handle.module = mALSADevice;
770 alsa_handle.bufferSize = bufferSize;
771 alsa_handle.devices = devices;
772 alsa_handle.handle = 0;
773 if(*format == AudioSystem::PCM_16_BIT)
774 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
775 else
776 alsa_handle.format = *format;
777 alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
778 alsa_handle.sampleRate = *sampleRate;
779 alsa_handle.latency = VOIP_PLAYBACK_LATENCY;
780 alsa_handle.rxHandle = 0;
781 alsa_handle.ucMgr = mUcMgr;
782 mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
783 char *use_case;
784 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
785 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
786 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
787 } else {
788 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
789 }
790 free(use_case);
791 mDeviceList.push_back(alsa_handle);
792 it = mDeviceList.end();
793 it--;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700794 ALOGV("openoutput: mALSADevice->route useCase %s mCurDevice %d mVoipStreamCount %d mode %d", it->useCase,mCurDevice,mVoipStreamCount, mode());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700795 if((mCurDevice & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
796 (mCurDevice & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)||
797 (mCurDevice & AudioSystem::DEVICE_OUT_PROXY)){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700798 ALOGD("Routing to proxy for normal voip call in openOutputStream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700799 mCurDevice |= AudioSystem::DEVICE_OUT_PROXY;
800 alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
801 mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700802 ALOGD("enabling VOIP in openoutputstream, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700803 startUsbPlaybackIfNotStarted();
804 musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700805 ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700806 startUsbRecordingIfNotStarted();
807 musbRecordingState |= USBRECBIT_VOIPCALL;
808 } else{
809 mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
810 }
811 if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
812 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
813 } else {
814 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
815 }
816 err = mALSADevice->startVoipCall(&(*it));
817 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700818 ALOGE("Device open failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700819 return NULL;
820 }
821 }
822 out = new AudioStreamOutALSA(this, &(*it));
823 err = out->set(format, channels, sampleRate, devices);
824 if(err == NO_ERROR) {
825 mVoipStreamCount++; //increment VoipstreamCount only if success
Iliyan Malchev4113f342012-06-11 14:39:47 -0700826 ALOGD("openoutput mVoipStreamCount %d",mVoipStreamCount);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700827 }
828 if (status) *status = err;
829 return out;
830 } else
831#endif
832 {
833
834 alsa_handle_t alsa_handle;
835 unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
836
837 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
838 bufferSize &= ~b;
839
840 alsa_handle.module = mALSADevice;
841 alsa_handle.bufferSize = bufferSize;
842 alsa_handle.devices = devices;
843 alsa_handle.handle = 0;
844 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
845 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
846 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
847 alsa_handle.latency = PLAYBACK_LATENCY;
848 alsa_handle.rxHandle = 0;
849 alsa_handle.ucMgr = mUcMgr;
SathishKumar Mani88613382012-08-13 18:40:18 -0700850 alsa_handle.isDeepbufferOutput = false;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700851
852 char *use_case;
853 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
SathishKumar Mani88613382012-08-13 18:40:18 -0700854
855 if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
856 ALOGD("openOutputStream: DeepBuffer Output");
857 alsa_handle.isDeepbufferOutput = true;
858 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
859 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI, sizeof(alsa_handle.useCase));
860 } else {
861 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC, sizeof(alsa_handle.useCase));
862 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700863 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -0700864 ALOGD("openOutputStream: Lowlatency Output");
865 alsa_handle.bufferSize = PLAYBACK_LOW_LATENCY_BUFFER_SIZE;
866 alsa_handle.latency = PLAYBACK_LOW_LATENCY;
867 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
868 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
869 } else {
870 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
871 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700872 }
873 free(use_case);
874 mDeviceList.push_back(alsa_handle);
875 ALSAHandleList::iterator it = mDeviceList.end();
876 it--;
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700877 ALOGV("useCase %s", it->useCase);
Ajay Dudani9746c472012-06-18 16:01:16 -0700878#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700879 if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
880 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -0700881 ALOGD("Routing to proxy for normal playback in openOutputStream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700882 devices |= AudioSystem::DEVICE_OUT_PROXY;
883 }
884#endif
885 mALSADevice->route(&(*it), devices, mode());
SathishKumar Mani88613382012-08-13 18:40:18 -0700886 if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
887 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI)) {
888 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI);
889 } else {
890 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC);
891 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700892 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -0700893 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) {
894 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC);
895 } else {
896 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC);
897 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700898 }
899 err = mALSADevice->open(&(*it));
900 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700901 ALOGE("Device open failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700902 } else {
903 out = new AudioStreamOutALSA(this, &(*it));
904 err = out->set(format, channels, sampleRate, devices);
905 }
906
907 if (status) *status = err;
908 return out;
909 }
910}
911
912void
913AudioHardwareALSA::closeOutputStream(AudioStreamOut* out)
914{
915 delete out;
916}
917
Ajay Dudani9746c472012-06-18 16:01:16 -0700918#ifdef QCOM_TUNNEL_LPA_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700919AudioStreamOut *
920AudioHardwareALSA::openOutputSession(uint32_t devices,
921 int *format,
922 status_t *status,
923 int sessionId,
924 uint32_t samplingRate,
925 uint32_t channels)
926{
927 Mutex::Autolock autoLock(mLock);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700928 ALOGD("openOutputSession = %d" ,sessionId);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700929 AudioStreamOutALSA *out = 0;
930 status_t err = BAD_VALUE;
931
932 alsa_handle_t alsa_handle;
933 unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
934
935 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
936 bufferSize &= ~b;
937
938 alsa_handle.module = mALSADevice;
939 alsa_handle.bufferSize = bufferSize;
940 alsa_handle.devices = devices;
941 alsa_handle.handle = 0;
942 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
943 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
944 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
945 alsa_handle.latency = VOICE_LATENCY;
946 alsa_handle.rxHandle = 0;
947 alsa_handle.ucMgr = mUcMgr;
948
949 char *use_case;
950 if(sessionId == TUNNEL_SESSION_ID) {
951 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
952 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
953 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_TUNNEL, sizeof(alsa_handle.useCase));
954 } else {
955 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_TUNNEL, sizeof(alsa_handle.useCase));
956 }
957 } else {
958 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
959 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
960 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER, sizeof(alsa_handle.useCase));
961 } else {
962 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LPA, sizeof(alsa_handle.useCase));
963 }
964 }
965 free(use_case);
966 mDeviceList.push_back(alsa_handle);
967 ALSAHandleList::iterator it = mDeviceList.end();
968 it--;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700969 ALOGD("useCase %s", it->useCase);
Ajay Dudani9746c472012-06-18 16:01:16 -0700970#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700971 if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
972 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -0700973 ALOGD("Routing to proxy for LPA in openOutputSession");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700974 devices |= AudioSystem::DEVICE_OUT_PROXY;
975 mALSADevice->route(&(*it), devices, mode());
976 devices = AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700977 ALOGD("Starting USBPlayback for LPA");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700978 startUsbPlaybackIfNotStarted();
979 musbPlaybackState |= USBPLAYBACKBIT_LPA;
980 } else
981#endif
982 {
983 mALSADevice->route(&(*it), devices, mode());
984 }
985 if(sessionId == TUNNEL_SESSION_ID) {
986 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) {
987 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_TUNNEL);
988 } else {
989 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_TUNNEL);
990 }
991 }
992 else {
993 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) {
994 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOW_POWER);
995 } else {
996 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LPA);
997 }
998 }
999 err = mALSADevice->open(&(*it));
1000 out = new AudioStreamOutALSA(this, &(*it));
1001
1002 if (status) *status = err;
1003 return out;
1004}
1005
1006void
1007AudioHardwareALSA::closeOutputSession(AudioStreamOut* out)
1008{
1009 delete out;
1010}
Ajay Dudani9746c472012-06-18 16:01:16 -07001011#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001012
1013AudioStreamIn *
1014AudioHardwareALSA::openInputStream(uint32_t devices,
1015 int *format,
1016 uint32_t *channels,
1017 uint32_t *sampleRate,
1018 status_t *status,
1019 AudioSystem::audio_in_acoustics acoustics)
1020{
1021 Mutex::Autolock autoLock(mLock);
1022 char *use_case;
1023 int newMode = mode();
1024 uint32_t route_devices;
1025
1026 status_t err = BAD_VALUE;
1027 AudioStreamInALSA *in = 0;
1028 ALSAHandleList::iterator it;
1029
Iliyan Malchev4113f342012-06-11 14:39:47 -07001030 ALOGD("openInputStream: devices 0x%x channels %d sampleRate %d", devices, *channels, *sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001031 if (devices & (devices - 1)) {
1032 if (status) *status = err;
1033 return in;
1034 }
1035
1036 if((devices == AudioSystem::DEVICE_IN_COMMUNICATION) &&
1037 ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
1038 bool voipstream_active = false;
1039 for(it = mDeviceList.begin();
1040 it != mDeviceList.end(); ++it) {
1041 if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
1042 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001043 ALOGD("openInput: it->rxHandle %p it->handle %p",it->rxHandle,it->handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001044 voipstream_active = true;
1045 break;
1046 }
1047 }
1048 if(voipstream_active == false) {
1049 mVoipStreamCount = 0;
1050 mVoipMicMute = false;
1051 alsa_handle_t alsa_handle;
1052 unsigned long bufferSize;
1053 if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
1054 bufferSize = VOIP_BUFFER_SIZE_8K;
1055 }
1056 else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
1057 bufferSize = VOIP_BUFFER_SIZE_16K;
1058 }
1059 else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001060 ALOGE("unsupported samplerate %d for voip",*sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001061 if (status) *status = err;
1062 return in;
1063 }
1064 alsa_handle.module = mALSADevice;
1065 alsa_handle.bufferSize = bufferSize;
1066 alsa_handle.devices = devices;
1067 alsa_handle.handle = 0;
1068 if(*format == AudioSystem::PCM_16_BIT)
1069 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1070 else
1071 alsa_handle.format = *format;
1072 alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
1073 alsa_handle.sampleRate = *sampleRate;
1074 alsa_handle.latency = VOIP_RECORD_LATENCY;
1075 alsa_handle.rxHandle = 0;
1076 alsa_handle.ucMgr = mUcMgr;
1077 mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
1078 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1079 if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1080 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
1081 } else {
1082 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
1083 }
1084 free(use_case);
1085 mDeviceList.push_back(alsa_handle);
1086 it = mDeviceList.end();
1087 it--;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001088 ALOGD("mCurrDevice: %d", mCurDevice);
Ajay Dudani9746c472012-06-18 16:01:16 -07001089#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001090 if((mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1091 (mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -07001092 ALOGD("Routing everything from proxy for voipcall");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001093 mALSADevice->route(&(*it), AudioSystem::DEVICE_IN_PROXY, AudioSystem::MODE_IN_COMMUNICATION);
Iliyan Malchev4113f342012-06-11 14:39:47 -07001094 ALOGD("enabling VOIP in openInputstream, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001095 startUsbPlaybackIfNotStarted();
1096 musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001097 ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001098 startUsbRecordingIfNotStarted();
1099 musbRecordingState |= USBRECBIT_VOIPCALL;
SathishKumar Manie42406e2012-08-29 16:25:54 -07001100 } else
Iliyan Malchev4765c432012-06-11 14:36:16 -07001101#endif
1102 {
1103 mALSADevice->route(&(*it),mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
1104 }
1105 if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
1106 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
1107 } else {
1108 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
1109 }
1110 if(sampleRate) {
1111 it->sampleRate = *sampleRate;
1112 }
1113 if(channels)
1114 it->channels = AudioSystem::popCount(*channels);
1115 err = mALSADevice->startVoipCall(&(*it));
1116 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001117 ALOGE("Error opening pcm input device");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001118 return NULL;
1119 }
1120 }
1121 in = new AudioStreamInALSA(this, &(*it), acoustics);
1122 err = in->set(format, channels, sampleRate, devices);
1123 if(err == NO_ERROR) {
1124 mVoipStreamCount++; //increment VoipstreamCount only if success
Iliyan Malchev4113f342012-06-11 14:39:47 -07001125 ALOGD("OpenInput mVoipStreamCount %d",mVoipStreamCount);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001126 }
SathishKumar Mani0a019912012-09-11 12:33:11 -07001127 ALOGD("openInput: After Get alsahandle");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001128 if (status) *status = err;
1129 return in;
1130 } else
1131 {
1132 for(ALSAHandleList::iterator itDev = mDeviceList.begin();
1133 itDev != mDeviceList.end(); ++itDev)
1134 {
1135 if((0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_HIFI_REC, MAX_UC_LEN))
1136 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, MAX_UC_LEN))
SathishKumar Mani88613382012-08-13 18:40:18 -07001137 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, MAX_UC_LEN))
1138 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, MAX_UC_LEN))
Iliyan Malchev4765c432012-06-11 14:36:16 -07001139 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_FM, MAX_UC_LEN))
Ajay Dudani9746c472012-06-18 16:01:16 -07001140#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001141 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_FM_REC, MAX_UC_LEN))
1142#endif
1143 )
1144 {
Ajay Dudani9746c472012-06-18 16:01:16 -07001145#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001146 if(!(devices == AudioSystem::DEVICE_IN_FM_RX_A2DP)){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001147 ALOGD("Input stream already exists, new stream not permitted: useCase:%s, devices:0x%x, module:%p",
Iliyan Malchev4765c432012-06-11 14:36:16 -07001148 itDev->useCase, itDev->devices, itDev->module);
1149 return in;
1150 }
1151#endif
1152 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001153#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001154 else if ((0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_FM_A2DP_REC, MAX_UC_LEN))
1155 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, MAX_UC_LEN)))
1156 {
1157 if((devices == AudioSystem::DEVICE_IN_FM_RX_A2DP)){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001158 ALOGD("Input stream already exists, new stream not permitted: useCase:%s, devices:0x%x, module:%p",
Iliyan Malchev4765c432012-06-11 14:36:16 -07001159 itDev->useCase, itDev->devices, itDev->module);
1160 return in;
1161 }
1162 }
1163#endif
1164 }
1165
1166 alsa_handle_t alsa_handle;
1167 unsigned long bufferSize = DEFAULT_IN_BUFFER_SIZE;
1168
1169 alsa_handle.module = mALSADevice;
1170 alsa_handle.bufferSize = bufferSize;
1171 alsa_handle.devices = devices;
1172 alsa_handle.handle = 0;
1173 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1174 alsa_handle.channels = VOICE_CHANNEL_MODE;
1175 alsa_handle.sampleRate = android::AudioRecord::DEFAULT_SAMPLE_RATE;
1176 alsa_handle.latency = RECORD_LATENCY;
1177 alsa_handle.rxHandle = 0;
1178 alsa_handle.ucMgr = mUcMgr;
1179 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1180 if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1181 if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
1182 (newMode == AudioSystem::MODE_IN_CALL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001183 ALOGD("openInputStream: into incall recording, channels %d", *channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001184 mIncallMode = *channels;
1185 if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
1186 (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
1187 if (mFusion3Platform) {
1188 mALSADevice->setVocRecMode(INCALL_REC_STEREO);
1189 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1190 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001191 } else {
1192 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
1193 sizeof(alsa_handle.useCase));
1194 }
1195 } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
1196 if (mFusion3Platform) {
1197 mALSADevice->setVocRecMode(INCALL_REC_MONO);
1198 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1199 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001200 } else {
1201 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
1202 sizeof(alsa_handle.useCase));
1203 }
1204 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001205#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001206 } else if((devices == AudioSystem::DEVICE_IN_FM_RX)) {
1207 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_FM, sizeof(alsa_handle.useCase));
1208 } else if(devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
1209 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, sizeof(alsa_handle.useCase));
1210#endif
1211 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -07001212 char value[128];
1213 property_get("persist.audio.lowlatency.rec",value,"0");
1214 if (!strcmp("true", value)) {
1215 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
1216 } else {
1217 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, sizeof(alsa_handle.useCase));
1218 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001219 }
1220 } else {
1221 if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
1222 (newMode == AudioSystem::MODE_IN_CALL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001223 ALOGD("openInputStream: incall recording, channels %d", *channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001224 mIncallMode = *channels;
1225 if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
1226 (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
1227 if (mFusion3Platform) {
1228 mALSADevice->setVocRecMode(INCALL_REC_STEREO);
1229 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
1230 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001231 } else {
1232 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_UL_DL_REC,
1233 sizeof(alsa_handle.useCase));
1234 }
1235 } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
1236 if (mFusion3Platform) {
1237 mALSADevice->setVocRecMode(INCALL_REC_MONO);
1238 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
1239 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001240 } else {
1241 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DL_REC,
1242 sizeof(alsa_handle.useCase));
1243 }
1244 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001245#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001246 } else if(devices == AudioSystem::DEVICE_IN_FM_RX) {
1247 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_REC, sizeof(alsa_handle.useCase));
1248 } else if (devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
1249 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_A2DP_REC, sizeof(alsa_handle.useCase));
1250#endif
1251 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -07001252 char value[128];
1253 property_get("persist.audio.lowlatency.rec",value,"0");
1254 if (!strcmp("true", value)) {
1255 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, sizeof(alsa_handle.useCase));
1256 } else {
1257 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_REC, sizeof(alsa_handle.useCase));
1258 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001259 }
1260 }
1261 free(use_case);
1262 mDeviceList.push_back(alsa_handle);
1263 ALSAHandleList::iterator it = mDeviceList.end();
1264 it--;
1265 //update channel info before do routing
1266 if(channels) {
1267 it->channels = AudioSystem::popCount((*channels) &
Ajay Dudani9746c472012-06-18 16:01:16 -07001268 (AudioSystem::CHANNEL_IN_STEREO
1269 | AudioSystem::CHANNEL_IN_MONO
1270#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001271 | AudioSystem::CHANNEL_IN_5POINT1
1272#endif
1273 ));
Iliyan Malchev4113f342012-06-11 14:39:47 -07001274 ALOGV("updated channel info: channels=%d", it->channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001275 }
1276 if (devices == AudioSystem::DEVICE_IN_VOICE_CALL){
1277 /* Add current devices info to devices to do route */
Ajay Dudani9746c472012-06-18 16:01:16 -07001278#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001279 if(mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET ||
1280 mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001281 ALOGD("Routing everything from proxy for VOIP call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001282 route_devices = devices | AudioSystem::DEVICE_IN_PROXY;
1283 } else
1284#endif
1285 {
1286 route_devices = devices | mCurDevice;
1287 }
1288 mALSADevice->route(&(*it), route_devices, mode());
1289 } else {
Ajay Dudani9746c472012-06-18 16:01:16 -07001290#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001291 if(devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET ||
1292 devices & AudioSystem::DEVICE_IN_PROXY) {
1293 devices |= AudioSystem::DEVICE_IN_PROXY;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001294 ALOGD("routing everything from proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001295 mALSADevice->route(&(*it), devices, mode());
1296 } else
1297#endif
1298 {
1299 mALSADevice->route(&(*it), devices, mode());
1300 }
1301 }
1302
1303 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001304 !strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC) ||
Ajay Dudani9746c472012-06-18 16:01:16 -07001305#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001306 !strcmp(it->useCase, SND_USE_CASE_VERB_FM_REC) ||
1307 !strcmp(it->useCase, SND_USE_CASE_VERB_FM_A2DP_REC) ||
1308#endif
1309 !strcmp(it->useCase, SND_USE_CASE_VERB_DL_REC) ||
1310 !strcmp(it->useCase, SND_USE_CASE_VERB_UL_DL_REC) ||
1311 !strcmp(it->useCase, SND_USE_CASE_VERB_INCALL_REC)) {
1312 snd_use_case_set(mUcMgr, "_verb", it->useCase);
1313 } else {
1314 snd_use_case_set(mUcMgr, "_enamod", it->useCase);
1315 }
1316 if(sampleRate) {
1317 it->sampleRate = *sampleRate;
1318 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001319#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001320 if (6 == it->channels) {
1321 if (!strncmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
1322 || !strncmp(it->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001323 ALOGV("OpenInoutStream: Use larger buffer size for 5.1(%s) recording ", it->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001324 it->bufferSize = getInputBufferSize(it->sampleRate,*format,it->channels);
1325 }
1326 }
1327#endif
1328 err = mALSADevice->open(&(*it));
1329 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001330 ALOGE("Error opening pcm input device");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001331 } else {
1332 in = new AudioStreamInALSA(this, &(*it), acoustics);
1333 err = in->set(format, channels, sampleRate, devices);
1334 }
1335 if (status) *status = err;
1336 return in;
1337 }
1338}
1339
1340void
1341AudioHardwareALSA::closeInputStream(AudioStreamIn* in)
1342{
1343 delete in;
1344}
1345
1346status_t AudioHardwareALSA::setMicMute(bool state)
1347{
1348 int newMode = mode();
Iliyan Malchev4113f342012-06-11 14:39:47 -07001349 ALOGD("setMicMute newMode %d",newMode);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001350 if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
1351 if (mVoipMicMute != state) {
1352 mVoipMicMute = state;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001353 ALOGD("setMicMute: mVoipMicMute %d", mVoipMicMute);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001354 if(mALSADevice) {
1355 mALSADevice->setVoipMicMute(state);
1356 }
1357 }
1358 } else {
1359 if (mMicMute != state) {
1360 mMicMute = state;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001361 ALOGD("setMicMute: mMicMute %d", mMicMute);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001362 if(mALSADevice) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001363 if(mCSCallActive == CS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -07001364 mALSADevice->setMicMute(state);
Ajay Dudani9746c472012-06-18 16:01:16 -07001365 if(mVolteCallActive == IMS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -07001366 mALSADevice->setVoLTEMicMute(state);
1367 }
1368 }
1369 }
1370 return NO_ERROR;
1371}
1372
1373status_t AudioHardwareALSA::getMicMute(bool *state)
1374{
1375 int newMode = mode();
1376 if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
1377 *state = mVoipMicMute;
1378 } else {
1379 *state = mMicMute;
1380 }
1381 return NO_ERROR;
1382}
1383
1384status_t AudioHardwareALSA::dump(int fd, const Vector<String16>& args)
1385{
1386 return NO_ERROR;
1387}
1388
1389size_t AudioHardwareALSA::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
1390{
1391 size_t bufferSize;
1392 if (format != AudioSystem::PCM_16_BIT
1393 && format != AudioSystem::AMR_NB
1394 && format != AudioSystem::AMR_WB
Ajay Dudani9746c472012-06-18 16:01:16 -07001395#ifdef QCOM_QCHAT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001396 && format != AudioSystem::EVRC
1397 && format != AudioSystem::EVRCB
Ajay Dudani9746c472012-06-18 16:01:16 -07001398 && format != AudioSystem::EVRCWB
1399#endif
1400 ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001401 ALOGW("getInputBufferSize bad format: %d", format);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001402 return 0;
1403 }
1404 if(sampleRate == 16000) {
1405 bufferSize = DEFAULT_IN_BUFFER_SIZE * 2 * channelCount;
1406 } else if(sampleRate < 44100) {
1407 bufferSize = DEFAULT_IN_BUFFER_SIZE * channelCount;
1408 } else {
1409 bufferSize = DEFAULT_IN_BUFFER_SIZE * 12;
1410 }
1411 return bufferSize;
1412}
1413
Ajay Dudani9746c472012-06-18 16:01:16 -07001414#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001415void AudioHardwareALSA::handleFm(int device)
1416{
1417int newMode = mode();
1418 if(device & AudioSystem::DEVICE_OUT_FM && mIsFmActive == 0) {
1419 // Start FM Radio on current active device
1420 unsigned long bufferSize = FM_BUFFER_SIZE;
1421 alsa_handle_t alsa_handle;
1422 char *use_case;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001423 ALOGV("Start FM");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001424 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1425 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1426 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DIGITAL_RADIO, sizeof(alsa_handle.useCase));
1427 } else {
1428 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_FM, sizeof(alsa_handle.useCase));
1429 }
1430 free(use_case);
1431
1432 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1433 bufferSize &= ~b;
1434 alsa_handle.module = mALSADevice;
1435 alsa_handle.bufferSize = bufferSize;
1436 alsa_handle.devices = device;
1437 alsa_handle.handle = 0;
1438 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1439 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
1440 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
1441 alsa_handle.latency = VOICE_LATENCY;
1442 alsa_handle.rxHandle = 0;
1443 alsa_handle.ucMgr = mUcMgr;
1444 mIsFmActive = 1;
1445 mDeviceList.push_back(alsa_handle);
1446 ALSAHandleList::iterator it = mDeviceList.end();
1447 it--;
1448 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1449 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1450 device |= AudioSystem::DEVICE_OUT_PROXY;
1451 alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001452 ALOGD("Routing to proxy for FM case");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001453 }
1454 mALSADevice->route(&(*it), (uint32_t)device, newMode);
1455 if(!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) {
1456 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_DIGITAL_RADIO);
1457 } else {
1458 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_FM);
1459 }
1460 mALSADevice->startFm(&(*it));
1461 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1462 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -07001463 ALOGD("Starting FM, musbPlaybackState %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001464 startUsbPlaybackIfNotStarted();
1465 musbPlaybackState |= USBPLAYBACKBIT_FM;
1466 }
1467 } else if (!(device & AudioSystem::DEVICE_OUT_FM) && mIsFmActive == 1) {
1468 //i Stop FM Radio
Iliyan Malchev4113f342012-06-11 14:39:47 -07001469 ALOGV("Stop FM");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001470 for(ALSAHandleList::iterator it = mDeviceList.begin();
1471 it != mDeviceList.end(); ++it) {
1472 if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
1473 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
1474 mALSADevice->close(&(*it));
1475 //mALSADevice->route(&(*it), (uint32_t)device, newMode);
1476 mDeviceList.erase(it);
1477 break;
1478 }
1479 }
1480 mIsFmActive = 0;
1481 musbPlaybackState &= ~USBPLAYBACKBIT_FM;
1482 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1483 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1484 closeUsbPlaybackIfNothingActive();
1485 }
1486 }
1487}
1488#endif
1489
1490void AudioHardwareALSA::disableVoiceCall(char* verb, char* modifier, int mode, int device)
1491{
1492 for(ALSAHandleList::iterator it = mDeviceList.begin();
1493 it != mDeviceList.end(); ++it) {
1494 if((!strcmp(it->useCase, verb)) ||
1495 (!strcmp(it->useCase, modifier))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001496 ALOGV("Disabling voice call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001497 mALSADevice->close(&(*it));
1498 mALSADevice->route(&(*it), (uint32_t)device, mode);
1499 mDeviceList.erase(it);
1500 break;
1501 }
1502 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001503#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001504 if(musbPlaybackState & USBPLAYBACKBIT_VOICECALL) {
SathishKumar Mani0a019912012-09-11 12:33:11 -07001505 ALOGD("Voice call ended on USB");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001506 musbPlaybackState &= ~USBPLAYBACKBIT_VOICECALL;
1507 musbRecordingState &= ~USBRECBIT_VOICECALL;
1508 closeUsbRecordingIfNothingActive();
1509 closeUsbPlaybackIfNothingActive();
1510 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001511#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001512}
1513void AudioHardwareALSA::enableVoiceCall(char* verb, char* modifier, int mode, int device)
1514{
1515// Start voice call
SathishKumar Mani018d1c52012-09-11 14:58:18 -07001516unsigned long bufferSize = DEFAULT_VOICE_BUFFER_SIZE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001517alsa_handle_t alsa_handle;
1518char *use_case;
1519 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1520 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1521 strlcpy(alsa_handle.useCase, verb, sizeof(alsa_handle.useCase));
1522 } else {
1523 strlcpy(alsa_handle.useCase, modifier, sizeof(alsa_handle.useCase));
1524 }
1525 free(use_case);
1526
1527 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1528 bufferSize &= ~b;
1529 alsa_handle.module = mALSADevice;
1530 alsa_handle.bufferSize = bufferSize;
1531 alsa_handle.devices = device;
1532 alsa_handle.handle = 0;
1533 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1534 alsa_handle.channels = VOICE_CHANNEL_MODE;
1535 alsa_handle.sampleRate = VOICE_SAMPLING_RATE;
1536 alsa_handle.latency = VOICE_LATENCY;
1537 alsa_handle.rxHandle = 0;
1538 alsa_handle.ucMgr = mUcMgr;
1539 mDeviceList.push_back(alsa_handle);
1540 ALSAHandleList::iterator it = mDeviceList.end();
1541 it--;
Ajay Dudani9746c472012-06-18 16:01:16 -07001542#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001543 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1544 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1545 device |= AudioSystem::DEVICE_OUT_PROXY;
1546 alsa_handle.devices = device;
1547 }
1548#endif
1549 mALSADevice->route(&(*it), (uint32_t)device, mode);
1550 if (!strcmp(it->useCase, verb)) {
1551 snd_use_case_set(mUcMgr, "_verb", verb);
1552 } else {
1553 snd_use_case_set(mUcMgr, "_enamod", modifier);
1554 }
1555 mALSADevice->startVoiceCall(&(*it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001556#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001557 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1558 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1559 startUsbRecordingIfNotStarted();
1560 startUsbPlaybackIfNotStarted();
1561 musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
1562 musbRecordingState |= USBRECBIT_VOICECALL;
1563 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001564#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001565}
1566
1567bool AudioHardwareALSA::routeVoiceCall(int device, int newMode)
1568{
1569int csCallState = mCallState&0xF;
1570 bool isRouted = false;
1571 switch (csCallState) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001572 case CS_INACTIVE:
1573 if (mCSCallActive != CS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001574 ALOGD("doRouting: Disabling voice call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001575 disableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
1576 (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
1577 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001578 mCSCallActive = CS_INACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001579 }
1580 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001581 case CS_ACTIVE:
1582 if (mCSCallActive == CS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001583 ALOGD("doRouting: Enabling CS voice call ");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001584 enableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
1585 (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
1586 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001587 mCSCallActive = CS_ACTIVE;
1588 } else if (mCSCallActive == CS_HOLD) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001589 ALOGD("doRouting: Resume voice call from hold state");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001590 ALSAHandleList::iterator vt_it;
1591 for(vt_it = mDeviceList.begin();
1592 vt_it != mDeviceList.end(); ++vt_it) {
1593 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
1594 strlen(SND_USE_CASE_VERB_VOICECALL))) ||
1595 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1596 strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
1597 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001598 mCSCallActive = CS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001599 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001600 ALOGE("VoLTE resume failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001601 break;
1602 }
1603 }
1604 }
1605 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001606 case CS_HOLD:
1607 if (mCSCallActive == CS_ACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001608 ALOGD("doRouting: Voice call going to Hold");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001609 ALSAHandleList::iterator vt_it;
1610 for(vt_it = mDeviceList.begin();
1611 vt_it != mDeviceList.end(); ++vt_it) {
1612 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
1613 strlen(SND_USE_CASE_VERB_VOICECALL))) ||
1614 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1615 strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001616 mCSCallActive = CS_HOLD;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001617 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1618 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001619 ALOGE("Voice pause failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001620 break;
1621 }
1622 }
1623 }
1624 break;
1625 }
1626 return isRouted;
1627}
1628bool AudioHardwareALSA::routeVoLTECall(int device, int newMode)
1629{
1630int volteCallState = mCallState&0xF0;
1631bool isRouted = false;
1632switch (volteCallState) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001633 case IMS_INACTIVE:
1634 if (mVolteCallActive != IMS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001635 ALOGD("doRouting: Disabling IMS call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001636 disableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
1637 (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
1638 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001639 mVolteCallActive = IMS_INACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001640 }
1641 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001642 case IMS_ACTIVE:
1643 if (mVolteCallActive == IMS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001644 ALOGD("doRouting: Enabling IMS voice call ");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001645 enableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
1646 (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
1647 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001648 mVolteCallActive = IMS_ACTIVE;
1649 } else if (mVolteCallActive == IMS_HOLD) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001650 ALOGD("doRouting: Resume IMS call from hold state");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001651 ALSAHandleList::iterator vt_it;
1652 for(vt_it = mDeviceList.begin();
1653 vt_it != mDeviceList.end(); ++vt_it) {
1654 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
1655 strlen(SND_USE_CASE_VERB_VOLTE))) ||
1656 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1657 strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
1658 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001659 mVolteCallActive = IMS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001660 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001661 ALOGE("VoLTE resume failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001662 break;
1663 }
1664 }
1665 }
1666 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001667 case IMS_HOLD:
1668 if (mVolteCallActive == IMS_ACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001669 ALOGD("doRouting: IMS ACTIVE going to HOLD");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001670 ALSAHandleList::iterator vt_it;
1671 for(vt_it = mDeviceList.begin();
1672 vt_it != mDeviceList.end(); ++vt_it) {
1673 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
1674 strlen(SND_USE_CASE_VERB_VOLTE))) ||
1675 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1676 strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001677 mVolteCallActive = IMS_HOLD;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001678 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1679 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001680 ALOGE("VoLTE Pause failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001681 break;
1682 }
1683 }
1684 }
1685 break;
1686 }
1687 return isRouted;
1688}
1689
1690} // namespace android_audio_legacy