blob: a53f1619dba51c6045e573afac222a97f9d7a95f [file] [log] [blame]
Iliyan Malchev4765c432012-06-11 14:36:16 -07001/* AudioHardwareALSA.cpp
2 **
3 ** Copyright 2008-2010 Wind River Systems
4 ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
5 **
6 ** Licensed under the Apache License, Version 2.0 (the "License");
7 ** you may not use this file except in compliance with the License.
8 ** You may obtain a copy of the License at
9 **
10 ** http://www.apache.org/licenses/LICENSE-2.0
11 **
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 */
18
19#include <errno.h>
20#include <stdarg.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <stdlib.h>
24#include <unistd.h>
25#include <dlfcn.h>
26#include <math.h>
27
Ajay Dudani9746c472012-06-18 16:01:16 -070028#define LOG_TAG "AudioHardwareALSA"
Iliyan Malchev4765c432012-06-11 14:36:16 -070029//#define LOG_NDEBUG 0
Ajay Dudani9746c472012-06-18 16:01:16 -070030#define LOG_NDDEBUG 0
Iliyan Malchev4765c432012-06-11 14:36:16 -070031#include <utils/Log.h>
32#include <utils/String8.h>
33#include <sys/prctl.h>
34#include <sys/resource.h>
35#include <sys/poll.h>
36#include <sys/ioctl.h>
37#include <cutils/properties.h>
38#include <media/AudioRecord.h>
39#include <hardware_legacy/power.h>
40
41#include "AudioHardwareALSA.h"
Ajay Dudani9746c472012-06-18 16:01:16 -070042#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -070043#include "AudioUsbALSA.h"
Ajay Dudani9746c472012-06-18 16:01:16 -070044#endif
SathishKumar Manibf1c8742012-09-25 23:34:51 -070045#include "AudioUtil.h"
Iliyan Malchev4765c432012-06-11 14:36:16 -070046
Iliyan Malchev4765c432012-06-11 14:36:16 -070047extern "C"
48{
49 //
50 // Function for dlsym() to look up for creating a new AudioHardwareInterface.
51 //
52 android_audio_legacy::AudioHardwareInterface *createAudioHardware(void) {
53 return android_audio_legacy::AudioHardwareALSA::create();
54 }
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070055#ifdef QCOM_ACDB_ENABLED
56 static int (*acdb_init)();
57 static void (*acdb_deallocate)();
58#endif
59#ifdef QCOM_CSDCLIENT_ENABLED
60 static int (*csd_start_playback)();
61 static int (*csd_stop_playback)();
62#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070063} // extern "C"
64
65namespace android_audio_legacy
66{
67
68// ----------------------------------------------------------------------------
69
70AudioHardwareInterface *AudioHardwareALSA::create() {
71 return new AudioHardwareALSA();
72}
73
74AudioHardwareALSA::AudioHardwareALSA() :
SathishKumar Mani6ccde102012-09-26 20:23:34 -070075 mALSADevice(0),mVoipStreamCount(0),mVoipBitRate(0)
76 ,mCallState(0),mAcdbHandle(NULL),mCsdHandle(NULL),mMicMute(0)
Iliyan Malchev4765c432012-06-11 14:36:16 -070077{
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
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700110 mAcdbHandle = ::dlopen("/system/lib/libacdbloader.so", RTLD_NOW);
111 if (mAcdbHandle == NULL) {
112 ALOGE("AudioHardware: DLOPEN not successful for ACDBLOADER");
113 } else {
114 ALOGD("AudioHardware: DLOPEN successful for ACDBLOADER");
115 acdb_init = (int (*)())::dlsym(mAcdbHandle,"acdb_loader_init_ACDB");
116 if (acdb_init == NULL) {
117 ALOGE("dlsym:Error:%s Loading acdb_loader_init_ACDB", dlerror());
118 }else {
119 acdb_init();
120 acdb_deallocate = (void (*)())::dlsym(mAcdbHandle,"acdb_loader_deallocate_ACDB");
121 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700122 }
123#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700124
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700125#ifdef QCOM_CSDCLIENT_ENABLED
126 mCsdHandle = ::dlopen("/system/lib/libcsd-client.so", RTLD_NOW);
127 if (mCsdHandle == NULL) {
128 ALOGE("AudioHardware: DLOPEN not successful for CSD CLIENT");
129 } else {
130 ALOGD("AudioHardware: DLOPEN successful for CSD CLIENT");
131 csd_start_playback = (int (*)())::dlsym(mCsdHandle,"csd_client_start_playback");
132 csd_stop_playback = (int (*)())::dlsym(mCsdHandle,"csd_client_stop_playback");
133 }
134 mALSADevice->setCsdHandle(mCsdHandle);
135#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700136 if((fp = fopen("/proc/asound/cards","r")) == NULL) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700137 ALOGE("Cannot open /proc/asound/cards file to get sound card info");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700138 } else {
139 while((fgets(soundCardInfo, sizeof(soundCardInfo), fp) != NULL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700140 ALOGV("SoundCardInfo %s", soundCardInfo);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700141 if (strstr(soundCardInfo, "msm8960-tabla1x-snd-card")) {
142 codec_rev = 1;
143 break;
144 } else if (strstr(soundCardInfo, "msm-snd-card")) {
145 codec_rev = 2;
146 break;
147 } else if (strstr(soundCardInfo, "msm8930-sitar-snd-card")) {
148 codec_rev = 3;
149 break;
150 }
151 }
152 fclose(fp);
153 }
154
155 if (codec_rev == 1) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700156 ALOGV("Detected tabla 1.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700157 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm");
158 } else if (codec_rev == 3) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700159 ALOGV("Detected sitar 1.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700160 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_Sitar");
161 } else {
162 property_get("ro.board.platform", platform, "");
163 property_get("ro.baseband", baseband, "");
164 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700165 ALOGV("Detected Fusion tabla 2.x");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700166 mFusion3Platform = true;
167 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x_Fusion3");
168 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700169 ALOGV("Detected tabla 2.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700170 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x");
171 }
172 }
173
174 if (mUcMgr < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700175 ALOGE("Failed to open ucm instance: %d", errno);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700176 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700177 ALOGI("ucm instance opened: %u", (unsigned)mUcMgr);
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700178 mUcMgr->acdb_handle = NULL;
179#ifdef QCOM_ACDB_ENABLED
180 if (mAcdbHandle) {
181 mUcMgr->acdb_handle = static_cast<void*> (mAcdbHandle);
182 }
183#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700184 }
185 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700186 ALOGE("ALSA Module could not be opened!!!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700187 }
188 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700189 ALOGE("ALSA Module not found!!!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700190 }
191}
192
193AudioHardwareALSA::~AudioHardwareALSA()
194{
195 if (mUcMgr != NULL) {
SathishKumar Mani9efed762012-09-18 18:52:48 -0700196 ALOGV("closing ucm instance: %u", (unsigned)mUcMgr);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700197 snd_use_case_mgr_close(mUcMgr);
198 }
199 if (mALSADevice) {
200 mALSADevice->common.close(&mALSADevice->common);
201 }
202 for(ALSAHandleList::iterator it = mDeviceList.begin();
203 it != mDeviceList.end(); ++it) {
204 it->useCase[0] = 0;
205 mDeviceList.erase(it);
206 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700207#ifdef QCOM_ACDB_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700208 if (acdb_deallocate == NULL) {
209 ALOGE("dlsym: Error:%s Loading acdb_deallocate_ACDB", dlerror());
210 } else {
211 acdb_deallocate();
212 }
213 if (mAcdbHandle) {
214 ::dlclose(mAcdbHandle);
215 mAcdbHandle = NULL;
216 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700217#endif
218#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700219 delete mAudioUsbALSA;
Ajay Dudani9746c472012-06-18 16:01:16 -0700220#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700221
222#ifdef QCOM_CSDCLEINT_ENABLED
223 if (mCsdHandle) {
224 ::dlclose(mCsdHandle);
225 mCsdHandle = NULL;
226 }
227#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700228}
229
230status_t AudioHardwareALSA::initCheck()
231{
232 if (!mALSADevice)
233 return NO_INIT;
234
235 return NO_ERROR;
236}
237
238status_t AudioHardwareALSA::setVoiceVolume(float v)
239{
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700240 ALOGV("setVoiceVolume(%f)\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700241 if (v < 0.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700242 ALOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700243 v = 0.0;
244 } else if (v > 1.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700245 ALOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700246 v = 1.0;
247 }
248
249 int newMode = mode();
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700250 ALOGV("setVoiceVolume newMode %d",newMode);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700251 int vol = lrint(v * 100.0);
252
253 // Voice volume levels from android are mapped to driver volume levels as follows.
254 // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
255 // So adjust the volume to get the correct volume index in driver
256 vol = 100 - vol;
257
258 if (mALSADevice) {
259 if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
260 mALSADevice->setVoipVolume(vol);
261 } else if (newMode == AudioSystem::MODE_IN_CALL){
Ajay Dudani9746c472012-06-18 16:01:16 -0700262 if (mCSCallActive == CS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700263 mALSADevice->setVoiceVolume(vol);
Ajay Dudani9746c472012-06-18 16:01:16 -0700264 if (mVolteCallActive == IMS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700265 mALSADevice->setVoLTEVolume(vol);
266 }
267 }
268
269 return NO_ERROR;
270}
271
Ajay Dudani9746c472012-06-18 16:01:16 -0700272#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700273status_t AudioHardwareALSA::setFmVolume(float value)
274{
275 status_t status = NO_ERROR;
276
277 int vol;
278
279 if (value < 0.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700280 ALOGW("setFmVolume(%f) under 0.0, assuming 0.0\n", value);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700281 value = 0.0;
282 } else if (value > 1.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700283 ALOGW("setFmVolume(%f) over 1.0, assuming 1.0\n", value);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700284 value = 1.0;
285 }
286 vol = lrint((value * 0x2000) + 0.5);
287
SathishKumar Mani9efed762012-09-18 18:52:48 -0700288 ALOGV("setFmVolume(%f)\n", value);
289 ALOGV("Setting FM volume to %d (available range is 0 to 0x2000)\n", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700290
291 mALSADevice->setFmVolume(vol);
292
293 return status;
294}
295#endif
296
297status_t AudioHardwareALSA::setMasterVolume(float volume)
298{
299 return NO_ERROR;
300}
301
302status_t AudioHardwareALSA::setMode(int mode)
303{
304 status_t status = NO_ERROR;
305
306 if (mode != mMode) {
307 status = AudioHardwareBase::setMode(mode);
308 }
309
310 if (mode == AudioSystem::MODE_IN_CALL) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700311 mCallState = CS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700312 }else if (mode == AudioSystem::MODE_NORMAL) {
313 mCallState = 0;
314 }
315
316 return status;
317}
318
319status_t AudioHardwareALSA::setParameters(const String8& keyValuePairs)
320{
321 AudioParameter param = AudioParameter(keyValuePairs);
322 String8 key;
323 String8 value;
324 status_t status = NO_ERROR;
325 int device;
326 int btRate;
327 int state;
SathishKumar Mani9efed762012-09-18 18:52:48 -0700328 ALOGV("setParameters() %s", keyValuePairs.string());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700329
330 key = String8(TTY_MODE_KEY);
331 if (param.get(key, value) == NO_ERROR) {
332 mDevSettingsFlag &= TTY_CLEAR;
ty.leea97e6f62012-08-15 10:11:50 +0900333 if (value == "tty_full") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700334 mDevSettingsFlag |= TTY_FULL;
ty.leea97e6f62012-08-15 10:11:50 +0900335 } else if (value == "tty_hco") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700336 mDevSettingsFlag |= TTY_HCO;
ty.leea97e6f62012-08-15 10:11:50 +0900337 } else if (value == "tty_vco") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700338 mDevSettingsFlag |= TTY_VCO;
339 } else {
340 mDevSettingsFlag |= TTY_OFF;
341 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700342 ALOGI("Changed TTY Mode=%s", value.string());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700343 mALSADevice->setFlags(mDevSettingsFlag);
344 if(mMode != AudioSystem::MODE_IN_CALL){
345 return NO_ERROR;
346 }
347 doRouting(0);
348 }
349
350 key = String8(FLUENCE_KEY);
351 if (param.get(key, value) == NO_ERROR) {
352 if (value == "quadmic") {
353 mDevSettingsFlag |= QMIC_FLAG;
354 mDevSettingsFlag &= (~DMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700355 ALOGV("Fluence quadMic feature Enabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700356 } else if (value == "dualmic") {
357 mDevSettingsFlag |= DMIC_FLAG;
358 mDevSettingsFlag &= (~QMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700359 ALOGV("Fluence dualmic feature Enabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700360 } else if (value == "none") {
361 mDevSettingsFlag &= (~DMIC_FLAG);
362 mDevSettingsFlag &= (~QMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700363 ALOGV("Fluence feature Disabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700364 }
365 mALSADevice->setFlags(mDevSettingsFlag);
366 doRouting(0);
367 }
368
Ajay Dudani9746c472012-06-18 16:01:16 -0700369#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700370 if (mFusion3Platform) {
371 key = String8(INCALLMUSIC_KEY);
372 if (param.get(key, value) == NO_ERROR) {
373 if (value == "true") {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700374 ALOGV("Enabling Incall Music setting in the setparameter\n");
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700375 if (csd_start_playback == NULL) {
376 ALOGE("dlsym: Error:%s Loading csd_client_start_playback", dlerror());
377 } else {
378 csd_start_playback();
379 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700380 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700381 ALOGV("Disabling Incall Music setting in the setparameter\n");
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700382 if (csd_stop_playback == NULL) {
383 ALOGE("dlsym: Error:%s Loading csd_client_stop_playback", dlerror());
384 } else {
385 csd_stop_playback();
386 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700387 }
388 }
389 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700390#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700391
392 key = String8(ANC_KEY);
393 if (param.get(key, value) == NO_ERROR) {
394 if (value == "true") {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700395 ALOGV("Enabling ANC setting in the setparameter\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700396 mDevSettingsFlag |= ANC_FLAG;
397 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700398 ALOGV("Disabling ANC setting in the setparameter\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700399 mDevSettingsFlag &= (~ANC_FLAG);
400 }
401 mALSADevice->setFlags(mDevSettingsFlag);
402 doRouting(0);
403 }
404
405 key = String8(AudioParameter::keyRouting);
406 if (param.getInt(key, device) == NO_ERROR) {
407 // Ignore routing if device is 0.
408 if(device) {
409 doRouting(device);
410 }
411 param.remove(key);
412 }
413
414 key = String8(BT_SAMPLERATE_KEY);
415 if (param.getInt(key, btRate) == NO_ERROR) {
416 mALSADevice->setBtscoRate(btRate);
417 param.remove(key);
418 }
419
420 key = String8(BTHEADSET_VGS);
421 if (param.get(key, value) == NO_ERROR) {
422 if (value == "on") {
423 mBluetoothVGS = true;
424 } else {
425 mBluetoothVGS = false;
426 }
427 }
428
429 key = String8(WIDEVOICE_KEY);
430 if (param.get(key, value) == NO_ERROR) {
431 bool flag = false;
432 if (value == "true") {
433 flag = true;
434 }
435 if(mALSADevice) {
436 mALSADevice->enableWideVoice(flag);
437 }
438 param.remove(key);
439 }
440
441 key = String8(VOIPRATE_KEY);
442 if (param.get(key, value) == NO_ERROR) {
443 mVoipBitRate = atoi(value);
444 param.remove(key);
445 }
446
447 key = String8(FENS_KEY);
448 if (param.get(key, value) == NO_ERROR) {
449 bool flag = false;
450 if (value == "true") {
451 flag = true;
452 }
453 if(mALSADevice) {
454 mALSADevice->enableFENS(flag);
455 }
456 param.remove(key);
457 }
458
Ajay Dudani9746c472012-06-18 16:01:16 -0700459#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700460 key = String8(AudioParameter::keyHandleFm);
461 if (param.getInt(key, device) == NO_ERROR) {
462 // Ignore if device is 0
463 if(device) {
464 handleFm(device);
465 }
466 param.remove(key);
467 }
468#endif
469
470 key = String8(ST_KEY);
471 if (param.get(key, value) == NO_ERROR) {
472 bool flag = false;
473 if (value == "true") {
474 flag = true;
475 }
476 if(mALSADevice) {
477 mALSADevice->enableSlowTalk(flag);
478 }
479 param.remove(key);
480 }
481 key = String8(MODE_CALL_KEY);
482 if (param.getInt(key,state) == NO_ERROR) {
483 if (mCallState != state) {
484 mCallState = state;
485 doRouting(0);
486 }
487 mCallState = state;
488 }
489 if (param.size()) {
490 status = BAD_VALUE;
491 }
492 return status;
493}
494
495String8 AudioHardwareALSA::getParameters(const String8& keys)
496{
497 AudioParameter param = AudioParameter(keys);
498 String8 value;
499
500 String8 key = String8(DUALMIC_KEY);
501 if (param.get(key, value) == NO_ERROR) {
502 value = String8("false");
503 param.add(key, value);
504 }
505
506 key = String8(FLUENCE_KEY);
507 if (param.get(key, value) == NO_ERROR) {
508 if ((mDevSettingsFlag & QMIC_FLAG) &&
509 (mDevSettingsFlag & ~DMIC_FLAG))
510 value = String8("quadmic");
511 else if ((mDevSettingsFlag & DMIC_FLAG) &&
512 (mDevSettingsFlag & ~QMIC_FLAG))
513 value = String8("dualmic");
514 else if ((mDevSettingsFlag & ~DMIC_FLAG) &&
515 (mDevSettingsFlag & ~QMIC_FLAG))
516 value = String8("none");
517 param.add(key, value);
518 }
519
Ajay Dudani9746c472012-06-18 16:01:16 -0700520#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700521 key = String8("Fm-radio");
522 if ( param.get(key,value) == NO_ERROR ) {
523 if ( mIsFmActive ) {
524 param.addInt(String8("isFMON"), true );
525 }
526 }
527#endif
528
529 key = String8(BTHEADSET_VGS);
530 if (param.get(key, value) == NO_ERROR) {
531 if(mBluetoothVGS)
532 param.addInt(String8("isVGS"), true);
533 }
534
Iliyan Malchev4113f342012-06-11 14:39:47 -0700535 ALOGV("AudioHardwareALSA::getParameters() %s", param.toString().string());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700536 return param.toString();
537}
538
Ajay Dudani9746c472012-06-18 16:01:16 -0700539#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700540void AudioHardwareALSA::closeUSBPlayback()
541{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700542 ALOGV("closeUSBPlayback, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700543 musbPlaybackState = 0;
544 mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_KILLTHREAD);
545}
546
547void AudioHardwareALSA::closeUSBRecording()
548{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700549 ALOGV("closeUSBRecording");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700550 musbRecordingState = 0;
551 mAudioUsbALSA->exitRecordingThread(SIGNAL_EVENT_KILLTHREAD);
552}
553
554void AudioHardwareALSA::closeUsbPlaybackIfNothingActive(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700555 ALOGV("closeUsbPlaybackIfNothingActive, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700556 if(!musbPlaybackState && mAudioUsbALSA != NULL) {
557 mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_TIMEOUT);
558 }
559}
560
561void AudioHardwareALSA::closeUsbRecordingIfNothingActive(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700562 ALOGV("closeUsbRecordingIfNothingActive, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700563 if(!musbRecordingState && mAudioUsbALSA != NULL) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700564 ALOGD("Closing USB Recording Session as no stream is active");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700565 mAudioUsbALSA->setkillUsbRecordingThread(true);
566 }
567}
568
569void AudioHardwareALSA::startUsbPlaybackIfNotStarted(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700570 ALOGV("Starting the USB playback %d kill %d", musbPlaybackState,
Iliyan Malchev4765c432012-06-11 14:36:16 -0700571 mAudioUsbALSA->getkillUsbPlaybackThread());
572 if((!musbPlaybackState) || (mAudioUsbALSA->getkillUsbPlaybackThread() == true)) {
573 mAudioUsbALSA->startPlayback();
574 }
575}
576
577void AudioHardwareALSA::startUsbRecordingIfNotStarted(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700578 ALOGV("Starting the recording musbRecordingState: %d killUsbRecordingThread %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700579 musbRecordingState, mAudioUsbALSA->getkillUsbRecordingThread());
580 if((!musbRecordingState) || (mAudioUsbALSA->getkillUsbRecordingThread() == true)) {
581 mAudioUsbALSA->startRecording();
582 }
583}
Ajay Dudani9746c472012-06-18 16:01:16 -0700584#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700585
586void AudioHardwareALSA::doRouting(int device)
587{
588 Mutex::Autolock autoLock(mLock);
589 int newMode = mode();
590 bool isRouted = false;
591
Ajay Dudani9746c472012-06-18 16:01:16 -0700592 if ((device == AudioSystem::DEVICE_IN_VOICE_CALL)
593#ifdef QCOM_FM_ENABLED
594 || (device == AudioSystem::DEVICE_IN_FM_RX)
595 || (device == AudioSystem::DEVICE_OUT_DIRECTOUTPUT)
596 || (device == AudioSystem::DEVICE_IN_FM_RX_A2DP)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700597#endif
Ajay Dudani9746c472012-06-18 16:01:16 -0700598 || (device == AudioSystem::DEVICE_IN_COMMUNICATION)
599 ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700600 ALOGV("Ignoring routing for FM/INCALL/VOIP recording");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700601 return;
602 }
603 if (device == 0)
604 device = mCurDevice;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700605 ALOGV("doRouting: device %d newMode %d mCSCallActive %d mVolteCallActive %d"
Iliyan Malchev4765c432012-06-11 14:36:16 -0700606 "mIsFmActive %d", device, newMode, mCSCallActive, mVolteCallActive,
607 mIsFmActive);
608
609 isRouted = routeVoLTECall(device, newMode);
610 isRouted |= routeVoiceCall(device, newMode);
611
612 if(!isRouted) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700613#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700614 if(!(device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) &&
615 !(device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET) &&
616 !(device & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) &&
617 (musbPlaybackState)){
618 //USB unplugged
619 device &= ~ AudioSystem::DEVICE_OUT_PROXY;
620 device &= ~ AudioSystem::DEVICE_IN_PROXY;
621 ALSAHandleList::iterator it = mDeviceList.end();
622 it--;
623 mALSADevice->route(&(*it), (uint32_t)device, newMode);
SathishKumar Mani0a019912012-09-11 12:33:11 -0700624 ALOGD("USB UNPLUGGED, setting musbPlaybackState to 0");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700625 musbPlaybackState = 0;
626 musbRecordingState = 0;
627 closeUSBRecording();
628 closeUSBPlayback();
629 } else if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
630 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -0700631 ALOGD("Routing everything to prox now");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700632 ALSAHandleList::iterator it = mDeviceList.end();
633 it--;
634 mALSADevice->route(&(*it), AudioSystem::DEVICE_OUT_PROXY,
635 newMode);
636 for(it = mDeviceList.begin(); it != mDeviceList.end(); ++it) {
637 if((!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
638 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_LPA))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700639 ALOGV("doRouting: LPA device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700640 startUsbPlaybackIfNotStarted();
641 musbPlaybackState |= USBPLAYBACKBIT_LPA;
642 break;
643 } else if((!strcmp(it->useCase, SND_USE_CASE_VERB_VOICECALL)) ||
644 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOICE))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700645 ALOGV("doRouting: VOICE device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700646 startUsbRecordingIfNotStarted();
647 startUsbPlaybackIfNotStarted();
648 musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
649 musbRecordingState |= USBPLAYBACKBIT_VOICECALL;
650 break;
651 }else if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
652 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700653 ALOGV("doRouting: FM device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700654 startUsbPlaybackIfNotStarted();
655 musbPlaybackState |= USBPLAYBACKBIT_FM;
656 break;
657 }
658 }
SathishKumar Manie42406e2012-08-29 16:25:54 -0700659 } else
Iliyan Malchev4765c432012-06-11 14:36:16 -0700660#endif
SathishKumar Manie42406e2012-08-29 16:25:54 -0700661 {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700662 ALSAHandleList::iterator it = mDeviceList.end();
663 it--;
664 mALSADevice->route(&(*it), (uint32_t)device, newMode);
665 }
666 }
667 mCurDevice = device;
668}
669
670uint32_t AudioHardwareALSA::getVoipMode(int format)
671{
672 switch(format) {
673 case AudioSystem::PCM_16_BIT:
674 return MODE_PCM;
675 break;
676 case AudioSystem::AMR_NB:
677 return MODE_AMR;
678 break;
679 case AudioSystem::AMR_WB:
680 return MODE_AMR_WB;
681 break;
682
Ajay Dudani9746c472012-06-18 16:01:16 -0700683#ifdef QCOM_QCHAT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700684 case AudioSystem::EVRC:
685 return MODE_IS127;
686 break;
687
688 case AudioSystem::EVRCB:
689 return MODE_4GV_NB;
690 break;
691 case AudioSystem::EVRCWB:
692 return MODE_4GV_WB;
693 break;
Ajay Dudani9746c472012-06-18 16:01:16 -0700694#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700695
696 default:
697 return MODE_PCM;
698 }
699}
700
701AudioStreamOut *
702AudioHardwareALSA::openOutputStream(uint32_t devices,
703 int *format,
704 uint32_t *channels,
705 uint32_t *sampleRate,
706 status_t *status)
707{
708 Mutex::Autolock autoLock(mLock);
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700709 ALOGV("openOutputStream: devices 0x%x channels %d sampleRate %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700710 devices, *channels, *sampleRate);
711
SathishKumar Mani88613382012-08-13 18:40:18 -0700712 audio_output_flags_t flag = static_cast<audio_output_flags_t> (*status);
713
Iliyan Malchev4765c432012-06-11 14:36:16 -0700714 status_t err = BAD_VALUE;
SathishKumar Mani88613382012-08-13 18:40:18 -0700715 *status = NO_ERROR;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700716 AudioStreamOutALSA *out = 0;
717 ALSAHandleList::iterator it;
718
719 if (devices & (devices - 1)) {
720 if (status) *status = err;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700721 ALOGE("openOutputStream called with bad devices");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700722 return out;
723 }
SathishKumar Mani88613382012-08-13 18:40:18 -0700724
725
Iliyan Malchev4765c432012-06-11 14:36:16 -0700726# if 0
727 if((devices == AudioSystem::DEVICE_OUT_DIRECTOUTPUT) &&
728 ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
729 bool voipstream_active = false;
730 for(it = mDeviceList.begin();
731 it != mDeviceList.end(); ++it) {
732 if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
733 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700734 ALOGD("openOutput: it->rxHandle %d it->handle %d",it->rxHandle,it->handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700735 voipstream_active = true;
736 break;
737 }
738 }
739 if(voipstream_active == false) {
740 mVoipStreamCount = 0;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700741 alsa_handle_t alsa_handle;
742 unsigned long bufferSize;
743 if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
744 bufferSize = VOIP_BUFFER_SIZE_8K;
745 }
746 else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
747 bufferSize = VOIP_BUFFER_SIZE_16K;
748 }
749 else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700750 ALOGE("unsupported samplerate %d for voip",*sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700751 if (status) *status = err;
752 return out;
753 }
754 alsa_handle.module = mALSADevice;
755 alsa_handle.bufferSize = bufferSize;
756 alsa_handle.devices = devices;
757 alsa_handle.handle = 0;
758 if(*format == AudioSystem::PCM_16_BIT)
759 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
760 else
761 alsa_handle.format = *format;
762 alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
763 alsa_handle.sampleRate = *sampleRate;
764 alsa_handle.latency = VOIP_PLAYBACK_LATENCY;
765 alsa_handle.rxHandle = 0;
766 alsa_handle.ucMgr = mUcMgr;
767 mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
768 char *use_case;
769 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
770 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
771 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
772 } else {
773 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
774 }
775 free(use_case);
776 mDeviceList.push_back(alsa_handle);
777 it = mDeviceList.end();
778 it--;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700779 ALOGV("openoutput: mALSADevice->route useCase %s mCurDevice %d mVoipStreamCount %d mode %d", it->useCase,mCurDevice,mVoipStreamCount, mode());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700780 if((mCurDevice & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
781 (mCurDevice & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)||
782 (mCurDevice & AudioSystem::DEVICE_OUT_PROXY)){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700783 ALOGD("Routing to proxy for normal voip call in openOutputStream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700784 mCurDevice |= AudioSystem::DEVICE_OUT_PROXY;
785 alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
786 mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700787 ALOGD("enabling VOIP in openoutputstream, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700788 startUsbPlaybackIfNotStarted();
789 musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700790 ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700791 startUsbRecordingIfNotStarted();
792 musbRecordingState |= USBRECBIT_VOIPCALL;
793 } else{
794 mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
795 }
796 if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
797 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
798 } else {
799 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
800 }
801 err = mALSADevice->startVoipCall(&(*it));
802 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700803 ALOGE("Device open failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700804 return NULL;
805 }
806 }
807 out = new AudioStreamOutALSA(this, &(*it));
808 err = out->set(format, channels, sampleRate, devices);
809 if(err == NO_ERROR) {
810 mVoipStreamCount++; //increment VoipstreamCount only if success
Iliyan Malchev4113f342012-06-11 14:39:47 -0700811 ALOGD("openoutput mVoipStreamCount %d",mVoipStreamCount);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700812 }
813 if (status) *status = err;
814 return out;
815 } else
816#endif
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700817 if ((flag & AUDIO_OUTPUT_FLAG_DIRECT) &&
818 (devices == AudioSystem::DEVICE_OUT_AUX_DIGITAL)) {
819 ALOGD("Multi channel PCM");
820 alsa_handle_t alsa_handle;
821 EDID_AUDIO_INFO info = { 0 };
822
823 alsa_handle.module = mALSADevice;
824 alsa_handle.devices = devices;
825 alsa_handle.handle = 0;
826 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
827
828 if (!AudioUtil::getHDMIAudioSinkCaps(&info)) {
829 ALOGE("openOutputStream: Failed to get HDMI sink capabilities");
830 return NULL;
831 }
832 if (0 == *channels) {
833 alsa_handle.channels = info.AudioBlocksArray[info.nAudioBlocks-1].nChannels;
834 if (alsa_handle.channels > 6) {
835 alsa_handle.channels = 6;
836 }
837 *channels = audio_channel_out_mask_from_count(alsa_handle.channels);
838 } else {
839 alsa_handle.channels = AudioSystem::popCount(*channels);
840 }
841 if (6 == alsa_handle.channels) {
842 alsa_handle.bufferSize = DEFAULT_MULTI_CHANNEL_BUF_SIZE;
843 } else {
844 alsa_handle.bufferSize = DEFAULT_BUFFER_SIZE;
845 }
846 if (0 == *sampleRate) {
847 alsa_handle.sampleRate = info.AudioBlocksArray[info.nAudioBlocks-1].nSamplingFreq;
848 *sampleRate = alsa_handle.sampleRate;
849 } else {
850 alsa_handle.sampleRate = *sampleRate;
851 }
852 alsa_handle.latency = PLAYBACK_LATENCY;
853 alsa_handle.rxHandle = 0;
854 alsa_handle.ucMgr = mUcMgr;
855 ALOGD("alsa_handle.channels %d alsa_handle.sampleRate %d",alsa_handle.channels,alsa_handle.sampleRate);
856
857 char *use_case;
858 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
859 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
860 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI2 , sizeof(alsa_handle.useCase));
861 } else {
862 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC2, sizeof(alsa_handle.useCase));
863 }
864 free(use_case);
865 mDeviceList.push_back(alsa_handle);
866 ALSAHandleList::iterator it = mDeviceList.end();
867 it--;
868 ALOGD("it->useCase %s", it->useCase);
869 mALSADevice->route(&(*it), devices, mode());
870 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI2)) {
871 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI2 );
872 } else {
873 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC2);
874 }
875 ALOGD("channels: %d", AudioSystem::popCount(*channels));
876 err = mALSADevice->open(&(*it));
877
878 if (err) {
879 ALOGE("Device open failed err:%d",err);
880 } else {
881 out = new AudioStreamOutALSA(this, &(*it));
882 err = out->set(format, channels, sampleRate, devices);
883 }
884 if (status) *status = err;
885 return out;
886 } else {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700887
888 alsa_handle_t alsa_handle;
889 unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
890
891 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
892 bufferSize &= ~b;
893
894 alsa_handle.module = mALSADevice;
895 alsa_handle.bufferSize = bufferSize;
896 alsa_handle.devices = devices;
897 alsa_handle.handle = 0;
898 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
899 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
900 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
901 alsa_handle.latency = PLAYBACK_LATENCY;
902 alsa_handle.rxHandle = 0;
903 alsa_handle.ucMgr = mUcMgr;
SathishKumar Mani88613382012-08-13 18:40:18 -0700904 alsa_handle.isDeepbufferOutput = false;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700905
906 char *use_case;
907 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
SathishKumar Mani88613382012-08-13 18:40:18 -0700908
909 if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
SathishKumar Mani9efed762012-09-18 18:52:48 -0700910 ALOGD("openOutputStream: DeepBuffer Output");
SathishKumar Mani88613382012-08-13 18:40:18 -0700911 alsa_handle.isDeepbufferOutput = true;
912 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
913 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI, sizeof(alsa_handle.useCase));
914 } else {
915 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC, sizeof(alsa_handle.useCase));
916 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700917 } else {
SathishKumar Mani9efed762012-09-18 18:52:48 -0700918 ALOGD("openOutputStream: Lowlatency Output");
SathishKumar Mani88613382012-08-13 18:40:18 -0700919 alsa_handle.bufferSize = PLAYBACK_LOW_LATENCY_BUFFER_SIZE;
SathishKumar Mani77780382012-09-21 20:58:33 -0700920 alsa_handle.latency = PLAYBACK_LOW_LATENCY_MEASURED;
SathishKumar Mani88613382012-08-13 18:40:18 -0700921 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
922 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
923 } else {
924 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
925 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700926 }
927 free(use_case);
928 mDeviceList.push_back(alsa_handle);
929 ALSAHandleList::iterator it = mDeviceList.end();
930 it--;
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700931 ALOGV("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 normal playback in openOutputStream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700936 devices |= AudioSystem::DEVICE_OUT_PROXY;
937 }
938#endif
939 mALSADevice->route(&(*it), devices, mode());
SathishKumar Mani88613382012-08-13 18:40:18 -0700940 if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
941 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI)) {
942 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI);
943 } else {
944 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC);
945 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700946 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -0700947 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) {
948 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC);
949 } else {
950 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC);
951 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700952 }
953 err = mALSADevice->open(&(*it));
954 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700955 ALOGE("Device open failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700956 } else {
957 out = new AudioStreamOutALSA(this, &(*it));
958 err = out->set(format, channels, sampleRate, devices);
959 }
960
961 if (status) *status = err;
962 return out;
963 }
964}
965
966void
967AudioHardwareALSA::closeOutputStream(AudioStreamOut* out)
968{
969 delete out;
970}
971
Ajay Dudani9746c472012-06-18 16:01:16 -0700972#ifdef QCOM_TUNNEL_LPA_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700973AudioStreamOut *
974AudioHardwareALSA::openOutputSession(uint32_t devices,
975 int *format,
976 status_t *status,
977 int sessionId,
978 uint32_t samplingRate,
979 uint32_t channels)
980{
981 Mutex::Autolock autoLock(mLock);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700982 ALOGD("openOutputSession = %d" ,sessionId);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700983 AudioStreamOutALSA *out = 0;
984 status_t err = BAD_VALUE;
985
986 alsa_handle_t alsa_handle;
987 unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
988
989 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
990 bufferSize &= ~b;
991
992 alsa_handle.module = mALSADevice;
993 alsa_handle.bufferSize = bufferSize;
994 alsa_handle.devices = devices;
995 alsa_handle.handle = 0;
996 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
997 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
998 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
999 alsa_handle.latency = VOICE_LATENCY;
1000 alsa_handle.rxHandle = 0;
1001 alsa_handle.ucMgr = mUcMgr;
1002
1003 char *use_case;
1004 if(sessionId == TUNNEL_SESSION_ID) {
1005 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1006 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1007 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_TUNNEL, sizeof(alsa_handle.useCase));
1008 } else {
1009 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_TUNNEL, sizeof(alsa_handle.useCase));
1010 }
1011 } else {
1012 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1013 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1014 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER, sizeof(alsa_handle.useCase));
1015 } else {
1016 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LPA, sizeof(alsa_handle.useCase));
1017 }
1018 }
1019 free(use_case);
1020 mDeviceList.push_back(alsa_handle);
1021 ALSAHandleList::iterator it = mDeviceList.end();
1022 it--;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001023 ALOGD("useCase %s", it->useCase);
Ajay Dudani9746c472012-06-18 16:01:16 -07001024#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001025 if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1026 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -07001027 ALOGD("Routing to proxy for LPA in openOutputSession");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001028 devices |= AudioSystem::DEVICE_OUT_PROXY;
1029 mALSADevice->route(&(*it), devices, mode());
1030 devices = AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001031 ALOGD("Starting USBPlayback for LPA");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001032 startUsbPlaybackIfNotStarted();
1033 musbPlaybackState |= USBPLAYBACKBIT_LPA;
1034 } else
1035#endif
1036 {
1037 mALSADevice->route(&(*it), devices, mode());
1038 }
1039 if(sessionId == TUNNEL_SESSION_ID) {
1040 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) {
1041 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_TUNNEL);
1042 } else {
1043 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_TUNNEL);
1044 }
1045 }
1046 else {
1047 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) {
1048 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOW_POWER);
1049 } else {
1050 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LPA);
1051 }
1052 }
1053 err = mALSADevice->open(&(*it));
1054 out = new AudioStreamOutALSA(this, &(*it));
1055
1056 if (status) *status = err;
1057 return out;
1058}
1059
1060void
1061AudioHardwareALSA::closeOutputSession(AudioStreamOut* out)
1062{
1063 delete out;
1064}
Ajay Dudani9746c472012-06-18 16:01:16 -07001065#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001066
1067AudioStreamIn *
1068AudioHardwareALSA::openInputStream(uint32_t devices,
1069 int *format,
1070 uint32_t *channels,
1071 uint32_t *sampleRate,
1072 status_t *status,
1073 AudioSystem::audio_in_acoustics acoustics)
1074{
1075 Mutex::Autolock autoLock(mLock);
1076 char *use_case;
1077 int newMode = mode();
1078 uint32_t route_devices;
1079
1080 status_t err = BAD_VALUE;
1081 AudioStreamInALSA *in = 0;
1082 ALSAHandleList::iterator it;
1083
Iliyan Malchev4113f342012-06-11 14:39:47 -07001084 ALOGD("openInputStream: devices 0x%x channels %d sampleRate %d", devices, *channels, *sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001085 if (devices & (devices - 1)) {
1086 if (status) *status = err;
1087 return in;
1088 }
1089
1090 if((devices == AudioSystem::DEVICE_IN_COMMUNICATION) &&
1091 ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
1092 bool voipstream_active = false;
1093 for(it = mDeviceList.begin();
1094 it != mDeviceList.end(); ++it) {
1095 if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
1096 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001097 ALOGD("openInput: it->rxHandle %p it->handle %p",it->rxHandle,it->handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001098 voipstream_active = true;
1099 break;
1100 }
1101 }
1102 if(voipstream_active == false) {
1103 mVoipStreamCount = 0;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001104 alsa_handle_t alsa_handle;
1105 unsigned long bufferSize;
1106 if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
1107 bufferSize = VOIP_BUFFER_SIZE_8K;
1108 }
1109 else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
1110 bufferSize = VOIP_BUFFER_SIZE_16K;
1111 }
1112 else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001113 ALOGE("unsupported samplerate %d for voip",*sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001114 if (status) *status = err;
1115 return in;
1116 }
1117 alsa_handle.module = mALSADevice;
1118 alsa_handle.bufferSize = bufferSize;
1119 alsa_handle.devices = devices;
1120 alsa_handle.handle = 0;
1121 if(*format == AudioSystem::PCM_16_BIT)
1122 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1123 else
1124 alsa_handle.format = *format;
1125 alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
1126 alsa_handle.sampleRate = *sampleRate;
1127 alsa_handle.latency = VOIP_RECORD_LATENCY;
1128 alsa_handle.rxHandle = 0;
1129 alsa_handle.ucMgr = mUcMgr;
1130 mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
1131 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1132 if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1133 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
1134 } else {
1135 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
1136 }
1137 free(use_case);
1138 mDeviceList.push_back(alsa_handle);
1139 it = mDeviceList.end();
1140 it--;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001141 ALOGD("mCurrDevice: %d", mCurDevice);
Ajay Dudani9746c472012-06-18 16:01:16 -07001142#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001143 if((mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1144 (mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -07001145 ALOGD("Routing everything from proxy for voipcall");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001146 mALSADevice->route(&(*it), AudioSystem::DEVICE_IN_PROXY, AudioSystem::MODE_IN_COMMUNICATION);
Iliyan Malchev4113f342012-06-11 14:39:47 -07001147 ALOGD("enabling VOIP in openInputstream, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001148 startUsbPlaybackIfNotStarted();
1149 musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001150 ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001151 startUsbRecordingIfNotStarted();
1152 musbRecordingState |= USBRECBIT_VOIPCALL;
SathishKumar Manie42406e2012-08-29 16:25:54 -07001153 } else
Iliyan Malchev4765c432012-06-11 14:36:16 -07001154#endif
1155 {
1156 mALSADevice->route(&(*it),mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
1157 }
1158 if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
1159 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
1160 } else {
1161 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
1162 }
1163 if(sampleRate) {
1164 it->sampleRate = *sampleRate;
1165 }
1166 if(channels)
1167 it->channels = AudioSystem::popCount(*channels);
1168 err = mALSADevice->startVoipCall(&(*it));
1169 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001170 ALOGE("Error opening pcm input device");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001171 return NULL;
1172 }
1173 }
1174 in = new AudioStreamInALSA(this, &(*it), acoustics);
1175 err = in->set(format, channels, sampleRate, devices);
1176 if(err == NO_ERROR) {
1177 mVoipStreamCount++; //increment VoipstreamCount only if success
Iliyan Malchev4113f342012-06-11 14:39:47 -07001178 ALOGD("OpenInput mVoipStreamCount %d",mVoipStreamCount);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001179 }
SathishKumar Mani0a019912012-09-11 12:33:11 -07001180 ALOGD("openInput: After Get alsahandle");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001181 if (status) *status = err;
1182 return in;
SathishKumar Manied3c0fd2012-09-21 10:31:40 -07001183 } else {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001184 alsa_handle_t alsa_handle;
SathishKumar Mani77780382012-09-21 20:58:33 -07001185 unsigned long bufferSize = MIN_CAPTURE_BUFFER_SIZE_PER_CH;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001186
1187 alsa_handle.module = mALSADevice;
1188 alsa_handle.bufferSize = bufferSize;
1189 alsa_handle.devices = devices;
1190 alsa_handle.handle = 0;
1191 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1192 alsa_handle.channels = VOICE_CHANNEL_MODE;
1193 alsa_handle.sampleRate = android::AudioRecord::DEFAULT_SAMPLE_RATE;
1194 alsa_handle.latency = RECORD_LATENCY;
1195 alsa_handle.rxHandle = 0;
1196 alsa_handle.ucMgr = mUcMgr;
1197 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1198 if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1199 if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
1200 (newMode == AudioSystem::MODE_IN_CALL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001201 ALOGD("openInputStream: into incall recording, channels %d", *channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001202 mIncallMode = *channels;
1203 if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
1204 (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
1205 if (mFusion3Platform) {
1206 mALSADevice->setVocRecMode(INCALL_REC_STEREO);
1207 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1208 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001209 } else {
1210 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
1211 sizeof(alsa_handle.useCase));
1212 }
1213 } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
1214 if (mFusion3Platform) {
1215 mALSADevice->setVocRecMode(INCALL_REC_MONO);
1216 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1217 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001218 } else {
1219 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
1220 sizeof(alsa_handle.useCase));
1221 }
1222 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001223#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001224 } else if((devices == AudioSystem::DEVICE_IN_FM_RX)) {
1225 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_FM, sizeof(alsa_handle.useCase));
1226 } else if(devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
1227 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, sizeof(alsa_handle.useCase));
1228#endif
1229 } else {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001230 char value[128];
1231 property_get("persist.audio.lowlatency.rec",value,"0");
SathishKumar Mani88613382012-08-13 18:40:18 -07001232 if (!strcmp("true", value)) {
1233 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
1234 } else {
1235 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, sizeof(alsa_handle.useCase));
1236 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001237 }
1238 } else {
1239 if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
1240 (newMode == AudioSystem::MODE_IN_CALL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001241 ALOGD("openInputStream: incall recording, channels %d", *channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001242 mIncallMode = *channels;
1243 if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
1244 (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
1245 if (mFusion3Platform) {
1246 mALSADevice->setVocRecMode(INCALL_REC_STEREO);
1247 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
1248 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001249 } else {
1250 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_UL_DL_REC,
1251 sizeof(alsa_handle.useCase));
1252 }
1253 } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
1254 if (mFusion3Platform) {
1255 mALSADevice->setVocRecMode(INCALL_REC_MONO);
1256 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
1257 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001258 } else {
1259 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DL_REC,
1260 sizeof(alsa_handle.useCase));
1261 }
1262 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001263#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001264 } else if(devices == AudioSystem::DEVICE_IN_FM_RX) {
1265 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_REC, sizeof(alsa_handle.useCase));
1266 } else if (devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
1267 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_A2DP_REC, sizeof(alsa_handle.useCase));
1268#endif
1269 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -07001270 char value[128];
1271 property_get("persist.audio.lowlatency.rec",value,"0");
1272 if (!strcmp("true", value)) {
1273 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, sizeof(alsa_handle.useCase));
1274 } else {
1275 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_REC, sizeof(alsa_handle.useCase));
1276 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001277 }
1278 }
1279 free(use_case);
1280 mDeviceList.push_back(alsa_handle);
1281 ALSAHandleList::iterator it = mDeviceList.end();
1282 it--;
1283 //update channel info before do routing
1284 if(channels) {
1285 it->channels = AudioSystem::popCount((*channels) &
Ajay Dudani9746c472012-06-18 16:01:16 -07001286 (AudioSystem::CHANNEL_IN_STEREO
1287 | AudioSystem::CHANNEL_IN_MONO
1288#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001289 | AudioSystem::CHANNEL_IN_5POINT1
1290#endif
1291 ));
Iliyan Malchev4113f342012-06-11 14:39:47 -07001292 ALOGV("updated channel info: channels=%d", it->channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001293 }
1294 if (devices == AudioSystem::DEVICE_IN_VOICE_CALL){
1295 /* Add current devices info to devices to do route */
Ajay Dudani9746c472012-06-18 16:01:16 -07001296#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001297 if(mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET ||
1298 mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001299 ALOGD("Routing everything from proxy for VOIP call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001300 route_devices = devices | AudioSystem::DEVICE_IN_PROXY;
1301 } else
1302#endif
1303 {
1304 route_devices = devices | mCurDevice;
1305 }
1306 mALSADevice->route(&(*it), route_devices, mode());
1307 } else {
Ajay Dudani9746c472012-06-18 16:01:16 -07001308#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001309 if(devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET ||
1310 devices & AudioSystem::DEVICE_IN_PROXY) {
1311 devices |= AudioSystem::DEVICE_IN_PROXY;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001312 ALOGD("routing everything from proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001313 mALSADevice->route(&(*it), devices, mode());
1314 } else
1315#endif
1316 {
1317 mALSADevice->route(&(*it), devices, mode());
1318 }
1319 }
1320
1321 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001322 !strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC) ||
Ajay Dudani9746c472012-06-18 16:01:16 -07001323#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001324 !strcmp(it->useCase, SND_USE_CASE_VERB_FM_REC) ||
1325 !strcmp(it->useCase, SND_USE_CASE_VERB_FM_A2DP_REC) ||
1326#endif
1327 !strcmp(it->useCase, SND_USE_CASE_VERB_DL_REC) ||
1328 !strcmp(it->useCase, SND_USE_CASE_VERB_UL_DL_REC) ||
1329 !strcmp(it->useCase, SND_USE_CASE_VERB_INCALL_REC)) {
1330 snd_use_case_set(mUcMgr, "_verb", it->useCase);
1331 } else {
1332 snd_use_case_set(mUcMgr, "_enamod", it->useCase);
1333 }
1334 if(sampleRate) {
1335 it->sampleRate = *sampleRate;
1336 }
SathishKumar Mani77780382012-09-21 20:58:33 -07001337 if (!strncmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
1338 || !strncmp(it->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
1339 ALOGV("OpenInoutStream: Use larger buffer size for 5.1(%s) recording ", it->useCase);
1340 it->bufferSize = getInputBufferSize(it->sampleRate,*format,it->channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001341 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001342 err = mALSADevice->open(&(*it));
1343 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001344 ALOGE("Error opening pcm input device");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001345 } else {
1346 in = new AudioStreamInALSA(this, &(*it), acoustics);
1347 err = in->set(format, channels, sampleRate, devices);
1348 }
1349 if (status) *status = err;
1350 return in;
1351 }
1352}
1353
1354void
1355AudioHardwareALSA::closeInputStream(AudioStreamIn* in)
1356{
1357 delete in;
1358}
1359
1360status_t AudioHardwareALSA::setMicMute(bool state)
1361{
SathishKumar Mani6ccde102012-09-26 20:23:34 -07001362 if (mMicMute != state) {
1363 mMicMute = state;
1364 ALOGD("setMicMute: mMicMute %d", mMicMute);
1365 if(mALSADevice) {
1366 mALSADevice->setMicMute(state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001367 }
1368 }
1369 return NO_ERROR;
1370}
1371
1372status_t AudioHardwareALSA::getMicMute(bool *state)
1373{
SathishKumar Mani6ccde102012-09-26 20:23:34 -07001374 *state = mMicMute;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001375 return NO_ERROR;
1376}
1377
1378status_t AudioHardwareALSA::dump(int fd, const Vector<String16>& args)
1379{
1380 return NO_ERROR;
1381}
1382
1383size_t AudioHardwareALSA::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
1384{
SathishKumar Mani77780382012-09-21 20:58:33 -07001385 size_t bufferSize = 0;
1386 if (format == AudioSystem::PCM_16_BIT) {
1387 if(sampleRate == 8000 || sampleRate == 16000 || sampleRate == 32000) {
1388 bufferSize = (sampleRate * channelCount * 20 * sizeof(int16_t)) / 1000;
1389 } else if (sampleRate == 11025 || sampleRate == 12000) {
1390 bufferSize = 256 * sizeof(int16_t) * channelCount;
1391 } else if (sampleRate == 22050 || sampleRate == 24000) {
1392 bufferSize = 512 * sizeof(int16_t) * channelCount;
1393 } else if (sampleRate == 44100 || sampleRate == 48000) {
1394 bufferSize = 1024 * sizeof(int16_t) * channelCount;
1395 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001396 } else {
SathishKumar Mani77780382012-09-21 20:58:33 -07001397 ALOGE("getInputBufferSize bad format: %d", format);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001398 }
1399 return bufferSize;
1400}
1401
Ajay Dudani9746c472012-06-18 16:01:16 -07001402#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001403void AudioHardwareALSA::handleFm(int device)
1404{
1405int newMode = mode();
1406 if(device & AudioSystem::DEVICE_OUT_FM && mIsFmActive == 0) {
1407 // Start FM Radio on current active device
1408 unsigned long bufferSize = FM_BUFFER_SIZE;
1409 alsa_handle_t alsa_handle;
1410 char *use_case;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001411 ALOGV("Start FM");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001412 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1413 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1414 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DIGITAL_RADIO, sizeof(alsa_handle.useCase));
1415 } else {
1416 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_FM, sizeof(alsa_handle.useCase));
1417 }
1418 free(use_case);
1419
1420 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1421 bufferSize &= ~b;
1422 alsa_handle.module = mALSADevice;
1423 alsa_handle.bufferSize = bufferSize;
1424 alsa_handle.devices = device;
1425 alsa_handle.handle = 0;
1426 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1427 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
1428 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
1429 alsa_handle.latency = VOICE_LATENCY;
1430 alsa_handle.rxHandle = 0;
1431 alsa_handle.ucMgr = mUcMgr;
1432 mIsFmActive = 1;
1433 mDeviceList.push_back(alsa_handle);
1434 ALSAHandleList::iterator it = mDeviceList.end();
1435 it--;
1436 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1437 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1438 device |= AudioSystem::DEVICE_OUT_PROXY;
1439 alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001440 ALOGD("Routing to proxy for FM case");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001441 }
1442 mALSADevice->route(&(*it), (uint32_t)device, newMode);
1443 if(!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) {
1444 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_DIGITAL_RADIO);
1445 } else {
1446 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_FM);
1447 }
1448 mALSADevice->startFm(&(*it));
1449 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1450 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -07001451 ALOGD("Starting FM, musbPlaybackState %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001452 startUsbPlaybackIfNotStarted();
1453 musbPlaybackState |= USBPLAYBACKBIT_FM;
1454 }
1455 } else if (!(device & AudioSystem::DEVICE_OUT_FM) && mIsFmActive == 1) {
1456 //i Stop FM Radio
Iliyan Malchev4113f342012-06-11 14:39:47 -07001457 ALOGV("Stop FM");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001458 for(ALSAHandleList::iterator it = mDeviceList.begin();
1459 it != mDeviceList.end(); ++it) {
1460 if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
1461 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
1462 mALSADevice->close(&(*it));
1463 //mALSADevice->route(&(*it), (uint32_t)device, newMode);
1464 mDeviceList.erase(it);
1465 break;
1466 }
1467 }
1468 mIsFmActive = 0;
1469 musbPlaybackState &= ~USBPLAYBACKBIT_FM;
1470 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1471 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1472 closeUsbPlaybackIfNothingActive();
1473 }
1474 }
1475}
1476#endif
1477
1478void AudioHardwareALSA::disableVoiceCall(char* verb, char* modifier, int mode, int device)
1479{
1480 for(ALSAHandleList::iterator it = mDeviceList.begin();
1481 it != mDeviceList.end(); ++it) {
1482 if((!strcmp(it->useCase, verb)) ||
1483 (!strcmp(it->useCase, modifier))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001484 ALOGV("Disabling voice call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001485 mALSADevice->close(&(*it));
1486 mALSADevice->route(&(*it), (uint32_t)device, mode);
1487 mDeviceList.erase(it);
1488 break;
1489 }
1490 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001491#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001492 if(musbPlaybackState & USBPLAYBACKBIT_VOICECALL) {
SathishKumar Mani0a019912012-09-11 12:33:11 -07001493 ALOGD("Voice call ended on USB");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001494 musbPlaybackState &= ~USBPLAYBACKBIT_VOICECALL;
1495 musbRecordingState &= ~USBRECBIT_VOICECALL;
1496 closeUsbRecordingIfNothingActive();
1497 closeUsbPlaybackIfNothingActive();
1498 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001499#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001500}
1501void AudioHardwareALSA::enableVoiceCall(char* verb, char* modifier, int mode, int device)
1502{
1503// Start voice call
SathishKumar Mani018d1c52012-09-11 14:58:18 -07001504unsigned long bufferSize = DEFAULT_VOICE_BUFFER_SIZE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001505alsa_handle_t alsa_handle;
1506char *use_case;
1507 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1508 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1509 strlcpy(alsa_handle.useCase, verb, sizeof(alsa_handle.useCase));
1510 } else {
1511 strlcpy(alsa_handle.useCase, modifier, sizeof(alsa_handle.useCase));
1512 }
1513 free(use_case);
1514
1515 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1516 bufferSize &= ~b;
1517 alsa_handle.module = mALSADevice;
1518 alsa_handle.bufferSize = bufferSize;
1519 alsa_handle.devices = device;
1520 alsa_handle.handle = 0;
1521 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1522 alsa_handle.channels = VOICE_CHANNEL_MODE;
1523 alsa_handle.sampleRate = VOICE_SAMPLING_RATE;
1524 alsa_handle.latency = VOICE_LATENCY;
1525 alsa_handle.rxHandle = 0;
1526 alsa_handle.ucMgr = mUcMgr;
1527 mDeviceList.push_back(alsa_handle);
1528 ALSAHandleList::iterator it = mDeviceList.end();
1529 it--;
Ajay Dudani9746c472012-06-18 16:01:16 -07001530#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001531 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1532 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1533 device |= AudioSystem::DEVICE_OUT_PROXY;
1534 alsa_handle.devices = device;
1535 }
1536#endif
1537 mALSADevice->route(&(*it), (uint32_t)device, mode);
1538 if (!strcmp(it->useCase, verb)) {
1539 snd_use_case_set(mUcMgr, "_verb", verb);
1540 } else {
1541 snd_use_case_set(mUcMgr, "_enamod", modifier);
1542 }
1543 mALSADevice->startVoiceCall(&(*it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001544#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001545 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1546 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1547 startUsbRecordingIfNotStarted();
1548 startUsbPlaybackIfNotStarted();
1549 musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
1550 musbRecordingState |= USBRECBIT_VOICECALL;
1551 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001552#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001553}
1554
1555bool AudioHardwareALSA::routeVoiceCall(int device, int newMode)
1556{
1557int csCallState = mCallState&0xF;
1558 bool isRouted = false;
1559 switch (csCallState) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001560 case CS_INACTIVE:
1561 if (mCSCallActive != CS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001562 ALOGD("doRouting: Disabling voice call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001563 disableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
1564 (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
1565 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001566 mCSCallActive = CS_INACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001567 }
1568 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001569 case CS_ACTIVE:
1570 if (mCSCallActive == CS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001571 ALOGD("doRouting: Enabling CS voice call ");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001572 enableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
1573 (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
1574 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001575 mCSCallActive = CS_ACTIVE;
1576 } else if (mCSCallActive == CS_HOLD) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001577 ALOGD("doRouting: Resume voice call from hold state");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001578 ALSAHandleList::iterator vt_it;
1579 for(vt_it = mDeviceList.begin();
1580 vt_it != mDeviceList.end(); ++vt_it) {
1581 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
1582 strlen(SND_USE_CASE_VERB_VOICECALL))) ||
1583 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1584 strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
1585 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001586 mCSCallActive = CS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001587 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001588 ALOGE("VoLTE resume failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001589 break;
1590 }
1591 }
1592 }
1593 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001594 case CS_HOLD:
1595 if (mCSCallActive == CS_ACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001596 ALOGD("doRouting: Voice call going to Hold");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001597 ALSAHandleList::iterator vt_it;
1598 for(vt_it = mDeviceList.begin();
1599 vt_it != mDeviceList.end(); ++vt_it) {
1600 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
1601 strlen(SND_USE_CASE_VERB_VOICECALL))) ||
1602 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1603 strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001604 mCSCallActive = CS_HOLD;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001605 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1606 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001607 ALOGE("Voice pause failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001608 break;
1609 }
1610 }
1611 }
1612 break;
1613 }
1614 return isRouted;
1615}
1616bool AudioHardwareALSA::routeVoLTECall(int device, int newMode)
1617{
1618int volteCallState = mCallState&0xF0;
1619bool isRouted = false;
1620switch (volteCallState) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001621 case IMS_INACTIVE:
1622 if (mVolteCallActive != IMS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001623 ALOGD("doRouting: Disabling IMS call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001624 disableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
1625 (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
1626 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001627 mVolteCallActive = IMS_INACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001628 }
1629 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001630 case IMS_ACTIVE:
1631 if (mVolteCallActive == IMS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001632 ALOGD("doRouting: Enabling IMS voice call ");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001633 enableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
1634 (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
1635 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001636 mVolteCallActive = IMS_ACTIVE;
1637 } else if (mVolteCallActive == IMS_HOLD) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001638 ALOGD("doRouting: Resume IMS call from hold state");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001639 ALSAHandleList::iterator vt_it;
1640 for(vt_it = mDeviceList.begin();
1641 vt_it != mDeviceList.end(); ++vt_it) {
1642 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
1643 strlen(SND_USE_CASE_VERB_VOLTE))) ||
1644 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1645 strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
1646 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001647 mVolteCallActive = IMS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001648 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001649 ALOGE("VoLTE resume failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001650 break;
1651 }
1652 }
1653 }
1654 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001655 case IMS_HOLD:
1656 if (mVolteCallActive == IMS_ACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001657 ALOGD("doRouting: IMS ACTIVE going to HOLD");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001658 ALSAHandleList::iterator vt_it;
1659 for(vt_it = mDeviceList.begin();
1660 vt_it != mDeviceList.end(); ++vt_it) {
1661 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
1662 strlen(SND_USE_CASE_VERB_VOLTE))) ||
1663 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1664 strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001665 mVolteCallActive = IMS_HOLD;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001666 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1667 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001668 ALOGE("VoLTE Pause failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001669 break;
1670 }
1671 }
1672 }
1673 break;
1674 }
1675 return isRouted;
1676}
1677
1678} // namespace android_audio_legacy