blob: 7db7e63f732dd397d7ead1548fc8a5e658971b78 [file] [log] [blame]
Iliyan Malchev4765c432012-06-11 14:36:16 -07001/* AudioHardwareALSA.cpp
2 **
3 ** Copyright 2008-2010 Wind River Systems
4 ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
5 **
6 ** Licensed under the Apache License, Version 2.0 (the "License");
7 ** you may not use this file except in compliance with the License.
8 ** You may obtain a copy of the License at
9 **
10 ** http://www.apache.org/licenses/LICENSE-2.0
11 **
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 */
18
19#include <errno.h>
20#include <stdarg.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <stdlib.h>
24#include <unistd.h>
25#include <dlfcn.h>
26#include <math.h>
27
Ajay Dudani9746c472012-06-18 16:01:16 -070028#define LOG_TAG "AudioHardwareALSA"
Iliyan Malchev4765c432012-06-11 14:36:16 -070029//#define LOG_NDEBUG 0
Ajay Dudani9746c472012-06-18 16:01:16 -070030#define LOG_NDDEBUG 0
Iliyan Malchev4765c432012-06-11 14:36:16 -070031#include <utils/Log.h>
32#include <utils/String8.h>
33#include <sys/prctl.h>
34#include <sys/resource.h>
35#include <sys/poll.h>
36#include <sys/ioctl.h>
37#include <cutils/properties.h>
38#include <media/AudioRecord.h>
39#include <hardware_legacy/power.h>
40
41#include "AudioHardwareALSA.h"
Ajay Dudani9746c472012-06-18 16:01:16 -070042#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -070043#include "AudioUsbALSA.h"
Ajay Dudani9746c472012-06-18 16:01:16 -070044#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070045
46extern "C" {
Ajay Dudani9746c472012-06-18 16:01:16 -070047#ifdef QCOM_CSDCLIENT_ENABLED
48#include "csd_client.h"
49#endif
50#ifdef QCOM_ACDB_ENABLED
51#include "acdb-loader.h"
52#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070053}
54
55extern "C"
56{
57 //
58 // Function for dlsym() to look up for creating a new AudioHardwareInterface.
59 //
60 android_audio_legacy::AudioHardwareInterface *createAudioHardware(void) {
61 return android_audio_legacy::AudioHardwareALSA::create();
62 }
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070063#ifdef QCOM_ACDB_ENABLED
64 static int (*acdb_init)();
65 static void (*acdb_deallocate)();
66#endif
67#ifdef QCOM_CSDCLIENT_ENABLED
68 static int (*csd_start_playback)();
69 static int (*csd_stop_playback)();
70#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070071} // extern "C"
72
73namespace android_audio_legacy
74{
75
76// ----------------------------------------------------------------------------
77
78AudioHardwareInterface *AudioHardwareALSA::create() {
79 return new AudioHardwareALSA();
80}
81
82AudioHardwareALSA::AudioHardwareALSA() :
83 mALSADevice(0),mVoipStreamCount(0),mVoipMicMute(false),mVoipBitRate(0)
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070084 ,mCallState(0),mAcdbHandle(NULL),mCsdHandle(NULL)
Iliyan Malchev4765c432012-06-11 14:36:16 -070085{
86 FILE *fp;
87 char soundCardInfo[200];
88 hw_module_t *module;
89 char platform[128], baseband[128];
90 int err = hw_get_module(ALSA_HARDWARE_MODULE_ID,
91 (hw_module_t const**)&module);
92 int codec_rev = 2;
Iliyan Malchev4113f342012-06-11 14:39:47 -070093 ALOGD("hw_get_module(ALSA_HARDWARE_MODULE_ID) returned err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -070094 if (err == 0) {
95 hw_device_t* device;
96 err = module->methods->open(module, ALSA_HARDWARE_NAME, &device);
97 if (err == 0) {
98 mALSADevice = (alsa_device_t *)device;
99 mALSADevice->init(mALSADevice, mDeviceList);
100 mCSCallActive = 0;
101 mVolteCallActive = 0;
102 mIsFmActive = 0;
103 mDevSettingsFlag = 0;
Ajay Dudani9746c472012-06-18 16:01:16 -0700104#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700105 mAudioUsbALSA = new AudioUsbALSA();
Ajay Dudani9746c472012-06-18 16:01:16 -0700106 musbPlaybackState = 0;
107 musbRecordingState = 0;
108#endif
ty.lee924f7982012-08-01 23:15:30 +0900109#ifdef USES_FLUENCE_INCALL
110 mDevSettingsFlag |= TTY_OFF | DMIC_FLAG;
111#else
Iliyan Malchev4765c432012-06-11 14:36:16 -0700112 mDevSettingsFlag |= TTY_OFF;
ty.lee924f7982012-08-01 23:15:30 +0900113#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700114 mBluetoothVGS = false;
115 mFusion3Platform = false;
Ajay Dudani9746c472012-06-18 16:01:16 -0700116
117#ifdef QCOM_ACDB_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700118 mAcdbHandle = ::dlopen("/system/lib/libacdbloader.so", RTLD_NOW);
119 if (mAcdbHandle == NULL) {
120 ALOGE("AudioHardware: DLOPEN not successful for ACDBLOADER");
121 } else {
122 ALOGD("AudioHardware: DLOPEN successful for ACDBLOADER");
123 acdb_init = (int (*)())::dlsym(mAcdbHandle,"acdb_loader_init_ACDB");
124 if (acdb_init == NULL) {
125 ALOGE("dlsym:Error:%s Loading acdb_loader_init_ACDB", dlerror());
126 }else {
127 acdb_init();
128 acdb_deallocate = (void (*)())::dlsym(mAcdbHandle,"acdb_loader_deallocate_ACDB");
129 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700130 }
131#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700132
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700133#ifdef QCOM_CSDCLIENT_ENABLED
134 mCsdHandle = ::dlopen("/system/lib/libcsd-client.so", RTLD_NOW);
135 if (mCsdHandle == NULL) {
136 ALOGE("AudioHardware: DLOPEN not successful for CSD CLIENT");
137 } else {
138 ALOGD("AudioHardware: DLOPEN successful for CSD CLIENT");
139 csd_start_playback = (int (*)())::dlsym(mCsdHandle,"csd_client_start_playback");
140 csd_stop_playback = (int (*)())::dlsym(mCsdHandle,"csd_client_stop_playback");
141 }
142 mALSADevice->setCsdHandle(mCsdHandle);
143#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700144 if((fp = fopen("/proc/asound/cards","r")) == NULL) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700145 ALOGE("Cannot open /proc/asound/cards file to get sound card info");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700146 } else {
147 while((fgets(soundCardInfo, sizeof(soundCardInfo), fp) != NULL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700148 ALOGV("SoundCardInfo %s", soundCardInfo);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700149 if (strstr(soundCardInfo, "msm8960-tabla1x-snd-card")) {
150 codec_rev = 1;
151 break;
152 } else if (strstr(soundCardInfo, "msm-snd-card")) {
153 codec_rev = 2;
154 break;
155 } else if (strstr(soundCardInfo, "msm8930-sitar-snd-card")) {
156 codec_rev = 3;
157 break;
158 }
159 }
160 fclose(fp);
161 }
162
163 if (codec_rev == 1) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700164 ALOGV("Detected tabla 1.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700165 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm");
166 } else if (codec_rev == 3) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700167 ALOGV("Detected sitar 1.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700168 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_Sitar");
169 } else {
170 property_get("ro.board.platform", platform, "");
171 property_get("ro.baseband", baseband, "");
172 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700173 ALOGV("Detected Fusion tabla 2.x");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700174 mFusion3Platform = true;
175 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x_Fusion3");
176 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700177 ALOGV("Detected tabla 2.x sound card");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700178 snd_use_case_mgr_open(&mUcMgr, "snd_soc_msm_2x");
179 }
180 }
181
182 if (mUcMgr < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700183 ALOGE("Failed to open ucm instance: %d", errno);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700184 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700185 ALOGI("ucm instance opened: %u", (unsigned)mUcMgr);
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700186 mUcMgr->acdb_handle = NULL;
187#ifdef QCOM_ACDB_ENABLED
188 if (mAcdbHandle) {
189 mUcMgr->acdb_handle = static_cast<void*> (mAcdbHandle);
190 }
191#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700192 }
193 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700194 ALOGE("ALSA Module could not be opened!!!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700195 }
196 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700197 ALOGE("ALSA Module not found!!!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700198 }
199}
200
201AudioHardwareALSA::~AudioHardwareALSA()
202{
203 if (mUcMgr != NULL) {
SathishKumar Mani9efed762012-09-18 18:52:48 -0700204 ALOGV("closing ucm instance: %u", (unsigned)mUcMgr);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700205 snd_use_case_mgr_close(mUcMgr);
206 }
207 if (mALSADevice) {
208 mALSADevice->common.close(&mALSADevice->common);
209 }
210 for(ALSAHandleList::iterator it = mDeviceList.begin();
211 it != mDeviceList.end(); ++it) {
212 it->useCase[0] = 0;
213 mDeviceList.erase(it);
214 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700215#ifdef QCOM_ACDB_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700216 if (acdb_deallocate == NULL) {
217 ALOGE("dlsym: Error:%s Loading acdb_deallocate_ACDB", dlerror());
218 } else {
219 acdb_deallocate();
220 }
221 if (mAcdbHandle) {
222 ::dlclose(mAcdbHandle);
223 mAcdbHandle = NULL;
224 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700225#endif
226#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700227 delete mAudioUsbALSA;
Ajay Dudani9746c472012-06-18 16:01:16 -0700228#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700229
230#ifdef QCOM_CSDCLEINT_ENABLED
231 if (mCsdHandle) {
232 ::dlclose(mCsdHandle);
233 mCsdHandle = NULL;
234 }
235#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700236}
237
238status_t AudioHardwareALSA::initCheck()
239{
240 if (!mALSADevice)
241 return NO_INIT;
242
243 return NO_ERROR;
244}
245
246status_t AudioHardwareALSA::setVoiceVolume(float v)
247{
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700248 ALOGV("setVoiceVolume(%f)\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700249 if (v < 0.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700250 ALOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700251 v = 0.0;
252 } else if (v > 1.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700253 ALOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700254 v = 1.0;
255 }
256
257 int newMode = mode();
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700258 ALOGV("setVoiceVolume newMode %d",newMode);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700259 int vol = lrint(v * 100.0);
260
261 // Voice volume levels from android are mapped to driver volume levels as follows.
262 // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
263 // So adjust the volume to get the correct volume index in driver
264 vol = 100 - vol;
265
266 if (mALSADevice) {
267 if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
268 mALSADevice->setVoipVolume(vol);
269 } else if (newMode == AudioSystem::MODE_IN_CALL){
Ajay Dudani9746c472012-06-18 16:01:16 -0700270 if (mCSCallActive == CS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700271 mALSADevice->setVoiceVolume(vol);
Ajay Dudani9746c472012-06-18 16:01:16 -0700272 if (mVolteCallActive == IMS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700273 mALSADevice->setVoLTEVolume(vol);
274 }
275 }
276
277 return NO_ERROR;
278}
279
Ajay Dudani9746c472012-06-18 16:01:16 -0700280#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700281status_t AudioHardwareALSA::setFmVolume(float value)
282{
283 status_t status = NO_ERROR;
284
285 int vol;
286
287 if (value < 0.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700288 ALOGW("setFmVolume(%f) under 0.0, assuming 0.0\n", value);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700289 value = 0.0;
290 } else if (value > 1.0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700291 ALOGW("setFmVolume(%f) over 1.0, assuming 1.0\n", value);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700292 value = 1.0;
293 }
294 vol = lrint((value * 0x2000) + 0.5);
295
SathishKumar Mani9efed762012-09-18 18:52:48 -0700296 ALOGV("setFmVolume(%f)\n", value);
297 ALOGV("Setting FM volume to %d (available range is 0 to 0x2000)\n", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700298
299 mALSADevice->setFmVolume(vol);
300
301 return status;
302}
303#endif
304
305status_t AudioHardwareALSA::setMasterVolume(float volume)
306{
307 return NO_ERROR;
308}
309
310status_t AudioHardwareALSA::setMode(int mode)
311{
312 status_t status = NO_ERROR;
313
314 if (mode != mMode) {
315 status = AudioHardwareBase::setMode(mode);
316 }
317
318 if (mode == AudioSystem::MODE_IN_CALL) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700319 mCallState = CS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700320 }else if (mode == AudioSystem::MODE_NORMAL) {
321 mCallState = 0;
322 }
323
324 return status;
325}
326
327status_t AudioHardwareALSA::setParameters(const String8& keyValuePairs)
328{
329 AudioParameter param = AudioParameter(keyValuePairs);
330 String8 key;
331 String8 value;
332 status_t status = NO_ERROR;
333 int device;
334 int btRate;
335 int state;
SathishKumar Mani9efed762012-09-18 18:52:48 -0700336 ALOGV("setParameters() %s", keyValuePairs.string());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700337
338 key = String8(TTY_MODE_KEY);
339 if (param.get(key, value) == NO_ERROR) {
340 mDevSettingsFlag &= TTY_CLEAR;
ty.leea97e6f62012-08-15 10:11:50 +0900341 if (value == "tty_full") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700342 mDevSettingsFlag |= TTY_FULL;
ty.leea97e6f62012-08-15 10:11:50 +0900343 } else if (value == "tty_hco") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700344 mDevSettingsFlag |= TTY_HCO;
ty.leea97e6f62012-08-15 10:11:50 +0900345 } else if (value == "tty_vco") {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700346 mDevSettingsFlag |= TTY_VCO;
347 } else {
348 mDevSettingsFlag |= TTY_OFF;
349 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700350 ALOGI("Changed TTY Mode=%s", value.string());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700351 mALSADevice->setFlags(mDevSettingsFlag);
352 if(mMode != AudioSystem::MODE_IN_CALL){
353 return NO_ERROR;
354 }
355 doRouting(0);
356 }
357
358 key = String8(FLUENCE_KEY);
359 if (param.get(key, value) == NO_ERROR) {
360 if (value == "quadmic") {
361 mDevSettingsFlag |= QMIC_FLAG;
362 mDevSettingsFlag &= (~DMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700363 ALOGV("Fluence quadMic feature Enabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700364 } else if (value == "dualmic") {
365 mDevSettingsFlag |= DMIC_FLAG;
366 mDevSettingsFlag &= (~QMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700367 ALOGV("Fluence dualmic feature Enabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700368 } else if (value == "none") {
369 mDevSettingsFlag &= (~DMIC_FLAG);
370 mDevSettingsFlag &= (~QMIC_FLAG);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700371 ALOGV("Fluence feature Disabled");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700372 }
373 mALSADevice->setFlags(mDevSettingsFlag);
374 doRouting(0);
375 }
376
Ajay Dudani9746c472012-06-18 16:01:16 -0700377#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700378 if (mFusion3Platform) {
379 key = String8(INCALLMUSIC_KEY);
380 if (param.get(key, value) == NO_ERROR) {
381 if (value == "true") {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700382 ALOGV("Enabling Incall Music setting in the setparameter\n");
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700383 if (csd_start_playback == NULL) {
384 ALOGE("dlsym: Error:%s Loading csd_client_start_playback", dlerror());
385 } else {
386 csd_start_playback();
387 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700388 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700389 ALOGV("Disabling Incall Music setting in the setparameter\n");
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700390 if (csd_stop_playback == NULL) {
391 ALOGE("dlsym: Error:%s Loading csd_client_stop_playback", dlerror());
392 } else {
393 csd_stop_playback();
394 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700395 }
396 }
397 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700398#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700399
400 key = String8(ANC_KEY);
401 if (param.get(key, value) == NO_ERROR) {
402 if (value == "true") {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700403 ALOGV("Enabling ANC setting in the setparameter\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700404 mDevSettingsFlag |= ANC_FLAG;
405 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700406 ALOGV("Disabling ANC setting in the setparameter\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700407 mDevSettingsFlag &= (~ANC_FLAG);
408 }
409 mALSADevice->setFlags(mDevSettingsFlag);
410 doRouting(0);
411 }
412
413 key = String8(AudioParameter::keyRouting);
414 if (param.getInt(key, device) == NO_ERROR) {
415 // Ignore routing if device is 0.
416 if(device) {
417 doRouting(device);
418 }
419 param.remove(key);
420 }
421
422 key = String8(BT_SAMPLERATE_KEY);
423 if (param.getInt(key, btRate) == NO_ERROR) {
424 mALSADevice->setBtscoRate(btRate);
425 param.remove(key);
426 }
427
428 key = String8(BTHEADSET_VGS);
429 if (param.get(key, value) == NO_ERROR) {
430 if (value == "on") {
431 mBluetoothVGS = true;
432 } else {
433 mBluetoothVGS = false;
434 }
435 }
436
437 key = String8(WIDEVOICE_KEY);
438 if (param.get(key, value) == NO_ERROR) {
439 bool flag = false;
440 if (value == "true") {
441 flag = true;
442 }
443 if(mALSADevice) {
444 mALSADevice->enableWideVoice(flag);
445 }
446 param.remove(key);
447 }
448
449 key = String8(VOIPRATE_KEY);
450 if (param.get(key, value) == NO_ERROR) {
451 mVoipBitRate = atoi(value);
452 param.remove(key);
453 }
454
455 key = String8(FENS_KEY);
456 if (param.get(key, value) == NO_ERROR) {
457 bool flag = false;
458 if (value == "true") {
459 flag = true;
460 }
461 if(mALSADevice) {
462 mALSADevice->enableFENS(flag);
463 }
464 param.remove(key);
465 }
466
Ajay Dudani9746c472012-06-18 16:01:16 -0700467#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700468 key = String8(AudioParameter::keyHandleFm);
469 if (param.getInt(key, device) == NO_ERROR) {
470 // Ignore if device is 0
471 if(device) {
472 handleFm(device);
473 }
474 param.remove(key);
475 }
476#endif
477
478 key = String8(ST_KEY);
479 if (param.get(key, value) == NO_ERROR) {
480 bool flag = false;
481 if (value == "true") {
482 flag = true;
483 }
484 if(mALSADevice) {
485 mALSADevice->enableSlowTalk(flag);
486 }
487 param.remove(key);
488 }
489 key = String8(MODE_CALL_KEY);
490 if (param.getInt(key,state) == NO_ERROR) {
491 if (mCallState != state) {
492 mCallState = state;
493 doRouting(0);
494 }
495 mCallState = state;
496 }
497 if (param.size()) {
498 status = BAD_VALUE;
499 }
500 return status;
501}
502
503String8 AudioHardwareALSA::getParameters(const String8& keys)
504{
505 AudioParameter param = AudioParameter(keys);
506 String8 value;
507
508 String8 key = String8(DUALMIC_KEY);
509 if (param.get(key, value) == NO_ERROR) {
510 value = String8("false");
511 param.add(key, value);
512 }
513
514 key = String8(FLUENCE_KEY);
515 if (param.get(key, value) == NO_ERROR) {
516 if ((mDevSettingsFlag & QMIC_FLAG) &&
517 (mDevSettingsFlag & ~DMIC_FLAG))
518 value = String8("quadmic");
519 else if ((mDevSettingsFlag & DMIC_FLAG) &&
520 (mDevSettingsFlag & ~QMIC_FLAG))
521 value = String8("dualmic");
522 else if ((mDevSettingsFlag & ~DMIC_FLAG) &&
523 (mDevSettingsFlag & ~QMIC_FLAG))
524 value = String8("none");
525 param.add(key, value);
526 }
527
Ajay Dudani9746c472012-06-18 16:01:16 -0700528#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700529 key = String8("Fm-radio");
530 if ( param.get(key,value) == NO_ERROR ) {
531 if ( mIsFmActive ) {
532 param.addInt(String8("isFMON"), true );
533 }
534 }
535#endif
536
537 key = String8(BTHEADSET_VGS);
538 if (param.get(key, value) == NO_ERROR) {
539 if(mBluetoothVGS)
540 param.addInt(String8("isVGS"), true);
541 }
542
Iliyan Malchev4113f342012-06-11 14:39:47 -0700543 ALOGV("AudioHardwareALSA::getParameters() %s", param.toString().string());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700544 return param.toString();
545}
546
Ajay Dudani9746c472012-06-18 16:01:16 -0700547#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700548void AudioHardwareALSA::closeUSBPlayback()
549{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700550 ALOGV("closeUSBPlayback, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700551 musbPlaybackState = 0;
552 mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_KILLTHREAD);
553}
554
555void AudioHardwareALSA::closeUSBRecording()
556{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700557 ALOGV("closeUSBRecording");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700558 musbRecordingState = 0;
559 mAudioUsbALSA->exitRecordingThread(SIGNAL_EVENT_KILLTHREAD);
560}
561
562void AudioHardwareALSA::closeUsbPlaybackIfNothingActive(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700563 ALOGV("closeUsbPlaybackIfNothingActive, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700564 if(!musbPlaybackState && mAudioUsbALSA != NULL) {
565 mAudioUsbALSA->exitPlaybackThread(SIGNAL_EVENT_TIMEOUT);
566 }
567}
568
569void AudioHardwareALSA::closeUsbRecordingIfNothingActive(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700570 ALOGV("closeUsbRecordingIfNothingActive, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700571 if(!musbRecordingState && mAudioUsbALSA != NULL) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700572 ALOGD("Closing USB Recording Session as no stream is active");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700573 mAudioUsbALSA->setkillUsbRecordingThread(true);
574 }
575}
576
577void AudioHardwareALSA::startUsbPlaybackIfNotStarted(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700578 ALOGV("Starting the USB playback %d kill %d", musbPlaybackState,
Iliyan Malchev4765c432012-06-11 14:36:16 -0700579 mAudioUsbALSA->getkillUsbPlaybackThread());
580 if((!musbPlaybackState) || (mAudioUsbALSA->getkillUsbPlaybackThread() == true)) {
581 mAudioUsbALSA->startPlayback();
582 }
583}
584
585void AudioHardwareALSA::startUsbRecordingIfNotStarted(){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700586 ALOGV("Starting the recording musbRecordingState: %d killUsbRecordingThread %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700587 musbRecordingState, mAudioUsbALSA->getkillUsbRecordingThread());
588 if((!musbRecordingState) || (mAudioUsbALSA->getkillUsbRecordingThread() == true)) {
589 mAudioUsbALSA->startRecording();
590 }
591}
Ajay Dudani9746c472012-06-18 16:01:16 -0700592#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700593
594void AudioHardwareALSA::doRouting(int device)
595{
596 Mutex::Autolock autoLock(mLock);
597 int newMode = mode();
598 bool isRouted = false;
599
Ajay Dudani9746c472012-06-18 16:01:16 -0700600 if ((device == AudioSystem::DEVICE_IN_VOICE_CALL)
601#ifdef QCOM_FM_ENABLED
602 || (device == AudioSystem::DEVICE_IN_FM_RX)
603 || (device == AudioSystem::DEVICE_OUT_DIRECTOUTPUT)
604 || (device == AudioSystem::DEVICE_IN_FM_RX_A2DP)
Iliyan Malchev4765c432012-06-11 14:36:16 -0700605#endif
Ajay Dudani9746c472012-06-18 16:01:16 -0700606 || (device == AudioSystem::DEVICE_IN_COMMUNICATION)
607 ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700608 ALOGV("Ignoring routing for FM/INCALL/VOIP recording");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700609 return;
610 }
611 if (device == 0)
612 device = mCurDevice;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700613 ALOGV("doRouting: device %d newMode %d mCSCallActive %d mVolteCallActive %d"
Iliyan Malchev4765c432012-06-11 14:36:16 -0700614 "mIsFmActive %d", device, newMode, mCSCallActive, mVolteCallActive,
615 mIsFmActive);
616
617 isRouted = routeVoLTECall(device, newMode);
618 isRouted |= routeVoiceCall(device, newMode);
619
620 if(!isRouted) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700621#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700622 if(!(device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) &&
623 !(device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET) &&
624 !(device & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) &&
625 (musbPlaybackState)){
626 //USB unplugged
627 device &= ~ AudioSystem::DEVICE_OUT_PROXY;
628 device &= ~ AudioSystem::DEVICE_IN_PROXY;
629 ALSAHandleList::iterator it = mDeviceList.end();
630 it--;
631 mALSADevice->route(&(*it), (uint32_t)device, newMode);
SathishKumar Mani0a019912012-09-11 12:33:11 -0700632 ALOGD("USB UNPLUGGED, setting musbPlaybackState to 0");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700633 musbPlaybackState = 0;
634 musbRecordingState = 0;
635 closeUSBRecording();
636 closeUSBPlayback();
637 } else if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
638 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -0700639 ALOGD("Routing everything to prox now");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700640 ALSAHandleList::iterator it = mDeviceList.end();
641 it--;
642 mALSADevice->route(&(*it), AudioSystem::DEVICE_OUT_PROXY,
643 newMode);
644 for(it = mDeviceList.begin(); it != mDeviceList.end(); ++it) {
645 if((!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
646 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_LPA))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700647 ALOGV("doRouting: LPA device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700648 startUsbPlaybackIfNotStarted();
649 musbPlaybackState |= USBPLAYBACKBIT_LPA;
650 break;
651 } else if((!strcmp(it->useCase, SND_USE_CASE_VERB_VOICECALL)) ||
652 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOICE))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700653 ALOGV("doRouting: VOICE device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700654 startUsbRecordingIfNotStarted();
655 startUsbPlaybackIfNotStarted();
656 musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
657 musbRecordingState |= USBPLAYBACKBIT_VOICECALL;
658 break;
659 }else if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
660 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700661 ALOGV("doRouting: FM device switch to proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700662 startUsbPlaybackIfNotStarted();
663 musbPlaybackState |= USBPLAYBACKBIT_FM;
664 break;
665 }
666 }
SathishKumar Manie42406e2012-08-29 16:25:54 -0700667 } else
Iliyan Malchev4765c432012-06-11 14:36:16 -0700668#endif
SathishKumar Manie42406e2012-08-29 16:25:54 -0700669 {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700670 ALSAHandleList::iterator it = mDeviceList.end();
671 it--;
672 mALSADevice->route(&(*it), (uint32_t)device, newMode);
673 }
674 }
675 mCurDevice = device;
676}
677
678uint32_t AudioHardwareALSA::getVoipMode(int format)
679{
680 switch(format) {
681 case AudioSystem::PCM_16_BIT:
682 return MODE_PCM;
683 break;
684 case AudioSystem::AMR_NB:
685 return MODE_AMR;
686 break;
687 case AudioSystem::AMR_WB:
688 return MODE_AMR_WB;
689 break;
690
Ajay Dudani9746c472012-06-18 16:01:16 -0700691#ifdef QCOM_QCHAT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700692 case AudioSystem::EVRC:
693 return MODE_IS127;
694 break;
695
696 case AudioSystem::EVRCB:
697 return MODE_4GV_NB;
698 break;
699 case AudioSystem::EVRCWB:
700 return MODE_4GV_WB;
701 break;
Ajay Dudani9746c472012-06-18 16:01:16 -0700702#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700703
704 default:
705 return MODE_PCM;
706 }
707}
708
709AudioStreamOut *
710AudioHardwareALSA::openOutputStream(uint32_t devices,
711 int *format,
712 uint32_t *channels,
713 uint32_t *sampleRate,
714 status_t *status)
715{
716 Mutex::Autolock autoLock(mLock);
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700717 ALOGV("openOutputStream: devices 0x%x channels %d sampleRate %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700718 devices, *channels, *sampleRate);
719
SathishKumar Mani88613382012-08-13 18:40:18 -0700720 audio_output_flags_t flag = static_cast<audio_output_flags_t> (*status);
721
Iliyan Malchev4765c432012-06-11 14:36:16 -0700722 status_t err = BAD_VALUE;
SathishKumar Mani88613382012-08-13 18:40:18 -0700723 *status = NO_ERROR;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700724 AudioStreamOutALSA *out = 0;
725 ALSAHandleList::iterator it;
726
727 if (devices & (devices - 1)) {
728 if (status) *status = err;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700729 ALOGE("openOutputStream called with bad devices");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700730 return out;
731 }
SathishKumar Mani88613382012-08-13 18:40:18 -0700732
733
Iliyan Malchev4765c432012-06-11 14:36:16 -0700734# if 0
735 if((devices == AudioSystem::DEVICE_OUT_DIRECTOUTPUT) &&
736 ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
737 bool voipstream_active = false;
738 for(it = mDeviceList.begin();
739 it != mDeviceList.end(); ++it) {
740 if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
741 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700742 ALOGD("openOutput: it->rxHandle %d it->handle %d",it->rxHandle,it->handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700743 voipstream_active = true;
744 break;
745 }
746 }
747 if(voipstream_active == false) {
748 mVoipStreamCount = 0;
749 mVoipMicMute = false;
750 alsa_handle_t alsa_handle;
751 unsigned long bufferSize;
752 if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
753 bufferSize = VOIP_BUFFER_SIZE_8K;
754 }
755 else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
756 bufferSize = VOIP_BUFFER_SIZE_16K;
757 }
758 else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700759 ALOGE("unsupported samplerate %d for voip",*sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700760 if (status) *status = err;
761 return out;
762 }
763 alsa_handle.module = mALSADevice;
764 alsa_handle.bufferSize = bufferSize;
765 alsa_handle.devices = devices;
766 alsa_handle.handle = 0;
767 if(*format == AudioSystem::PCM_16_BIT)
768 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
769 else
770 alsa_handle.format = *format;
771 alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
772 alsa_handle.sampleRate = *sampleRate;
773 alsa_handle.latency = VOIP_PLAYBACK_LATENCY;
774 alsa_handle.rxHandle = 0;
775 alsa_handle.ucMgr = mUcMgr;
776 mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
777 char *use_case;
778 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
779 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
780 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
781 } else {
782 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
783 }
784 free(use_case);
785 mDeviceList.push_back(alsa_handle);
786 it = mDeviceList.end();
787 it--;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700788 ALOGV("openoutput: mALSADevice->route useCase %s mCurDevice %d mVoipStreamCount %d mode %d", it->useCase,mCurDevice,mVoipStreamCount, mode());
Iliyan Malchev4765c432012-06-11 14:36:16 -0700789 if((mCurDevice & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
790 (mCurDevice & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)||
791 (mCurDevice & AudioSystem::DEVICE_OUT_PROXY)){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700792 ALOGD("Routing to proxy for normal voip call in openOutputStream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700793 mCurDevice |= AudioSystem::DEVICE_OUT_PROXY;
794 alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
795 mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700796 ALOGD("enabling VOIP in openoutputstream, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700797 startUsbPlaybackIfNotStarted();
798 musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700799 ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700800 startUsbRecordingIfNotStarted();
801 musbRecordingState |= USBRECBIT_VOIPCALL;
802 } else{
803 mALSADevice->route(&(*it), mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
804 }
805 if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
806 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
807 } else {
808 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
809 }
810 err = mALSADevice->startVoipCall(&(*it));
811 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700812 ALOGE("Device open failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700813 return NULL;
814 }
815 }
816 out = new AudioStreamOutALSA(this, &(*it));
817 err = out->set(format, channels, sampleRate, devices);
818 if(err == NO_ERROR) {
819 mVoipStreamCount++; //increment VoipstreamCount only if success
Iliyan Malchev4113f342012-06-11 14:39:47 -0700820 ALOGD("openoutput mVoipStreamCount %d",mVoipStreamCount);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700821 }
822 if (status) *status = err;
823 return out;
824 } else
825#endif
826 {
827
828 alsa_handle_t alsa_handle;
829 unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
830
831 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
832 bufferSize &= ~b;
833
834 alsa_handle.module = mALSADevice;
835 alsa_handle.bufferSize = bufferSize;
836 alsa_handle.devices = devices;
837 alsa_handle.handle = 0;
838 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
839 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
840 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
841 alsa_handle.latency = PLAYBACK_LATENCY;
842 alsa_handle.rxHandle = 0;
843 alsa_handle.ucMgr = mUcMgr;
SathishKumar Mani88613382012-08-13 18:40:18 -0700844 alsa_handle.isDeepbufferOutput = false;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700845
846 char *use_case;
847 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
SathishKumar Mani88613382012-08-13 18:40:18 -0700848
849 if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
SathishKumar Mani9efed762012-09-18 18:52:48 -0700850 ALOGD("openOutputStream: DeepBuffer Output");
SathishKumar Mani88613382012-08-13 18:40:18 -0700851 alsa_handle.isDeepbufferOutput = true;
852 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
853 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI, sizeof(alsa_handle.useCase));
854 } else {
855 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC, sizeof(alsa_handle.useCase));
856 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700857 } else {
SathishKumar Mani9efed762012-09-18 18:52:48 -0700858 ALOGD("openOutputStream: Lowlatency Output");
SathishKumar Mani88613382012-08-13 18:40:18 -0700859 alsa_handle.bufferSize = PLAYBACK_LOW_LATENCY_BUFFER_SIZE;
860 alsa_handle.latency = PLAYBACK_LOW_LATENCY;
861 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
862 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
863 } else {
864 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
865 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700866 }
867 free(use_case);
868 mDeviceList.push_back(alsa_handle);
869 ALSAHandleList::iterator it = mDeviceList.end();
870 it--;
Ajay Dudani8a9785b2012-09-10 23:28:45 -0700871 ALOGV("useCase %s", it->useCase);
Ajay Dudani9746c472012-06-18 16:01:16 -0700872#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700873 if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
874 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -0700875 ALOGD("Routing to proxy for normal playback in openOutputStream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700876 devices |= AudioSystem::DEVICE_OUT_PROXY;
877 }
878#endif
879 mALSADevice->route(&(*it), devices, mode());
SathishKumar Mani88613382012-08-13 18:40:18 -0700880 if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
881 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI)) {
882 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI);
883 } else {
884 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC);
885 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700886 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -0700887 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) {
888 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC);
889 } else {
890 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC);
891 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700892 }
893 err = mALSADevice->open(&(*it));
894 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700895 ALOGE("Device open failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700896 } else {
897 out = new AudioStreamOutALSA(this, &(*it));
898 err = out->set(format, channels, sampleRate, devices);
899 }
900
901 if (status) *status = err;
902 return out;
903 }
904}
905
906void
907AudioHardwareALSA::closeOutputStream(AudioStreamOut* out)
908{
909 delete out;
910}
911
Ajay Dudani9746c472012-06-18 16:01:16 -0700912#ifdef QCOM_TUNNEL_LPA_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700913AudioStreamOut *
914AudioHardwareALSA::openOutputSession(uint32_t devices,
915 int *format,
916 status_t *status,
917 int sessionId,
918 uint32_t samplingRate,
919 uint32_t channels)
920{
921 Mutex::Autolock autoLock(mLock);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700922 ALOGD("openOutputSession = %d" ,sessionId);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700923 AudioStreamOutALSA *out = 0;
924 status_t err = BAD_VALUE;
925
926 alsa_handle_t alsa_handle;
927 unsigned long bufferSize = DEFAULT_BUFFER_SIZE;
928
929 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
930 bufferSize &= ~b;
931
932 alsa_handle.module = mALSADevice;
933 alsa_handle.bufferSize = bufferSize;
934 alsa_handle.devices = devices;
935 alsa_handle.handle = 0;
936 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
937 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
938 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
939 alsa_handle.latency = VOICE_LATENCY;
940 alsa_handle.rxHandle = 0;
941 alsa_handle.ucMgr = mUcMgr;
942
943 char *use_case;
944 if(sessionId == TUNNEL_SESSION_ID) {
945 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
946 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
947 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_TUNNEL, sizeof(alsa_handle.useCase));
948 } else {
949 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_TUNNEL, sizeof(alsa_handle.useCase));
950 }
951 } else {
952 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
953 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
954 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER, sizeof(alsa_handle.useCase));
955 } else {
956 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LPA, sizeof(alsa_handle.useCase));
957 }
958 }
959 free(use_case);
960 mDeviceList.push_back(alsa_handle);
961 ALSAHandleList::iterator it = mDeviceList.end();
962 it--;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700963 ALOGD("useCase %s", it->useCase);
Ajay Dudani9746c472012-06-18 16:01:16 -0700964#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700965 if((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
966 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -0700967 ALOGD("Routing to proxy for LPA in openOutputSession");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700968 devices |= AudioSystem::DEVICE_OUT_PROXY;
969 mALSADevice->route(&(*it), devices, mode());
970 devices = AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700971 ALOGD("Starting USBPlayback for LPA");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700972 startUsbPlaybackIfNotStarted();
973 musbPlaybackState |= USBPLAYBACKBIT_LPA;
974 } else
975#endif
976 {
977 mALSADevice->route(&(*it), devices, mode());
978 }
979 if(sessionId == TUNNEL_SESSION_ID) {
980 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) {
981 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_TUNNEL);
982 } else {
983 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_TUNNEL);
984 }
985 }
986 else {
987 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) {
988 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOW_POWER);
989 } else {
990 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LPA);
991 }
992 }
993 err = mALSADevice->open(&(*it));
994 out = new AudioStreamOutALSA(this, &(*it));
995
996 if (status) *status = err;
997 return out;
998}
999
1000void
1001AudioHardwareALSA::closeOutputSession(AudioStreamOut* out)
1002{
1003 delete out;
1004}
Ajay Dudani9746c472012-06-18 16:01:16 -07001005#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001006
1007AudioStreamIn *
1008AudioHardwareALSA::openInputStream(uint32_t devices,
1009 int *format,
1010 uint32_t *channels,
1011 uint32_t *sampleRate,
1012 status_t *status,
1013 AudioSystem::audio_in_acoustics acoustics)
1014{
1015 Mutex::Autolock autoLock(mLock);
1016 char *use_case;
1017 int newMode = mode();
1018 uint32_t route_devices;
1019
1020 status_t err = BAD_VALUE;
1021 AudioStreamInALSA *in = 0;
1022 ALSAHandleList::iterator it;
1023
Iliyan Malchev4113f342012-06-11 14:39:47 -07001024 ALOGD("openInputStream: devices 0x%x channels %d sampleRate %d", devices, *channels, *sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001025 if (devices & (devices - 1)) {
1026 if (status) *status = err;
1027 return in;
1028 }
1029
1030 if((devices == AudioSystem::DEVICE_IN_COMMUNICATION) &&
1031 ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
1032 bool voipstream_active = false;
1033 for(it = mDeviceList.begin();
1034 it != mDeviceList.end(); ++it) {
1035 if((!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
1036 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001037 ALOGD("openInput: it->rxHandle %p it->handle %p",it->rxHandle,it->handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001038 voipstream_active = true;
1039 break;
1040 }
1041 }
1042 if(voipstream_active == false) {
1043 mVoipStreamCount = 0;
1044 mVoipMicMute = false;
1045 alsa_handle_t alsa_handle;
1046 unsigned long bufferSize;
1047 if(*sampleRate == VOIP_SAMPLING_RATE_8K) {
1048 bufferSize = VOIP_BUFFER_SIZE_8K;
1049 }
1050 else if(*sampleRate == VOIP_SAMPLING_RATE_16K) {
1051 bufferSize = VOIP_BUFFER_SIZE_16K;
1052 }
1053 else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001054 ALOGE("unsupported samplerate %d for voip",*sampleRate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001055 if (status) *status = err;
1056 return in;
1057 }
1058 alsa_handle.module = mALSADevice;
1059 alsa_handle.bufferSize = bufferSize;
1060 alsa_handle.devices = devices;
1061 alsa_handle.handle = 0;
1062 if(*format == AudioSystem::PCM_16_BIT)
1063 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1064 else
1065 alsa_handle.format = *format;
1066 alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
1067 alsa_handle.sampleRate = *sampleRate;
1068 alsa_handle.latency = VOIP_RECORD_LATENCY;
1069 alsa_handle.rxHandle = 0;
1070 alsa_handle.ucMgr = mUcMgr;
1071 mALSADevice->setVoipConfig(getVoipMode(*format), mVoipBitRate);
1072 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1073 if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1074 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(alsa_handle.useCase));
1075 } else {
1076 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(alsa_handle.useCase));
1077 }
1078 free(use_case);
1079 mDeviceList.push_back(alsa_handle);
1080 it = mDeviceList.end();
1081 it--;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001082 ALOGD("mCurrDevice: %d", mCurDevice);
Ajay Dudani9746c472012-06-18 16:01:16 -07001083#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001084 if((mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1085 (mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -07001086 ALOGD("Routing everything from proxy for voipcall");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001087 mALSADevice->route(&(*it), AudioSystem::DEVICE_IN_PROXY, AudioSystem::MODE_IN_COMMUNICATION);
Iliyan Malchev4113f342012-06-11 14:39:47 -07001088 ALOGD("enabling VOIP in openInputstream, musbPlaybackState: %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001089 startUsbPlaybackIfNotStarted();
1090 musbPlaybackState |= USBPLAYBACKBIT_VOIPCALL;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001091 ALOGD("Starting recording in openoutputstream, musbRecordingState: %d", musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001092 startUsbRecordingIfNotStarted();
1093 musbRecordingState |= USBRECBIT_VOIPCALL;
SathishKumar Manie42406e2012-08-29 16:25:54 -07001094 } else
Iliyan Malchev4765c432012-06-11 14:36:16 -07001095#endif
1096 {
1097 mALSADevice->route(&(*it),mCurDevice, AudioSystem::MODE_IN_COMMUNICATION);
1098 }
1099 if(!strcmp(it->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) {
1100 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_IP_VOICECALL);
1101 } else {
1102 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_VOIP);
1103 }
1104 if(sampleRate) {
1105 it->sampleRate = *sampleRate;
1106 }
1107 if(channels)
1108 it->channels = AudioSystem::popCount(*channels);
1109 err = mALSADevice->startVoipCall(&(*it));
1110 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001111 ALOGE("Error opening pcm input device");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001112 return NULL;
1113 }
1114 }
1115 in = new AudioStreamInALSA(this, &(*it), acoustics);
1116 err = in->set(format, channels, sampleRate, devices);
1117 if(err == NO_ERROR) {
1118 mVoipStreamCount++; //increment VoipstreamCount only if success
Iliyan Malchev4113f342012-06-11 14:39:47 -07001119 ALOGD("OpenInput mVoipStreamCount %d",mVoipStreamCount);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001120 }
SathishKumar Mani0a019912012-09-11 12:33:11 -07001121 ALOGD("openInput: After Get alsahandle");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001122 if (status) *status = err;
1123 return in;
1124 } else
1125 {
1126 for(ALSAHandleList::iterator itDev = mDeviceList.begin();
1127 itDev != mDeviceList.end(); ++itDev)
1128 {
1129 if((0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_HIFI_REC, MAX_UC_LEN))
1130 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, MAX_UC_LEN))
SathishKumar Mani88613382012-08-13 18:40:18 -07001131 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, MAX_UC_LEN))
1132 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, MAX_UC_LEN))
Iliyan Malchev4765c432012-06-11 14:36:16 -07001133 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_FM, MAX_UC_LEN))
Ajay Dudani9746c472012-06-18 16:01:16 -07001134#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001135 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_FM_REC, MAX_UC_LEN))
1136#endif
1137 )
1138 {
Ajay Dudani9746c472012-06-18 16:01:16 -07001139#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001140 if(!(devices == AudioSystem::DEVICE_IN_FM_RX_A2DP)){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001141 ALOGD("Input stream already exists, new stream not permitted: useCase:%s, devices:0x%x, module:%p",
Iliyan Malchev4765c432012-06-11 14:36:16 -07001142 itDev->useCase, itDev->devices, itDev->module);
1143 return in;
1144 }
1145#endif
1146 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001147#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001148 else if ((0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_FM_A2DP_REC, MAX_UC_LEN))
1149 ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, MAX_UC_LEN)))
1150 {
1151 if((devices == AudioSystem::DEVICE_IN_FM_RX_A2DP)){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001152 ALOGD("Input stream already exists, new stream not permitted: useCase:%s, devices:0x%x, module:%p",
Iliyan Malchev4765c432012-06-11 14:36:16 -07001153 itDev->useCase, itDev->devices, itDev->module);
1154 return in;
1155 }
1156 }
1157#endif
1158 }
1159
1160 alsa_handle_t alsa_handle;
1161 unsigned long bufferSize = DEFAULT_IN_BUFFER_SIZE;
1162
1163 alsa_handle.module = mALSADevice;
1164 alsa_handle.bufferSize = bufferSize;
1165 alsa_handle.devices = devices;
1166 alsa_handle.handle = 0;
1167 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1168 alsa_handle.channels = VOICE_CHANNEL_MODE;
1169 alsa_handle.sampleRate = android::AudioRecord::DEFAULT_SAMPLE_RATE;
1170 alsa_handle.latency = RECORD_LATENCY;
1171 alsa_handle.rxHandle = 0;
1172 alsa_handle.ucMgr = mUcMgr;
1173 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1174 if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1175 if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
1176 (newMode == AudioSystem::MODE_IN_CALL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001177 ALOGD("openInputStream: into incall recording, channels %d", *channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001178 mIncallMode = *channels;
1179 if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
1180 (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
1181 if (mFusion3Platform) {
1182 mALSADevice->setVocRecMode(INCALL_REC_STEREO);
1183 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1184 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001185 } else {
1186 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
1187 sizeof(alsa_handle.useCase));
1188 }
1189 } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
1190 if (mFusion3Platform) {
1191 mALSADevice->setVocRecMode(INCALL_REC_MONO);
1192 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1193 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001194 } else {
1195 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
1196 sizeof(alsa_handle.useCase));
1197 }
1198 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001199#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001200 } else if((devices == AudioSystem::DEVICE_IN_FM_RX)) {
1201 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_FM, sizeof(alsa_handle.useCase));
1202 } else if(devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
1203 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, sizeof(alsa_handle.useCase));
1204#endif
1205 } else {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001206 char value[128];
1207 property_get("persist.audio.lowlatency.rec",value,"0");
SathishKumar Mani88613382012-08-13 18:40:18 -07001208 if (!strcmp("true", value)) {
1209 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
1210 } else {
1211 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, sizeof(alsa_handle.useCase));
1212 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001213 }
1214 } else {
1215 if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
1216 (newMode == AudioSystem::MODE_IN_CALL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001217 ALOGD("openInputStream: incall recording, channels %d", *channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001218 mIncallMode = *channels;
1219 if ((*channels & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
1220 (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
1221 if (mFusion3Platform) {
1222 mALSADevice->setVocRecMode(INCALL_REC_STEREO);
1223 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
1224 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001225 } else {
1226 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_UL_DL_REC,
1227 sizeof(alsa_handle.useCase));
1228 }
1229 } else if (*channels & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
1230 if (mFusion3Platform) {
1231 mALSADevice->setVocRecMode(INCALL_REC_MONO);
1232 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_INCALL_REC,
1233 sizeof(alsa_handle.useCase));
Iliyan Malchev4765c432012-06-11 14:36:16 -07001234 } else {
1235 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DL_REC,
1236 sizeof(alsa_handle.useCase));
1237 }
1238 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001239#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001240 } else if(devices == AudioSystem::DEVICE_IN_FM_RX) {
1241 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_REC, sizeof(alsa_handle.useCase));
1242 } else if (devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
1243 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_A2DP_REC, sizeof(alsa_handle.useCase));
1244#endif
1245 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -07001246 char value[128];
1247 property_get("persist.audio.lowlatency.rec",value,"0");
1248 if (!strcmp("true", value)) {
1249 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, sizeof(alsa_handle.useCase));
1250 } else {
1251 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_REC, sizeof(alsa_handle.useCase));
1252 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001253 }
1254 }
1255 free(use_case);
1256 mDeviceList.push_back(alsa_handle);
1257 ALSAHandleList::iterator it = mDeviceList.end();
1258 it--;
1259 //update channel info before do routing
1260 if(channels) {
1261 it->channels = AudioSystem::popCount((*channels) &
Ajay Dudani9746c472012-06-18 16:01:16 -07001262 (AudioSystem::CHANNEL_IN_STEREO
1263 | AudioSystem::CHANNEL_IN_MONO
1264#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001265 | AudioSystem::CHANNEL_IN_5POINT1
1266#endif
1267 ));
Iliyan Malchev4113f342012-06-11 14:39:47 -07001268 ALOGV("updated channel info: channels=%d", it->channels);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001269 }
1270 if (devices == AudioSystem::DEVICE_IN_VOICE_CALL){
1271 /* Add current devices info to devices to do route */
Ajay Dudani9746c472012-06-18 16:01:16 -07001272#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001273 if(mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET ||
1274 mCurDevice == AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001275 ALOGD("Routing everything from proxy for VOIP call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001276 route_devices = devices | AudioSystem::DEVICE_IN_PROXY;
1277 } else
1278#endif
1279 {
1280 route_devices = devices | mCurDevice;
1281 }
1282 mALSADevice->route(&(*it), route_devices, mode());
1283 } else {
Ajay Dudani9746c472012-06-18 16:01:16 -07001284#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001285 if(devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET ||
1286 devices & AudioSystem::DEVICE_IN_PROXY) {
1287 devices |= AudioSystem::DEVICE_IN_PROXY;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001288 ALOGD("routing everything from proxy");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001289 mALSADevice->route(&(*it), devices, mode());
1290 } else
1291#endif
1292 {
1293 mALSADevice->route(&(*it), devices, mode());
1294 }
1295 }
1296
1297 if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001298 !strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC) ||
Ajay Dudani9746c472012-06-18 16:01:16 -07001299#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001300 !strcmp(it->useCase, SND_USE_CASE_VERB_FM_REC) ||
1301 !strcmp(it->useCase, SND_USE_CASE_VERB_FM_A2DP_REC) ||
1302#endif
1303 !strcmp(it->useCase, SND_USE_CASE_VERB_DL_REC) ||
1304 !strcmp(it->useCase, SND_USE_CASE_VERB_UL_DL_REC) ||
1305 !strcmp(it->useCase, SND_USE_CASE_VERB_INCALL_REC)) {
1306 snd_use_case_set(mUcMgr, "_verb", it->useCase);
1307 } else {
1308 snd_use_case_set(mUcMgr, "_enamod", it->useCase);
1309 }
1310 if(sampleRate) {
1311 it->sampleRate = *sampleRate;
1312 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001313#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001314 if (6 == it->channels) {
1315 if (!strncmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
1316 || !strncmp(it->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001317 ALOGV("OpenInoutStream: Use larger buffer size for 5.1(%s) recording ", it->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001318 it->bufferSize = getInputBufferSize(it->sampleRate,*format,it->channels);
1319 }
1320 }
1321#endif
1322 err = mALSADevice->open(&(*it));
1323 if (err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001324 ALOGE("Error opening pcm input device");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001325 } else {
1326 in = new AudioStreamInALSA(this, &(*it), acoustics);
1327 err = in->set(format, channels, sampleRate, devices);
1328 }
1329 if (status) *status = err;
1330 return in;
1331 }
1332}
1333
1334void
1335AudioHardwareALSA::closeInputStream(AudioStreamIn* in)
1336{
1337 delete in;
1338}
1339
1340status_t AudioHardwareALSA::setMicMute(bool state)
1341{
1342 int newMode = mode();
Iliyan Malchev4113f342012-06-11 14:39:47 -07001343 ALOGD("setMicMute newMode %d",newMode);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001344 if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
1345 if (mVoipMicMute != state) {
1346 mVoipMicMute = state;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001347 ALOGD("setMicMute: mVoipMicMute %d", mVoipMicMute);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001348 if(mALSADevice) {
1349 mALSADevice->setVoipMicMute(state);
1350 }
1351 }
1352 } else {
1353 if (mMicMute != state) {
1354 mMicMute = state;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001355 ALOGD("setMicMute: mMicMute %d", mMicMute);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001356 if(mALSADevice) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001357 if(mCSCallActive == CS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -07001358 mALSADevice->setMicMute(state);
Ajay Dudani9746c472012-06-18 16:01:16 -07001359 if(mVolteCallActive == IMS_ACTIVE)
Iliyan Malchev4765c432012-06-11 14:36:16 -07001360 mALSADevice->setVoLTEMicMute(state);
1361 }
1362 }
1363 }
1364 return NO_ERROR;
1365}
1366
1367status_t AudioHardwareALSA::getMicMute(bool *state)
1368{
1369 int newMode = mode();
1370 if(newMode == AudioSystem::MODE_IN_COMMUNICATION) {
1371 *state = mVoipMicMute;
1372 } else {
1373 *state = mMicMute;
1374 }
1375 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{
1385 size_t bufferSize;
1386 if (format != AudioSystem::PCM_16_BIT
1387 && format != AudioSystem::AMR_NB
1388 && format != AudioSystem::AMR_WB
Ajay Dudani9746c472012-06-18 16:01:16 -07001389#ifdef QCOM_QCHAT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001390 && format != AudioSystem::EVRC
1391 && format != AudioSystem::EVRCB
Ajay Dudani9746c472012-06-18 16:01:16 -07001392 && format != AudioSystem::EVRCWB
1393#endif
1394 ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001395 ALOGW("getInputBufferSize bad format: %d", format);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001396 return 0;
1397 }
1398 if(sampleRate == 16000) {
1399 bufferSize = DEFAULT_IN_BUFFER_SIZE * 2 * channelCount;
1400 } else if(sampleRate < 44100) {
1401 bufferSize = DEFAULT_IN_BUFFER_SIZE * channelCount;
1402 } else {
1403 bufferSize = DEFAULT_IN_BUFFER_SIZE * 12;
1404 }
1405 return bufferSize;
1406}
1407
Ajay Dudani9746c472012-06-18 16:01:16 -07001408#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001409void AudioHardwareALSA::handleFm(int device)
1410{
1411int newMode = mode();
1412 if(device & AudioSystem::DEVICE_OUT_FM && mIsFmActive == 0) {
1413 // Start FM Radio on current active device
1414 unsigned long bufferSize = FM_BUFFER_SIZE;
1415 alsa_handle_t alsa_handle;
1416 char *use_case;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001417 ALOGV("Start FM");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001418 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1419 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1420 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_DIGITAL_RADIO, sizeof(alsa_handle.useCase));
1421 } else {
1422 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_FM, sizeof(alsa_handle.useCase));
1423 }
1424 free(use_case);
1425
1426 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1427 bufferSize &= ~b;
1428 alsa_handle.module = mALSADevice;
1429 alsa_handle.bufferSize = bufferSize;
1430 alsa_handle.devices = device;
1431 alsa_handle.handle = 0;
1432 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1433 alsa_handle.channels = DEFAULT_CHANNEL_MODE;
1434 alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
1435 alsa_handle.latency = VOICE_LATENCY;
1436 alsa_handle.rxHandle = 0;
1437 alsa_handle.ucMgr = mUcMgr;
1438 mIsFmActive = 1;
1439 mDeviceList.push_back(alsa_handle);
1440 ALSAHandleList::iterator it = mDeviceList.end();
1441 it--;
1442 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1443 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1444 device |= AudioSystem::DEVICE_OUT_PROXY;
1445 alsa_handle.devices = AudioSystem::DEVICE_OUT_PROXY;
SathishKumar Mani0a019912012-09-11 12:33:11 -07001446 ALOGD("Routing to proxy for FM case");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001447 }
1448 mALSADevice->route(&(*it), (uint32_t)device, newMode);
1449 if(!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) {
1450 snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_DIGITAL_RADIO);
1451 } else {
1452 snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_FM);
1453 }
1454 mALSADevice->startFm(&(*it));
1455 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1456 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
SathishKumar Mani0a019912012-09-11 12:33:11 -07001457 ALOGD("Starting FM, musbPlaybackState %d", musbPlaybackState);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001458 startUsbPlaybackIfNotStarted();
1459 musbPlaybackState |= USBPLAYBACKBIT_FM;
1460 }
1461 } else if (!(device & AudioSystem::DEVICE_OUT_FM) && mIsFmActive == 1) {
1462 //i Stop FM Radio
Iliyan Malchev4113f342012-06-11 14:39:47 -07001463 ALOGV("Stop FM");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001464 for(ALSAHandleList::iterator it = mDeviceList.begin();
1465 it != mDeviceList.end(); ++it) {
1466 if((!strcmp(it->useCase, SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
1467 (!strcmp(it->useCase, SND_USE_CASE_MOD_PLAY_FM))) {
1468 mALSADevice->close(&(*it));
1469 //mALSADevice->route(&(*it), (uint32_t)device, newMode);
1470 mDeviceList.erase(it);
1471 break;
1472 }
1473 }
1474 mIsFmActive = 0;
1475 musbPlaybackState &= ~USBPLAYBACKBIT_FM;
1476 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1477 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1478 closeUsbPlaybackIfNothingActive();
1479 }
1480 }
1481}
1482#endif
1483
1484void AudioHardwareALSA::disableVoiceCall(char* verb, char* modifier, int mode, int device)
1485{
1486 for(ALSAHandleList::iterator it = mDeviceList.begin();
1487 it != mDeviceList.end(); ++it) {
1488 if((!strcmp(it->useCase, verb)) ||
1489 (!strcmp(it->useCase, modifier))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001490 ALOGV("Disabling voice call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001491 mALSADevice->close(&(*it));
1492 mALSADevice->route(&(*it), (uint32_t)device, mode);
1493 mDeviceList.erase(it);
1494 break;
1495 }
1496 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001497#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001498 if(musbPlaybackState & USBPLAYBACKBIT_VOICECALL) {
SathishKumar Mani0a019912012-09-11 12:33:11 -07001499 ALOGD("Voice call ended on USB");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001500 musbPlaybackState &= ~USBPLAYBACKBIT_VOICECALL;
1501 musbRecordingState &= ~USBRECBIT_VOICECALL;
1502 closeUsbRecordingIfNothingActive();
1503 closeUsbPlaybackIfNothingActive();
1504 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001505#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001506}
1507void AudioHardwareALSA::enableVoiceCall(char* verb, char* modifier, int mode, int device)
1508{
1509// Start voice call
SathishKumar Mani018d1c52012-09-11 14:58:18 -07001510unsigned long bufferSize = DEFAULT_VOICE_BUFFER_SIZE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001511alsa_handle_t alsa_handle;
1512char *use_case;
1513 snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
1514 if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
1515 strlcpy(alsa_handle.useCase, verb, sizeof(alsa_handle.useCase));
1516 } else {
1517 strlcpy(alsa_handle.useCase, modifier, sizeof(alsa_handle.useCase));
1518 }
1519 free(use_case);
1520
1521 for (size_t b = 1; (bufferSize & ~b) != 0; b <<= 1)
1522 bufferSize &= ~b;
1523 alsa_handle.module = mALSADevice;
1524 alsa_handle.bufferSize = bufferSize;
1525 alsa_handle.devices = device;
1526 alsa_handle.handle = 0;
1527 alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
1528 alsa_handle.channels = VOICE_CHANNEL_MODE;
1529 alsa_handle.sampleRate = VOICE_SAMPLING_RATE;
1530 alsa_handle.latency = VOICE_LATENCY;
1531 alsa_handle.rxHandle = 0;
1532 alsa_handle.ucMgr = mUcMgr;
1533 mDeviceList.push_back(alsa_handle);
1534 ALSAHandleList::iterator it = mDeviceList.end();
1535 it--;
Ajay Dudani9746c472012-06-18 16:01:16 -07001536#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001537 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1538 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1539 device |= AudioSystem::DEVICE_OUT_PROXY;
1540 alsa_handle.devices = device;
1541 }
1542#endif
1543 mALSADevice->route(&(*it), (uint32_t)device, mode);
1544 if (!strcmp(it->useCase, verb)) {
1545 snd_use_case_set(mUcMgr, "_verb", verb);
1546 } else {
1547 snd_use_case_set(mUcMgr, "_enamod", modifier);
1548 }
1549 mALSADevice->startVoiceCall(&(*it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001550#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001551 if((device & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
1552 (device & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)){
1553 startUsbRecordingIfNotStarted();
1554 startUsbPlaybackIfNotStarted();
1555 musbPlaybackState |= USBPLAYBACKBIT_VOICECALL;
1556 musbRecordingState |= USBRECBIT_VOICECALL;
1557 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001558#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001559}
1560
1561bool AudioHardwareALSA::routeVoiceCall(int device, int newMode)
1562{
1563int csCallState = mCallState&0xF;
1564 bool isRouted = false;
1565 switch (csCallState) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001566 case CS_INACTIVE:
1567 if (mCSCallActive != CS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001568 ALOGD("doRouting: Disabling voice call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001569 disableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
1570 (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
1571 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001572 mCSCallActive = CS_INACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001573 }
1574 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001575 case CS_ACTIVE:
1576 if (mCSCallActive == CS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001577 ALOGD("doRouting: Enabling CS voice call ");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001578 enableVoiceCall((char *)SND_USE_CASE_VERB_VOICECALL,
1579 (char *)SND_USE_CASE_MOD_PLAY_VOICE, newMode, device);
1580 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001581 mCSCallActive = CS_ACTIVE;
1582 } else if (mCSCallActive == CS_HOLD) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001583 ALOGD("doRouting: Resume voice call from hold state");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001584 ALSAHandleList::iterator vt_it;
1585 for(vt_it = mDeviceList.begin();
1586 vt_it != mDeviceList.end(); ++vt_it) {
1587 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
1588 strlen(SND_USE_CASE_VERB_VOICECALL))) ||
1589 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1590 strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
1591 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001592 mCSCallActive = CS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001593 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001594 ALOGE("VoLTE resume failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001595 break;
1596 }
1597 }
1598 }
1599 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001600 case CS_HOLD:
1601 if (mCSCallActive == CS_ACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001602 ALOGD("doRouting: Voice call going to Hold");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001603 ALSAHandleList::iterator vt_it;
1604 for(vt_it = mDeviceList.begin();
1605 vt_it != mDeviceList.end(); ++vt_it) {
1606 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOICECALL,
1607 strlen(SND_USE_CASE_VERB_VOICECALL))) ||
1608 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1609 strlen(SND_USE_CASE_MOD_PLAY_VOICE)))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001610 mCSCallActive = CS_HOLD;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001611 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1612 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001613 ALOGE("Voice pause failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001614 break;
1615 }
1616 }
1617 }
1618 break;
1619 }
1620 return isRouted;
1621}
1622bool AudioHardwareALSA::routeVoLTECall(int device, int newMode)
1623{
1624int volteCallState = mCallState&0xF0;
1625bool isRouted = false;
1626switch (volteCallState) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001627 case IMS_INACTIVE:
1628 if (mVolteCallActive != IMS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001629 ALOGD("doRouting: Disabling IMS call");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001630 disableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
1631 (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
1632 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001633 mVolteCallActive = IMS_INACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001634 }
1635 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001636 case IMS_ACTIVE:
1637 if (mVolteCallActive == IMS_INACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001638 ALOGD("doRouting: Enabling IMS voice call ");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001639 enableVoiceCall((char *)SND_USE_CASE_VERB_VOLTE,
1640 (char *)SND_USE_CASE_MOD_PLAY_VOLTE, newMode, device);
1641 isRouted = true;
Ajay Dudani9746c472012-06-18 16:01:16 -07001642 mVolteCallActive = IMS_ACTIVE;
1643 } else if (mVolteCallActive == IMS_HOLD) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001644 ALOGD("doRouting: Resume IMS call from hold state");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001645 ALSAHandleList::iterator vt_it;
1646 for(vt_it = mDeviceList.begin();
1647 vt_it != mDeviceList.end(); ++vt_it) {
1648 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
1649 strlen(SND_USE_CASE_VERB_VOLTE))) ||
1650 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1651 strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
1652 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
Ajay Dudani9746c472012-06-18 16:01:16 -07001653 mVolteCallActive = IMS_ACTIVE;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001654 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,0)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001655 ALOGE("VoLTE resume failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001656 break;
1657 }
1658 }
1659 }
1660 break;
Ajay Dudani9746c472012-06-18 16:01:16 -07001661 case IMS_HOLD:
1662 if (mVolteCallActive == IMS_ACTIVE) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001663 ALOGD("doRouting: IMS ACTIVE going to HOLD");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001664 ALSAHandleList::iterator vt_it;
1665 for(vt_it = mDeviceList.begin();
1666 vt_it != mDeviceList.end(); ++vt_it) {
1667 if((!strncmp(vt_it->useCase, SND_USE_CASE_VERB_VOLTE,
1668 strlen(SND_USE_CASE_VERB_VOLTE))) ||
1669 (!strncmp(vt_it->useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1670 strlen(SND_USE_CASE_MOD_PLAY_VOLTE)))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001671 mVolteCallActive = IMS_HOLD;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001672 alsa_handle_t *handle = (alsa_handle_t *)(&(*vt_it));
1673 if(ioctl((int)handle->handle->fd,SNDRV_PCM_IOCTL_PAUSE,1)<0)
Iliyan Malchev4113f342012-06-11 14:39:47 -07001674 ALOGE("VoLTE Pause failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001675 break;
1676 }
1677 }
1678 }
1679 break;
1680 }
1681 return isRouted;
1682}
1683
1684} // namespace android_audio_legacy