Make ASM handling external.
[profile/ivi/libmm-sound.git] / server / mm_sound_mgr_session.c
1 /*
2  * libmm-sound
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Seungbae Shin <seungbae.shin@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <pthread.h>
25 #include <sys/shm.h>
26 #include <sys/msg.h>
27 #include <sys/mman.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <stdbool.h>
31 #include <errno.h>
32
33 #include <vconf.h>
34 #include <mm_error.h>
35 #include <mm_debug.h>
36 #include <audio-session-manager.h>
37 #include <avsys-audio.h>
38
39 #include "../include/mm_sound_common.h"
40 #include "../include/mm_sound_utils.h"
41 #include "include/mm_sound_mgr_common.h"
42 #include "include/mm_sound_mgr_session.h"
43 #include "include/mm_sound_mgr_device.h"
44 #include "include/mm_sound_mgr_headset.h"
45 #include "include/mm_sound_mgr_pulse.h"
46 #include "include/mm_sound_mgr_asm.h"
47
48 #define EARJACK_WITH_MIC        2
49
50 #define MAX_STRING_LEN  256
51
52 #define DEVICE_API_BLUETOOTH    "bluez"
53 #define DEVICE_API_ALSA "alsa"
54 #ifdef USE_PULSE_WFD /* Not enabled yet */
55 #define DEVICE_API_WFD  "wfd"
56 #endif
57
58 #define DEVICE_BUS_BLUETOOTH "bluetooth"
59 #define DEVICE_BUS_USB "usb"
60 #define DEVICE_BUS_BUILTIN "builtin"
61 #ifdef SEPARATE_SPEAKER_AND_WIRED_ACCESSORY
62 #define DEVICE_BUS_WIRED "wired"
63 #endif
64
65 #define MM_SOUND_DEVICE_OUT_ANY 0x000FFF00
66 #define MM_SOUND_DEVICE_IN_ANY   0x000000FF
67
68 #define MM_SOUND_DEVICE_OUT_FILTER 0x000000FF
69 #define MM_SOUND_DEVICE_IN_FILTER        0x000FFF00
70
71 pthread_mutex_t g_mutex_session = PTHREAD_MUTEX_INITIALIZER;
72
73 #define LOCK_SESSION()  do { debug_log("(*)LOCKING\n"); /*pthread_mutex_lock(&g_mutex_session);*/ debug_log("(+)LOCKED\n"); }while(0)
74 #define UNLOCK_SESSION()  do {  /* pthread_mutex_unlock(&g_mutex_session);*/ debug_log("(-)UNLOCKED\n"); }while(0)
75
76 #define RESET_ACTIVE(x)    (g_info.device_active &= x)
77 #define RESET_AVAILABLE(x)    (g_info.device_available &= x)
78
79 #define SET_ACTIVE(x)    (g_info.device_active |= x)
80 #define SET_AVAILABLE(x)    (g_info.device_available |= x)
81
82 #define SET_PLAYBACK_ONLY_ACTIVE(x)  do { RESET_ACTIVE(MM_SOUND_DEVICE_OUT_FILTER); SET_ACTIVE(x); }while(0)
83 #define SET_CAPTURE_ONLY_ACTIVE(x)  do {  RESET_ACTIVE(MM_SOUND_DEVICE_IN_FILTER); SET_ACTIVE(x); }while(0)
84
85
86 #define UNSET_ACTIVE(x)    (g_info.device_active &= (~x))
87 #define UNSET_AVAILABLE(x)    (g_info.device_available &= (~x))
88
89 #define TOGGLE_ACTIVE(x)    (g_info.device_active ^= x)
90 #define TOGGLE_AVAILABLE(x)    (g_info.device_available ^= x)
91
92 #define IS_ACTIVE(x)    (g_info.device_active & x)
93 #define IS_AVAILABLE(x)    (g_info.device_available & x)
94
95 #define GET_AVAILABLE_PLAYBACK()        IS_AVAILABLE(MM_SOUND_DEVICE_OUT_ANY)
96 #define GET_AVAILABLE_CAPTURE() IS_AVAILABLE(MM_SOUND_DEVICE_IN_ANY)
97
98 #define GET_ACTIVE_PLAYBACK()   IS_ACTIVE(MM_SOUND_DEVICE_OUT_ANY)
99 #define GET_ACTIVE_CAPTURE()    IS_ACTIVE(MM_SOUND_DEVICE_IN_ANY)
100
101 #define IS_COMMUNICATION_SESSION() ((g_info.session == SESSION_VOICECALL) || (g_info.session == SESSION_VOIP))
102 #define IS_NOTIFICATION_SESSION() (g_info.session == SESSION_NOTIFICATION)
103 #define IS_EMERGENCY_SESSION() (g_info.session == SESSION_EMERGENCY)
104
105 static int __set_sound_path_for_current_active ();
106 static int __set_sound_path_to_dual ();
107 static int __set_sound_path_to_speaker ();
108 static void __select_playback_active_device (void);
109 static void __select_capture_active_device (void);
110
111 #define ENABLE_CALLBACK
112 #ifndef ENABLE_CALLBACK
113 #define _mm_sound_mgr_device_available_device_callback(a,b,c)   MM_ERROR_NONE
114 #define _mm_sound_mgr_device_active_device_callback(a,b)        MM_ERROR_NONE
115 #endif
116
117 typedef struct _session_info_struct
118 {
119         int asm_handle;
120         int device_available;
121         int device_active;
122         int headset_type;
123
124         session_t session;
125         subsession_t subsession;
126
127         char bt_name[MAX_STRING_LEN];
128         char default_sink_name[MAX_STRING_LEN];
129
130
131 } SESSION_INFO_STRUCT;
132
133
134 SESSION_INFO_STRUCT g_info;
135
136 typedef enum
137 {
138         NO_NOTI = 0,
139         DO_NOTI
140 } noti_t;
141
142
143 static void dump_info ()
144 {
145         int i = 0;
146
147         const char *playback_device_str[] = { "SPEAKER ", "RECEIVER ", "HEADSET ", "BTSCO ", "BTA2DP ", "DOCK ", "HDMI ", "WFD ", "USB " };
148         const char *capture_device_str[] = { "MAINMIC ", "HEADSET ", "BTMIC "  };
149
150         int playback_max = sizeof (playback_device_str) / sizeof (char*);
151         int capture_max = sizeof (capture_device_str) / sizeof (char*);
152
153         static char tmp_str[128];
154         static char tmp_str2[128];
155
156         debug_log ("<----------------------------------------------------->\n");
157
158
159         strcpy (tmp_str, "PLAYBACK = [ ");
160         for (i=0; i<playback_max; i++) {
161                 if (((g_info.device_available & MM_SOUND_DEVICE_OUT_ANY) >> 8) & (0x01 << i)) {
162                         strcat (tmp_str, playback_device_str[i]);
163                 }
164         }
165         strcat (tmp_str, "]");
166
167         strcpy (tmp_str2, "CAPTURE = [ ");
168                 for (i=0; i<capture_max; i++) {
169                         if ((g_info.device_available & MM_SOUND_DEVICE_IN_ANY) & (0x01 << i)) {
170                                 strcat (tmp_str2, capture_device_str[i]);
171                         }
172         }
173         strcat (tmp_str2, "]");
174         debug_log ("*** Available = [0x%08x], %s %s", g_info.device_available, tmp_str, tmp_str2);
175
176         strcpy (tmp_str, "PLAYBACK = [ ");
177         for (i=0; i<playback_max; i++) {
178                 if (((g_info.device_active & MM_SOUND_DEVICE_OUT_ANY) >> 8) & (0x01 << i)) {
179                         strcat (tmp_str, playback_device_str[i]);
180                 }
181         }
182         strcat (tmp_str, "]");
183
184         strcpy (tmp_str2, "CAPTURE = [ ");
185                 for (i=0; i<capture_max; i++) {
186                         if ((g_info.device_active & MM_SOUND_DEVICE_IN_ANY) & (0x01 << i)) {
187                                 strcat (tmp_str2, capture_device_str[i]);
188                         }
189         }
190         strcat (tmp_str2, "]");
191         debug_log ("***    Active = [0x%08x], %s %s", g_info.device_active, tmp_str, tmp_str2);
192
193
194         debug_log ("*** Headset type = [%d], BT = [%s], default sink = [%s]\n", g_info.headset_type, g_info.bt_name, g_info.default_sink_name);
195         debug_log ("*** Session = [%d], SubSession = [%d]\n", g_info.session, g_info.subsession);
196         debug_log ("<----------------------------------------------------->\n");
197 }
198
199 /* ------------------------- ASM ------------------------------------*/
200 static pthread_mutex_t _asm_mutex = PTHREAD_MUTEX_INITIALIZER;
201
202 static bool _asm_register_for_headset (int * handle)
203 {
204         int asm_error = 0;
205
206         if (handle == NULL) {
207                 debug_error ("Handle is not valid!!!\n");
208                 return false;
209         }
210
211         if(!ASM_register_sound (-1, handle, ASM_EVENT_EARJACK_UNPLUG, ASM_STATE_NONE, NULL, NULL, ASM_RESOURCE_NONE, &asm_error)) {
212                         debug_warning("earjack event register failed with 0x%x\n", asm_error);
213                         return false;
214         }
215
216         return true;
217 }
218
219 static void _asm_pause_process(int handle)
220 {
221         int asm_error = 0;
222
223         MMSOUND_ENTER_CRITICAL_SECTION( &_asm_mutex )
224
225         /* If no asm handle register here */
226         if (g_info.asm_handle ==  -1) {
227                 debug_msg ("ASM handle is not valid, try to register once more\n");
228
229                 /* This register should be success */
230                 if (_asm_register_for_headset (&g_info.asm_handle)) {
231                         debug_msg("_asm_register_for_headset() success\n");
232                 } else {
233                         debug_error("_asm_register_for_headset() failed\n");
234                 }
235         }
236
237         //do pause
238         debug_warning("Send earphone unplug event to Audio Session Manager Server for BT headset\n");
239
240         if(!ASM_set_sound_state(handle, ASM_EVENT_EARJACK_UNPLUG, ASM_STATE_PLAYING, ASM_RESOURCE_NONE, &asm_error)) {
241                 debug_error("earjack event set sound state to playing failed with 0x%x\n", asm_error);
242         }
243
244         if(!ASM_set_sound_state(handle, ASM_EVENT_EARJACK_UNPLUG, ASM_STATE_STOP, ASM_RESOURCE_NONE, &asm_error)) {
245                 debug_error("earjack event set sound state to stop failed with 0x%x\n", asm_error);
246         }
247
248         MMSOUND_LEAVE_CRITICAL_SECTION( &_asm_mutex )
249 }
250
251 static bool _asm_unregister_for_headset (int *handle)
252 {
253         int asm_error = 0;
254
255         if (handle == NULL) {
256                 debug_error ("Handle is not valid!!!\n");
257                 return false;
258         }
259
260         if(!ASM_unregister_sound(handle, ASM_EVENT_EARJACK_UNPLUG, &asm_error)) {
261                 debug_error("earjack event unregister failed with 0x%x\n", asm_error);
262                 return false;
263         }
264
265         return true;
266 }
267
268 /* ------------------------- INTERNAL FUNCTIONS ------------------------------------*/
269
270 static void __set_path_with_notification(noti_t noti)
271 {
272         int ret = MM_ERROR_NONE;
273
274         debug_msg ("[%s] noti=%d\n", __func__,noti);
275
276         /* Set path based on current active device */
277         ret = __set_sound_path_for_current_active();
278         if (ret != MM_ERROR_NONE) {
279                 debug_error ("__set_sound_path_for_current_active() failed [%x]\n", ret);
280                 return;
281         }
282
283         if (noti == DO_NOTI) {
284                 /* Notify current active device */
285                 ret = _mm_sound_mgr_device_active_device_callback(GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
286                 if (ret != MM_ERROR_NONE) {
287                         debug_error ("_mm_sound_mgr_device_active_device_callback() failed [%x]\n", ret);
288                 }
289         }
290 }
291
292 static int __set_playback_route_communication (session_state_t state)
293 {
294         int ret = MM_ERROR_NONE;
295         int gain;
296
297         debug_fenter();
298
299         if (state == SESSION_START) {
300                 SET_AVAILABLE(MM_SOUND_DEVICE_OUT_RECEIVER);
301                 debug_log ("voicecall session started...only receiver available set on...");
302
303                 ret = _mm_sound_mgr_device_available_device_callback(MM_SOUND_DEVICE_IN_NONE, MM_SOUND_DEVICE_OUT_RECEIVER, 1);
304                 if (ret != MM_ERROR_NONE) {
305                         debug_error ("_mm_sound_mgr_device_available_device_callback() failed [%x]\n", ret);
306                         goto ROUTE_COMM_EXIT;
307                 }
308
309                 /* Set default subsession as MEDIA */
310                 g_info.subsession = SUBSESSION_MEDIA;
311
312                 /* (speaker = receiver, headset = headset, bt a2dp = bt sco) */
313                 /* OUT */
314                 if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_SPEAKER)) {
315                         debug_log ("active out was SPEAKER => activate receiver!!\n");
316                         SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_RECEIVER);
317
318                 } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
319                         debug_log ("active out was BT A2DP => activate BT SCO!!\n");
320                         SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_BT_SCO);
321                         SET_CAPTURE_ONLY_ACTIVE(MM_SOUND_DEVICE_IN_BT_SCO);
322                 }
323                 /* FIXME : Do we have to set IN device ??? */
324
325                 __set_path_with_notification(DO_NOTI);
326
327                 dump_info();
328
329         } else { /* SESSION_END */
330                 UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_RECEIVER);
331
332                 ret = _mm_sound_mgr_device_available_device_callback(MM_SOUND_DEVICE_IN_NONE, MM_SOUND_DEVICE_OUT_RECEIVER, 0);
333                 if (ret != MM_ERROR_NONE) {
334                         debug_error ("_mm_sound_mgr_device_available_device_callback() failed [%x]\n", ret);
335                         goto ROUTE_COMM_EXIT;
336                 }
337
338                 // RESET
339                 if (g_info.session == SESSION_VOICECALL)
340                         gain = AVSYS_AUDIO_GAIN_EX_VOICECALL;
341                 else if (g_info.session == SESSION_VOIP)
342                         gain = AVSYS_AUDIO_GAIN_EX_VIDEOCALL;
343                 else {
344                         debug_warning ("Not valid session info....\n");
345                         gain = AVSYS_AUDIO_GAIN_EX_VOICECALL;
346                 }
347
348
349                 if (AVSYS_FAIL(avsys_audio_set_path_ex( gain,
350                                 AVSYS_AUDIO_PATH_EX_NONE, AVSYS_AUDIO_PATH_EX_NONE,
351                                 AVSYS_AUDIO_PATH_OPTION_NONE ))) {
352                         debug_error ("avsys_audio_set_path_ex() failed [%x]\n", ret);
353                         ret = MM_ERROR_SOUND_INTERNAL;
354                         goto ROUTE_COMM_EXIT;
355                 }
356
357                 /* activate current available device based on priority */
358                 debug_log ("Reset ACTIVE and find new one by priority.\n");
359                 RESET_ACTIVE(0);
360                 __select_playback_active_device();
361                 __select_capture_active_device();
362
363                 debug_log ("voicecall session stopped...set path based on current active device");
364                 __set_path_with_notification(DO_NOTI);
365
366                 dump_info();
367         }
368
369 ROUTE_COMM_EXIT:
370
371         debug_fleave();
372
373         return ret;
374 }
375
376 static int __set_playback_route_fmradio (session_state_t state)
377 {
378         int ret = MM_ERROR_NONE;
379         int out;
380
381         debug_fenter();
382
383         if (state == SESSION_START) {
384
385                 if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_SPEAKER))
386                         out = AVSYS_AUDIO_PATH_EX_SPK;
387                 else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY))
388                         out = AVSYS_AUDIO_PATH_EX_HEADSET;
389                 else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP))
390                         out = AVSYS_AUDIO_PATH_EX_A2DP;
391
392                 /* PATH SET */
393                 if (AVSYS_FAIL(avsys_audio_set_path_ex( AVSYS_AUDIO_GAIN_EX_FMRADIO,
394                                                                                 out, AVSYS_AUDIO_PATH_EX_FMINPUT,
395                                                                                 AVSYS_AUDIO_PATH_OPTION_NONE))) {
396                         debug_error ("avsys_audio_set_path_ex() failed\n");
397                         ret = MM_ERROR_SOUND_INTERNAL;
398                         goto ROUTE_FMRADIO_EXIT;
399                 }
400
401
402         } else { /* SESSION_END */
403                 /* PATH RELEASE */
404                 if (AVSYS_FAIL(avsys_audio_set_path_ex( AVSYS_AUDIO_GAIN_EX_FMRADIO,
405                                                                                 AVSYS_AUDIO_PATH_EX_NONE, AVSYS_AUDIO_PATH_EX_NONE,
406                                                                                 AVSYS_AUDIO_PATH_OPTION_NONE ))) {
407                         debug_error ("avsys_audio_set_path_ex() failed\n");
408                         ret = MM_ERROR_SOUND_INTERNAL;
409                         goto ROUTE_FMRADIO_EXIT;
410                 }
411
412                 /* Set as current active status */
413                 __set_path_with_notification (NO_NOTI);
414         }
415
416         if (AVSYS_FAIL(avsys_audio_set_ext_device_status(AVSYS_AUDIO_EXT_DEVICE_FMRADIO, state))) {
417                 debug_error ("avsys_audio_set_ext_device_status() failed\n");
418                 ret = MM_ERROR_SOUND_INTERNAL;
419         }
420
421 ROUTE_FMRADIO_EXIT:
422
423         debug_fleave();
424
425         return ret;
426 }
427
428 static int __set_playback_route_notification (session_state_t state)
429 {
430         int ret = MM_ERROR_NONE;
431
432         debug_fenter();
433
434         if (state == SESSION_START) {
435                 ret = __set_sound_path_to_dual ();
436                 if (ret != MM_ERROR_NONE) {
437                         debug_error ("__set_sound_path_to_dual() failed [%x]\n", ret);
438                 }
439
440         } else { /* SESSION_END */
441                 __set_path_with_notification (NO_NOTI);
442         }
443
444         debug_fleave();
445
446         return ret;
447 }
448
449 static int __set_playback_route_emergency (session_state_t state)
450 {
451         int ret = MM_ERROR_NONE;
452
453         debug_fenter();
454
455         if (state == SESSION_START) {
456                 ret = __set_sound_path_to_speaker ();
457                 if (ret != MM_ERROR_NONE) {
458                         debug_error ("__set_sound_path_to_speaker() failed [%x]\n", ret);
459                 }
460
461         } else { /* SESSION_END */
462                 __set_path_with_notification (NO_NOTI);
463         }
464
465         debug_fleave();
466
467         return ret;
468 }
469
470 static bool __is_forced_session ()
471 {
472         return (IS_NOTIFICATION_SESSION() || IS_EMERGENCY_SESSION())? true : false;
473 }
474
475 static int __set_sound_path_for_current_active (void)
476 {
477         int ret = MM_ERROR_NONE;
478         int option = AVSYS_AUDIO_PATH_OPTION_NONE;
479         int in = 0, out = 0, gain = 0;
480         int sound_play;
481
482         debug_fenter();
483
484         if (__is_forced_session()) {
485                 debug_log ("Current session is NOTI/EMER, pending path setting. path set will be done after session ends")
486                 goto CURRENT_ACTIVE_END;
487         }
488
489         /* Pulseaudio route */
490         if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
491                 debug_log ("BT A2DP is active, Set default sink to BLUEZ");
492                 MMSoundMgrPulseSetDefaultSink (DEVICE_API_BLUETOOTH, DEVICE_BUS_BLUETOOTH);
493                 goto CURRENT_ACTIVE_END;
494         } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_WFD)) {
495 #ifdef USE_PULSE_WFD /* Not enabled yet */
496                 debug_log ("WFD is active, Set default sink to WFD");
497                 MMSoundMgrPulseSetDefaultSink (DEVICE_API_WFD, DEVICE_BUS_BUILTIN);
498                 goto CURRENT_ACTIVE_END;
499 #endif
500         } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_USB_AUDIO)) {
501                 debug_log ("USB Audio is active, Set default sink to USB Audio");
502                 MMSoundMgrPulseSetDefaultSink (DEVICE_API_ALSA, DEVICE_BUS_USB);
503                 goto CURRENT_ACTIVE_END;
504         }
505
506 #ifndef SEPARATE_SPEAKER_AND_WIRED_ACCESSORY
507         /* ALSA route */
508         debug_log ("Set default sink to ALSA with BUILTIN");
509         MMSoundMgrPulseSetDefaultSink (DEVICE_API_ALSA, DEVICE_BUS_BUILTIN);
510 #endif
511
512         /* prepare IN */
513         if (IS_ACTIVE(MM_SOUND_DEVICE_IN_MIC)) {
514                 in = AVSYS_AUDIO_PATH_EX_MIC;
515         } else if (IS_ACTIVE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY)) {
516                 in = AVSYS_AUDIO_PATH_EX_HEADSETMIC;
517         } else if (IS_ACTIVE(MM_SOUND_DEVICE_IN_BT_SCO)) {
518                 in = AVSYS_AUDIO_PATH_EX_BTMIC;
519         }
520
521         /* prepare OUT */
522         if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_SPEAKER)) {
523                 out = AVSYS_AUDIO_PATH_EX_SPK;
524         } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_RECEIVER)) {
525                 out = AVSYS_AUDIO_PATH_EX_RECV;
526         } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY)) {
527                 out = AVSYS_AUDIO_PATH_EX_HEADSET;
528         } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_SCO)) {
529                 out = AVSYS_AUDIO_PATH_EX_BTHEADSET;
530         } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_DOCK)) {
531                 out = AVSYS_AUDIO_PATH_EX_DOCK;
532         } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_HDMI)) {
533                 out = AVSYS_AUDIO_PATH_EX_HDMI;
534         } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_WFD)) {
535 #ifndef USE_PULSE_WFD
536                 out = AVSYS_AUDIO_PATH_EX_HDMI;
537 #endif
538         }
539
540         /* prepare GAIN */
541         switch (g_info.session) {
542         case SESSION_MEDIA:
543         case SESSION_NOTIFICATION:
544         case SESSION_EMERGENCY:
545                 gain = AVSYS_AUDIO_GAIN_EX_KEYTONE;
546                 break;
547
548         case SESSION_VOICECALL:
549         case SESSION_VOIP:
550                 if (g_info.subsession == SUBSESSION_RINGTONE) {
551                         gain = AVSYS_AUDIO_GAIN_EX_RINGTONE;
552                         in = AVSYS_AUDIO_PATH_EX_NONE;
553
554                         /* If sound is mute mode, force ringtone path to headset */
555                         vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sound_play);
556                         if (sound_play) {
557                                 /* Normal Ringtone */
558                                 out = AVSYS_AUDIO_PATH_EX_SPK;
559                                 option = AVSYS_AUDIO_PATH_OPTION_DUAL_OUT;
560                         } else {
561                                 /* Mute Ringtone */
562                                 out = AVSYS_AUDIO_PATH_EX_HEADSET;
563                         }
564                 } else if (g_info.subsession == SUBSESSION_MEDIA) {
565                         gain = AVSYS_AUDIO_GAIN_EX_CALLTONE;
566                         in = AVSYS_AUDIO_PATH_EX_NONE;
567                 } else if (g_info.subsession == SUBSESSION_VOICE) {
568                         gain = (g_info.session == SESSION_VOICECALL)?
569                                         AVSYS_AUDIO_GAIN_EX_VOICECALL : AVSYS_AUDIO_GAIN_EX_VIDEOCALL;
570
571                         if (out == AVSYS_AUDIO_PATH_EX_HEADSET) {
572                                 debug_log ("Fix in path to headsetmic when out path is headset\n");
573                                 in = AVSYS_AUDIO_PATH_EX_HEADSETMIC;
574                         }
575                 } else {
576                         debug_warning ("Unexpected SUBSESSION [%d]\n", g_info.subsession);
577                 }
578                 break;
579
580         case SESSION_FMRADIO:
581                 gain = AVSYS_AUDIO_GAIN_EX_FMRADIO;
582                 in = AVSYS_AUDIO_PATH_EX_FMINPUT;
583                 break;
584
585         default:
586                 debug_warning ("session [%d] is not handled...\n", g_info.session);
587                 break;
588         }
589
590 #ifdef SEPARATE_SPEAKER_AND_WIRED_ACCESSORY
591         if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
592                 debug_log ("BT A2DP is not active, Set default sink to ALSA_XX");
593                 if (out == AVSYS_AUDIO_PATH_EX_HEADSET) {
594                         debug_log ("Set default sink to ALSA_WIRED_ACCESSORY");
595                         MMSoundMgrPulseSetDefaultSink (DEVICE_API_ALSA, DEVICE_BUS_WIRED);
596                 } else if (out == AVSYS_AUDIO_PATH_EX_SPK) {
597                         debug_log ("Set default sink to ALSA_SPEAKER");
598                         MMSoundMgrPulseSetDefaultSink (DEVICE_API_ALSA, DEVICE_BUS_BUILTIN);
599                 }
600         }
601 #endif
602
603         debug_log ("Trying to set avsys set path gain[%d], out[%d], in[%d], option[%d]\n", gain, out, in, option);
604
605         /* Set Path (GAIN, OUT, IN) */
606         if (AVSYS_FAIL(avsys_audio_set_path_ex(gain, out, in, option))) {
607                 debug_error ("avsys_audio_set_path_ex failed\n");
608                 ret = MM_ERROR_SOUND_INTERNAL;
609         }
610
611 CURRENT_ACTIVE_END:
612         /* clean up */
613         debug_fleave();
614         return ret;
615 }
616
617 static int __set_sound_path_to_dual (void)
618 {
619         int ret = MM_ERROR_NONE;
620
621         debug_fenter();
622
623         /* Sound path for ALSA */
624         debug_log ("Set path to DUAL.\n");
625         if (AVSYS_FAIL(avsys_audio_set_path_ex(AVSYS_AUDIO_GAIN_EX_KEYTONE,
626                                                 AVSYS_AUDIO_PATH_EX_SPK, AVSYS_AUDIO_PATH_EX_NONE,
627                                                 AVSYS_AUDIO_PATH_OPTION_DUAL_OUT))) {
628                 debug_error ("avsys_audio_set_path_ex failed\n");
629                 ret = MM_ERROR_SOUND_INTERNAL;
630         }
631
632         /* clean up */
633         debug_fleave();
634         return ret;
635 }
636
637 static int __set_sound_path_to_speaker (void)
638 {
639         int ret = MM_ERROR_NONE;
640
641         debug_fenter();
642
643         /* Sound path for ALSA */
644         debug_log ("Set path to SPEAKER.\n");
645         if(AVSYS_FAIL(avsys_audio_set_path_ex(AVSYS_AUDIO_GAIN_EX_KEYTONE,
646                                                 AVSYS_AUDIO_PATH_EX_SPK, AVSYS_AUDIO_PATH_EX_NONE,
647                                                 AVSYS_AUDIO_PATH_OPTION_NONE))) {
648                 debug_error ("avsys_audio_set_path_ex failed\n");
649                 ret = MM_ERROR_SOUND_INTERNAL;
650         }
651
652         /* clean up */
653         debug_fleave();
654         return ret;
655 }
656
657 static void __select_playback_active_device (void)
658 {
659         if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_ANY)) {
660                 debug_log ("Active device exists. Nothing needed...\n");
661                 return;
662         }
663
664         debug_log ("No playback active device, set active based on priority!!\n");
665
666         /* set active device based on device priority (bt>ear>spk) */
667         if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
668                 debug_log ("BT A2DP available, set as active!!\n");
669                 SET_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP);
670         } else if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_WFD)) {
671                 debug_log ("WFD available, set as active!!\n");
672                 SET_ACTIVE(MM_SOUND_DEVICE_OUT_WFD);
673         } else if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_DOCK)) {
674                 debug_log ("DOCK available, set as active!!\n");
675                 SET_ACTIVE(MM_SOUND_DEVICE_OUT_DOCK);
676         } else if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_HDMI)) {
677                 debug_log ("HDMI available, set as active!!\n");
678                 SET_ACTIVE(MM_SOUND_DEVICE_OUT_HDMI);
679         } else if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_USB_AUDIO)) {
680                 debug_log ("USB Audio available, set as active!!\n");
681                 SET_ACTIVE(MM_SOUND_DEVICE_OUT_USB_AUDIO);
682         } else if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY)) {
683                 debug_log ("WIRED available, set as active!!\n");
684                 SET_ACTIVE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY);
685         } else {
686                 debug_log ("SPEAKER available, set as active!!\n");
687                 SET_ACTIVE(MM_SOUND_DEVICE_OUT_SPEAKER);
688         }
689 }
690
691 static void __select_capture_active_device (void)
692 {
693         if (IS_ACTIVE(MM_SOUND_DEVICE_IN_ANY)) {
694                 debug_log ("Active device exists. Nothing needed...\n");
695                 return;
696         }
697
698         debug_log ("No capture active device, set active based on priority!!\n");
699
700         /* set active device based on device priority (bt>ear>spk) */
701         if (IS_AVAILABLE(MM_SOUND_DEVICE_IN_BT_SCO) && IS_COMMUNICATION_SESSION()) {
702                 debug_log ("BT SCO available, set as active!!\n");
703                 SET_ACTIVE(MM_SOUND_DEVICE_IN_BT_SCO);
704         } else if (IS_AVAILABLE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY)) {
705                 debug_log ("WIRED available, set as active!!\n");
706                 SET_ACTIVE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY);
707         } else {
708                 debug_log ("MIC available, set as active!!\n");
709                 SET_ACTIVE(MM_SOUND_DEVICE_IN_MIC);
710         }
711 }
712
713 static void __set_initial_active_device (void)
714 {
715         int type = 0;
716         bool a2dp = 0, sco = 0;
717
718         /* Set SPK & MIC as default available device */
719         /* FIXME : spk & mic can be always on??? */
720         SET_AVAILABLE(MM_SOUND_DEVICE_OUT_SPEAKER);
721         SET_AVAILABLE(MM_SOUND_DEVICE_IN_MIC);
722
723         /* Get wired status and set available status */
724         MMSoundMgrHeadsetGetType (&type);
725         if (type > 0) {
726                 SET_AVAILABLE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY);
727                 if (type == EARJACK_WITH_MIC) {
728                         SET_AVAILABLE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY);
729                 }
730         }
731
732         /* Get BT status and set available status */
733         MMSoundMgrPulseGetInitialBTStatus (&a2dp, &sco);
734         if (a2dp) {
735                 SET_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_A2DP);
736         }
737         if (sco) {
738                 SET_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_SCO);
739                 SET_AVAILABLE(MM_SOUND_DEVICE_IN_BT_SCO);
740         }
741
742         /* Set Active device based on priority */
743         __select_playback_active_device ();
744         __select_capture_active_device ();
745
746         __set_path_with_notification (NO_NOTI);
747
748         dump_info();
749 }
750
751 static void __handle_bt_a2dp_on (void)
752 {
753         int ret = MM_ERROR_NONE;
754
755         /* at this time, pulseaudio default sink is bt sink */
756         if (IS_COMMUNICATION_SESSION()) {
757                 debug_log ("Current session is VOICECALL, no auto-activation!!!\n");
758                 return;
759         }
760
761         debug_log ("Activate BT_A2DP device\n");
762         SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP);
763
764         ret = _mm_sound_mgr_device_active_device_callback(GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
765         if (ret != MM_ERROR_NONE) {
766                 debug_error ("_mm_sound_mgr_device_active_device_callback() failed [%x]\n", ret);
767         }
768
769         dump_info ();
770 }
771
772 static void __handle_bt_a2dp_off (void)
773 {
774         if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
775                 debug_msg("MM_SOUND_DEVICE_OUT_BT_A2DP was not active. nothing to do here.");
776                 dump_info ();
777                 return;
778         }
779
780         /* if bt was active, then do asm pause */
781         debug_msg("Do pause here");
782         _asm_pause_process (g_info.asm_handle);
783
784         /* set bt device to none */
785         debug_msg("Deactivate BT_A2DP device\n");
786         UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP);
787
788         /* activate current available device based on priority */
789         __select_playback_active_device();
790
791         /* Do set path and notify result */
792         __set_path_with_notification(DO_NOTI);
793
794         dump_info ();
795 }
796
797 static void __handle_bt_sco_off (void)
798 {
799         /* If sco is not activated, just return */
800         if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_SCO) && !IS_ACTIVE(MM_SOUND_DEVICE_IN_BT_SCO)) {
801                 debug_msg("BT SCO was not active. nothing to do here.");
802                 dump_info ();
803                 return;
804         }
805
806         /* set bt device to none */
807         debug_msg("Deactivate BT_SCO device\n");
808         UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_BT_SCO);
809         UNSET_ACTIVE(MM_SOUND_DEVICE_IN_BT_SCO);
810
811         /* activate current available device based on priority */
812         __select_playback_active_device();
813         __select_capture_active_device();
814
815         /* Do set path and notify result */
816         __set_path_with_notification(DO_NOTI);
817
818         dump_info ();
819 }
820
821 static void __handle_headset_on (int type)
822 {
823         /* at this time, pulseaudio default sink is bt sink */
824         /* if fmradio session, do nothing */
825
826         /* Skip when noti session */
827
828         /* ToDo : alarm/notification session ???? */
829         if (IS_COMMUNICATION_SESSION()) {
830                 debug_log ("Current session is VOICECALL, no auto-activation!!!\n");
831                 return;
832         }
833
834         debug_log ("Activate WIRED OUT device\n");
835         SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY);
836         if (type == EARJACK_WITH_MIC) {
837                 debug_log ("Activate WIRED IN device\n");
838                 SET_CAPTURE_ONLY_ACTIVE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY);
839         }
840
841         /* Do set path and notify result */
842         __set_path_with_notification(DO_NOTI);
843
844         dump_info ();
845 }
846
847 static void __handle_headset_off (void)
848 {
849         if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY)) {
850                 debug_msg("MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY was not active. nothing to do here.");
851                 return;
852         }
853
854         /* if bt was active, then do asm pause */
855         debug_msg("Do pause here");
856         _asm_pause_process (g_info.asm_handle);
857
858         /* set bt device to none */
859         debug_msg("Deactivate WIRED IN/OUT device\n");
860         UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY);
861         UNSET_ACTIVE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY);
862
863         /* For voicecall session, activation device is up-to application policy */
864         if (IS_COMMUNICATION_SESSION()) {
865                 debug_log ("Current session is VOICECALL, no auto-activation!!!\n");
866                 return;
867         }
868
869         /* activate current available device based on priority */
870         __select_playback_active_device();
871         __select_capture_active_device();
872
873         /* Do set path and notify result */
874         __set_path_with_notification(DO_NOTI);
875
876         dump_info ();
877 }
878
879 static void __handle_dock_on (void)
880 {
881         /* ToDo : alarm/notification session ???? */
882         if (IS_COMMUNICATION_SESSION()) {
883                 debug_log ("Current session is VOICECALL, no auto-activation!!!\n");
884                 return;
885         }
886
887         debug_log ("Activate DOCK device\n");
888         SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_DOCK);
889
890         /* Do set path and notify result */
891         __set_path_with_notification(DO_NOTI);
892
893         dump_info ();
894 }
895
896 static void __handle_dock_off (void)
897 {
898         if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_DOCK)) {
899                 debug_msg("MM_SOUND_DEVICE_OUT_DOCK was not active. nothing to do here.");
900                 return;
901         }
902
903         /* No PAUSE on Dock off case */
904
905         /* set DOCK device to none */
906         debug_msg("Deactivate DOCK device\n");
907         UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_DOCK);
908
909         /* activate current available device based on priority */
910         __select_playback_active_device();
911
912         /* Do set path and notify result */
913         __set_path_with_notification(DO_NOTI);
914
915         dump_info ();
916 }
917
918 static void __handle_hdmi_on (void)
919 {
920         /* ToDo : alarm/notification session ???? */
921         if (IS_COMMUNICATION_SESSION()) {
922                 debug_log ("Current session is VOICECALL, no auto-activation!!!\n");
923                 return;
924         }
925
926         debug_log ("Activate HDMI device\n");
927         SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_HDMI);
928
929         /* Do set path and notify result */
930         __set_path_with_notification(DO_NOTI);
931
932         dump_info ();
933 }
934
935 static void __handle_hdmi_off (void)
936 {
937         if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_HDMI)) {
938                 debug_msg("MM_SOUND_DEVICE_OUT_HDMI was not active. nothing to do here.");
939                 return;
940         }
941
942         /* if HDMI was active, then do asm pause */
943         debug_msg("Do pause here");
944         _asm_pause_process (g_info.asm_handle);
945
946         /* set DOCK device to none */
947         debug_msg("Deactivate HDMIdevice\n");
948         UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_HDMI);
949
950         /* activate current available device based on priority */
951         __select_playback_active_device();
952
953         /* Do set path and notify result */
954         __set_path_with_notification(DO_NOTI);
955
956         dump_info ();
957 }
958
959 static void __handle_wfd_on (void)
960 {
961         /* ToDo : alarm/notification session ???? */
962         if (IS_COMMUNICATION_SESSION()) {
963                 debug_log ("Current session is VOICECALL, no auto-activation!!!\n");
964                 return;
965         }
966
967         debug_log ("Activate WFD device\n");
968         SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_WFD);
969
970         /* Do set path and notify result */
971         __set_path_with_notification(DO_NOTI);
972
973         dump_info ();
974 }
975
976 static void __handle_wfd_off (void)
977 {
978         if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_WFD)) {
979                 debug_msg("MM_SOUND_DEVICE_OUT_WFD was not active. nothing to do here.");
980                 return;
981         }
982
983         /* if WFD was active, then do asm pause */
984         debug_msg("Do pause here");
985         _asm_pause_process (g_info.asm_handle);
986
987         /* set WFD device to none */
988         debug_msg("Deactivate WFD device\n");
989         UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_WFD);
990
991         /* activate current available device based on priority */
992         __select_playback_active_device();
993
994         /* Do set path and notify result */
995         __set_path_with_notification(DO_NOTI);
996
997         dump_info ();
998 }
999
1000 static void __handle_usb_audio_on (void)
1001 {
1002         int ret = MM_ERROR_NONE;
1003
1004         if (IS_COMMUNICATION_SESSION()) {
1005                 debug_log ("Current session is VOICECALL, no auto-activation!!!\n");
1006                 return;
1007         }
1008
1009         debug_log ("Activate USB Audio device\n");
1010         SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_USB_AUDIO);
1011
1012         ret = _mm_sound_mgr_device_active_device_callback(GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
1013         if (ret != MM_ERROR_NONE) {
1014                 debug_error ("_mm_sound_mgr_device_active_device_callback() failed [%x]\n", ret);
1015         }
1016
1017         dump_info ();
1018 }
1019
1020 static void __handle_usb_audio_off (void)
1021 {
1022         if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_USB_AUDIO)) {
1023                 debug_msg("MM_SOUND_DEVICE_OUT_USB_AUDIO was not active. nothing to do here.");
1024                 dump_info ();
1025                 return;
1026         }
1027
1028         /* if device was active, then do asm pause */
1029         debug_msg("Do pause here");
1030         _asm_pause_process (g_info.asm_handle);
1031
1032         /* set bt device to none */
1033         debug_msg("Deactivate USB Audio device\n");
1034         UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_USB_AUDIO);
1035
1036         /* activate current available device based on priority */
1037         __select_playback_active_device();
1038
1039         /* Do set path and notify result */
1040         __set_path_with_notification(DO_NOTI);
1041
1042         dump_info ();
1043 }
1044
1045
1046 /* ------------------------- EXTERNAL FUNCTIONS ------------------------------------*/
1047 /* DEVICE : Called by mgr_pulse for updating current default_sink_name */
1048 int MMSoundMgrSessionSetDefaultSink (char *default_sink_name)
1049 {
1050         LOCK_SESSION();
1051
1052         strcpy (g_info.default_sink_name, default_sink_name);
1053         debug_msg ("[SESSION][%s][%d] default sink=[%s]\n", __func__, __LINE__, default_sink_name);
1054
1055         /* ToDo: do something */
1056
1057         UNLOCK_SESSION();
1058
1059         return MM_ERROR_NONE;
1060 }
1061
1062 /* DEVICE : Called by mgr_pulse for bt and mgr_headset for headset */
1063 int MMSoundMgrSessionSetDeviceAvailable (device_type_t device, int available, int type, char* name)
1064 {
1065         LOCK_SESSION();
1066
1067         debug_msg ("[SESSION] device = %d, available = %d, type = %d, name = %s\n", device, available, type, name);
1068         switch (device) {
1069         case DEVICE_WIRED:
1070                 if (available) {
1071
1072                         if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY)) {
1073                                 SET_AVAILABLE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY);
1074                                 if (type == EARJACK_WITH_MIC) {
1075                                         SET_AVAILABLE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY);
1076                                         _mm_sound_mgr_device_available_device_callback(
1077                                                                                         MM_SOUND_DEVICE_IN_WIRED_ACCESSORY,
1078                                                                                         MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY,
1079                                                                                         AVAILABLE);
1080                                 } else {
1081                                         _mm_sound_mgr_device_available_device_callback(
1082                                                                                         MM_SOUND_DEVICE_IN_NONE,
1083                                                                                         MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY,
1084                                                                                         AVAILABLE);
1085                                 }
1086                                 __handle_headset_on(type);
1087                         } else {
1088                                 debug_log ("Already device [%d] is available...\n", device);
1089                         }
1090
1091                 } else {
1092
1093                         if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY)) {
1094                                 UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY);
1095                                 if (IS_AVAILABLE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY)) {
1096                                         UNSET_AVAILABLE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY);
1097                                         _mm_sound_mgr_device_available_device_callback(
1098                                                                                         MM_SOUND_DEVICE_IN_WIRED_ACCESSORY,
1099                                                                                         MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY,
1100                                                                                         NOT_AVAILABLE);
1101
1102                                 } else {
1103                                         _mm_sound_mgr_device_available_device_callback(
1104                                                                                         MM_SOUND_DEVICE_IN_NONE,
1105                                                                                         MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY,
1106                                                                                         NOT_AVAILABLE);
1107                                 }
1108                                 __handle_headset_off();
1109                         } else {
1110                                 debug_log ("Already device [%d] is unavailable...\n", device);
1111                         }
1112
1113                 }
1114                 break;
1115
1116         case DEVICE_BT_A2DP:
1117                 strcpy (g_info.bt_name, (name)? name : "");
1118                 if (available) {
1119                         if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
1120                                 SET_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_A2DP);
1121                                 _mm_sound_mgr_device_available_device_callback(
1122                                                                                         MM_SOUND_DEVICE_IN_NONE,
1123                                                                                         MM_SOUND_DEVICE_OUT_BT_A2DP,
1124                                                                                         AVAILABLE);
1125
1126                                 __handle_bt_a2dp_on();
1127                         } else {
1128                                 debug_log ("Already device [%d] is available...\n", device);
1129                         }
1130                 } else {
1131                         if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
1132                                 UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_A2DP);
1133                                 _mm_sound_mgr_device_available_device_callback(
1134                                                                                         MM_SOUND_DEVICE_IN_NONE,
1135                                                                                         MM_SOUND_DEVICE_OUT_BT_A2DP,
1136                                                                                         NOT_AVAILABLE);
1137
1138                                 __handle_bt_a2dp_off();
1139                         } else {
1140                                 debug_log ("Already device [%d] is unavailable...\n", device);
1141                         }
1142                 }
1143                 break;
1144
1145         case DEVICE_BT_SCO:
1146                 if (available) {
1147                         if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_SCO)) {
1148                                 SET_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_SCO);
1149                                 SET_AVAILABLE(MM_SOUND_DEVICE_IN_BT_SCO);
1150                                 _mm_sound_mgr_device_available_device_callback(
1151                                                                                         MM_SOUND_DEVICE_IN_BT_SCO,
1152                                                                                         MM_SOUND_DEVICE_OUT_BT_SCO,
1153                                                                                         AVAILABLE);
1154                         } else {
1155                                 debug_log ("Already device [%d] is available...\n", device);
1156                         }
1157                 } else {
1158                         if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_SCO)) {
1159                                 UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_SCO);
1160                                 UNSET_AVAILABLE(MM_SOUND_DEVICE_IN_BT_SCO);
1161                                 _mm_sound_mgr_device_available_device_callback(
1162                                                                                         MM_SOUND_DEVICE_IN_BT_SCO,
1163                                                                                         MM_SOUND_DEVICE_OUT_BT_SCO,
1164                                                                                         NOT_AVAILABLE);
1165
1166                                 __handle_bt_sco_off();
1167                         } else {
1168                                 debug_log ("Already device [%d] is unavailable...\n", device);
1169                         }
1170                 }
1171                 break;
1172
1173         case DEVICE_DOCK:
1174                 if (available) {
1175                         if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_DOCK)) {
1176                                 SET_AVAILABLE(MM_SOUND_DEVICE_OUT_DOCK);
1177                                 _mm_sound_mgr_device_available_device_callback(
1178                                                                                         MM_SOUND_DEVICE_IN_NONE,
1179                                                                                         MM_SOUND_DEVICE_OUT_DOCK,
1180                                                                                         AVAILABLE);
1181                                 __handle_dock_on();
1182                         } else {
1183                                 debug_log ("Already device [%d] is available...\n", device);
1184                         }
1185                 } else {
1186                         if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_DOCK)) {
1187                                 UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_DOCK);
1188                                 _mm_sound_mgr_device_available_device_callback(
1189                                                                                         MM_SOUND_DEVICE_IN_NONE,
1190                                                                                         MM_SOUND_DEVICE_OUT_DOCK,
1191                                                                                         NOT_AVAILABLE);
1192
1193                                 __handle_dock_off();
1194                         } else {
1195                                 debug_log ("Already device [%d] is unavailable...\n", device);
1196                         }
1197                 }
1198                 break;
1199
1200         case DEVICE_HDMI:
1201                 if (available) {
1202                         if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_HDMI)) {
1203                                 SET_AVAILABLE(MM_SOUND_DEVICE_OUT_HDMI);
1204                                 _mm_sound_mgr_device_available_device_callback(
1205                                                                                         MM_SOUND_DEVICE_IN_NONE,
1206                                                                                         MM_SOUND_DEVICE_OUT_HDMI,
1207                                                                                         AVAILABLE);
1208                                 __handle_hdmi_on();
1209                         } else {
1210                                 debug_log ("Already device [%d] is available...\n", device);
1211                         }
1212                 } else {
1213                         if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_HDMI)) {
1214                                 UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_HDMI);
1215                                 _mm_sound_mgr_device_available_device_callback(
1216                                                                                         MM_SOUND_DEVICE_IN_NONE,
1217                                                                                         MM_SOUND_DEVICE_OUT_HDMI,
1218                                                                                         NOT_AVAILABLE);
1219
1220                                 __handle_hdmi_off();
1221                         } else {
1222                                 debug_log ("Already device [%d] is unavailable...\n", device);
1223                         }
1224                 }
1225                 break;
1226
1227         case DEVICE_WFD:
1228                 if (available) {
1229                         if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_WFD)) {
1230                                 SET_AVAILABLE(MM_SOUND_DEVICE_OUT_WFD);
1231                                 _mm_sound_mgr_device_available_device_callback(
1232                                                                                         MM_SOUND_DEVICE_IN_NONE,
1233                                                                                         MM_SOUND_DEVICE_OUT_WFD,
1234                                                                                         AVAILABLE);
1235                                 __handle_wfd_on();
1236                         } else {
1237                                 debug_log ("Already device [%d] is available...\n", device);
1238                         }
1239                 } else {
1240                         if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_WFD)) {
1241                                 UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_WFD);
1242                                 _mm_sound_mgr_device_available_device_callback(
1243                                                                                         MM_SOUND_DEVICE_IN_NONE,
1244                                                                                         MM_SOUND_DEVICE_OUT_WFD,
1245                                                                                         NOT_AVAILABLE);
1246
1247                                 __handle_wfd_off();
1248                         } else {
1249                                 debug_log ("Already device [%d] is unavailable...\n", device);
1250                         }
1251                 }
1252                 break;
1253
1254         case DEVICE_USB_AUDIO:
1255                 if (available) {
1256                         if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_USB_AUDIO)) {
1257                                 SET_AVAILABLE(MM_SOUND_DEVICE_OUT_USB_AUDIO);
1258                                 _mm_sound_mgr_device_available_device_callback(
1259                                                                                         MM_SOUND_DEVICE_IN_NONE,
1260                                                                                         MM_SOUND_DEVICE_OUT_USB_AUDIO,
1261                                                                                         AVAILABLE);
1262                                 __handle_usb_audio_on();
1263                         } else {
1264                                 debug_log ("Already device [%d] is available...\n", device);
1265                         }
1266                 } else {
1267                         if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_USB_AUDIO)) {
1268                                 UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_USB_AUDIO);
1269                                 _mm_sound_mgr_device_available_device_callback(
1270                                                                                         MM_SOUND_DEVICE_IN_NONE,
1271                                                                                         MM_SOUND_DEVICE_OUT_USB_AUDIO,
1272                                                                                         NOT_AVAILABLE);
1273
1274                                 __handle_usb_audio_off();
1275                         } else {
1276                                 debug_log ("Already device [%d] is unavailable...\n", device);
1277                         }
1278                 }
1279                 break;
1280
1281         default:
1282                 debug_warning ("device [%d] is not handled...\n", device);
1283                 break;
1284         }
1285
1286         UNLOCK_SESSION();
1287
1288         return MM_ERROR_NONE;
1289 }
1290
1291 int MMSoundMgrSessionIsDeviceAvailableNoLock (mm_sound_device_out playback, mm_sound_device_in capture, bool *available)
1292 {
1293         int ret = MM_ERROR_NONE;
1294         debug_log ("[SESSION][%s][%d] query playback=[0x%X] capture=[0x%X], current available = [0x%X]\n",
1295                         __func__, __LINE__, playback, capture, g_info.device_available);
1296
1297         if (available) {
1298                 if (playback == MM_SOUND_DEVICE_OUT_NONE) {
1299                         *available = IS_AVAILABLE(capture);
1300                 } else if (capture == MM_SOUND_DEVICE_IN_NONE) {
1301                         *available = IS_AVAILABLE(playback);
1302                 } else {
1303                         *available = (IS_AVAILABLE(playback) && IS_AVAILABLE(capture));
1304                 }
1305                 debug_log ("[%s][%d] return available = [%d]\n", __func__, __LINE__, *available);
1306         } else {
1307                 debug_warning ("Invalid argument!!!\n");
1308                 ret = MM_ERROR_INVALID_ARGUMENT;
1309         }
1310
1311         return ret;
1312 }
1313
1314
1315 int MMSoundMgrSessionIsDeviceAvailable (mm_sound_device_out playback, mm_sound_device_in capture, bool *available)
1316 {
1317         int ret = MM_ERROR_NONE;
1318
1319         LOCK_SESSION();
1320         ret = MMSoundMgrSessionIsDeviceAvailableNoLock (playback, capture, available);
1321         UNLOCK_SESSION();
1322
1323         return ret;
1324 }
1325
1326 int MMSoundMgrSessionGetAvailableDevices (int *playback, int *capture)
1327 {
1328         if (playback == NULL || capture == NULL) {
1329                 debug_error ("Invalid input parameter\n");
1330                 return MM_ERROR_INVALID_ARGUMENT;
1331         }
1332
1333         LOCK_SESSION();
1334
1335         *playback = GET_AVAILABLE_PLAYBACK();
1336         *capture  = GET_AVAILABLE_CAPTURE();
1337         debug_msg ("[SESSION][%s][%d] return available playback=[0x%X]/capture=[0x%X]\n", __func__, __LINE__, *playback, *capture);
1338
1339         UNLOCK_SESSION();
1340
1341         return MM_ERROR_NONE;
1342 }
1343
1344 int MMSoundMgrSessionSetDeviceActive (mm_sound_device_out playback, mm_sound_device_in capture)
1345 {
1346         int ret = MM_ERROR_NONE;
1347         int old_active = g_info.device_active;
1348
1349         LOCK_SESSION();
1350
1351         debug_msg ("[SESSION][%s][%d] playback=[0x%X] capture=[0x%X]\n", __func__, __LINE__, playback, capture);
1352
1353         /* Check whether device is available */
1354         if ((playback && !IS_AVAILABLE(playback)) || (capture && !IS_AVAILABLE(capture))) {
1355                 debug_warning ("Failed to set active state to unavailable device!!!\n");
1356                 ret = MM_ERROR_INVALID_ARGUMENT;
1357                 goto END_SET_DEVICE;
1358         }
1359
1360         /* Update active state */
1361         debug_log ("Update active device as request\n");
1362         if (playback) {
1363                 SET_PLAYBACK_ONLY_ACTIVE(playback);
1364         }
1365         if (capture) {
1366                 SET_CAPTURE_ONLY_ACTIVE(capture);
1367         }
1368
1369         /* If there's changes do path set and inform callback */
1370         if (old_active != g_info.device_active) {
1371                 debug_msg ("Changes happens....set path based on current active device and inform callback!!!\n");
1372
1373                 /* Do set path based on current active state */
1374                 __set_path_with_notification(DO_NOTI);
1375         } else {
1376                 debug_msg ("No changes....nothing to do...\n");
1377         }
1378
1379 END_SET_DEVICE:
1380         UNLOCK_SESSION();
1381         return ret;
1382 }
1383
1384 int MMSoundMgrSessionGetDeviceActive (mm_sound_device_out *playback, mm_sound_device_in *capture)
1385 {
1386         if (playback == NULL || capture == NULL) {
1387                 debug_error ("Invalid input parameter\n");
1388                 return MM_ERROR_INVALID_ARGUMENT;
1389         }
1390
1391         LOCK_SESSION();
1392
1393         *playback = GET_ACTIVE_PLAYBACK();
1394         *capture  = GET_ACTIVE_CAPTURE();
1395         debug_msg ("[SESSION][%s][%d] return active playback=[0x%X]/capture=[0x%X]\n", __func__, __LINE__,
1396                                 *playback,*capture);
1397
1398         UNLOCK_SESSION();
1399         return MM_ERROR_NONE;
1400 }
1401
1402 /* SUBSESSION */
1403 int MMSoundMgrSessionSetSession(session_t session, session_state_t state)
1404 {
1405         LOCK_SESSION();
1406
1407         debug_msg ("[SESSION][%s][%d] session=[%d] state=[%d]\n", __func__, __LINE__, session, state);
1408
1409         /* Update session */
1410         if (state)
1411                 g_info.session = session;
1412         else
1413                 g_info.session = SESSION_MEDIA;
1414
1415         /* Do action based on new session */
1416         switch (session) {
1417         case SESSION_MEDIA:
1418                 /* ToDo:
1419                 start
1420                         mic setting
1421                 end
1422                 */
1423                 break;
1424
1425         case SESSION_VOICECALL:
1426         case SESSION_VOIP:
1427                 __set_playback_route_communication (state);
1428                 break;
1429
1430         case SESSION_FMRADIO:
1431                 __set_playback_route_fmradio (state);
1432                 break;
1433
1434         case SESSION_NOTIFICATION:
1435                 __set_playback_route_notification (state);
1436                 break;
1437
1438         case SESSION_EMERGENCY:
1439                 __set_playback_route_emergency (state);
1440                 break;
1441
1442         default:
1443                 debug_warning ("session [%d] is not handled...\n", session);
1444                 break;
1445         }
1446
1447         UNLOCK_SESSION();
1448         return MM_ERROR_NONE;
1449 }
1450
1451 int MMSoundMgrSessionGetSession(session_t *session)
1452 {
1453         if (session == NULL) {
1454                 debug_error ("Invalid input parameter\n");
1455                 return MM_ERROR_INVALID_ARGUMENT;
1456         }
1457
1458         //LOCK_SESSION();
1459         *session = g_info.session;
1460         //UNLOCK_SESSION();
1461
1462         return MM_ERROR_NONE;
1463 }
1464
1465 /* SUBSESSION */
1466 int MMSoundMgrSessionSetSubSession(subsession_t subsession)
1467 {
1468         LOCK_SESSION();
1469
1470         if (g_info.subsession == subsession) {
1471                 debug_msg ("[SESSION][%s][%d] already subsession is [%d]. skip this!!\n", __func__, __LINE__, subsession);
1472         } else {
1473                 g_info.subsession = subsession;
1474                 debug_msg ("[SESSION][%s][%d] subsession=[%d]\n", __func__, __LINE__, subsession);
1475
1476                 __set_path_with_notification (NO_NOTI);
1477         }
1478
1479         UNLOCK_SESSION();
1480
1481         return MM_ERROR_NONE;
1482 }
1483
1484 int MMSoundMgrSessionGetSubSession(subsession_t *subsession)
1485 {
1486         if (subsession == NULL) {
1487                 debug_error ("Invalid input parameter\n");
1488                 return MM_ERROR_INVALID_ARGUMENT;
1489         }
1490
1491         LOCK_SESSION();
1492
1493         *subsession = g_info.subsession;
1494
1495         UNLOCK_SESSION();
1496
1497         return MM_ERROR_NONE;
1498 }
1499
1500 char* MMSoundMgrSessionGetBtA2DPName ()
1501 {
1502         return g_info.bt_name;
1503 }
1504
1505 int MMSoundMgrSessionInit(void)
1506 {
1507         LOCK_SESSION();
1508
1509         debug_fenter();
1510
1511         memset (&g_info, 0, sizeof (SESSION_INFO_STRUCT));
1512
1513         /* FIXME: Initial status should be updated */
1514         __set_initial_active_device ();
1515
1516         /* Register for headset unplug */
1517         if (_asm_register_for_headset (&g_info.asm_handle) == false) {
1518                 debug_error ("Failed to register ASM for headset\n");
1519         }
1520
1521         debug_fleave();
1522
1523         UNLOCK_SESSION();
1524         return MM_ERROR_NONE;
1525 }
1526
1527 int MMSoundMgrSessionFini(void)
1528 {
1529         LOCK_SESSION();
1530
1531         debug_fenter();
1532
1533         /* Unregister for headset unplug */
1534         _asm_unregister_for_headset (&g_info.asm_handle);
1535
1536         debug_fleave();
1537
1538         UNLOCK_SESSION();
1539
1540         return MM_ERROR_NONE;
1541 }
1542