blob: 508418ccd4b826c4ce76807b047ca518774b4746 [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
SathishKumar Manibf1c8742012-09-25 23:34:51 -070045#include "AudioUtil.h"
Iliyan Malchev4765c432012-06-11 14:36:16 -070046
Iliyan Malchev4765c432012-06-11 14:36:16 -070047extern "C"
48{
49 //
50 // Function for dlsym() to look up for creating a new AudioHardwareInterface.
51 //
52 android_audio_legacy::AudioHardwareInterface *createAudioHardware(void) {
53 return android_audio_legacy::AudioHardwareALSA::create();
54 }
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070055#ifdef QCOM_ACDB_ENABLED
56 static int (*acdb_init)();
57 static void (*acdb_deallocate)();
58#endif
59#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani29555932012-12-07 18:34:52 -080060 static int (*csd_client_init)();
61 static int (*csd_client_deinit)();
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070062 static int (*csd_start_playback)();
63 static int (*csd_stop_playback)();
64#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070065} // extern "C"
66
67namespace android_audio_legacy
68{
69
70// ----------------------------------------------------------------------------
71
72AudioHardwareInterface *AudioHardwareALSA::create() {
73 return new AudioHardwareALSA();
74}
75
76AudioHardwareALSA::AudioHardwareALSA() :
SathishKumar Mani6ccde102012-09-26 20:23:34 -070077 mALSADevice(0),mVoipStreamCount(0),mVoipBitRate(0)
78 ,mCallState(0),mAcdbHandle(NULL),mCsdHandle(NULL),mMicMute(0)
Iliyan Malchev4765c432012-06-11 14:36:16 -070079{
80 FILE *fp;
81 char soundCardInfo[200];
82 hw_module_t *module;
83 char platform[128], baseband[128];
84 int err = hw_get_module(ALSA_HARDWARE_MODULE_ID,
85 (hw_module_t const**)&module);
86 int codec_rev = 2;
Iliyan Malchev4113f342012-06-11 14:39:47 -070087 ALOGD("hw_get_module(ALSA_HARDWARE_MODULE_ID) returned err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -070088 if (err == 0) {
89 hw_device_t* device;
90 err = module->methods->open(module, ALSA_HARDWARE_NAME, &device);
91 if (err == 0) {
92 mALSADevice = (alsa_device_t *)device;
93 mALSADevice->init(mALSADevice, mDeviceList);
94 mCSCallActive = 0;
95 mVolteCallActive = 0;
96 mIsFmActive = 0;
97 mDevSettingsFlag = 0;
Ajay Dudani9746c472012-06-18 16:01:16 -070098#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -070099 mAudioUsbALSA = new AudioUsbALSA();
Ajay Dudani9746c472012-06-18 16:01:16 -0700100 musbPlaybackState = 0;
101 musbRecordingState = 0;
102#endif
ty.lee924f7982012-08-01 23:15:30 +0900103#ifdef USES_FLUENCE_INCALL
104 mDevSettingsFlag |= TTY_OFF | DMIC_FLAG;
105#else
Iliyan Malchev4765c432012-06-11 14:36:16 -0700106 mDevSettingsFlag |= TTY_OFF;
ty.lee924f7982012-08-01 23:15:30 +0900107#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700108 mBluetoothVGS = false;
109 mFusion3Platform = false;
Ajay Dudani9746c472012-06-18 16:01:16 -0700110
111#ifdef QCOM_ACDB_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700112 mAcdbHandle = ::dlopen("/system/lib/libacdbloader.so", RTLD_NOW);
113 if (mAcdbHandle == NULL) {
114 ALOGE("AudioHardware: DLOPEN not successful for ACDBLOADER");
115 } else {
116 ALOGD("AudioHardware: DLOPEN successful for ACDBLOADER");
117 acdb_init = (int (*)())::dlsym(mAcdbHandle,"acdb_loader_init_ACDB");
118 if (acdb_init == NULL) {
119 ALOGE("dlsym:Error:%s Loading acdb_loader_init_ACDB", dlerror());
120 }else {
121 acdb_init();
122 acdb_deallocate = (void (*)())::dlsym(mAcdbHandle,"acdb_loader_deallocate_ACDB");
123 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700124 }
125#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700126
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700127#ifdef QCOM_CSDCLIENT_ENABLED
128 mCsdHandle = ::dlopen("/system/lib/libcsd-client.so", RTLD_NOW);
129 if (mCsdHandle == NULL) {
130 ALOGE("AudioHardware: DLOPEN not successful for CSD CLIENT");
131 } else {
132 ALOGD("AudioHardware: DLOPEN successful for CSD CLIENT");
SathishKumar Mani29555932012-12-07 18:34:52 -0800133 csd_client_init = (int (*)())::dlsym(mCsdHandle,"csd_client_init");
134 csd_client_deinit = (int (*)())::dlsym(mCsdHandle,"csd_client_deinit");
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700135 csd_start_playback = (int (*)())::dlsym(mCsdHandle,"csd_client_start_playback");
136 csd_stop_playback = (int (*)())::dlsym(mCsdHandle,"csd_client_stop_playback");
SathishKumar Mani29555932012-12-07 18:34:52 -0800137
138 if (csd_client_init == NULL) {
139 ALOGE("dlsym: Error:%s Loading csd_client_init", dlerror());
140 } else {
141 csd_client_init();
142 }
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700143 }
144 mALSADevice->setCsdHandle(mCsdHandle);
145#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700146 if((fp = fopen("/proc/asound/cards","r")) == NULL) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700147 ALOGE("Cannot open /proc/asound/cards file to get sound card info");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700148 } else {
149 while((fgets(soundCardInfo, sizeof(soundCardInfo), fp) != NULL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700150 ALOGV("SoundCardInfo %s", soundCardInfo);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700151 if (strstr(soundCardInfo, "msm8960-tabla1x-snd-card")) {
152 codec_rev = 1;
153 break;
154 } else if (strstr(soundCardInfo, "msm-snd-card")) {
155 codec_rev = 2;
156 break;
157 } else if (strstr(soundCardInfo, "msm8930-sitar-snd-card")) {
158 codec_rev = 3;
159 break;
160 }
161 }
162 fclose(fp);
163 }
164
165 if (codec_rev == 1) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700166 ALOGV("Detected tabla 1.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700167 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm");
168 } else if (codec_rev == 3) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700169 ALOGV("Detected sitar 1.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700170 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_Sitar");
171 } else {
172 property_get("ro.board.platform", platform, "");
173 property_get("ro.baseband", baseband, "");
174 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700175 ALOGV("Detected Fusion tabla 2.x");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700176 mFusion3Platform = true;
177 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x_Fusion3");
178 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700179 ALOGV("Detected tabla 2.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700180 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x");
181 }
182 }
183
184 if (mUcMgr < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700185 ALOGE("Failed to open ucm instance: %d", errno);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700186 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700187 ALOGI("ucm instance opened: %u", (unsigned)mUcMgr);
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700188 mUcMgr->acdb_handle = NULL;
189#ifdef QCOM_ACDB_ENABLED
190 if (mAcdbHandle) {
191 mUcMgr->acdb_handle = static_cast<void*> (mAcdbHandle);
SathishKumar Mani29555932012-12-07 18:34:52 -0800192 if (mFusion3Platform)
193 mUcMgr->isFusion3Platform = true;
194 else
195 mUcMgr->isFusion3Platform = false;
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700196 }
197#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700198 }
199 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700200 ALOGE("ALSA Module could not be opened!!!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700201 }
202 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700203 ALOGE("ALSA Module not found!!!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700204 }
205}
206
207AudioHardwareALSA::~AudioHardwareALSA()
208{
209 if (mUcMgr != NULL) {
SathishKumar Mani9efed762012-09-18 18:52:48 -0700210 ALOGV("closing ucm instance: %u", (unsigned)mUcMgr);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700211 snd_use_case_mgr_close(mUcMgr);
212 }
213 if (mALSADevice) {
214 mALSADevice->common.close(&mALSADevice->common);
215 }
216 for(ALSAHandleList::iterator it = mDeviceList.begin();
217 it != mDeviceList.end(); ++it) {
218 it->useCase[0] = 0;
219 mDeviceList.erase(it);
220 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700221#ifdef QCOM_ACDB_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700222 if (acdb_deallocate == NULL) {
223 ALOGE("dlsym: Error:%s Loading acdb_deallocate_ACDB", dlerror());
224 } else {
225 acdb_deallocate();
226 }
227 if (mAcdbHandle) {
228 ::dlclose(mAcdbHandle);
229 mAcdbHandle = NULL;
230 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700231#endif
232#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700233 delete mAudioUsbALSA;
Ajay Dudani9746c472012-06-18 16:01:16 -0700234#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700235
236#ifdef QCOM_CSDCLEINT_ENABLED
237 if (mCsdHandle) {
SathishKumar Mani29555932012-12-07 18:34:52 -0800238 if (csd_client_deinit == NULL) {
239 ALOGE("dlsym: Error:%s Loading csd_client_deinit", dlerror());
240 } else {
241 csd_client_deinit();
242 }
243 ::dlclose(mCsdHandle);
244 mCsdHandle = NULL;
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700245 }
246#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700247}
248
249status_t AudioHardwareALSA::initCheck()
250{
251 if (!mALSADevice)
252 return NO_INIT;
253
254 return NO_ERROR;
255}
256
257status_t AudioHardwareALSA::setVoiceVolume(float v)
258{
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700259 ALOGV("setVoiceVolume(%f)\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700260 if (v < 0.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700261 ALOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700262 v = 0.0;
263 } else if (v > 1.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700264 ALOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700265 v = 1.0;
266 }
267
268 int newMode = mode();
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700269 ALOGV("setVoiceVolume newMode %d",newMode);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700270 int vol = lrint(v * 100.0);
271
272 // Voice volume levels from android are mapped to driver volume levels as follows.
273 // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
274 // So adjust the volume to get the correct volume index in driver
275 vol = 100 - vol;
276
277 if (mALSADevice) {
278 if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
279 mALSADevice->setVoipVolume(vol);
280 } else if (newMode == AudioSystem::MODE_IN_CALL){
Ajay Dudani9746c472012-06-18 16:01:16 -0700281 if (mCSCallActive == CS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700282 mALSADevice->setVoiceVolume(vol);
Ajay Dudani9746c472012-06-18 16:01:16 -0700283 if (mVolteCallActive == IMS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700284 mALSADevice->setVoLTEVolume(vol);
285 }
286 }
287
288 return NO_ERROR;
289}
290
Ajay Dudani9746c472012-06-18 16:01:16 -0700291#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700292status_t AudioHardwareALSA::setFmVolume(float value)
293{
294 status_t status = NO_ERROR;
295
296 int vol;
297
298 if (value < 0.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700299 ALOGW("setFmVolume(%f) under 0.0, assuming 0.0\n", value);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700300 value = 0.0;
301 } else if (value > 1.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700302 ALOGW("setFmVolume(%f) over 1.0, assuming 1.0\n", value);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700303 value = 1.0;
304 }
305 vol = lrint((value * 0x2000) + 0.5);
306
SathishKumar Mani9efed762012-09-18 18:52:48 -0700307 ALOGV("setFmVolume(%f)\n", value);
308 ALOGV("Setting FM volume to %d (available range is 0 to 0x2000)\n", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700309
310 mALSADevice->setFmVolume(vol);
311
312 return status;
313}
314#endif
315
316status_t AudioHardwareALSA::setMasterVolume(float volume)
317{
318 return NO_ERROR;
319}
320
321status_t AudioHardwareALSA::setMode(int mode)
322{
323 status_t status = NO_ERROR;
324
325 if (mode != mMode) {
326 status = AudioHardwareBase::setMode(mode);
327 }
328
329 if (mode == AudioSystem::MODE_IN_CALL) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700330 mCallState = CS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700331 }else if (mode == AudioSystem::MODE_NORMAL) {
332 mCallState = 0;
333 }
334
335 return status;
336}
337
338status_t AudioHardwareALSA::setParameters(const String8& keyValuePairs)
339{
340 AudioParameter param = AudioParameter(keyValuePairs);
341 String8 key;
342 String8 value;
343 status_t status = NO_ERROR;
344 int device;
345 int btRate;
346 int state;
SathishKumar Mani9efed762012-09-18 18:52:48 -0700347 ALOGV("setParameters() %s", keyValuePairs.string());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700348
349 key = String8(TTY_MODE_KEY);
350 if (param.get(key, value) == NO_ERROR) {
351 mDevSettingsFlag &= TTY_CLEAR;
ty.leea97e6f62012-08-15 10:11:50 +0900352 if (value == "tty_full") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700353 mDevSettingsFlag |= TTY_FULL;
ty.leea97e6f62012-08-15 10:11:50 +0900354 } else if (value == "tty_hco") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700355 mDevSettingsFlag |= TTY_HCO;
ty.leea97e6f62012-08-15 10:11:50 +0900356 } else if (value == "tty_vco") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700357 mDevSettingsFlag |= TTY_VCO;
358 } else {
359 mDevSettingsFlag |= TTY_OFF;
360 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700361 ALOGI("Changed TTY Mode=%s", value.string());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700362 mALSADevice->setFlags(mDevSettingsFlag);
363 if(mMode != AudioSystem::MODE_IN_CALL){
364 return NO_ERROR;
365 }
366 doRouting(0);
367 }
368
369 key = String8(FLUENCE_KEY);
370 if (param.get(key, value) == NO_ERROR) {
371 if (value == "quadmic") {
372 mDevSettingsFlag |= QMIC_FLAG;
373 mDevSettingsFlag &= (~DMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700374 ALOGV("Fluence quadMic feature Enabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700375 } else if (value == "dualmic") {
376 mDevSettingsFlag |= DMIC_FLAG;
377 mDevSettingsFlag &= (~QMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700378 ALOGV("Fluence dualmic feature Enabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700379 } else if (value == "none") {
380 mDevSettingsFlag &= (~DMIC_FLAG);
381 mDevSettingsFlag &= (~QMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700382 ALOGV("Fluence feature Disabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700383 }
384 mALSADevice->setFlags(mDevSettingsFlag);
385 doRouting(0);
386 }
387
Ajay Dudani9746c472012-06-18 16:01:16 -0700388#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700389 if (mFusion3Platform) {
390 key = String8(INCALLMUSIC_KEY);
391 if (param.get(key, value) == NO_ERROR) {
392 if (value == "true") {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700393 ALOGV("Enabling Incall Music setting in the setparameter\n");
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700394 if (csd_start_playback == NULL) {
395 ALOGE("dlsym: Error:%s Loading csd_client_start_playback", dlerror());
396 } else {
397 csd_start_playback();
398 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700399 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700400 ALOGV("Disabling Incall Music setting in the setparameter\n");
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700401 if (csd_stop_playback == NULL) {
402 ALOGE("dlsym: Error:%s Loading csd_client_stop_playback", dlerror());
403 } else {
404 csd_stop_playback();
405 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700406 }
407 }
408 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700409#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700410
411 key = String8(ANC_KEY);
412 if (param.get(key, value) == NO_ERROR) {
413 if (value == "true") {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700414 ALOGV("Enabling ANC setting in the setparameter\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700415 mDevSettingsFlag |= ANC_FLAG;
416 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700417 ALOGV("Disabling ANC setting in the setparameter\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700418 mDevSettingsFlag &= (~ANC_FLAG);
419 }
420 mALSADevice->setFlags(mDevSettingsFlag);
421 doRouting(0);
422 }
423
424 key = String8(AudioParameter::keyRouting);
425 if (param.getInt(key, device) == NO_ERROR) {
426 // Ignore routing if device is 0.
427 if(device) {
428 doRouting(device);
429 }
430 param.remove(key);
431 }
432
433 key = String8(BT_SAMPLERATE_KEY);
434 if (param.getInt(key, btRate) == NO_ERROR) {
435 mALSADevice->setBtscoRate(btRate);
436 param.remove(key);
437 }
438
439 key = String8(BTHEADSET_VGS);
440 if (param.get(key, value) == NO_ERROR) {
441 if (value == "on") {
442 mBluetoothVGS = true;
443 } else {
444 mBluetoothVGS = false;
445 }
446 }
447
448 key = String8(WIDEVOICE_KEY);
449 if (param.get(key, value) == NO_ERROR) {
450 bool flag = false;
451 if (value == "true") {
452 flag = true;
453 }
454 if(mALSADevice) {
455 mALSADevice->enableWideVoice(flag);
456 }
457 param.remove(key);
458 }
459
460 key = String8(VOIPRATE_KEY);
461 if (param.get(key, value) == NO_ERROR) {
462 mVoipBitRate = atoi(value);
463 param.remove(key);
464 }
465
466 key = String8(FENS_KEY);
467 if (param.get(key, value) == NO_ERROR) {
468 bool flag = false;
469 if (value == "true") {
470 flag = true;
471 }
472 if(mALSADevice) {
473 mALSADevice->enableFENS(flag);
474 }
475 param.remove(key);
476 }
477
Ajay Dudani9746c472012-06-18 16:01:16 -0700478#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700479 key = String8(AudioParameter::keyHandleFm);
480 if (param.getInt(key, device) == NO_ERROR) {
481 // Ignore if device is 0
482 if(device) {
483 handleFm(device);
484 }
485 param.remove(key);
486 }
487#endif
488
489 key = String8(ST_KEY);
490 if (param.get(key, value) == NO_ERROR) {
491 bool flag = false;
492 if (value == "true") {
493 flag = true;
494 }
495 if(mALSADevice) {
496 mALSADevice->enableSlowTalk(flag);
497 }
498 param.remove(key);
499 }
500 key = String8(MODE_CALL_KEY);
501 if (param.getInt(key,state) == NO_ERROR) {
502 if (mCallState != state) {
503 mCallState = state;
504 doRouting(0);
505 }
506 mCallState = state;
507 }
508 if (param.size()) {
509 status = BAD_VALUE;
510 }
511 return status;
512}
513
514String8 AudioHardwareALSA::getParameters(const String8& keys)
515{
516 AudioParameter param = AudioParameter(keys);
517 String8 value;
518
519 String8 key = String8(DUALMIC_KEY);
520 if (param.get(key, value) == NO_ERROR) {
521 value = String8("false");
522 param.add(key, value);
523 }
524
525 key = String8(FLUENCE_KEY);
526 if (param.get(key, value) == NO_ERROR) {
527 if ((mDevSettingsFlag & QMIC_FLAG) &&
528 (mDevSettingsFlag & ~DMIC_FLAG))
529 value = String8("quadmic");
530 else if ((mDevSettingsFlag & DMIC_FLAG) &&
531 (mDevSettingsFlag & ~QMIC_FLAG))
532 value = String8("dualmic");
533 else if ((mDevSettingsFlag & ~DMIC_FLAG) &&
534 (mDevSettingsFlag & ~QMIC_FLAG))
535 value = String8("none");
536 param.add(key, value);
537 }
538
Ajay Dudani9746c472012-06-18 16:01:16 -0700539#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700540 key = String8("Fm-radio");
541 if ( param.get(key,value) == NO_ERROR ) {
542 if ( mIsFmActive ) {
543 param.addInt(String8("isFMON"), true );
544 }
545 }
546#endif
547
548 key = String8(BTHEADSET_VGS);
549 if (param.get(key, value) == NO_ERROR) {
550 if(mBluetoothVGS)
551 param.addInt(String8("isVGS"), true);
552 }
553
Iliyan Malchev4113f342012-06-11 14:39:47 -0700554 ALOGV("AudioHardwareALSA::getParameters() %s", param.toString().string());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700555 return param.toString();
556}
557
Ajay Dudani9746c472012-06-18 16:01:16 -0700558#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700559void AudioHardwareALSA::closeUSBPlayback()
560{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700561 ALOGV("closeUSBPlayback, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700562 musbPlaybackState = 0;
563 mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_KILLTHREAD);
564}
565
566void AudioHardwareALSA::closeUSBRecording()
567{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700568 ALOGV("closeUSBRecording");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700569 musbRecordingState = 0;
570 mAudioUsbALSA->exitRecordingThread(SIGNAL_EVENT_KILLTHREAD);
571}
572
573void AudioHardwareALSA::closeUsbPlaybackIfNothingActive(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700574 ALOGV("closeUsbPlaybackIfNothingActive, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700575 if(!musbPlaybackState && mAudioUsbALSA != NULL) {
576 mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_TIMEOUT);
577 }
578}
579
580void AudioHardwareALSA::closeUsbRecordingIfNothingActive(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700581 ALOGV("closeUsbRecordingIfNothingActive, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700582 if(!musbRecordingState && mAudioUsbALSA != NULL) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700583 ALOGD("Closing USB Recording Session as no stream is active");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700584 mAudioUsbALSA->setkillUsbRecordingThread(true);
585 }
586}
587
588void AudioHardwareALSA::startUsbPlaybackIfNotStarted(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700589 ALOGV("Starting the USB playback %d kill %d", musbPlaybackState,
Iliyan Malchev4765c432012-06-11 14:36:16 -0700590 mAudioUsbALSA->getkillUsbPlaybackThread());
591 if((!musbPlaybackState) || (mAudioUsbALSA->getkillUsbPlaybackThread() == true)) {
592 mAudioUsbALSA->startPlayback();
593 }
594}
595
596void AudioHardwareALSA::startUsbRecordingIfNotStarted(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700597 ALOGV("Starting the recording musbRecordingState: %d killUsbRecordingThread %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700598 musbRecordingState, mAudioUsbALSA->getkillUsbRecordingThread());
599 if((!musbRecordingState) || (mAudioUsbALSA->getkillUsbRecordingThread() == true)) {
600 mAudioUsbALSA->startRecording();
601 }
602}
Ajay Dudani9746c472012-06-18 16:01:16 -0700603#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700604
605void AudioHardwareALSA::doRouting(int device)
606{
607 Mutex::Autolock autoLock(mLock);
608 int newMode = mode();
609 bool isRouted = false;
610
Ajay Dudani9746c472012-06-18 16:01:16 -0700611 if ((device == AudioSystem::DEVICE_IN_VOICE_CALL)
612#ifdef QCOM_FM_ENABLED
613 || (device == AudioSystem::DEVICE_IN_FM_RX)
614 || (device == AudioSystem::DEVICE_OUT_DIRECTOUTPUT)
615 || (device == AudioSystem::DEVICE_IN_FM_RX_A2DP)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700616#endif
Ajay Dudani9746c472012-06-18 16:01:16 -0700617 || (device == AudioSystem::DEVICE_IN_COMMUNICATION)
618 ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700619 ALOGV("Ignoring routing for FM/INCALL/VOIP recording");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700620 return;
621 }
622 if (device == 0)
623 device = mCurDevice;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700624 ALOGV("doRouting: device %d newMode %d mCSCallActive %d mVolteCallActive %d"
Iliyan Malchev4765c432012-06-11 14:36:16 -0700625 "mIsFmActive %d", device, newMode, mCSCallActive, mVolteCallActive,
626 mIsFmActive);
627
628 isRouted = routeVoLTECall(device, newMode);
629 isRouted |= routeVoiceCall(device, newMode);
630
631 if(!isRouted) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700632#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700633 if(!(device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) &&
634 !(device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET) &&
635 !(device & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) &&
636 (musbPlaybackState)){
637 //USB unplugged
638 device &= ~ AudioSystem::DEVICE_OUT_PROXY;
639 device &= ~ AudioSystem::DEVICE_IN_PROXY;
640 ALSAHandleList::iterator it = mDeviceList.end();
641 it--;
642 mALSADevice->route(&(*it), (uint32_t)device, newMode);
SathishKumar Mani0a019912012-09-11 12:33:11 -0700643 ALOGD("USB UNPLUGGED, setting musbPlaybackState to 0");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700644 musbPlaybackState = 0;
645 musbRecordingState = 0;
646 closeUSBRecording();
647 closeUSBPlayback();
648 } else if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
649 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -0700650 ALOGD("Routing everything to prox now");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700651 ALSAHandleList::iterator it = mDeviceList.end();
652 it--;
653 mALSADevice->route(&(*it), AudioSystem::DEVICE_OUT_PROXY,
654 newMode);
655 for(it = mDeviceList.begin(); it != mDeviceList.end(); ++it) {
656 if((!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
657 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_LPA))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700658 ALOGV("doRouting: LPA device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700659 startUsbPlaybackIfNotStarted();
660 musbPlaybackState |= USBPLAYBACKBIT_LPA;
661 break;
662 } else if((!strcmp(it->useCase, SND_USE_CASE_VERB_VOICECALL)) ||
663 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOICE))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700664 ALOGV("doRouting: VOICE device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700665 startUsbRecordingIfNotStarted();
666 startUsbPlaybackIfNotStarted();
667 musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
668 musbRecordingState |= USBPLAYBACKBIT_VOICECALL;
669 break;
670 }else if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
671 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700672 ALOGV("doRouting: FM device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700673 startUsbPlaybackIfNotStarted();
674 musbPlaybackState |= USBPLAYBACKBIT_FM;
675 break;
676 }
677 }
SathishKumar Manie42406e2012-08-29 16:25:54 -0700678 } else
Iliyan Malchev4765c432012-06-11 14:36:16 -0700679#endif
SathishKumar Manie42406e2012-08-29 16:25:54 -0700680 {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700681 ALSAHandleList::iterator it = mDeviceList.end();
682 it--;
683 mALSADevice->route(&(*it), (uint32_t)device, newMode);
684 }
685 }
686 mCurDevice = device;
687}
688
689uint32_t AudioHardwareALSA::getVoipMode(int format)
690{
691 switch(format) {
692 case AudioSystem::PCM_16_BIT:
693 return MODE_PCM;
694 break;
695 case AudioSystem::AMR_NB:
696 return MODE_AMR;
697 break;
698 case AudioSystem::AMR_WB:
699 return MODE_AMR_WB;
700 break;
701
Ajay Dudani9746c472012-06-18 16:01:16 -0700702#ifdef QCOM_QCHAT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700703 case AudioSystem::EVRC:
704 return MODE_IS127;
705 break;
706
707 case AudioSystem::EVRCB:
708 return MODE_4GV_NB;
709 break;
710 case AudioSystem::EVRCWB:
711 return MODE_4GV_WB;
712 break;
Ajay Dudani9746c472012-06-18 16:01:16 -0700713#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700714
715 default:
716 return MODE_PCM;
717 }
718}
719
720AudioStreamOut *
721AudioHardwareALSA::openOutputStream(uint32_t devices,
722 int *format,
723 uint32_t *channels,
724 uint32_t *sampleRate,
725 status_t *status)
726{
727 Mutex::Autolock autoLock(mLock);
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700728 ALOGV("openOutputStream: devices 0x%x channels %d sampleRate %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700729 devices, *channels, *sampleRate);
730
SathishKumar Mani88613382012-08-13 18:40:18 -0700731 audio_output_flags_t flag = static_cast<audio_output_flags_t> (*status);
732
Iliyan Malchev4765c432012-06-11 14:36:16 -0700733 status_t err = BAD_VALUE;
SathishKumar Mani88613382012-08-13 18:40:18 -0700734 *status = NO_ERROR;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700735 AudioStreamOutALSA *out = 0;
736 ALSAHandleList::iterator it;
737
738 if (devices & (devices - 1)) {
739 if (status) *status = err;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700740 ALOGE("openOutputStream called with bad devices");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700741 return out;
742 }
SathishKumar Mani88613382012-08-13 18:40:18 -0700743
744
Iliyan Malchev4765c432012-06-11 14:36:16 -0700745# if 0
746 if((devices == AudioSystem::DEVICE_OUT_DIRECTOUTPUT) &&
747 ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
748 bool voipstream_active = false;
749 for(it = mDeviceList.begin();
750 it != mDeviceList.end(); ++it) {
751 if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
752 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700753 ALOGD("openOutput: it->rxHandle %d it->handle %d",it->rxHandle,it->handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700754 voipstream_active = true;
755 break;
756 }
757 }
758 if(voipstream_active == false) {
759 mVoipStreamCount = 0;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700760 alsa_handle_t alsa_handle;
761 unsigned long bufferSize;
762 if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
763 bufferSize = VOIP_BUFFER_SIZE_8K;
764 }
765 else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
766 bufferSize = VOIP_BUFFER_SIZE_16K;
767 }
768 else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700769 ALOGE("unsupported samplerate %d for voip",*sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700770 if (status) *status = err;
771 return out;
772 }
773 alsa_handle.module = mALSADevice;
774 alsa_handle.bufferSize = bufferSize;
775 alsa_handle.devices = devices;
776 alsa_handle.handle = 0;
777 if(*format == AudioSystem::PCM_16_BIT)
778 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
779 else
780 alsa_handle.format = *format;
781 alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
Eric Laurent61f44982013-01-17 18:21:59 -0800782 alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700783 alsa_handle.sampleRate = *sampleRate;
784 alsa_handle.latency = VOIP_PLAYBACK_LATENCY;
785 alsa_handle.rxHandle = 0;
786 alsa_handle.ucMgr = mUcMgr;
787 mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
788 char *use_case;
789 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
790 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
791 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
792 } else {
793 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
794 }
795 free(use_case);
796 mDeviceList.push_back(alsa_handle);
797 it = mDeviceList.end();
798 it--;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700799 ALOGV("openoutput: mALSADevice->route useCase %s mCurDevice %d mVoipStreamCount %d mode %d", it->useCase,mCurDevice,mVoipStreamCount, mode());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700800 if((mCurDevice & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
801 (mCurDevice & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)||
802 (mCurDevice & AudioSystem::DEVICE_OUT_PROXY)){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700803 ALOGD("Routing to proxy for normal voip call in openOutputStream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700804 mCurDevice |= AudioSystem::DEVICE_OUT_PROXY;
805 alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
806 mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700807 ALOGD("enabling VOIP in openoutputstream, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700808 startUsbPlaybackIfNotStarted();
809 musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700810 ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700811 startUsbRecordingIfNotStarted();
812 musbRecordingState |= USBRECBIT_VOIPCALL;
813 } else{
814 mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
815 }
816 if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
817 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
818 } else {
819 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
820 }
821 err = mALSADevice->startVoipCall(&(*it));
822 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700823 ALOGE("Device open failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700824 return NULL;
825 }
826 }
827 out = new AudioStreamOutALSA(this, &(*it));
828 err = out->set(format, channels, sampleRate, devices);
829 if(err == NO_ERROR) {
830 mVoipStreamCount++; //increment VoipstreamCount only if success
Iliyan Malchev4113f342012-06-11 14:39:47 -0700831 ALOGD("openoutput mVoipStreamCount %d",mVoipStreamCount);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700832 }
833 if (status) *status = err;
834 return out;
835 } else
836#endif
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700837 if ((flag & AUDIO_OUTPUT_FLAG_DIRECT) &&
838 (devices == AudioSystem::DEVICE_OUT_AUX_DIGITAL)) {
839 ALOGD("Multi channel PCM");
840 alsa_handle_t alsa_handle;
841 EDID_AUDIO_INFO info = { 0 };
842
843 alsa_handle.module = mALSADevice;
844 alsa_handle.devices = devices;
845 alsa_handle.handle = 0;
846 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
847
848 if (!AudioUtil::getHDMIAudioSinkCaps(&info)) {
849 ALOGE("openOutputStream: Failed to get HDMI sink capabilities");
850 return NULL;
851 }
852 if (0 == *channels) {
853 alsa_handle.channels = info.AudioBlocksArray[info.nAudioBlocks-1].nChannels;
854 if (alsa_handle.channels > 6) {
855 alsa_handle.channels = 6;
856 }
857 *channels = audio_channel_out_mask_from_count(alsa_handle.channels);
858 } else {
859 alsa_handle.channels = AudioSystem::popCount(*channels);
860 }
Eric Laurent61f44982013-01-17 18:21:59 -0800861 alsa_handle.channelMask = *channels;
862
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700863 if (6 == alsa_handle.channels) {
864 alsa_handle.bufferSize = DEFAULT_MULTI_CHANNEL_BUF_SIZE;
865 } else {
866 alsa_handle.bufferSize = DEFAULT_BUFFER_SIZE;
867 }
868 if (0 == *sampleRate) {
869 alsa_handle.sampleRate = info.AudioBlocksArray[info.nAudioBlocks-1].nSamplingFreq;
870 *sampleRate = alsa_handle.sampleRate;
871 } else {
872 alsa_handle.sampleRate = *sampleRate;
873 }
874 alsa_handle.latency = PLAYBACK_LATENCY;
875 alsa_handle.rxHandle = 0;
876 alsa_handle.ucMgr = mUcMgr;
877 ALOGD("alsa_handle.channels %d alsa_handle.sampleRate %d",alsa_handle.channels,alsa_handle.sampleRate);
878
879 char *use_case;
880 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
881 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
882 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI2 , sizeof(alsa_handle.useCase));
883 } else {
884 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC2, sizeof(alsa_handle.useCase));
885 }
886 free(use_case);
887 mDeviceList.push_back(alsa_handle);
888 ALSAHandleList::iterator it = mDeviceList.end();
889 it--;
890 ALOGD("it->useCase %s", it->useCase);
891 mALSADevice->route(&(*it), devices, mode());
892 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI2)) {
893 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI2 );
894 } else {
895 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC2);
896 }
897 ALOGD("channels: %d", AudioSystem::popCount(*channels));
898 err = mALSADevice->open(&(*it));
899
900 if (err) {
901 ALOGE("Device open failed err:%d",err);
902 } else {
903 out = new AudioStreamOutALSA(this, &(*it));
904 err = out->set(format, channels, sampleRate, devices);
905 }
906 if (status) *status = err;
907 return out;
908 } else {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700909
910 alsa_handle_t alsa_handle;
911 unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
912
913 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
914 bufferSize &= ~b;
915
916 alsa_handle.module = mALSADevice;
917 alsa_handle.bufferSize = bufferSize;
918 alsa_handle.devices = devices;
919 alsa_handle.handle = 0;
920 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
921 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
Eric Laurent61f44982013-01-17 18:21:59 -0800922 alsa_handle.channelMask = AUDIO_CHANNEL_OUT_STEREO;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700923 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
924 alsa_handle.latency = PLAYBACK_LATENCY;
925 alsa_handle.rxHandle = 0;
926 alsa_handle.ucMgr = mUcMgr;
SathishKumar Mani88613382012-08-13 18:40:18 -0700927 alsa_handle.isDeepbufferOutput = false;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700928
929 char *use_case;
930 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
SathishKumar Mani88613382012-08-13 18:40:18 -0700931
932 if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
SathishKumar Mani9efed762012-09-18 18:52:48 -0700933 ALOGD("openOutputStream: DeepBuffer Output");
SathishKumar Mani88613382012-08-13 18:40:18 -0700934 alsa_handle.isDeepbufferOutput = true;
935 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
936 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI, sizeof(alsa_handle.useCase));
937 } else {
938 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC, sizeof(alsa_handle.useCase));
939 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700940 } else {
SathishKumar Mani9efed762012-09-18 18:52:48 -0700941 ALOGD("openOutputStream: Lowlatency Output");
SathishKumar Mani88613382012-08-13 18:40:18 -0700942 alsa_handle.bufferSize = PLAYBACK_LOW_LATENCY_BUFFER_SIZE;
SathishKumar Mani77780382012-09-21 20:58:33 -0700943 alsa_handle.latency = PLAYBACK_LOW_LATENCY_MEASURED;
SathishKumar Mani88613382012-08-13 18:40:18 -0700944 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
945 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
946 } else {
947 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
948 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700949 }
950 free(use_case);
951 mDeviceList.push_back(alsa_handle);
952 ALSAHandleList::iterator it = mDeviceList.end();
953 it--;
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700954 ALOGV("useCase %s", it->useCase);
Ajay Dudani9746c472012-06-18 16:01:16 -0700955#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700956 if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
957 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -0700958 ALOGD("Routing to proxy for normal playback in openOutputStream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700959 devices |= AudioSystem::DEVICE_OUT_PROXY;
960 }
961#endif
962 mALSADevice->route(&(*it), devices, mode());
SathishKumar Mani88613382012-08-13 18:40:18 -0700963 if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
964 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI)) {
965 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI);
966 } else {
967 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC);
968 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700969 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -0700970 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) {
971 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC);
972 } else {
973 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC);
974 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700975 }
976 err = mALSADevice->open(&(*it));
977 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700978 ALOGE("Device open failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700979 } else {
980 out = new AudioStreamOutALSA(this, &(*it));
981 err = out->set(format, channels, sampleRate, devices);
982 }
983
984 if (status) *status = err;
985 return out;
986 }
987}
988
989void
990AudioHardwareALSA::closeOutputStream(AudioStreamOut* out)
991{
992 delete out;
993}
994
Ajay Dudani9746c472012-06-18 16:01:16 -0700995#ifdef QCOM_TUNNEL_LPA_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700996AudioStreamOut *
997AudioHardwareALSA::openOutputSession(uint32_t devices,
998 int *format,
999 status_t *status,
1000 int sessionId,
1001 uint32_t samplingRate,
1002 uint32_t channels)
1003{
1004 Mutex::Autolock autoLock(mLock);
Iliyan Malchev4113f342012-06-11 14:39:47 -07001005 ALOGD("openOutputSession = %d" ,sessionId);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001006 AudioStreamOutALSA *out = 0;
1007 status_t err = BAD_VALUE;
1008
1009 alsa_handle_t alsa_handle;
1010 unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
1011
1012 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1013 bufferSize &= ~b;
1014
1015 alsa_handle.module = mALSADevice;
1016 alsa_handle.bufferSize = bufferSize;
1017 alsa_handle.devices = devices;
1018 alsa_handle.handle = 0;
1019 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1020 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
Eric Laurent61f44982013-01-17 18:21:59 -08001021 alsa_handle.channelMask = AUDIO_CHANNEL_OUT_STEREO;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001022 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
1023 alsa_handle.latency = VOICE_LATENCY;
1024 alsa_handle.rxHandle = 0;
1025 alsa_handle.ucMgr = mUcMgr;
1026
1027 char *use_case;
1028 if(sessionId == TUNNEL_SESSION_ID) {
1029 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1030 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1031 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_TUNNEL, sizeof(alsa_handle.useCase));
1032 } else {
1033 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_TUNNEL, sizeof(alsa_handle.useCase));
1034 }
1035 } else {
1036 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1037 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1038 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER, sizeof(alsa_handle.useCase));
1039 } else {
1040 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LPA, sizeof(alsa_handle.useCase));
1041 }
1042 }
1043 free(use_case);
1044 mDeviceList.push_back(alsa_handle);
1045 ALSAHandleList::iterator it = mDeviceList.end();
1046 it--;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001047 ALOGD("useCase %s", it->useCase);
Ajay Dudani9746c472012-06-18 16:01:16 -07001048#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001049 if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1050 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -07001051 ALOGD("Routing to proxy for LPA in openOutputSession");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001052 devices |= AudioSystem::DEVICE_OUT_PROXY;
1053 mALSADevice->route(&(*it), devices, mode());
1054 devices = AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001055 ALOGD("Starting USBPlayback for LPA");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001056 startUsbPlaybackIfNotStarted();
1057 musbPlaybackState |= USBPLAYBACKBIT_LPA;
1058 } else
1059#endif
1060 {
1061 mALSADevice->route(&(*it), devices, mode());
1062 }
1063 if(sessionId == TUNNEL_SESSION_ID) {
1064 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) {
1065 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_TUNNEL);
1066 } else {
1067 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_TUNNEL);
1068 }
1069 }
1070 else {
1071 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) {
1072 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOW_POWER);
1073 } else {
1074 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LPA);
1075 }
1076 }
1077 err = mALSADevice->open(&(*it));
1078 out = new AudioStreamOutALSA(this, &(*it));
1079
1080 if (status) *status = err;
1081 return out;
1082}
1083
1084void
1085AudioHardwareALSA::closeOutputSession(AudioStreamOut* out)
1086{
1087 delete out;
1088}
Ajay Dudani9746c472012-06-18 16:01:16 -07001089#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001090
1091AudioStreamIn *
1092AudioHardwareALSA::openInputStream(uint32_t devices,
1093 int *format,
1094 uint32_t *channels,
1095 uint32_t *sampleRate,
1096 status_t *status,
1097 AudioSystem::audio_in_acoustics acoustics)
1098{
1099 Mutex::Autolock autoLock(mLock);
1100 char *use_case;
1101 int newMode = mode();
1102 uint32_t route_devices;
1103
1104 status_t err = BAD_VALUE;
1105 AudioStreamInALSA *in = 0;
1106 ALSAHandleList::iterator it;
1107
Iliyan Malchev4113f342012-06-11 14:39:47 -07001108 ALOGD("openInputStream: devices 0x%x channels %d sampleRate %d", devices, *channels, *sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001109 if (devices & (devices - 1)) {
1110 if (status) *status = err;
1111 return in;
1112 }
1113
1114 if((devices == AudioSystem::DEVICE_IN_COMMUNICATION) &&
1115 ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
1116 bool voipstream_active = false;
1117 for(it = mDeviceList.begin();
1118 it != mDeviceList.end(); ++it) {
1119 if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
1120 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001121 ALOGD("openInput: it->rxHandle %p it->handle %p",it->rxHandle,it->handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001122 voipstream_active = true;
1123 break;
1124 }
1125 }
1126 if(voipstream_active == false) {
1127 mVoipStreamCount = 0;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001128 alsa_handle_t alsa_handle;
1129 unsigned long bufferSize;
1130 if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
1131 bufferSize = VOIP_BUFFER_SIZE_8K;
1132 }
1133 else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
1134 bufferSize = VOIP_BUFFER_SIZE_16K;
1135 }
1136 else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001137 ALOGE("unsupported samplerate %d for voip",*sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001138 if (status) *status = err;
1139 return in;
1140 }
1141 alsa_handle.module = mALSADevice;
1142 alsa_handle.bufferSize = bufferSize;
1143 alsa_handle.devices = devices;
1144 alsa_handle.handle = 0;
1145 if(*format == AudioSystem::PCM_16_BIT)
1146 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1147 else
1148 alsa_handle.format = *format;
1149 alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
Eric Laurent61f44982013-01-17 18:21:59 -08001150 alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001151 alsa_handle.sampleRate = *sampleRate;
1152 alsa_handle.latency = VOIP_RECORD_LATENCY;
1153 alsa_handle.rxHandle = 0;
1154 alsa_handle.ucMgr = mUcMgr;
1155 mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
1156 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1157 if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1158 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
1159 } else {
1160 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
1161 }
1162 free(use_case);
1163 mDeviceList.push_back(alsa_handle);
1164 it = mDeviceList.end();
1165 it--;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001166 ALOGD("mCurrDevice: %d", mCurDevice);
Ajay Dudani9746c472012-06-18 16:01:16 -07001167#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001168 if((mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1169 (mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -07001170 ALOGD("Routing everything from proxy for voipcall");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001171 mALSADevice->route(&(*it), AudioSystem::DEVICE_IN_PROXY, AudioSystem::MODE_IN_COMMUNICATION);
Iliyan Malchev4113f342012-06-11 14:39:47 -07001172 ALOGD("enabling VOIP in openInputstream, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001173 startUsbPlaybackIfNotStarted();
1174 musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001175 ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001176 startUsbRecordingIfNotStarted();
1177 musbRecordingState |= USBRECBIT_VOIPCALL;
SathishKumar Manie42406e2012-08-29 16:25:54 -07001178 } else
Iliyan Malchev4765c432012-06-11 14:36:16 -07001179#endif
1180 {
1181 mALSADevice->route(&(*it),mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
1182 }
1183 if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
1184 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
1185 } else {
1186 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
1187 }
1188 if(sampleRate) {
1189 it->sampleRate = *sampleRate;
1190 }
1191 if(channels)
1192 it->channels = AudioSystem::popCount(*channels);
1193 err = mALSADevice->startVoipCall(&(*it));
1194 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001195 ALOGE("Error opening pcm input device");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001196 return NULL;
1197 }
1198 }
1199 in = new AudioStreamInALSA(this, &(*it), acoustics);
1200 err = in->set(format, channels, sampleRate, devices);
1201 if(err == NO_ERROR) {
1202 mVoipStreamCount++; //increment VoipstreamCount only if success
Iliyan Malchev4113f342012-06-11 14:39:47 -07001203 ALOGD("OpenInput mVoipStreamCount %d",mVoipStreamCount);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001204 }
SathishKumar Mani0a019912012-09-11 12:33:11 -07001205 ALOGD("openInput: After Get alsahandle");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001206 if (status) *status = err;
1207 return in;
SathishKumar Manied3c0fd2012-09-21 10:31:40 -07001208 } else {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001209 alsa_handle_t alsa_handle;
SathishKumar Mani77780382012-09-21 20:58:33 -07001210 unsigned long bufferSize = MIN_CAPTURE_BUFFER_SIZE_PER_CH;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001211
1212 alsa_handle.module = mALSADevice;
1213 alsa_handle.bufferSize = bufferSize;
1214 alsa_handle.devices = devices;
1215 alsa_handle.handle = 0;
1216 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1217 alsa_handle.channels = VOICE_CHANNEL_MODE;
Eric Laurent61f44982013-01-17 18:21:59 -08001218 alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001219 alsa_handle.sampleRate = android::AudioRecord::DEFAULT_SAMPLE_RATE;
1220 alsa_handle.latency = RECORD_LATENCY;
1221 alsa_handle.rxHandle = 0;
1222 alsa_handle.ucMgr = mUcMgr;
1223 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1224 if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1225 if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
1226 (newMode == AudioSystem::MODE_IN_CALL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001227 ALOGD("openInputStream: into incall recording, channels %d", *channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001228 mIncallMode = *channels;
1229 if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
1230 (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
1231 if (mFusion3Platform) {
1232 mALSADevice->setVocRecMode(INCALL_REC_STEREO);
1233 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1234 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001235 } else {
1236 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
1237 sizeof(alsa_handle.useCase));
1238 }
1239 } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
1240 if (mFusion3Platform) {
1241 mALSADevice->setVocRecMode(INCALL_REC_MONO);
1242 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1243 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001244 } else {
1245 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
1246 sizeof(alsa_handle.useCase));
1247 }
1248 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001249#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001250 } else if((devices == AudioSystem::DEVICE_IN_FM_RX)) {
1251 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_FM, sizeof(alsa_handle.useCase));
1252 } else if(devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
1253 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, sizeof(alsa_handle.useCase));
1254#endif
1255 } else {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001256 char value[128];
1257 property_get("persist.audio.lowlatency.rec",value,"0");
SathishKumar Mani88613382012-08-13 18:40:18 -07001258 if (!strcmp("true", value)) {
1259 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
1260 } else {
1261 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, sizeof(alsa_handle.useCase));
1262 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001263 }
1264 } else {
1265 if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
1266 (newMode == AudioSystem::MODE_IN_CALL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001267 ALOGD("openInputStream: incall recording, channels %d", *channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001268 mIncallMode = *channels;
1269 if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
1270 (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
1271 if (mFusion3Platform) {
1272 mALSADevice->setVocRecMode(INCALL_REC_STEREO);
1273 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
1274 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001275 } else {
1276 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_UL_DL_REC,
1277 sizeof(alsa_handle.useCase));
1278 }
1279 } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
1280 if (mFusion3Platform) {
1281 mALSADevice->setVocRecMode(INCALL_REC_MONO);
1282 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
1283 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001284 } else {
1285 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DL_REC,
1286 sizeof(alsa_handle.useCase));
1287 }
1288 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001289#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001290 } else if(devices == AudioSystem::DEVICE_IN_FM_RX) {
1291 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_REC, sizeof(alsa_handle.useCase));
1292 } else if (devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
1293 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_A2DP_REC, sizeof(alsa_handle.useCase));
1294#endif
1295 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -07001296 char value[128];
1297 property_get("persist.audio.lowlatency.rec",value,"0");
1298 if (!strcmp("true", value)) {
1299 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, sizeof(alsa_handle.useCase));
1300 } else {
1301 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_REC, sizeof(alsa_handle.useCase));
1302 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001303 }
1304 }
1305 free(use_case);
1306 mDeviceList.push_back(alsa_handle);
1307 ALSAHandleList::iterator it = mDeviceList.end();
1308 it--;
1309 //update channel info before do routing
1310 if(channels) {
1311 it->channels = AudioSystem::popCount((*channels) &
Ajay Dudani9746c472012-06-18 16:01:16 -07001312 (AudioSystem::CHANNEL_IN_STEREO
1313 | AudioSystem::CHANNEL_IN_MONO
1314#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001315 | AudioSystem::CHANNEL_IN_5POINT1
1316#endif
Eric Laurent61f44982013-01-17 18:21:59 -08001317 | AUDIO_CHANNEL_IN_FRONT_BACK));
1318 it->channelMask = *channels;
1319 ALOGV("updated channel info: channels=%d channelMask %08x",
1320 it->channels, it->channelMask);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001321 }
1322 if (devices == AudioSystem::DEVICE_IN_VOICE_CALL){
1323 /* Add current devices info to devices to do route */
Ajay Dudani9746c472012-06-18 16:01:16 -07001324#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001325 if(mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET ||
1326 mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001327 ALOGD("Routing everything from proxy for VOIP call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001328 route_devices = devices | AudioSystem::DEVICE_IN_PROXY;
1329 } else
1330#endif
1331 {
1332 route_devices = devices | mCurDevice;
1333 }
1334 mALSADevice->route(&(*it), route_devices, mode());
1335 } else {
Ajay Dudani9746c472012-06-18 16:01:16 -07001336#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001337 if(devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET ||
1338 devices & AudioSystem::DEVICE_IN_PROXY) {
1339 devices |= AudioSystem::DEVICE_IN_PROXY;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001340 ALOGD("routing everything from proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001341 mALSADevice->route(&(*it), devices, mode());
1342 } else
1343#endif
1344 {
1345 mALSADevice->route(&(*it), devices, mode());
1346 }
1347 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001348 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001349 !strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC) ||
Ajay Dudani9746c472012-06-18 16:01:16 -07001350#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001351 !strcmp(it->useCase, SND_USE_CASE_VERB_FM_REC) ||
1352 !strcmp(it->useCase, SND_USE_CASE_VERB_FM_A2DP_REC) ||
1353#endif
1354 !strcmp(it->useCase, SND_USE_CASE_VERB_DL_REC) ||
1355 !strcmp(it->useCase, SND_USE_CASE_VERB_UL_DL_REC) ||
1356 !strcmp(it->useCase, SND_USE_CASE_VERB_INCALL_REC)) {
1357 snd_use_case_set(mUcMgr, "_verb", it->useCase);
1358 } else {
1359 snd_use_case_set(mUcMgr, "_enamod", it->useCase);
1360 }
1361 if(sampleRate) {
1362 it->sampleRate = *sampleRate;
1363 }
SathishKumar Mani77780382012-09-21 20:58:33 -07001364 if (!strncmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
1365 || !strncmp(it->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
1366 ALOGV("OpenInoutStream: Use larger buffer size for 5.1(%s) recording ", it->useCase);
1367 it->bufferSize = getInputBufferSize(it->sampleRate,*format,it->channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001368 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001369 err = mALSADevice->open(&(*it));
1370 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001371 ALOGE("Error opening pcm input device");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001372 } else {
1373 in = new AudioStreamInALSA(this, &(*it), acoustics);
1374 err = in->set(format, channels, sampleRate, devices);
1375 }
1376 if (status) *status = err;
1377 return in;
1378 }
1379}
1380
1381void
1382AudioHardwareALSA::closeInputStream(AudioStreamIn* in)
1383{
1384 delete in;
1385}
1386
1387status_t AudioHardwareALSA::setMicMute(bool state)
1388{
SathishKumar Mani6ccde102012-09-26 20:23:34 -07001389 if (mMicMute != state) {
1390 mMicMute = state;
1391 ALOGD("setMicMute: mMicMute %d", mMicMute);
1392 if(mALSADevice) {
1393 mALSADevice->setMicMute(state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001394 }
1395 }
1396 return NO_ERROR;
1397}
1398
1399status_t AudioHardwareALSA::getMicMute(bool *state)
1400{
SathishKumar Mani6ccde102012-09-26 20:23:34 -07001401 *state = mMicMute;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001402 return NO_ERROR;
1403}
1404
1405status_t AudioHardwareALSA::dump(int fd, const Vector<String16>& args)
1406{
1407 return NO_ERROR;
1408}
1409
1410size_t AudioHardwareALSA::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
1411{
SathishKumar Mani77780382012-09-21 20:58:33 -07001412 size_t bufferSize = 0;
1413 if (format == AudioSystem::PCM_16_BIT) {
1414 if(sampleRate == 8000 || sampleRate == 16000 || sampleRate == 32000) {
1415 bufferSize = (sampleRate * channelCount * 20 * sizeof(int16_t)) / 1000;
1416 } else if (sampleRate == 11025 || sampleRate == 12000) {
1417 bufferSize = 256 * sizeof(int16_t) * channelCount;
1418 } else if (sampleRate == 22050 || sampleRate == 24000) {
1419 bufferSize = 512 * sizeof(int16_t) * channelCount;
1420 } else if (sampleRate == 44100 || sampleRate == 48000) {
1421 bufferSize = 1024 * sizeof(int16_t) * channelCount;
1422 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001423 } else {
SathishKumar Mani77780382012-09-21 20:58:33 -07001424 ALOGE("getInputBufferSize bad format: %d", format);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001425 }
1426 return bufferSize;
1427}
1428
Ajay Dudani9746c472012-06-18 16:01:16 -07001429#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001430void AudioHardwareALSA::handleFm(int device)
1431{
1432int newMode = mode();
1433 if(device & AudioSystem::DEVICE_OUT_FM && mIsFmActive == 0) {
1434 // Start FM Radio on current active device
1435 unsigned long bufferSize = FM_BUFFER_SIZE;
1436 alsa_handle_t alsa_handle;
1437 char *use_case;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001438 ALOGV("Start FM");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001439 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1440 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1441 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DIGITAL_RADIO, sizeof(alsa_handle.useCase));
1442 } else {
1443 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_FM, sizeof(alsa_handle.useCase));
1444 }
1445 free(use_case);
1446
1447 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1448 bufferSize &= ~b;
1449 alsa_handle.module = mALSADevice;
1450 alsa_handle.bufferSize = bufferSize;
1451 alsa_handle.devices = device;
1452 alsa_handle.handle = 0;
1453 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1454 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
Eric Laurent61f44982013-01-17 18:21:59 -08001455 alsa_handle.channelMask = AUDIO_CHANNEL_OUT_STEREO;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001456 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
1457 alsa_handle.latency = VOICE_LATENCY;
1458 alsa_handle.rxHandle = 0;
1459 alsa_handle.ucMgr = mUcMgr;
1460 mIsFmActive = 1;
1461 mDeviceList.push_back(alsa_handle);
1462 ALSAHandleList::iterator it = mDeviceList.end();
1463 it--;
1464 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1465 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1466 device |= AudioSystem::DEVICE_OUT_PROXY;
1467 alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001468 ALOGD("Routing to proxy for FM case");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001469 }
1470 mALSADevice->route(&(*it), (uint32_t)device, newMode);
1471 if(!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) {
1472 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_DIGITAL_RADIO);
1473 } else {
1474 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_FM);
1475 }
1476 mALSADevice->startFm(&(*it));
1477 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1478 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -07001479 ALOGD("Starting FM, musbPlaybackState %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001480 startUsbPlaybackIfNotStarted();
1481 musbPlaybackState |= USBPLAYBACKBIT_FM;
1482 }
1483 } else if (!(device & AudioSystem::DEVICE_OUT_FM) && mIsFmActive == 1) {
1484 //i Stop FM Radio
Iliyan Malchev4113f342012-06-11 14:39:47 -07001485 ALOGV("Stop FM");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001486 for(ALSAHandleList::iterator it = mDeviceList.begin();
1487 it != mDeviceList.end(); ++it) {
1488 if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
1489 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
1490 mALSADevice->close(&(*it));
1491 //mALSADevice->route(&(*it), (uint32_t)device, newMode);
1492 mDeviceList.erase(it);
1493 break;
1494 }
1495 }
1496 mIsFmActive = 0;
1497 musbPlaybackState &= ~USBPLAYBACKBIT_FM;
1498 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1499 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1500 closeUsbPlaybackIfNothingActive();
1501 }
1502 }
1503}
1504#endif
1505
1506void AudioHardwareALSA::disableVoiceCall(char* verb, char* modifier, int mode, int device)
1507{
1508 for(ALSAHandleList::iterator it = mDeviceList.begin();
1509 it != mDeviceList.end(); ++it) {
1510 if((!strcmp(it->useCase, verb)) ||
1511 (!strcmp(it->useCase, modifier))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001512 ALOGV("Disabling voice call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001513 mALSADevice->close(&(*it));
1514 mALSADevice->route(&(*it), (uint32_t)device, mode);
1515 mDeviceList.erase(it);
1516 break;
1517 }
1518 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001519#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001520 if(musbPlaybackState & USBPLAYBACKBIT_VOICECALL) {
SathishKumar Mani0a019912012-09-11 12:33:11 -07001521 ALOGD("Voice call ended on USB");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001522 musbPlaybackState &= ~USBPLAYBACKBIT_VOICECALL;
1523 musbRecordingState &= ~USBRECBIT_VOICECALL;
1524 closeUsbRecordingIfNothingActive();
1525 closeUsbPlaybackIfNothingActive();
1526 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001527#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001528}
1529void AudioHardwareALSA::enableVoiceCall(char* verb, char* modifier, int mode, int device)
1530{
1531// Start voice call
SathishKumar Mani018d1c52012-09-11 14:58:18 -07001532unsigned long bufferSize = DEFAULT_VOICE_BUFFER_SIZE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001533alsa_handle_t alsa_handle;
1534char *use_case;
1535 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1536 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1537 strlcpy(alsa_handle.useCase, verb, sizeof(alsa_handle.useCase));
1538 } else {
1539 strlcpy(alsa_handle.useCase, modifier, sizeof(alsa_handle.useCase));
1540 }
1541 free(use_case);
1542
1543 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1544 bufferSize &= ~b;
1545 alsa_handle.module = mALSADevice;
1546 alsa_handle.bufferSize = bufferSize;
1547 alsa_handle.devices = device;
1548 alsa_handle.handle = 0;
1549 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1550 alsa_handle.channels = VOICE_CHANNEL_MODE;
Eric Laurent61f44982013-01-17 18:21:59 -08001551 alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001552 alsa_handle.sampleRate = VOICE_SAMPLING_RATE;
1553 alsa_handle.latency = VOICE_LATENCY;
1554 alsa_handle.rxHandle = 0;
1555 alsa_handle.ucMgr = mUcMgr;
1556 mDeviceList.push_back(alsa_handle);
1557 ALSAHandleList::iterator it = mDeviceList.end();
1558 it--;
Ajay Dudani9746c472012-06-18 16:01:16 -07001559#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001560 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1561 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1562 device |= AudioSystem::DEVICE_OUT_PROXY;
1563 alsa_handle.devices = device;
1564 }
1565#endif
1566 mALSADevice->route(&(*it), (uint32_t)device, mode);
1567 if (!strcmp(it->useCase, verb)) {
1568 snd_use_case_set(mUcMgr, "_verb", verb);
1569 } else {
1570 snd_use_case_set(mUcMgr, "_enamod", modifier);
1571 }
1572 mALSADevice->startVoiceCall(&(*it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001573#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001574 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1575 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1576 startUsbRecordingIfNotStarted();
1577 startUsbPlaybackIfNotStarted();
1578 musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
1579 musbRecordingState |= USBRECBIT_VOICECALL;
1580 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001581#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001582}
1583
1584bool AudioHardwareALSA::routeVoiceCall(int device, int newMode)
1585{
1586int csCallState = mCallState&0xF;
1587 bool isRouted = false;
1588 switch (csCallState) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001589 case CS_INACTIVE:
1590 if (mCSCallActive != CS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001591 ALOGD("doRouting: Disabling voice call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001592 disableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
1593 (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
1594 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001595 mCSCallActive = CS_INACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001596 }
1597 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001598 case CS_ACTIVE:
1599 if (mCSCallActive == CS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001600 ALOGD("doRouting: Enabling CS voice call ");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001601 enableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
1602 (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
1603 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001604 mCSCallActive = CS_ACTIVE;
1605 } else if (mCSCallActive == CS_HOLD) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001606 ALOGD("doRouting: Resume voice call from hold state");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001607 ALSAHandleList::iterator vt_it;
1608 for(vt_it = mDeviceList.begin();
1609 vt_it != mDeviceList.end(); ++vt_it) {
1610 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
1611 strlen(SND_USE_CASE_VERB_VOICECALL))) ||
1612 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1613 strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
1614 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001615 mCSCallActive = CS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001616 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001617 ALOGE("VoLTE resume failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001618 break;
1619 }
1620 }
1621 }
1622 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001623 case CS_HOLD:
1624 if (mCSCallActive == CS_ACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001625 ALOGD("doRouting: Voice call going to Hold");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001626 ALSAHandleList::iterator vt_it;
1627 for(vt_it = mDeviceList.begin();
1628 vt_it != mDeviceList.end(); ++vt_it) {
1629 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
1630 strlen(SND_USE_CASE_VERB_VOICECALL))) ||
1631 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1632 strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001633 mCSCallActive = CS_HOLD;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001634 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1635 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001636 ALOGE("Voice pause failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001637 break;
1638 }
1639 }
1640 }
1641 break;
1642 }
1643 return isRouted;
1644}
1645bool AudioHardwareALSA::routeVoLTECall(int device, int newMode)
1646{
1647int volteCallState = mCallState&0xF0;
1648bool isRouted = false;
1649switch (volteCallState) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001650 case IMS_INACTIVE:
1651 if (mVolteCallActive != IMS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001652 ALOGD("doRouting: Disabling IMS call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001653 disableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
1654 (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
1655 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001656 mVolteCallActive = IMS_INACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001657 }
1658 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001659 case IMS_ACTIVE:
1660 if (mVolteCallActive == IMS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001661 ALOGD("doRouting: Enabling IMS voice call ");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001662 enableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
1663 (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
1664 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001665 mVolteCallActive = IMS_ACTIVE;
1666 } else if (mVolteCallActive == IMS_HOLD) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001667 ALOGD("doRouting: Resume IMS call from hold state");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001668 ALSAHandleList::iterator vt_it;
1669 for(vt_it = mDeviceList.begin();
1670 vt_it != mDeviceList.end(); ++vt_it) {
1671 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
1672 strlen(SND_USE_CASE_VERB_VOLTE))) ||
1673 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1674 strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
1675 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001676 mVolteCallActive = IMS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001677 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001678 ALOGE("VoLTE resume failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001679 break;
1680 }
1681 }
1682 }
1683 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001684 case IMS_HOLD:
1685 if (mVolteCallActive == IMS_ACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001686 ALOGD("doRouting: IMS ACTIVE going to HOLD");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001687 ALSAHandleList::iterator vt_it;
1688 for(vt_it = mDeviceList.begin();
1689 vt_it != mDeviceList.end(); ++vt_it) {
1690 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
1691 strlen(SND_USE_CASE_VERB_VOLTE))) ||
1692 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1693 strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001694 mVolteCallActive = IMS_HOLD;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001695 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1696 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001697 ALOGE("VoLTE Pause failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001698 break;
1699 }
1700 }
1701 }
1702 break;
1703 }
1704 return isRouted;
1705}
1706
1707} // namespace android_audio_legacy