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