blob: f33ef9f5ce8524032107e75732148eb872cc9fd4 [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 }
615 } else
616#endif
617 if((((mCurDevice & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
618 (mCurDevice & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) &&
619 (mCurDevice & AudioSystem::DEVICE_OUT_SPEAKER) &&
620 ((device & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
621 (device & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) ||
622 (((device & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
623 (device & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) &&
624 (device & AudioSystem::DEVICE_OUT_SPEAKER) &&
625 ((mCurDevice & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
626 (mCurDevice & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)))) {
627 for(ALSAHandleList::iterator it = mDeviceList.begin();
628 it != mDeviceList.end(); ++it) {
629 if((!strncmp(it->useCase, SND_USE_CASE_VERB_HIFI,
630 strlen(SND_USE_CASE_VERB_HIFI))) ||
631 (!strncmp(it->useCase, SND_USE_CASE_MOD_PLAY_MUSIC,
632 strlen(SND_USE_CASE_MOD_PLAY_MUSIC)))) {
633 mALSADevice->route(&(*it),(uint32_t)device, newMode);
634 break;
635 }
636 }
637 } else {
638 ALSAHandleList::iterator it = mDeviceList.end();
639 it--;
640 mALSADevice->route(&(*it), (uint32_t)device, newMode);
641 }
642 }
643 mCurDevice = device;
644}
645
646uint32_t AudioHardwareALSA::getVoipMode(int format)
647{
648 switch(format) {
649 case AudioSystem::PCM_16_BIT:
650 return MODE_PCM;
651 break;
652 case AudioSystem::AMR_NB:
653 return MODE_AMR;
654 break;
655 case AudioSystem::AMR_WB:
656 return MODE_AMR_WB;
657 break;
658
Ajay Dudani9746c472012-06-18 16:01:16 -0700659#ifdef QCOM_QCHAT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700660 case AudioSystem::EVRC:
661 return MODE_IS127;
662 break;
663
664 case AudioSystem::EVRCB:
665 return MODE_4GV_NB;
666 break;
667 case AudioSystem::EVRCWB:
668 return MODE_4GV_WB;
669 break;
Ajay Dudani9746c472012-06-18 16:01:16 -0700670#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700671
672 default:
673 return MODE_PCM;
674 }
675}
676
677AudioStreamOut *
678AudioHardwareALSA::openOutputStream(uint32_t devices,
679 int *format,
680 uint32_t *channels,
681 uint32_t *sampleRate,
682 status_t *status)
683{
684 Mutex::Autolock autoLock(mLock);
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700685 ALOGV("openOutputStream: devices 0x%x channels %d sampleRate %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700686 devices, *channels, *sampleRate);
687
SathishKumar Mani88613382012-08-13 18:40:18 -0700688 audio_output_flags_t flag = static_cast<audio_output_flags_t> (*status);
689
Iliyan Malchev4765c432012-06-11 14:36:16 -0700690 status_t err = BAD_VALUE;
SathishKumar Mani88613382012-08-13 18:40:18 -0700691 *status = NO_ERROR;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700692 AudioStreamOutALSA *out = 0;
693 ALSAHandleList::iterator it;
694
695 if (devices & (devices - 1)) {
696 if (status) *status = err;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700697 ALOGE("openOutputStream called with bad devices");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700698 return out;
699 }
SathishKumar Mani88613382012-08-13 18:40:18 -0700700
701
Iliyan Malchev4765c432012-06-11 14:36:16 -0700702# if 0
703 if((devices == AudioSystem::DEVICE_OUT_DIRECTOUTPUT) &&
704 ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
705 bool voipstream_active = false;
706 for(it = mDeviceList.begin();
707 it != mDeviceList.end(); ++it) {
708 if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
709 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700710 ALOGD("openOutput: it->rxHandle %d it->handle %d",it->rxHandle,it->handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700711 voipstream_active = true;
712 break;
713 }
714 }
715 if(voipstream_active == false) {
716 mVoipStreamCount = 0;
717 mVoipMicMute = false;
718 alsa_handle_t alsa_handle;
719 unsigned long bufferSize;
720 if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
721 bufferSize = VOIP_BUFFER_SIZE_8K;
722 }
723 else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
724 bufferSize = VOIP_BUFFER_SIZE_16K;
725 }
726 else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700727 ALOGE("unsupported samplerate %d for voip",*sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700728 if (status) *status = err;
729 return out;
730 }
731 alsa_handle.module = mALSADevice;
732 alsa_handle.bufferSize = bufferSize;
733 alsa_handle.devices = devices;
734 alsa_handle.handle = 0;
735 if(*format == AudioSystem::PCM_16_BIT)
736 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
737 else
738 alsa_handle.format = *format;
739 alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
740 alsa_handle.sampleRate = *sampleRate;
741 alsa_handle.latency = VOIP_PLAYBACK_LATENCY;
742 alsa_handle.rxHandle = 0;
743 alsa_handle.ucMgr = mUcMgr;
744 mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
745 char *use_case;
746 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
747 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
748 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
749 } else {
750 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
751 }
752 free(use_case);
753 mDeviceList.push_back(alsa_handle);
754 it = mDeviceList.end();
755 it--;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700756 ALOGV("openoutput: mALSADevice->route useCase %s mCurDevice %d mVoipStreamCount %d mode %d", it->useCase,mCurDevice,mVoipStreamCount, mode());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700757 if((mCurDevice & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
758 (mCurDevice & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)||
759 (mCurDevice & AudioSystem::DEVICE_OUT_PROXY)){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700760 ALOGD("Routing to proxy for normal voip call in openOutputStream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700761 mCurDevice |= AudioSystem::DEVICE_OUT_PROXY;
762 alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
763 mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700764 ALOGD("enabling VOIP in openoutputstream, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700765 startUsbPlaybackIfNotStarted();
766 musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700767 ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700768 startUsbRecordingIfNotStarted();
769 musbRecordingState |= USBRECBIT_VOIPCALL;
770 } else{
771 mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
772 }
773 if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
774 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
775 } else {
776 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
777 }
778 err = mALSADevice->startVoipCall(&(*it));
779 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700780 ALOGE("Device open failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700781 return NULL;
782 }
783 }
784 out = new AudioStreamOutALSA(this, &(*it));
785 err = out->set(format, channels, sampleRate, devices);
786 if(err == NO_ERROR) {
787 mVoipStreamCount++; //increment VoipstreamCount only if success
Iliyan Malchev4113f342012-06-11 14:39:47 -0700788 ALOGD("openoutput mVoipStreamCount %d",mVoipStreamCount);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700789 }
790 if (status) *status = err;
791 return out;
792 } else
793#endif
794 {
795
796 alsa_handle_t alsa_handle;
797 unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
798
799 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
800 bufferSize &= ~b;
801
802 alsa_handle.module = mALSADevice;
803 alsa_handle.bufferSize = bufferSize;
804 alsa_handle.devices = devices;
805 alsa_handle.handle = 0;
806 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
807 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
808 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
809 alsa_handle.latency = PLAYBACK_LATENCY;
810 alsa_handle.rxHandle = 0;
811 alsa_handle.ucMgr = mUcMgr;
SathishKumar Mani88613382012-08-13 18:40:18 -0700812 alsa_handle.isDeepbufferOutput = false;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700813
814 char *use_case;
815 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
SathishKumar Mani88613382012-08-13 18:40:18 -0700816
817 if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
818 ALOGD("openOutputStream: DeepBuffer Output");
819 alsa_handle.isDeepbufferOutput = true;
820 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
821 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI, sizeof(alsa_handle.useCase));
822 } else {
823 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC, sizeof(alsa_handle.useCase));
824 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700825 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -0700826 ALOGD("openOutputStream: Lowlatency Output");
827 alsa_handle.bufferSize = PLAYBACK_LOW_LATENCY_BUFFER_SIZE;
828 alsa_handle.latency = PLAYBACK_LOW_LATENCY;
829 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
830 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
831 } else {
832 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
833 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700834 }
835 free(use_case);
836 mDeviceList.push_back(alsa_handle);
837 ALSAHandleList::iterator it = mDeviceList.end();
838 it--;
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700839 ALOGV("useCase %s", it->useCase);
Ajay Dudani9746c472012-06-18 16:01:16 -0700840#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700841 if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
842 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -0700843 ALOGD("Routing to proxy for normal playback in openOutputStream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700844 devices |= AudioSystem::DEVICE_OUT_PROXY;
845 }
846#endif
847 mALSADevice->route(&(*it), devices, mode());
SathishKumar Mani88613382012-08-13 18:40:18 -0700848 if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
849 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI)) {
850 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI);
851 } else {
852 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC);
853 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700854 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -0700855 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) {
856 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC);
857 } else {
858 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC);
859 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700860 }
861 err = mALSADevice->open(&(*it));
862 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700863 ALOGE("Device open failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700864 } else {
865 out = new AudioStreamOutALSA(this, &(*it));
866 err = out->set(format, channels, sampleRate, devices);
867 }
868
869 if (status) *status = err;
870 return out;
871 }
872}
873
874void
875AudioHardwareALSA::closeOutputStream(AudioStreamOut* out)
876{
877 delete out;
878}
879
Ajay Dudani9746c472012-06-18 16:01:16 -0700880#ifdef QCOM_TUNNEL_LPA_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700881AudioStreamOut *
882AudioHardwareALSA::openOutputSession(uint32_t devices,
883 int *format,
884 status_t *status,
885 int sessionId,
886 uint32_t samplingRate,
887 uint32_t channels)
888{
889 Mutex::Autolock autoLock(mLock);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700890 ALOGD("openOutputSession = %d" ,sessionId);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700891 AudioStreamOutALSA *out = 0;
892 status_t err = BAD_VALUE;
893
894 alsa_handle_t alsa_handle;
895 unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
896
897 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
898 bufferSize &= ~b;
899
900 alsa_handle.module = mALSADevice;
901 alsa_handle.bufferSize = bufferSize;
902 alsa_handle.devices = devices;
903 alsa_handle.handle = 0;
904 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
905 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
906 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
907 alsa_handle.latency = VOICE_LATENCY;
908 alsa_handle.rxHandle = 0;
909 alsa_handle.ucMgr = mUcMgr;
910
911 char *use_case;
912 if(sessionId == TUNNEL_SESSION_ID) {
913 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
914 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
915 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_TUNNEL, sizeof(alsa_handle.useCase));
916 } else {
917 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_TUNNEL, sizeof(alsa_handle.useCase));
918 }
919 } else {
920 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
921 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
922 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER, sizeof(alsa_handle.useCase));
923 } else {
924 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LPA, sizeof(alsa_handle.useCase));
925 }
926 }
927 free(use_case);
928 mDeviceList.push_back(alsa_handle);
929 ALSAHandleList::iterator it = mDeviceList.end();
930 it--;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700931 ALOGD("useCase %s", it->useCase);
Ajay Dudani9746c472012-06-18 16:01:16 -0700932#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700933 if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
934 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -0700935 ALOGD("Routing to proxy for LPA in openOutputSession");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700936 devices |= AudioSystem::DEVICE_OUT_PROXY;
937 mALSADevice->route(&(*it), devices, mode());
938 devices = AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700939 ALOGD("Starting USBPlayback for LPA");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700940 startUsbPlaybackIfNotStarted();
941 musbPlaybackState |= USBPLAYBACKBIT_LPA;
942 } else
943#endif
944 {
945 mALSADevice->route(&(*it), devices, mode());
946 }
947 if(sessionId == TUNNEL_SESSION_ID) {
948 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) {
949 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_TUNNEL);
950 } else {
951 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_TUNNEL);
952 }
953 }
954 else {
955 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) {
956 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOW_POWER);
957 } else {
958 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LPA);
959 }
960 }
961 err = mALSADevice->open(&(*it));
962 out = new AudioStreamOutALSA(this, &(*it));
963
964 if (status) *status = err;
965 return out;
966}
967
968void
969AudioHardwareALSA::closeOutputSession(AudioStreamOut* out)
970{
971 delete out;
972}
Ajay Dudani9746c472012-06-18 16:01:16 -0700973#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700974
975AudioStreamIn *
976AudioHardwareALSA::openInputStream(uint32_t devices,
977 int *format,
978 uint32_t *channels,
979 uint32_t *sampleRate,
980 status_t *status,
981 AudioSystem::audio_in_acoustics acoustics)
982{
983 Mutex::Autolock autoLock(mLock);
984 char *use_case;
985 int newMode = mode();
986 uint32_t route_devices;
987
988 status_t err = BAD_VALUE;
989 AudioStreamInALSA *in = 0;
990 ALSAHandleList::iterator it;
991
Iliyan Malchev4113f342012-06-11 14:39:47 -0700992 ALOGD("openInputStream: devices 0x%x channels %d sampleRate %d", devices, *channels, *sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700993 if (devices & (devices - 1)) {
994 if (status) *status = err;
995 return in;
996 }
997
998 if((devices == AudioSystem::DEVICE_IN_COMMUNICATION) &&
999 ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
1000 bool voipstream_active = false;
1001 for(it = mDeviceList.begin();
1002 it != mDeviceList.end(); ++it) {
1003 if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
1004 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001005 ALOGD("openInput: it->rxHandle %p it->handle %p",it->rxHandle,it->handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001006 voipstream_active = true;
1007 break;
1008 }
1009 }
1010 if(voipstream_active == false) {
1011 mVoipStreamCount = 0;
1012 mVoipMicMute = false;
1013 alsa_handle_t alsa_handle;
1014 unsigned long bufferSize;
1015 if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
1016 bufferSize = VOIP_BUFFER_SIZE_8K;
1017 }
1018 else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
1019 bufferSize = VOIP_BUFFER_SIZE_16K;
1020 }
1021 else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001022 ALOGE("unsupported samplerate %d for voip",*sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001023 if (status) *status = err;
1024 return in;
1025 }
1026 alsa_handle.module = mALSADevice;
1027 alsa_handle.bufferSize = bufferSize;
1028 alsa_handle.devices = devices;
1029 alsa_handle.handle = 0;
1030 if(*format == AudioSystem::PCM_16_BIT)
1031 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1032 else
1033 alsa_handle.format = *format;
1034 alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
1035 alsa_handle.sampleRate = *sampleRate;
1036 alsa_handle.latency = VOIP_RECORD_LATENCY;
1037 alsa_handle.rxHandle = 0;
1038 alsa_handle.ucMgr = mUcMgr;
1039 mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
1040 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1041 if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1042 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
1043 } else {
1044 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
1045 }
1046 free(use_case);
1047 mDeviceList.push_back(alsa_handle);
1048 it = mDeviceList.end();
1049 it--;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001050 ALOGD("mCurrDevice: %d", mCurDevice);
Ajay Dudani9746c472012-06-18 16:01:16 -07001051#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001052 if((mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1053 (mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -07001054 ALOGD("Routing everything from proxy for voipcall");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001055 mALSADevice->route(&(*it), AudioSystem::DEVICE_IN_PROXY, AudioSystem::MODE_IN_COMMUNICATION);
Iliyan Malchev4113f342012-06-11 14:39:47 -07001056 ALOGD("enabling VOIP in openInputstream, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001057 startUsbPlaybackIfNotStarted();
1058 musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001059 ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001060 startUsbRecordingIfNotStarted();
1061 musbRecordingState |= USBRECBIT_VOIPCALL;
1062 }else
1063#endif
1064 {
1065 mALSADevice->route(&(*it),mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
1066 }
1067 if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
1068 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
1069 } else {
1070 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
1071 }
1072 if(sampleRate) {
1073 it->sampleRate = *sampleRate;
1074 }
1075 if(channels)
1076 it->channels = AudioSystem::popCount(*channels);
1077 err = mALSADevice->startVoipCall(&(*it));
1078 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001079 ALOGE("Error opening pcm input device");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001080 return NULL;
1081 }
1082 }
1083 in = new AudioStreamInALSA(this, &(*it), acoustics);
1084 err = in->set(format, channels, sampleRate, devices);
1085 if(err == NO_ERROR) {
1086 mVoipStreamCount++; //increment VoipstreamCount only if success
Iliyan Malchev4113f342012-06-11 14:39:47 -07001087 ALOGD("OpenInput mVoipStreamCount %d",mVoipStreamCount);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001088 }
SathishKumar Mani0a019912012-09-11 12:33:11 -07001089 ALOGD("openInput: After Get alsahandle");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001090 if (status) *status = err;
1091 return in;
1092 } else
1093 {
1094 for(ALSAHandleList::iterator itDev = mDeviceList.begin();
1095 itDev != mDeviceList.end(); ++itDev)
1096 {
1097 if((0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_HIFI_REC, MAX_UC_LEN))
1098 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, MAX_UC_LEN))
SathishKumar Mani88613382012-08-13 18:40:18 -07001099 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, MAX_UC_LEN))
1100 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, MAX_UC_LEN))
Iliyan Malchev4765c432012-06-11 14:36:16 -07001101 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_FM, MAX_UC_LEN))
Ajay Dudani9746c472012-06-18 16:01:16 -07001102#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001103 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_FM_REC, MAX_UC_LEN))
1104#endif
1105 )
1106 {
Ajay Dudani9746c472012-06-18 16:01:16 -07001107#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001108 if(!(devices == AudioSystem::DEVICE_IN_FM_RX_A2DP)){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001109 ALOGD("Input stream already exists, new stream not permitted: useCase:%s, devices:0x%x, module:%p",
Iliyan Malchev4765c432012-06-11 14:36:16 -07001110 itDev->useCase, itDev->devices, itDev->module);
1111 return in;
1112 }
1113#endif
1114 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001115#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001116 else if ((0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_FM_A2DP_REC, MAX_UC_LEN))
1117 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, MAX_UC_LEN)))
1118 {
1119 if((devices == AudioSystem::DEVICE_IN_FM_RX_A2DP)){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001120 ALOGD("Input stream already exists, new stream not permitted: useCase:%s, devices:0x%x, module:%p",
Iliyan Malchev4765c432012-06-11 14:36:16 -07001121 itDev->useCase, itDev->devices, itDev->module);
1122 return in;
1123 }
1124 }
1125#endif
1126 }
1127
1128 alsa_handle_t alsa_handle;
1129 unsigned long bufferSize = DEFAULT_IN_BUFFER_SIZE;
1130
1131 alsa_handle.module = mALSADevice;
1132 alsa_handle.bufferSize = bufferSize;
1133 alsa_handle.devices = devices;
1134 alsa_handle.handle = 0;
1135 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1136 alsa_handle.channels = VOICE_CHANNEL_MODE;
1137 alsa_handle.sampleRate = android::AudioRecord::DEFAULT_SAMPLE_RATE;
1138 alsa_handle.latency = RECORD_LATENCY;
1139 alsa_handle.rxHandle = 0;
1140 alsa_handle.ucMgr = mUcMgr;
1141 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1142 if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1143 if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
1144 (newMode == AudioSystem::MODE_IN_CALL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001145 ALOGD("openInputStream: into incall recording, channels %d", *channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001146 mIncallMode = *channels;
1147 if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
1148 (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
1149 if (mFusion3Platform) {
1150 mALSADevice->setVocRecMode(INCALL_REC_STEREO);
1151 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1152 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001153 } else {
1154 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
1155 sizeof(alsa_handle.useCase));
1156 }
1157 } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
1158 if (mFusion3Platform) {
1159 mALSADevice->setVocRecMode(INCALL_REC_MONO);
1160 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1161 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001162 } else {
1163 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
1164 sizeof(alsa_handle.useCase));
1165 }
1166 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001167#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001168 } else if((devices == AudioSystem::DEVICE_IN_FM_RX)) {
1169 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_FM, sizeof(alsa_handle.useCase));
1170 } else if(devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
1171 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, sizeof(alsa_handle.useCase));
1172#endif
1173 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -07001174 char value[128];
1175 property_get("persist.audio.lowlatency.rec",value,"0");
1176 if (!strcmp("true", value)) {
1177 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
1178 } else {
1179 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, sizeof(alsa_handle.useCase));
1180 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001181 }
1182 } else {
1183 if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
1184 (newMode == AudioSystem::MODE_IN_CALL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001185 ALOGD("openInputStream: incall recording, channels %d", *channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001186 mIncallMode = *channels;
1187 if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
1188 (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
1189 if (mFusion3Platform) {
1190 mALSADevice->setVocRecMode(INCALL_REC_STEREO);
1191 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
1192 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001193 } else {
1194 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_UL_DL_REC,
1195 sizeof(alsa_handle.useCase));
1196 }
1197 } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
1198 if (mFusion3Platform) {
1199 mALSADevice->setVocRecMode(INCALL_REC_MONO);
1200 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
1201 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001202 } else {
1203 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DL_REC,
1204 sizeof(alsa_handle.useCase));
1205 }
1206 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001207#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001208 } else if(devices == AudioSystem::DEVICE_IN_FM_RX) {
1209 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_REC, sizeof(alsa_handle.useCase));
1210 } else if (devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
1211 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_A2DP_REC, sizeof(alsa_handle.useCase));
1212#endif
1213 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -07001214 char value[128];
1215 property_get("persist.audio.lowlatency.rec",value,"0");
1216 if (!strcmp("true", value)) {
1217 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, sizeof(alsa_handle.useCase));
1218 } else {
1219 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_REC, sizeof(alsa_handle.useCase));
1220 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001221 }
1222 }
1223 free(use_case);
1224 mDeviceList.push_back(alsa_handle);
1225 ALSAHandleList::iterator it = mDeviceList.end();
1226 it--;
1227 //update channel info before do routing
1228 if(channels) {
1229 it->channels = AudioSystem::popCount((*channels) &
Ajay Dudani9746c472012-06-18 16:01:16 -07001230 (AudioSystem::CHANNEL_IN_STEREO
1231 | AudioSystem::CHANNEL_IN_MONO
1232#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001233 | AudioSystem::CHANNEL_IN_5POINT1
1234#endif
1235 ));
Iliyan Malchev4113f342012-06-11 14:39:47 -07001236 ALOGV("updated channel info: channels=%d", it->channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001237 }
1238 if (devices == AudioSystem::DEVICE_IN_VOICE_CALL){
1239 /* Add current devices info to devices to do route */
Ajay Dudani9746c472012-06-18 16:01:16 -07001240#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001241 if(mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET ||
1242 mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001243 ALOGD("Routing everything from proxy for VOIP call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001244 route_devices = devices | AudioSystem::DEVICE_IN_PROXY;
1245 } else
1246#endif
1247 {
1248 route_devices = devices | mCurDevice;
1249 }
1250 mALSADevice->route(&(*it), route_devices, mode());
1251 } else {
Ajay Dudani9746c472012-06-18 16:01:16 -07001252#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001253 if(devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET ||
1254 devices & AudioSystem::DEVICE_IN_PROXY) {
1255 devices |= AudioSystem::DEVICE_IN_PROXY;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001256 ALOGD("routing everything from proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001257 mALSADevice->route(&(*it), devices, mode());
1258 } else
1259#endif
1260 {
1261 mALSADevice->route(&(*it), devices, mode());
1262 }
1263 }
1264
1265 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001266 !strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC) ||
Ajay Dudani9746c472012-06-18 16:01:16 -07001267#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001268 !strcmp(it->useCase, SND_USE_CASE_VERB_FM_REC) ||
1269 !strcmp(it->useCase, SND_USE_CASE_VERB_FM_A2DP_REC) ||
1270#endif
1271 !strcmp(it->useCase, SND_USE_CASE_VERB_DL_REC) ||
1272 !strcmp(it->useCase, SND_USE_CASE_VERB_UL_DL_REC) ||
1273 !strcmp(it->useCase, SND_USE_CASE_VERB_INCALL_REC)) {
1274 snd_use_case_set(mUcMgr, "_verb", it->useCase);
1275 } else {
1276 snd_use_case_set(mUcMgr, "_enamod", it->useCase);
1277 }
1278 if(sampleRate) {
1279 it->sampleRate = *sampleRate;
1280 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001281#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001282 if (6 == it->channels) {
1283 if (!strncmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
1284 || !strncmp(it->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001285 ALOGV("OpenInoutStream: Use larger buffer size for 5.1(%s) recording ", it->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001286 it->bufferSize = getInputBufferSize(it->sampleRate,*format,it->channels);
1287 }
1288 }
1289#endif
1290 err = mALSADevice->open(&(*it));
1291 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001292 ALOGE("Error opening pcm input device");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001293 } else {
1294 in = new AudioStreamInALSA(this, &(*it), acoustics);
1295 err = in->set(format, channels, sampleRate, devices);
1296 }
1297 if (status) *status = err;
1298 return in;
1299 }
1300}
1301
1302void
1303AudioHardwareALSA::closeInputStream(AudioStreamIn* in)
1304{
1305 delete in;
1306}
1307
1308status_t AudioHardwareALSA::setMicMute(bool state)
1309{
1310 int newMode = mode();
Iliyan Malchev4113f342012-06-11 14:39:47 -07001311 ALOGD("setMicMute newMode %d",newMode);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001312 if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
1313 if (mVoipMicMute != state) {
1314 mVoipMicMute = state;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001315 ALOGD("setMicMute: mVoipMicMute %d", mVoipMicMute);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001316 if(mALSADevice) {
1317 mALSADevice->setVoipMicMute(state);
1318 }
1319 }
1320 } else {
1321 if (mMicMute != state) {
1322 mMicMute = state;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001323 ALOGD("setMicMute: mMicMute %d", mMicMute);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001324 if(mALSADevice) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001325 if(mCSCallActive == CS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -07001326 mALSADevice->setMicMute(state);
Ajay Dudani9746c472012-06-18 16:01:16 -07001327 if(mVolteCallActive == IMS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -07001328 mALSADevice->setVoLTEMicMute(state);
1329 }
1330 }
1331 }
1332 return NO_ERROR;
1333}
1334
1335status_t AudioHardwareALSA::getMicMute(bool *state)
1336{
1337 int newMode = mode();
1338 if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
1339 *state = mVoipMicMute;
1340 } else {
1341 *state = mMicMute;
1342 }
1343 return NO_ERROR;
1344}
1345
1346status_t AudioHardwareALSA::dump(int fd, const Vector<String16>& args)
1347{
1348 return NO_ERROR;
1349}
1350
1351size_t AudioHardwareALSA::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
1352{
1353 size_t bufferSize;
1354 if (format != AudioSystem::PCM_16_BIT
1355 && format != AudioSystem::AMR_NB
1356 && format != AudioSystem::AMR_WB
Ajay Dudani9746c472012-06-18 16:01:16 -07001357#ifdef QCOM_QCHAT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001358 && format != AudioSystem::EVRC
1359 && format != AudioSystem::EVRCB
Ajay Dudani9746c472012-06-18 16:01:16 -07001360 && format != AudioSystem::EVRCWB
1361#endif
1362 ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001363 ALOGW("getInputBufferSize bad format: %d", format);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001364 return 0;
1365 }
1366 if(sampleRate == 16000) {
1367 bufferSize = DEFAULT_IN_BUFFER_SIZE * 2 * channelCount;
1368 } else if(sampleRate < 44100) {
1369 bufferSize = DEFAULT_IN_BUFFER_SIZE * channelCount;
1370 } else {
1371 bufferSize = DEFAULT_IN_BUFFER_SIZE * 12;
1372 }
1373 return bufferSize;
1374}
1375
Ajay Dudani9746c472012-06-18 16:01:16 -07001376#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001377void AudioHardwareALSA::handleFm(int device)
1378{
1379int newMode = mode();
1380 if(device & AudioSystem::DEVICE_OUT_FM && mIsFmActive == 0) {
1381 // Start FM Radio on current active device
1382 unsigned long bufferSize = FM_BUFFER_SIZE;
1383 alsa_handle_t alsa_handle;
1384 char *use_case;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001385 ALOGV("Start FM");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001386 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1387 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1388 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DIGITAL_RADIO, sizeof(alsa_handle.useCase));
1389 } else {
1390 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_FM, sizeof(alsa_handle.useCase));
1391 }
1392 free(use_case);
1393
1394 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1395 bufferSize &= ~b;
1396 alsa_handle.module = mALSADevice;
1397 alsa_handle.bufferSize = bufferSize;
1398 alsa_handle.devices = device;
1399 alsa_handle.handle = 0;
1400 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1401 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
1402 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
1403 alsa_handle.latency = VOICE_LATENCY;
1404 alsa_handle.rxHandle = 0;
1405 alsa_handle.ucMgr = mUcMgr;
1406 mIsFmActive = 1;
1407 mDeviceList.push_back(alsa_handle);
1408 ALSAHandleList::iterator it = mDeviceList.end();
1409 it--;
1410 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1411 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1412 device |= AudioSystem::DEVICE_OUT_PROXY;
1413 alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001414 ALOGD("Routing to proxy for FM case");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001415 }
1416 mALSADevice->route(&(*it), (uint32_t)device, newMode);
1417 if(!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) {
1418 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_DIGITAL_RADIO);
1419 } else {
1420 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_FM);
1421 }
1422 mALSADevice->startFm(&(*it));
1423 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1424 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -07001425 ALOGD("Starting FM, musbPlaybackState %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001426 startUsbPlaybackIfNotStarted();
1427 musbPlaybackState |= USBPLAYBACKBIT_FM;
1428 }
1429 } else if (!(device & AudioSystem::DEVICE_OUT_FM) && mIsFmActive == 1) {
1430 //i Stop FM Radio
Iliyan Malchev4113f342012-06-11 14:39:47 -07001431 ALOGV("Stop FM");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001432 for(ALSAHandleList::iterator it = mDeviceList.begin();
1433 it != mDeviceList.end(); ++it) {
1434 if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
1435 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
1436 mALSADevice->close(&(*it));
1437 //mALSADevice->route(&(*it), (uint32_t)device, newMode);
1438 mDeviceList.erase(it);
1439 break;
1440 }
1441 }
1442 mIsFmActive = 0;
1443 musbPlaybackState &= ~USBPLAYBACKBIT_FM;
1444 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1445 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1446 closeUsbPlaybackIfNothingActive();
1447 }
1448 }
1449}
1450#endif
1451
1452void AudioHardwareALSA::disableVoiceCall(char* verb, char* modifier, int mode, int device)
1453{
1454 for(ALSAHandleList::iterator it = mDeviceList.begin();
1455 it != mDeviceList.end(); ++it) {
1456 if((!strcmp(it->useCase, verb)) ||
1457 (!strcmp(it->useCase, modifier))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001458 ALOGV("Disabling voice call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001459 mALSADevice->close(&(*it));
1460 mALSADevice->route(&(*it), (uint32_t)device, mode);
1461 mDeviceList.erase(it);
1462 break;
1463 }
1464 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001465#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001466 if(musbPlaybackState & USBPLAYBACKBIT_VOICECALL) {
SathishKumar Mani0a019912012-09-11 12:33:11 -07001467 ALOGD("Voice call ended on USB");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001468 musbPlaybackState &= ~USBPLAYBACKBIT_VOICECALL;
1469 musbRecordingState &= ~USBRECBIT_VOICECALL;
1470 closeUsbRecordingIfNothingActive();
1471 closeUsbPlaybackIfNothingActive();
1472 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001473#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001474}
1475void AudioHardwareALSA::enableVoiceCall(char* verb, char* modifier, int mode, int device)
1476{
1477// Start voice call
SathishKumar Mani018d1c52012-09-11 14:58:18 -07001478unsigned long bufferSize = DEFAULT_VOICE_BUFFER_SIZE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001479alsa_handle_t alsa_handle;
1480char *use_case;
1481 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1482 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1483 strlcpy(alsa_handle.useCase, verb, sizeof(alsa_handle.useCase));
1484 } else {
1485 strlcpy(alsa_handle.useCase, modifier, sizeof(alsa_handle.useCase));
1486 }
1487 free(use_case);
1488
1489 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1490 bufferSize &= ~b;
1491 alsa_handle.module = mALSADevice;
1492 alsa_handle.bufferSize = bufferSize;
1493 alsa_handle.devices = device;
1494 alsa_handle.handle = 0;
1495 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1496 alsa_handle.channels = VOICE_CHANNEL_MODE;
1497 alsa_handle.sampleRate = VOICE_SAMPLING_RATE;
1498 alsa_handle.latency = VOICE_LATENCY;
1499 alsa_handle.rxHandle = 0;
1500 alsa_handle.ucMgr = mUcMgr;
1501 mDeviceList.push_back(alsa_handle);
1502 ALSAHandleList::iterator it = mDeviceList.end();
1503 it--;
Ajay Dudani9746c472012-06-18 16:01:16 -07001504#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001505 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1506 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1507 device |= AudioSystem::DEVICE_OUT_PROXY;
1508 alsa_handle.devices = device;
1509 }
1510#endif
1511 mALSADevice->route(&(*it), (uint32_t)device, mode);
1512 if (!strcmp(it->useCase, verb)) {
1513 snd_use_case_set(mUcMgr, "_verb", verb);
1514 } else {
1515 snd_use_case_set(mUcMgr, "_enamod", modifier);
1516 }
1517 mALSADevice->startVoiceCall(&(*it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001518#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001519 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1520 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1521 startUsbRecordingIfNotStarted();
1522 startUsbPlaybackIfNotStarted();
1523 musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
1524 musbRecordingState |= USBRECBIT_VOICECALL;
1525 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001526#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001527}
1528
1529bool AudioHardwareALSA::routeVoiceCall(int device, int newMode)
1530{
1531int csCallState = mCallState&0xF;
1532 bool isRouted = false;
1533 switch (csCallState) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001534 case CS_INACTIVE:
1535 if (mCSCallActive != CS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001536 ALOGD("doRouting: Disabling voice call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001537 disableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
1538 (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
1539 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001540 mCSCallActive = CS_INACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001541 }
1542 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001543 case CS_ACTIVE:
1544 if (mCSCallActive == CS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001545 ALOGD("doRouting: Enabling CS voice call ");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001546 enableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
1547 (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
1548 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001549 mCSCallActive = CS_ACTIVE;
1550 } else if (mCSCallActive == CS_HOLD) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001551 ALOGD("doRouting: Resume voice call from hold state");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001552 ALSAHandleList::iterator vt_it;
1553 for(vt_it = mDeviceList.begin();
1554 vt_it != mDeviceList.end(); ++vt_it) {
1555 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
1556 strlen(SND_USE_CASE_VERB_VOICECALL))) ||
1557 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1558 strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
1559 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001560 mCSCallActive = CS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001561 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001562 ALOGE("VoLTE resume failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001563 break;
1564 }
1565 }
1566 }
1567 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001568 case CS_HOLD:
1569 if (mCSCallActive == CS_ACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001570 ALOGD("doRouting: Voice call going to Hold");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001571 ALSAHandleList::iterator vt_it;
1572 for(vt_it = mDeviceList.begin();
1573 vt_it != mDeviceList.end(); ++vt_it) {
1574 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
1575 strlen(SND_USE_CASE_VERB_VOICECALL))) ||
1576 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1577 strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001578 mCSCallActive = CS_HOLD;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001579 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1580 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001581 ALOGE("Voice pause failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001582 break;
1583 }
1584 }
1585 }
1586 break;
1587 }
1588 return isRouted;
1589}
1590bool AudioHardwareALSA::routeVoLTECall(int device, int newMode)
1591{
1592int volteCallState = mCallState&0xF0;
1593bool isRouted = false;
1594switch (volteCallState) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001595 case IMS_INACTIVE:
1596 if (mVolteCallActive != IMS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001597 ALOGD("doRouting: Disabling IMS call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001598 disableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
1599 (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
1600 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001601 mVolteCallActive = IMS_INACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001602 }
1603 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001604 case IMS_ACTIVE:
1605 if (mVolteCallActive == IMS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001606 ALOGD("doRouting: Enabling IMS voice call ");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001607 enableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
1608 (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
1609 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001610 mVolteCallActive = IMS_ACTIVE;
1611 } else if (mVolteCallActive == IMS_HOLD) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001612 ALOGD("doRouting: Resume IMS call from hold state");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001613 ALSAHandleList::iterator vt_it;
1614 for(vt_it = mDeviceList.begin();
1615 vt_it != mDeviceList.end(); ++vt_it) {
1616 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
1617 strlen(SND_USE_CASE_VERB_VOLTE))) ||
1618 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1619 strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
1620 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001621 mVolteCallActive = IMS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001622 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001623 ALOGE("VoLTE resume failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001624 break;
1625 }
1626 }
1627 }
1628 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001629 case IMS_HOLD:
1630 if (mVolteCallActive == IMS_ACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001631 ALOGD("doRouting: IMS ACTIVE going to HOLD");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001632 ALSAHandleList::iterator vt_it;
1633 for(vt_it = mDeviceList.begin();
1634 vt_it != mDeviceList.end(); ++vt_it) {
1635 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
1636 strlen(SND_USE_CASE_VERB_VOLTE))) ||
1637 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1638 strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001639 mVolteCallActive = IMS_HOLD;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001640 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1641 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001642 ALOGE("VoLTE Pause failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001643 break;
1644 }
1645 }
1646 }
1647 break;
1648 }
1649 return isRouted;
1650}
1651
1652} // namespace android_audio_legacy