blob: 6a880740663d7a6fc1742979ef10574e87279ca0 [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 }
63} // extern "C"
64
65namespace android_audio_legacy
66{
67
68// ----------------------------------------------------------------------------
69
70AudioHardwareInterface *AudioHardwareALSA::create() {
71 return new AudioHardwareALSA();
72}
73
74AudioHardwareALSA::AudioHardwareALSA() :
75 mALSADevice(0),mVoipStreamCount(0),mVoipMicMute(false),mVoipBitRate(0)
76 ,mCallState(0)
77{
78 FILE *fp;
79 char soundCardInfo[200];
80 hw_module_t *module;
81 char platform[128], baseband[128];
82 int err = hw_get_module(ALSA_HARDWARE_MODULE_ID,
83 (hw_module_t const**)&module);
84 int codec_rev = 2;
Iliyan Malchev4113f342012-06-11 14:39:47 -070085 ALOGD("hw_get_module(ALSA_HARDWARE_MODULE_ID) returned err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -070086 if (err == 0) {
87 hw_device_t* device;
88 err = module->methods->open(module, ALSA_HARDWARE_NAME, &device);
89 if (err == 0) {
90 mALSADevice = (alsa_device_t *)device;
91 mALSADevice->init(mALSADevice, mDeviceList);
92 mCSCallActive = 0;
93 mVolteCallActive = 0;
94 mIsFmActive = 0;
95 mDevSettingsFlag = 0;
Ajay Dudani9746c472012-06-18 16:01:16 -070096#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -070097 mAudioUsbALSA = new AudioUsbALSA();
Ajay Dudani9746c472012-06-18 16:01:16 -070098 musbPlaybackState = 0;
99 musbRecordingState = 0;
100#endif
ty.lee924f7982012-08-01 23:15:30 +0900101#ifdef USES_FLUENCE_INCALL
102 mDevSettingsFlag |= TTY_OFF | DMIC_FLAG;
103#else
Iliyan Malchev4765c432012-06-11 14:36:16 -0700104 mDevSettingsFlag |= TTY_OFF;
ty.lee924f7982012-08-01 23:15:30 +0900105#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700106 mBluetoothVGS = false;
107 mFusion3Platform = false;
Ajay Dudani9746c472012-06-18 16:01:16 -0700108
109#ifdef QCOM_ACDB_ENABLED
110 if ((acdb_loader_init_ACDB()) < 0) {
111 ALOGE("Failed to initialize ACDB");
112 }
113#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700114
115 if((fp = fopen("/proc/asound/cards","r")) == NULL) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700116 ALOGE("Cannot open /proc/asound/cards file to get sound card info");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700117 } else {
118 while((fgets(soundCardInfo, sizeof(soundCardInfo), fp) != NULL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700119 ALOGV("SoundCardInfo %s", soundCardInfo);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700120 if (strstr(soundCardInfo, "msm8960-tabla1x-snd-card")) {
121 codec_rev = 1;
122 break;
123 } else if (strstr(soundCardInfo, "msm-snd-card")) {
124 codec_rev = 2;
125 break;
126 } else if (strstr(soundCardInfo, "msm8930-sitar-snd-card")) {
127 codec_rev = 3;
128 break;
129 }
130 }
131 fclose(fp);
132 }
133
134 if (codec_rev == 1) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700135 ALOGV("Detected tabla 1.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700136 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm");
137 } else if (codec_rev == 3) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700138 ALOGV("Detected sitar 1.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700139 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_Sitar");
140 } else {
141 property_get("ro.board.platform", platform, "");
142 property_get("ro.baseband", baseband, "");
143 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700144 ALOGV("Detected Fusion tabla 2.x");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700145 mFusion3Platform = true;
146 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x_Fusion3");
147 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700148 ALOGV("Detected tabla 2.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700149 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x");
150 }
151 }
152
153 if (mUcMgr < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700154 ALOGE("Failed to open ucm instance: %d", errno);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700155 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700156 ALOGI("ucm instance opened: %u", (unsigned)mUcMgr);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700157 }
158 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700159 ALOGE("ALSA Module could not be opened!!!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700160 }
161 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700162 ALOGE("ALSA Module not found!!!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700163 }
164}
165
166AudioHardwareALSA::~AudioHardwareALSA()
167{
168 if (mUcMgr != NULL) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700169#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700170 ALOGD("closing ucm instance: %u", (unsigned)mUcMgr);
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700171#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700172 snd_use_case_mgr_close(mUcMgr);
173 }
174 if (mALSADevice) {
175 mALSADevice->common.close(&mALSADevice->common);
176 }
177 for(ALSAHandleList::iterator it = mDeviceList.begin();
178 it != mDeviceList.end(); ++it) {
179 it->useCase[0] = 0;
180 mDeviceList.erase(it);
181 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700182#ifdef QCOM_ACDB_ENABLED
183 acdb_loader_deallocate_ACDB();
184#endif
185#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700186 delete mAudioUsbALSA;
Ajay Dudani9746c472012-06-18 16:01:16 -0700187#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700188}
189
190status_t AudioHardwareALSA::initCheck()
191{
192 if (!mALSADevice)
193 return NO_INIT;
194
195 return NO_ERROR;
196}
197
198status_t AudioHardwareALSA::setVoiceVolume(float v)
199{
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700200 ALOGV("setVoiceVolume(%f)\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700201 if (v < 0.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700202 ALOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700203 v = 0.0;
204 } else if (v > 1.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700205 ALOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700206 v = 1.0;
207 }
208
209 int newMode = mode();
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700210 ALOGV("setVoiceVolume newMode %d",newMode);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700211 int vol = lrint(v * 100.0);
212
213 // Voice volume levels from android are mapped to driver volume levels as follows.
214 // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
215 // So adjust the volume to get the correct volume index in driver
216 vol = 100 - vol;
217
218 if (mALSADevice) {
219 if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
220 mALSADevice->setVoipVolume(vol);
221 } else if (newMode == AudioSystem::MODE_IN_CALL){
Ajay Dudani9746c472012-06-18 16:01:16 -0700222 if (mCSCallActive == CS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700223 mALSADevice->setVoiceVolume(vol);
Ajay Dudani9746c472012-06-18 16:01:16 -0700224 if (mVolteCallActive == IMS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700225 mALSADevice->setVoLTEVolume(vol);
226 }
227 }
228
229 return NO_ERROR;
230}
231
Ajay Dudani9746c472012-06-18 16:01:16 -0700232#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700233status_t AudioHardwareALSA::setFmVolume(float value)
234{
235 status_t status = NO_ERROR;
236
237 int vol;
238
239 if (value < 0.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700240 ALOGW("setFmVolume(%f) under 0.0, assuming 0.0\n", value);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700241 value = 0.0;
242 } else if (value > 1.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700243 ALOGW("setFmVolume(%f) over 1.0, assuming 1.0\n", value);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700244 value = 1.0;
245 }
246 vol = lrint((value * 0x2000) + 0.5);
247
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700248#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700249 ALOGD("setFmVolume(%f)\n", value);
250 ALOGD("Setting FM volume to %d (available range is 0 to 0x2000)\n", vol);
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700251#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700252
253 mALSADevice->setFmVolume(vol);
254
255 return status;
256}
257#endif
258
259status_t AudioHardwareALSA::setMasterVolume(float volume)
260{
261 return NO_ERROR;
262}
263
264status_t AudioHardwareALSA::setMode(int mode)
265{
266 status_t status = NO_ERROR;
267
268 if (mode != mMode) {
269 status = AudioHardwareBase::setMode(mode);
270 }
271
272 if (mode == AudioSystem::MODE_IN_CALL) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700273 mCallState = CS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700274 }else if (mode == AudioSystem::MODE_NORMAL) {
275 mCallState = 0;
276 }
277
278 return status;
279}
280
281status_t AudioHardwareALSA::setParameters(const String8& keyValuePairs)
282{
283 AudioParameter param = AudioParameter(keyValuePairs);
284 String8 key;
285 String8 value;
286 status_t status = NO_ERROR;
287 int device;
288 int btRate;
289 int state;
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700290#if LOCAL_LOGD
Iliyan Malchev4113f342012-06-11 14:39:47 -0700291 ALOGD("setParameters() %s", keyValuePairs.string());
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700292#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700293
294 key = String8(TTY_MODE_KEY);
295 if (param.get(key, value) == NO_ERROR) {
296 mDevSettingsFlag &= TTY_CLEAR;
ty.leea97e6f62012-08-15 10:11:50 +0900297 if (value == "tty_full") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700298 mDevSettingsFlag |= TTY_FULL;
ty.leea97e6f62012-08-15 10:11:50 +0900299 } else if (value == "tty_hco") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700300 mDevSettingsFlag |= TTY_HCO;
ty.leea97e6f62012-08-15 10:11:50 +0900301 } else if (value == "tty_vco") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700302 mDevSettingsFlag |= TTY_VCO;
303 } else {
304 mDevSettingsFlag |= TTY_OFF;
305 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700306 ALOGI("Changed TTY Mode=%s", value.string());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700307 mALSADevice->setFlags(mDevSettingsFlag);
308 if(mMode != AudioSystem::MODE_IN_CALL){
309 return NO_ERROR;
310 }
311 doRouting(0);
312 }
313
314 key = String8(FLUENCE_KEY);
315 if (param.get(key, value) == NO_ERROR) {
316 if (value == "quadmic") {
317 mDevSettingsFlag |= QMIC_FLAG;
318 mDevSettingsFlag &= (~DMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700319 ALOGV("Fluence quadMic feature Enabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700320 } else if (value == "dualmic") {
321 mDevSettingsFlag |= DMIC_FLAG;
322 mDevSettingsFlag &= (~QMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700323 ALOGV("Fluence dualmic feature Enabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700324 } else if (value == "none") {
325 mDevSettingsFlag &= (~DMIC_FLAG);
326 mDevSettingsFlag &= (~QMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700327 ALOGV("Fluence feature Disabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700328 }
329 mALSADevice->setFlags(mDevSettingsFlag);
330 doRouting(0);
331 }
332
Ajay Dudani9746c472012-06-18 16:01:16 -0700333#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700334 if (mFusion3Platform) {
335 key = String8(INCALLMUSIC_KEY);
336 if (param.get(key, value) == NO_ERROR) {
337 if (value == "true") {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700338 ALOGV("Enabling Incall Music setting in the setparameter\n");
Ajay Dudani9746c472012-06-18 16:01:16 -0700339 csd_client_start_playback();
Iliyan Malchev4765c432012-06-11 14:36:16 -0700340 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700341 ALOGV("Disabling Incall Music setting in the setparameter\n");
Ajay Dudani9746c472012-06-18 16:01:16 -0700342 csd_client_stop_playback();
Iliyan Malchev4765c432012-06-11 14:36:16 -0700343 }
344 }
345 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700346#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700347
348 key = String8(ANC_KEY);
349 if (param.get(key, value) == NO_ERROR) {
350 if (value == "true") {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700351 ALOGV("Enabling ANC setting in the setparameter\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700352 mDevSettingsFlag |= ANC_FLAG;
353 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700354 ALOGV("Disabling ANC setting in the setparameter\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700355 mDevSettingsFlag &= (~ANC_FLAG);
356 }
357 mALSADevice->setFlags(mDevSettingsFlag);
358 doRouting(0);
359 }
360
361 key = String8(AudioParameter::keyRouting);
362 if (param.getInt(key, device) == NO_ERROR) {
363 // Ignore routing if device is 0.
364 if(device) {
365 doRouting(device);
366 }
367 param.remove(key);
368 }
369
370 key = String8(BT_SAMPLERATE_KEY);
371 if (param.getInt(key, btRate) == NO_ERROR) {
372 mALSADevice->setBtscoRate(btRate);
373 param.remove(key);
374 }
375
376 key = String8(BTHEADSET_VGS);
377 if (param.get(key, value) == NO_ERROR) {
378 if (value == "on") {
379 mBluetoothVGS = true;
380 } else {
381 mBluetoothVGS = false;
382 }
383 }
384
385 key = String8(WIDEVOICE_KEY);
386 if (param.get(key, value) == NO_ERROR) {
387 bool flag = false;
388 if (value == "true") {
389 flag = true;
390 }
391 if(mALSADevice) {
392 mALSADevice->enableWideVoice(flag);
393 }
394 param.remove(key);
395 }
396
397 key = String8(VOIPRATE_KEY);
398 if (param.get(key, value) == NO_ERROR) {
399 mVoipBitRate = atoi(value);
400 param.remove(key);
401 }
402
403 key = String8(FENS_KEY);
404 if (param.get(key, value) == NO_ERROR) {
405 bool flag = false;
406 if (value == "true") {
407 flag = true;
408 }
409 if(mALSADevice) {
410 mALSADevice->enableFENS(flag);
411 }
412 param.remove(key);
413 }
414
Ajay Dudani9746c472012-06-18 16:01:16 -0700415#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700416 key = String8(AudioParameter::keyHandleFm);
417 if (param.getInt(key, device) == NO_ERROR) {
418 // Ignore if device is 0
419 if(device) {
420 handleFm(device);
421 }
422 param.remove(key);
423 }
424#endif
425
426 key = String8(ST_KEY);
427 if (param.get(key, value) == NO_ERROR) {
428 bool flag = false;
429 if (value == "true") {
430 flag = true;
431 }
432 if(mALSADevice) {
433 mALSADevice->enableSlowTalk(flag);
434 }
435 param.remove(key);
436 }
437 key = String8(MODE_CALL_KEY);
438 if (param.getInt(key,state) == NO_ERROR) {
439 if (mCallState != state) {
440 mCallState = state;
441 doRouting(0);
442 }
443 mCallState = state;
444 }
445 if (param.size()) {
446 status = BAD_VALUE;
447 }
448 return status;
449}
450
451String8 AudioHardwareALSA::getParameters(const String8& keys)
452{
453 AudioParameter param = AudioParameter(keys);
454 String8 value;
455
456 String8 key = String8(DUALMIC_KEY);
457 if (param.get(key, value) == NO_ERROR) {
458 value = String8("false");
459 param.add(key, value);
460 }
461
462 key = String8(FLUENCE_KEY);
463 if (param.get(key, value) == NO_ERROR) {
464 if ((mDevSettingsFlag & QMIC_FLAG) &&
465 (mDevSettingsFlag & ~DMIC_FLAG))
466 value = String8("quadmic");
467 else if ((mDevSettingsFlag & DMIC_FLAG) &&
468 (mDevSettingsFlag & ~QMIC_FLAG))
469 value = String8("dualmic");
470 else if ((mDevSettingsFlag & ~DMIC_FLAG) &&
471 (mDevSettingsFlag & ~QMIC_FLAG))
472 value = String8("none");
473 param.add(key, value);
474 }
475
Ajay Dudani9746c472012-06-18 16:01:16 -0700476#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700477 key = String8("Fm-radio");
478 if ( param.get(key,value) == NO_ERROR ) {
479 if ( mIsFmActive ) {
480 param.addInt(String8("isFMON"), true );
481 }
482 }
483#endif
484
485 key = String8(BTHEADSET_VGS);
486 if (param.get(key, value) == NO_ERROR) {
487 if(mBluetoothVGS)
488 param.addInt(String8("isVGS"), true);
489 }
490
Iliyan Malchev4113f342012-06-11 14:39:47 -0700491 ALOGV("AudioHardwareALSA::getParameters() %s", param.toString().string());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700492 return param.toString();
493}
494
Ajay Dudani9746c472012-06-18 16:01:16 -0700495#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700496void AudioHardwareALSA::closeUSBPlayback()
497{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700498 ALOGV("closeUSBPlayback, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700499 musbPlaybackState = 0;
500 mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_KILLTHREAD);
501}
502
503void AudioHardwareALSA::closeUSBRecording()
504{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700505 ALOGV("closeUSBRecording");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700506 musbRecordingState = 0;
507 mAudioUsbALSA->exitRecordingThread(SIGNAL_EVENT_KILLTHREAD);
508}
509
510void AudioHardwareALSA::closeUsbPlaybackIfNothingActive(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700511 ALOGV("closeUsbPlaybackIfNothingActive, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700512 if(!musbPlaybackState && mAudioUsbALSA != NULL) {
513 mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_TIMEOUT);
514 }
515}
516
517void AudioHardwareALSA::closeUsbRecordingIfNothingActive(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700518 ALOGV("closeUsbRecordingIfNothingActive, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700519 if(!musbRecordingState && mAudioUsbALSA != NULL) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700520 ALOGD("Closing USB Recording Session as no stream is active");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700521 mAudioUsbALSA->setkillUsbRecordingThread(true);
522 }
523}
524
525void AudioHardwareALSA::startUsbPlaybackIfNotStarted(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700526 ALOGV("Starting the USB playback %d kill %d", musbPlaybackState,
Iliyan Malchev4765c432012-06-11 14:36:16 -0700527 mAudioUsbALSA->getkillUsbPlaybackThread());
528 if((!musbPlaybackState) || (mAudioUsbALSA->getkillUsbPlaybackThread() == true)) {
529 mAudioUsbALSA->startPlayback();
530 }
531}
532
533void AudioHardwareALSA::startUsbRecordingIfNotStarted(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700534 ALOGV("Starting the recording musbRecordingState: %d killUsbRecordingThread %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700535 musbRecordingState, mAudioUsbALSA->getkillUsbRecordingThread());
536 if((!musbRecordingState) || (mAudioUsbALSA->getkillUsbRecordingThread() == true)) {
537 mAudioUsbALSA->startRecording();
538 }
539}
Ajay Dudani9746c472012-06-18 16:01:16 -0700540#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700541
542void AudioHardwareALSA::doRouting(int device)
543{
544 Mutex::Autolock autoLock(mLock);
545 int newMode = mode();
546 bool isRouted = false;
547
Ajay Dudani9746c472012-06-18 16:01:16 -0700548 if ((device == AudioSystem::DEVICE_IN_VOICE_CALL)
549#ifdef QCOM_FM_ENABLED
550 || (device == AudioSystem::DEVICE_IN_FM_RX)
551 || (device == AudioSystem::DEVICE_OUT_DIRECTOUTPUT)
552 || (device == AudioSystem::DEVICE_IN_FM_RX_A2DP)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700553#endif
Ajay Dudani9746c472012-06-18 16:01:16 -0700554 || (device == AudioSystem::DEVICE_IN_COMMUNICATION)
555 ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700556 ALOGV("Ignoring routing for FM/INCALL/VOIP recording");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700557 return;
558 }
559 if (device == 0)
560 device = mCurDevice;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700561 ALOGV("doRouting: device %d newMode %d mCSCallActive %d mVolteCallActive %d"
Iliyan Malchev4765c432012-06-11 14:36:16 -0700562 "mIsFmActive %d", device, newMode, mCSCallActive, mVolteCallActive,
563 mIsFmActive);
564
565 isRouted = routeVoLTECall(device, newMode);
566 isRouted |= routeVoiceCall(device, newMode);
567
568 if(!isRouted) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700569#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700570 if(!(device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) &&
571 !(device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET) &&
572 !(device & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) &&
573 (musbPlaybackState)){
574 //USB unplugged
575 device &= ~ AudioSystem::DEVICE_OUT_PROXY;
576 device &= ~ AudioSystem::DEVICE_IN_PROXY;
577 ALSAHandleList::iterator it = mDeviceList.end();
578 it--;
579 mALSADevice->route(&(*it), (uint32_t)device, newMode);
SathishKumar Mani0a019912012-09-11 12:33:11 -0700580 ALOGD("USB UNPLUGGED, setting musbPlaybackState to 0");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700581 musbPlaybackState = 0;
582 musbRecordingState = 0;
583 closeUSBRecording();
584 closeUSBPlayback();
585 } else if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
586 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -0700587 ALOGD("Routing everything to prox now");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700588 ALSAHandleList::iterator it = mDeviceList.end();
589 it--;
590 mALSADevice->route(&(*it), AudioSystem::DEVICE_OUT_PROXY,
591 newMode);
592 for(it = mDeviceList.begin(); it != mDeviceList.end(); ++it) {
593 if((!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
594 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_LPA))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700595 ALOGV("doRouting: LPA device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700596 startUsbPlaybackIfNotStarted();
597 musbPlaybackState |= USBPLAYBACKBIT_LPA;
598 break;
599 } else if((!strcmp(it->useCase, SND_USE_CASE_VERB_VOICECALL)) ||
600 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOICE))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700601 ALOGV("doRouting: VOICE device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700602 startUsbRecordingIfNotStarted();
603 startUsbPlaybackIfNotStarted();
604 musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
605 musbRecordingState |= USBPLAYBACKBIT_VOICECALL;
606 break;
607 }else if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
608 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700609 ALOGV("doRouting: FM device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700610 startUsbPlaybackIfNotStarted();
611 musbPlaybackState |= USBPLAYBACKBIT_FM;
612 break;
613 }
614 }
SathishKumar Manie42406e2012-08-29 16:25:54 -0700615 } else
Iliyan Malchev4765c432012-06-11 14:36:16 -0700616#endif
SathishKumar Manie42406e2012-08-29 16:25:54 -0700617 {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700618 ALSAHandleList::iterator it = mDeviceList.end();
619 it--;
620 mALSADevice->route(&(*it), (uint32_t)device, newMode);
621 }
622 }
623 mCurDevice = device;
624}
625
626uint32_t AudioHardwareALSA::getVoipMode(int format)
627{
628 switch(format) {
629 case AudioSystem::PCM_16_BIT:
630 return MODE_PCM;
631 break;
632 case AudioSystem::AMR_NB:
633 return MODE_AMR;
634 break;
635 case AudioSystem::AMR_WB:
636 return MODE_AMR_WB;
637 break;
638
Ajay Dudani9746c472012-06-18 16:01:16 -0700639#ifdef QCOM_QCHAT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700640 case AudioSystem::EVRC:
641 return MODE_IS127;
642 break;
643
644 case AudioSystem::EVRCB:
645 return MODE_4GV_NB;
646 break;
647 case AudioSystem::EVRCWB:
648 return MODE_4GV_WB;
649 break;
Ajay Dudani9746c472012-06-18 16:01:16 -0700650#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700651
652 default:
653 return MODE_PCM;
654 }
655}
656
657AudioStreamOut *
658AudioHardwareALSA::openOutputStream(uint32_t devices,
659 int *format,
660 uint32_t *channels,
661 uint32_t *sampleRate,
662 status_t *status)
663{
664 Mutex::Autolock autoLock(mLock);
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700665 ALOGV("openOutputStream: devices 0x%x channels %d sampleRate %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700666 devices, *channels, *sampleRate);
667
SathishKumar Mani88613382012-08-13 18:40:18 -0700668 audio_output_flags_t flag = static_cast<audio_output_flags_t> (*status);
669
Iliyan Malchev4765c432012-06-11 14:36:16 -0700670 status_t err = BAD_VALUE;
SathishKumar Mani88613382012-08-13 18:40:18 -0700671 *status = NO_ERROR;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700672 AudioStreamOutALSA *out = 0;
673 ALSAHandleList::iterator it;
674
675 if (devices & (devices - 1)) {
676 if (status) *status = err;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700677 ALOGE("openOutputStream called with bad devices");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700678 return out;
679 }
SathishKumar Mani88613382012-08-13 18:40:18 -0700680
681
Iliyan Malchev4765c432012-06-11 14:36:16 -0700682# if 0
683 if((devices == AudioSystem::DEVICE_OUT_DIRECTOUTPUT) &&
684 ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
685 bool voipstream_active = false;
686 for(it = mDeviceList.begin();
687 it != mDeviceList.end(); ++it) {
688 if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
689 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700690 ALOGD("openOutput: it->rxHandle %d it->handle %d",it->rxHandle,it->handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700691 voipstream_active = true;
692 break;
693 }
694 }
695 if(voipstream_active == false) {
696 mVoipStreamCount = 0;
697 mVoipMicMute = false;
698 alsa_handle_t alsa_handle;
699 unsigned long bufferSize;
700 if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
701 bufferSize = VOIP_BUFFER_SIZE_8K;
702 }
703 else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
704 bufferSize = VOIP_BUFFER_SIZE_16K;
705 }
706 else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700707 ALOGE("unsupported samplerate %d for voip",*sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700708 if (status) *status = err;
709 return out;
710 }
711 alsa_handle.module = mALSADevice;
712 alsa_handle.bufferSize = bufferSize;
713 alsa_handle.devices = devices;
714 alsa_handle.handle = 0;
715 if(*format == AudioSystem::PCM_16_BIT)
716 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
717 else
718 alsa_handle.format = *format;
719 alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
720 alsa_handle.sampleRate = *sampleRate;
721 alsa_handle.latency = VOIP_PLAYBACK_LATENCY;
722 alsa_handle.rxHandle = 0;
723 alsa_handle.ucMgr = mUcMgr;
724 mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
725 char *use_case;
726 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
727 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
728 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
729 } else {
730 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
731 }
732 free(use_case);
733 mDeviceList.push_back(alsa_handle);
734 it = mDeviceList.end();
735 it--;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700736 ALOGV("openoutput: mALSADevice->route useCase %s mCurDevice %d mVoipStreamCount %d mode %d", it->useCase,mCurDevice,mVoipStreamCount, mode());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700737 if((mCurDevice & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
738 (mCurDevice & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)||
739 (mCurDevice & AudioSystem::DEVICE_OUT_PROXY)){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700740 ALOGD("Routing to proxy for normal voip call in openOutputStream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700741 mCurDevice |= AudioSystem::DEVICE_OUT_PROXY;
742 alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
743 mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700744 ALOGD("enabling VOIP in openoutputstream, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700745 startUsbPlaybackIfNotStarted();
746 musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700747 ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700748 startUsbRecordingIfNotStarted();
749 musbRecordingState |= USBRECBIT_VOIPCALL;
750 } else{
751 mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
752 }
753 if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
754 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
755 } else {
756 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
757 }
758 err = mALSADevice->startVoipCall(&(*it));
759 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700760 ALOGE("Device open failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700761 return NULL;
762 }
763 }
764 out = new AudioStreamOutALSA(this, &(*it));
765 err = out->set(format, channels, sampleRate, devices);
766 if(err == NO_ERROR) {
767 mVoipStreamCount++; //increment VoipstreamCount only if success
Iliyan Malchev4113f342012-06-11 14:39:47 -0700768 ALOGD("openoutput mVoipStreamCount %d",mVoipStreamCount);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700769 }
770 if (status) *status = err;
771 return out;
772 } else
773#endif
774 {
775
776 alsa_handle_t alsa_handle;
777 unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
778
779 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
780 bufferSize &= ~b;
781
782 alsa_handle.module = mALSADevice;
783 alsa_handle.bufferSize = bufferSize;
784 alsa_handle.devices = devices;
785 alsa_handle.handle = 0;
786 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
787 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
788 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
789 alsa_handle.latency = PLAYBACK_LATENCY;
790 alsa_handle.rxHandle = 0;
791 alsa_handle.ucMgr = mUcMgr;
SathishKumar Mani88613382012-08-13 18:40:18 -0700792 alsa_handle.isDeepbufferOutput = false;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700793
794 char *use_case;
795 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
SathishKumar Mani88613382012-08-13 18:40:18 -0700796
797 if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
798 ALOGD("openOutputStream: DeepBuffer Output");
799 alsa_handle.isDeepbufferOutput = true;
800 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
801 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI, sizeof(alsa_handle.useCase));
802 } else {
803 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC, sizeof(alsa_handle.useCase));
804 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700805 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -0700806 ALOGD("openOutputStream: Lowlatency Output");
807 alsa_handle.bufferSize = PLAYBACK_LOW_LATENCY_BUFFER_SIZE;
808 alsa_handle.latency = PLAYBACK_LOW_LATENCY;
809 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
810 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
811 } else {
812 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
813 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700814 }
815 free(use_case);
816 mDeviceList.push_back(alsa_handle);
817 ALSAHandleList::iterator it = mDeviceList.end();
818 it--;
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700819 ALOGV("useCase %s", it->useCase);
Ajay Dudani9746c472012-06-18 16:01:16 -0700820#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700821 if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
822 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -0700823 ALOGD("Routing to proxy for normal playback in openOutputStream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700824 devices |= AudioSystem::DEVICE_OUT_PROXY;
825 }
826#endif
827 mALSADevice->route(&(*it), devices, mode());
SathishKumar Mani88613382012-08-13 18:40:18 -0700828 if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
829 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI)) {
830 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI);
831 } else {
832 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC);
833 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700834 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -0700835 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) {
836 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC);
837 } else {
838 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC);
839 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700840 }
841 err = mALSADevice->open(&(*it));
842 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700843 ALOGE("Device open failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700844 } else {
845 out = new AudioStreamOutALSA(this, &(*it));
846 err = out->set(format, channels, sampleRate, devices);
847 }
848
849 if (status) *status = err;
850 return out;
851 }
852}
853
854void
855AudioHardwareALSA::closeOutputStream(AudioStreamOut* out)
856{
857 delete out;
858}
859
Ajay Dudani9746c472012-06-18 16:01:16 -0700860#ifdef QCOM_TUNNEL_LPA_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700861AudioStreamOut *
862AudioHardwareALSA::openOutputSession(uint32_t devices,
863 int *format,
864 status_t *status,
865 int sessionId,
866 uint32_t samplingRate,
867 uint32_t channels)
868{
869 Mutex::Autolock autoLock(mLock);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700870 ALOGD("openOutputSession = %d" ,sessionId);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700871 AudioStreamOutALSA *out = 0;
872 status_t err = BAD_VALUE;
873
874 alsa_handle_t alsa_handle;
875 unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
876
877 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
878 bufferSize &= ~b;
879
880 alsa_handle.module = mALSADevice;
881 alsa_handle.bufferSize = bufferSize;
882 alsa_handle.devices = devices;
883 alsa_handle.handle = 0;
884 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
885 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
886 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
887 alsa_handle.latency = VOICE_LATENCY;
888 alsa_handle.rxHandle = 0;
889 alsa_handle.ucMgr = mUcMgr;
890
891 char *use_case;
892 if(sessionId == TUNNEL_SESSION_ID) {
893 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
894 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
895 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_TUNNEL, sizeof(alsa_handle.useCase));
896 } else {
897 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_TUNNEL, sizeof(alsa_handle.useCase));
898 }
899 } else {
900 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
901 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
902 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER, sizeof(alsa_handle.useCase));
903 } else {
904 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LPA, sizeof(alsa_handle.useCase));
905 }
906 }
907 free(use_case);
908 mDeviceList.push_back(alsa_handle);
909 ALSAHandleList::iterator it = mDeviceList.end();
910 it--;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700911 ALOGD("useCase %s", it->useCase);
Ajay Dudani9746c472012-06-18 16:01:16 -0700912#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700913 if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
914 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -0700915 ALOGD("Routing to proxy for LPA in openOutputSession");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700916 devices |= AudioSystem::DEVICE_OUT_PROXY;
917 mALSADevice->route(&(*it), devices, mode());
918 devices = AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700919 ALOGD("Starting USBPlayback for LPA");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700920 startUsbPlaybackIfNotStarted();
921 musbPlaybackState |= USBPLAYBACKBIT_LPA;
922 } else
923#endif
924 {
925 mALSADevice->route(&(*it), devices, mode());
926 }
927 if(sessionId == TUNNEL_SESSION_ID) {
928 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) {
929 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_TUNNEL);
930 } else {
931 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_TUNNEL);
932 }
933 }
934 else {
935 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) {
936 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOW_POWER);
937 } else {
938 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LPA);
939 }
940 }
941 err = mALSADevice->open(&(*it));
942 out = new AudioStreamOutALSA(this, &(*it));
943
944 if (status) *status = err;
945 return out;
946}
947
948void
949AudioHardwareALSA::closeOutputSession(AudioStreamOut* out)
950{
951 delete out;
952}
Ajay Dudani9746c472012-06-18 16:01:16 -0700953#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700954
955AudioStreamIn *
956AudioHardwareALSA::openInputStream(uint32_t devices,
957 int *format,
958 uint32_t *channels,
959 uint32_t *sampleRate,
960 status_t *status,
961 AudioSystem::audio_in_acoustics acoustics)
962{
963 Mutex::Autolock autoLock(mLock);
964 char *use_case;
965 int newMode = mode();
966 uint32_t route_devices;
967
968 status_t err = BAD_VALUE;
969 AudioStreamInALSA *in = 0;
970 ALSAHandleList::iterator it;
971
Iliyan Malchev4113f342012-06-11 14:39:47 -0700972 ALOGD("openInputStream: devices 0x%x channels %d sampleRate %d", devices, *channels, *sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700973 if (devices & (devices - 1)) {
974 if (status) *status = err;
975 return in;
976 }
977
978 if((devices == AudioSystem::DEVICE_IN_COMMUNICATION) &&
979 ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
980 bool voipstream_active = false;
981 for(it = mDeviceList.begin();
982 it != mDeviceList.end(); ++it) {
983 if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
984 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700985 ALOGD("openInput: it->rxHandle %p it->handle %p",it->rxHandle,it->handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700986 voipstream_active = true;
987 break;
988 }
989 }
990 if(voipstream_active == false) {
991 mVoipStreamCount = 0;
992 mVoipMicMute = false;
993 alsa_handle_t alsa_handle;
994 unsigned long bufferSize;
995 if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
996 bufferSize = VOIP_BUFFER_SIZE_8K;
997 }
998 else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
999 bufferSize = VOIP_BUFFER_SIZE_16K;
1000 }
1001 else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001002 ALOGE("unsupported samplerate %d for voip",*sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001003 if (status) *status = err;
1004 return in;
1005 }
1006 alsa_handle.module = mALSADevice;
1007 alsa_handle.bufferSize = bufferSize;
1008 alsa_handle.devices = devices;
1009 alsa_handle.handle = 0;
1010 if(*format == AudioSystem::PCM_16_BIT)
1011 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1012 else
1013 alsa_handle.format = *format;
1014 alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
1015 alsa_handle.sampleRate = *sampleRate;
1016 alsa_handle.latency = VOIP_RECORD_LATENCY;
1017 alsa_handle.rxHandle = 0;
1018 alsa_handle.ucMgr = mUcMgr;
1019 mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
1020 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1021 if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1022 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
1023 } else {
1024 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
1025 }
1026 free(use_case);
1027 mDeviceList.push_back(alsa_handle);
1028 it = mDeviceList.end();
1029 it--;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001030 ALOGD("mCurrDevice: %d", mCurDevice);
Ajay Dudani9746c472012-06-18 16:01:16 -07001031#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001032 if((mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1033 (mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -07001034 ALOGD("Routing everything from proxy for voipcall");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001035 mALSADevice->route(&(*it), AudioSystem::DEVICE_IN_PROXY, AudioSystem::MODE_IN_COMMUNICATION);
Iliyan Malchev4113f342012-06-11 14:39:47 -07001036 ALOGD("enabling VOIP in openInputstream, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001037 startUsbPlaybackIfNotStarted();
1038 musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001039 ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001040 startUsbRecordingIfNotStarted();
1041 musbRecordingState |= USBRECBIT_VOIPCALL;
SathishKumar Manie42406e2012-08-29 16:25:54 -07001042 } else
Iliyan Malchev4765c432012-06-11 14:36:16 -07001043#endif
1044 {
1045 mALSADevice->route(&(*it),mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
1046 }
1047 if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
1048 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
1049 } else {
1050 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
1051 }
1052 if(sampleRate) {
1053 it->sampleRate = *sampleRate;
1054 }
1055 if(channels)
1056 it->channels = AudioSystem::popCount(*channels);
1057 err = mALSADevice->startVoipCall(&(*it));
1058 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001059 ALOGE("Error opening pcm input device");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001060 return NULL;
1061 }
1062 }
1063 in = new AudioStreamInALSA(this, &(*it), acoustics);
1064 err = in->set(format, channels, sampleRate, devices);
1065 if(err == NO_ERROR) {
1066 mVoipStreamCount++; //increment VoipstreamCount only if success
Iliyan Malchev4113f342012-06-11 14:39:47 -07001067 ALOGD("OpenInput mVoipStreamCount %d",mVoipStreamCount);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001068 }
SathishKumar Mani0a019912012-09-11 12:33:11 -07001069 ALOGD("openInput: After Get alsahandle");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001070 if (status) *status = err;
1071 return in;
1072 } else
1073 {
1074 for(ALSAHandleList::iterator itDev = mDeviceList.begin();
1075 itDev != mDeviceList.end(); ++itDev)
1076 {
1077 if((0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_HIFI_REC, MAX_UC_LEN))
1078 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, MAX_UC_LEN))
SathishKumar Mani88613382012-08-13 18:40:18 -07001079 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, MAX_UC_LEN))
1080 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, MAX_UC_LEN))
Iliyan Malchev4765c432012-06-11 14:36:16 -07001081 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_FM, MAX_UC_LEN))
Ajay Dudani9746c472012-06-18 16:01:16 -07001082#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001083 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_FM_REC, MAX_UC_LEN))
1084#endif
1085 )
1086 {
Ajay Dudani9746c472012-06-18 16:01:16 -07001087#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001088 if(!(devices == AudioSystem::DEVICE_IN_FM_RX_A2DP)){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001089 ALOGD("Input stream already exists, new stream not permitted: useCase:%s, devices:0x%x, module:%p",
Iliyan Malchev4765c432012-06-11 14:36:16 -07001090 itDev->useCase, itDev->devices, itDev->module);
1091 return in;
1092 }
1093#endif
1094 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001095#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001096 else if ((0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_FM_A2DP_REC, MAX_UC_LEN))
1097 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, MAX_UC_LEN)))
1098 {
1099 if((devices == AudioSystem::DEVICE_IN_FM_RX_A2DP)){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001100 ALOGD("Input stream already exists, new stream not permitted: useCase:%s, devices:0x%x, module:%p",
Iliyan Malchev4765c432012-06-11 14:36:16 -07001101 itDev->useCase, itDev->devices, itDev->module);
1102 return in;
1103 }
1104 }
1105#endif
1106 }
1107
1108 alsa_handle_t alsa_handle;
1109 unsigned long bufferSize = DEFAULT_IN_BUFFER_SIZE;
1110
1111 alsa_handle.module = mALSADevice;
1112 alsa_handle.bufferSize = bufferSize;
1113 alsa_handle.devices = devices;
1114 alsa_handle.handle = 0;
1115 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1116 alsa_handle.channels = VOICE_CHANNEL_MODE;
1117 alsa_handle.sampleRate = android::AudioRecord::DEFAULT_SAMPLE_RATE;
1118 alsa_handle.latency = RECORD_LATENCY;
1119 alsa_handle.rxHandle = 0;
1120 alsa_handle.ucMgr = mUcMgr;
1121 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1122 if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1123 if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
1124 (newMode == AudioSystem::MODE_IN_CALL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001125 ALOGD("openInputStream: into incall recording, channels %d", *channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001126 mIncallMode = *channels;
1127 if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
1128 (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
1129 if (mFusion3Platform) {
1130 mALSADevice->setVocRecMode(INCALL_REC_STEREO);
1131 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1132 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001133 } else {
1134 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
1135 sizeof(alsa_handle.useCase));
1136 }
1137 } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
1138 if (mFusion3Platform) {
1139 mALSADevice->setVocRecMode(INCALL_REC_MONO);
1140 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1141 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001142 } else {
1143 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
1144 sizeof(alsa_handle.useCase));
1145 }
1146 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001147#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001148 } else if((devices == AudioSystem::DEVICE_IN_FM_RX)) {
1149 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_FM, sizeof(alsa_handle.useCase));
1150 } else if(devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
1151 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, sizeof(alsa_handle.useCase));
1152#endif
1153 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -07001154 char value[128];
1155 property_get("persist.audio.lowlatency.rec",value,"0");
1156 if (!strcmp("true", value)) {
1157 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
1158 } else {
1159 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, sizeof(alsa_handle.useCase));
1160 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001161 }
1162 } else {
1163 if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
1164 (newMode == AudioSystem::MODE_IN_CALL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001165 ALOGD("openInputStream: incall recording, channels %d", *channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001166 mIncallMode = *channels;
1167 if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
1168 (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
1169 if (mFusion3Platform) {
1170 mALSADevice->setVocRecMode(INCALL_REC_STEREO);
1171 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
1172 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001173 } else {
1174 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_UL_DL_REC,
1175 sizeof(alsa_handle.useCase));
1176 }
1177 } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
1178 if (mFusion3Platform) {
1179 mALSADevice->setVocRecMode(INCALL_REC_MONO);
1180 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
1181 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001182 } else {
1183 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DL_REC,
1184 sizeof(alsa_handle.useCase));
1185 }
1186 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001187#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001188 } else if(devices == AudioSystem::DEVICE_IN_FM_RX) {
1189 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_REC, sizeof(alsa_handle.useCase));
1190 } else if (devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
1191 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_A2DP_REC, sizeof(alsa_handle.useCase));
1192#endif
1193 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -07001194 char value[128];
1195 property_get("persist.audio.lowlatency.rec",value,"0");
1196 if (!strcmp("true", value)) {
1197 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, sizeof(alsa_handle.useCase));
1198 } else {
1199 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_REC, sizeof(alsa_handle.useCase));
1200 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001201 }
1202 }
1203 free(use_case);
1204 mDeviceList.push_back(alsa_handle);
1205 ALSAHandleList::iterator it = mDeviceList.end();
1206 it--;
1207 //update channel info before do routing
1208 if(channels) {
1209 it->channels = AudioSystem::popCount((*channels) &
Ajay Dudani9746c472012-06-18 16:01:16 -07001210 (AudioSystem::CHANNEL_IN_STEREO
1211 | AudioSystem::CHANNEL_IN_MONO
1212#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001213 | AudioSystem::CHANNEL_IN_5POINT1
1214#endif
1215 ));
Iliyan Malchev4113f342012-06-11 14:39:47 -07001216 ALOGV("updated channel info: channels=%d", it->channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001217 }
1218 if (devices == AudioSystem::DEVICE_IN_VOICE_CALL){
1219 /* Add current devices info to devices to do route */
Ajay Dudani9746c472012-06-18 16:01:16 -07001220#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001221 if(mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET ||
1222 mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001223 ALOGD("Routing everything from proxy for VOIP call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001224 route_devices = devices | AudioSystem::DEVICE_IN_PROXY;
1225 } else
1226#endif
1227 {
1228 route_devices = devices | mCurDevice;
1229 }
1230 mALSADevice->route(&(*it), route_devices, mode());
1231 } else {
Ajay Dudani9746c472012-06-18 16:01:16 -07001232#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001233 if(devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET ||
1234 devices & AudioSystem::DEVICE_IN_PROXY) {
1235 devices |= AudioSystem::DEVICE_IN_PROXY;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001236 ALOGD("routing everything from proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001237 mALSADevice->route(&(*it), devices, mode());
1238 } else
1239#endif
1240 {
1241 mALSADevice->route(&(*it), devices, mode());
1242 }
1243 }
1244
1245 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001246 !strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC) ||
Ajay Dudani9746c472012-06-18 16:01:16 -07001247#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001248 !strcmp(it->useCase, SND_USE_CASE_VERB_FM_REC) ||
1249 !strcmp(it->useCase, SND_USE_CASE_VERB_FM_A2DP_REC) ||
1250#endif
1251 !strcmp(it->useCase, SND_USE_CASE_VERB_DL_REC) ||
1252 !strcmp(it->useCase, SND_USE_CASE_VERB_UL_DL_REC) ||
1253 !strcmp(it->useCase, SND_USE_CASE_VERB_INCALL_REC)) {
1254 snd_use_case_set(mUcMgr, "_verb", it->useCase);
1255 } else {
1256 snd_use_case_set(mUcMgr, "_enamod", it->useCase);
1257 }
1258 if(sampleRate) {
1259 it->sampleRate = *sampleRate;
1260 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001261#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001262 if (6 == it->channels) {
1263 if (!strncmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
1264 || !strncmp(it->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001265 ALOGV("OpenInoutStream: Use larger buffer size for 5.1(%s) recording ", it->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001266 it->bufferSize = getInputBufferSize(it->sampleRate,*format,it->channels);
1267 }
1268 }
1269#endif
1270 err = mALSADevice->open(&(*it));
1271 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001272 ALOGE("Error opening pcm input device");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001273 } else {
1274 in = new AudioStreamInALSA(this, &(*it), acoustics);
1275 err = in->set(format, channels, sampleRate, devices);
1276 }
1277 if (status) *status = err;
1278 return in;
1279 }
1280}
1281
1282void
1283AudioHardwareALSA::closeInputStream(AudioStreamIn* in)
1284{
1285 delete in;
1286}
1287
1288status_t AudioHardwareALSA::setMicMute(bool state)
1289{
1290 int newMode = mode();
Iliyan Malchev4113f342012-06-11 14:39:47 -07001291 ALOGD("setMicMute newMode %d",newMode);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001292 if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
1293 if (mVoipMicMute != state) {
1294 mVoipMicMute = state;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001295 ALOGD("setMicMute: mVoipMicMute %d", mVoipMicMute);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001296 if(mALSADevice) {
1297 mALSADevice->setVoipMicMute(state);
1298 }
1299 }
1300 } else {
1301 if (mMicMute != state) {
1302 mMicMute = state;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001303 ALOGD("setMicMute: mMicMute %d", mMicMute);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001304 if(mALSADevice) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001305 if(mCSCallActive == CS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -07001306 mALSADevice->setMicMute(state);
Ajay Dudani9746c472012-06-18 16:01:16 -07001307 if(mVolteCallActive == IMS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -07001308 mALSADevice->setVoLTEMicMute(state);
1309 }
1310 }
1311 }
1312 return NO_ERROR;
1313}
1314
1315status_t AudioHardwareALSA::getMicMute(bool *state)
1316{
1317 int newMode = mode();
1318 if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
1319 *state = mVoipMicMute;
1320 } else {
1321 *state = mMicMute;
1322 }
1323 return NO_ERROR;
1324}
1325
1326status_t AudioHardwareALSA::dump(int fd, const Vector<String16>& args)
1327{
1328 return NO_ERROR;
1329}
1330
1331size_t AudioHardwareALSA::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
1332{
1333 size_t bufferSize;
1334 if (format != AudioSystem::PCM_16_BIT
1335 && format != AudioSystem::AMR_NB
1336 && format != AudioSystem::AMR_WB
Ajay Dudani9746c472012-06-18 16:01:16 -07001337#ifdef QCOM_QCHAT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001338 && format != AudioSystem::EVRC
1339 && format != AudioSystem::EVRCB
Ajay Dudani9746c472012-06-18 16:01:16 -07001340 && format != AudioSystem::EVRCWB
1341#endif
1342 ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001343 ALOGW("getInputBufferSize bad format: %d", format);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001344 return 0;
1345 }
1346 if(sampleRate == 16000) {
1347 bufferSize = DEFAULT_IN_BUFFER_SIZE * 2 * channelCount;
1348 } else if(sampleRate < 44100) {
1349 bufferSize = DEFAULT_IN_BUFFER_SIZE * channelCount;
1350 } else {
1351 bufferSize = DEFAULT_IN_BUFFER_SIZE * 12;
1352 }
1353 return bufferSize;
1354}
1355
Ajay Dudani9746c472012-06-18 16:01:16 -07001356#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001357void AudioHardwareALSA::handleFm(int device)
1358{
1359int newMode = mode();
1360 if(device & AudioSystem::DEVICE_OUT_FM && mIsFmActive == 0) {
1361 // Start FM Radio on current active device
1362 unsigned long bufferSize = FM_BUFFER_SIZE;
1363 alsa_handle_t alsa_handle;
1364 char *use_case;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001365 ALOGV("Start FM");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001366 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1367 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1368 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DIGITAL_RADIO, sizeof(alsa_handle.useCase));
1369 } else {
1370 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_FM, sizeof(alsa_handle.useCase));
1371 }
1372 free(use_case);
1373
1374 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1375 bufferSize &= ~b;
1376 alsa_handle.module = mALSADevice;
1377 alsa_handle.bufferSize = bufferSize;
1378 alsa_handle.devices = device;
1379 alsa_handle.handle = 0;
1380 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1381 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
1382 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
1383 alsa_handle.latency = VOICE_LATENCY;
1384 alsa_handle.rxHandle = 0;
1385 alsa_handle.ucMgr = mUcMgr;
1386 mIsFmActive = 1;
1387 mDeviceList.push_back(alsa_handle);
1388 ALSAHandleList::iterator it = mDeviceList.end();
1389 it--;
1390 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1391 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1392 device |= AudioSystem::DEVICE_OUT_PROXY;
1393 alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001394 ALOGD("Routing to proxy for FM case");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001395 }
1396 mALSADevice->route(&(*it), (uint32_t)device, newMode);
1397 if(!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) {
1398 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_DIGITAL_RADIO);
1399 } else {
1400 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_FM);
1401 }
1402 mALSADevice->startFm(&(*it));
1403 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1404 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -07001405 ALOGD("Starting FM, musbPlaybackState %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001406 startUsbPlaybackIfNotStarted();
1407 musbPlaybackState |= USBPLAYBACKBIT_FM;
1408 }
1409 } else if (!(device & AudioSystem::DEVICE_OUT_FM) && mIsFmActive == 1) {
1410 //i Stop FM Radio
Iliyan Malchev4113f342012-06-11 14:39:47 -07001411 ALOGV("Stop FM");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001412 for(ALSAHandleList::iterator it = mDeviceList.begin();
1413 it != mDeviceList.end(); ++it) {
1414 if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
1415 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
1416 mALSADevice->close(&(*it));
1417 //mALSADevice->route(&(*it), (uint32_t)device, newMode);
1418 mDeviceList.erase(it);
1419 break;
1420 }
1421 }
1422 mIsFmActive = 0;
1423 musbPlaybackState &= ~USBPLAYBACKBIT_FM;
1424 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1425 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1426 closeUsbPlaybackIfNothingActive();
1427 }
1428 }
1429}
1430#endif
1431
1432void AudioHardwareALSA::disableVoiceCall(char* verb, char* modifier, int mode, int device)
1433{
1434 for(ALSAHandleList::iterator it = mDeviceList.begin();
1435 it != mDeviceList.end(); ++it) {
1436 if((!strcmp(it->useCase, verb)) ||
1437 (!strcmp(it->useCase, modifier))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001438 ALOGV("Disabling voice call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001439 mALSADevice->close(&(*it));
1440 mALSADevice->route(&(*it), (uint32_t)device, mode);
1441 mDeviceList.erase(it);
1442 break;
1443 }
1444 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001445#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001446 if(musbPlaybackState & USBPLAYBACKBIT_VOICECALL) {
SathishKumar Mani0a019912012-09-11 12:33:11 -07001447 ALOGD("Voice call ended on USB");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001448 musbPlaybackState &= ~USBPLAYBACKBIT_VOICECALL;
1449 musbRecordingState &= ~USBRECBIT_VOICECALL;
1450 closeUsbRecordingIfNothingActive();
1451 closeUsbPlaybackIfNothingActive();
1452 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001453#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001454}
1455void AudioHardwareALSA::enableVoiceCall(char* verb, char* modifier, int mode, int device)
1456{
1457// Start voice call
SathishKumar Mani018d1c52012-09-11 14:58:18 -07001458unsigned long bufferSize = DEFAULT_VOICE_BUFFER_SIZE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001459alsa_handle_t alsa_handle;
1460char *use_case;
1461 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1462 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1463 strlcpy(alsa_handle.useCase, verb, sizeof(alsa_handle.useCase));
1464 } else {
1465 strlcpy(alsa_handle.useCase, modifier, sizeof(alsa_handle.useCase));
1466 }
1467 free(use_case);
1468
1469 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1470 bufferSize &= ~b;
1471 alsa_handle.module = mALSADevice;
1472 alsa_handle.bufferSize = bufferSize;
1473 alsa_handle.devices = device;
1474 alsa_handle.handle = 0;
1475 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1476 alsa_handle.channels = VOICE_CHANNEL_MODE;
1477 alsa_handle.sampleRate = VOICE_SAMPLING_RATE;
1478 alsa_handle.latency = VOICE_LATENCY;
1479 alsa_handle.rxHandle = 0;
1480 alsa_handle.ucMgr = mUcMgr;
1481 mDeviceList.push_back(alsa_handle);
1482 ALSAHandleList::iterator it = mDeviceList.end();
1483 it--;
Ajay Dudani9746c472012-06-18 16:01:16 -07001484#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001485 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1486 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1487 device |= AudioSystem::DEVICE_OUT_PROXY;
1488 alsa_handle.devices = device;
1489 }
1490#endif
1491 mALSADevice->route(&(*it), (uint32_t)device, mode);
1492 if (!strcmp(it->useCase, verb)) {
1493 snd_use_case_set(mUcMgr, "_verb", verb);
1494 } else {
1495 snd_use_case_set(mUcMgr, "_enamod", modifier);
1496 }
1497 mALSADevice->startVoiceCall(&(*it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001498#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001499 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1500 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1501 startUsbRecordingIfNotStarted();
1502 startUsbPlaybackIfNotStarted();
1503 musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
1504 musbRecordingState |= USBRECBIT_VOICECALL;
1505 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001506#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001507}
1508
1509bool AudioHardwareALSA::routeVoiceCall(int device, int newMode)
1510{
1511int csCallState = mCallState&0xF;
1512 bool isRouted = false;
1513 switch (csCallState) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001514 case CS_INACTIVE:
1515 if (mCSCallActive != CS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001516 ALOGD("doRouting: Disabling voice call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001517 disableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
1518 (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
1519 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001520 mCSCallActive = CS_INACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001521 }
1522 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001523 case CS_ACTIVE:
1524 if (mCSCallActive == CS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001525 ALOGD("doRouting: Enabling CS voice call ");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001526 enableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
1527 (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
1528 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001529 mCSCallActive = CS_ACTIVE;
1530 } else if (mCSCallActive == CS_HOLD) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001531 ALOGD("doRouting: Resume voice call from hold state");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001532 ALSAHandleList::iterator vt_it;
1533 for(vt_it = mDeviceList.begin();
1534 vt_it != mDeviceList.end(); ++vt_it) {
1535 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
1536 strlen(SND_USE_CASE_VERB_VOICECALL))) ||
1537 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1538 strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
1539 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001540 mCSCallActive = CS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001541 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001542 ALOGE("VoLTE resume failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001543 break;
1544 }
1545 }
1546 }
1547 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001548 case CS_HOLD:
1549 if (mCSCallActive == CS_ACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001550 ALOGD("doRouting: Voice call going to Hold");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001551 ALSAHandleList::iterator vt_it;
1552 for(vt_it = mDeviceList.begin();
1553 vt_it != mDeviceList.end(); ++vt_it) {
1554 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
1555 strlen(SND_USE_CASE_VERB_VOICECALL))) ||
1556 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1557 strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001558 mCSCallActive = CS_HOLD;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001559 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1560 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001561 ALOGE("Voice pause failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001562 break;
1563 }
1564 }
1565 }
1566 break;
1567 }
1568 return isRouted;
1569}
1570bool AudioHardwareALSA::routeVoLTECall(int device, int newMode)
1571{
1572int volteCallState = mCallState&0xF0;
1573bool isRouted = false;
1574switch (volteCallState) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001575 case IMS_INACTIVE:
1576 if (mVolteCallActive != IMS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001577 ALOGD("doRouting: Disabling IMS call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001578 disableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
1579 (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
1580 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001581 mVolteCallActive = IMS_INACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001582 }
1583 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001584 case IMS_ACTIVE:
1585 if (mVolteCallActive == IMS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001586 ALOGD("doRouting: Enabling IMS voice call ");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001587 enableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
1588 (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
1589 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001590 mVolteCallActive = IMS_ACTIVE;
1591 } else if (mVolteCallActive == IMS_HOLD) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001592 ALOGD("doRouting: Resume IMS call from hold state");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001593 ALSAHandleList::iterator vt_it;
1594 for(vt_it = mDeviceList.begin();
1595 vt_it != mDeviceList.end(); ++vt_it) {
1596 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
1597 strlen(SND_USE_CASE_VERB_VOLTE))) ||
1598 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1599 strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
1600 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001601 mVolteCallActive = IMS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001602 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001603 ALOGE("VoLTE resume failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001604 break;
1605 }
1606 }
1607 }
1608 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001609 case IMS_HOLD:
1610 if (mVolteCallActive == IMS_ACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001611 ALOGD("doRouting: IMS ACTIVE going to HOLD");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001612 ALSAHandleList::iterator vt_it;
1613 for(vt_it = mDeviceList.begin();
1614 vt_it != mDeviceList.end(); ++vt_it) {
1615 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
1616 strlen(SND_USE_CASE_VERB_VOLTE))) ||
1617 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1618 strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001619 mVolteCallActive = IMS_HOLD;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001620 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1621 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001622 ALOGE("VoLTE Pause failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001623 break;
1624 }
1625 }
1626 }
1627 break;
1628 }
1629 return isRouted;
1630}
1631
1632} // namespace android_audio_legacy