tizenaudio-policy: unload modules safely when daemon is on shutdown
[platform/core/multimedia/pulseaudio-modules-tizen.git] / src / module-tizenaudio-policy.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2013-2016 Seungbae Shin, Sangchul Lee, Jeongho Mok
5
6   PulseAudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU Lesser General Public License as published
8   by the Free Software Foundation; either version 2.1 of the License,
9   or (at your option) any later version.
10
11   PulseAudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with PulseAudio; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdbool.h>
27 #include <strings.h>
28 #include <vconf.h> // for mono
29 #include <iniparser.h>
30 #include <unistd.h>
31 #include <pthread.h>
32
33 #include <pulse/proplist.h>
34 #include <pulse/timeval.h>
35 #include <pulse/util.h>
36 #include <pulse/rtclock.h>
37
38 #include <pulsecore/core.h>
39 #include <pulsecore/module.h>
40 #include <pulsecore/modargs.h>
41 #include <pulsecore/core-error.h>
42 #include <pulsecore/core-rtclock.h>
43 #include <pulsecore/core-scache.h>
44 #include <pulsecore/core-subscribe.h>
45 #include <pulsecore/core-util.h>
46 #include <pulsecore/mutex.h>
47 #include <pulsecore/log.h>
48 #include <pulsecore/namereg.h>
49 #include <pulsecore/sink-input.h>
50 #include <pulsecore/source-output.h>
51 #include <pulsecore/pstream-util.h>
52 #include <pulsecore/strbuf.h>
53 #include <pulsecore/sink-input.h>
54 #include <pulsecore/sound-file.h>
55 #include <pulsecore/play-memblockq.h>
56 #include <pulsecore/shared.h>
57
58 #include "communicator.h"
59 #include "hal-interface.h"
60 #include "stream-manager.h"
61 #include "device-manager.h"
62
63 PA_MODULE_AUTHOR("Seungbae Shin, Sangchul Lee, Jeongho Mok");
64 PA_MODULE_DESCRIPTION("Tizen Audio Policy module");
65 PA_MODULE_VERSION(PACKAGE_VERSION);
66 PA_MODULE_LOAD_ONCE(true);
67 PA_MODULE_USAGE(" ");
68
69 static const char* const valid_modargs[] = {
70     NULL
71 };
72
73 struct userdata;
74
75 /* Modules for dynamic loading */
76 #define MODULE_COMBINE_SINK           "module-combine-sink"
77 #define MODULE_NULL_SINK              "module-null-sink"
78 #define MODULE_NULL_SOURCE            "module-null-source"
79 #define MODULE_LOOPBACK               "module-loopback"
80
81 /* Name of combine sink for external route type */
82 #define SINK_NAME_COMBINED_EX         SINK_NAME_COMBINED"_ex"
83
84 /* Default values */
85 #define LOOPBACK_DEFAULT_LATENCY_MSEC    40
86 #define LOOPBACK_DEFAULT_ADJUST_SEC      3
87
88 #define TIMED_BT_SCO_CLOSE_USEC          3000000
89
90 /* Macros */
91 #define CONVERT_TO_HAL_DIRECTION(stream_type) \
92     ((stream_type == STREAM_SINK_INPUT) ? DIRECTION_OUT : DIRECTION_IN)
93 #define CONVERT_TO_DEVICE_DIRECTION(stream_type) \
94     ((stream_type == STREAM_SINK_INPUT) ? DM_DEVICE_DIRECTION_OUT : DM_DEVICE_DIRECTION_IN)
95 #define IS_AVAILABLE_DIRECTION(stream_type, device_direction) \
96     ((stream_type == STREAM_SINK_INPUT) ? (device_direction & DM_DEVICE_DIRECTION_OUT) : (device_direction & DM_DEVICE_DIRECTION_IN))
97
98 /* PCM Dump */
99 #define PA_DUMP_INI_DEFAULT_PATH                SYSCONFDIR"/multimedia/mmfw_audio_pcm_dump.ini" /* SYSCONFDIR is defined at .spec */
100 #define PA_DUMP_INI_TEMP_PATH                   "/home/owner/media/mmfw_audio_pcm_dump.ini"
101 #define PA_DUMP_VCONF_KEY                       "memory/private/sound/pcm_dump"
102
103 typedef enum _device_type {
104     DEVICE_BUILTIN_SPEAKER,
105     DEVICE_BUILTIN_RECEIVER,
106     DEVICE_BUILTIN_MIC,
107     DEVICE_AUDIO_JACK,
108     DEVICE_BT_A2DP,
109     DEVICE_BT_SCO,
110     DEVICE_HDMI,
111     DEVICE_FORWARDING,
112     DEVICE_USB_AUDIO,
113     DEVICE_NETWORK,
114     DEVICE_UNKNOWN,
115     DEVICE_MAX,
116 } device_type_t;
117
118 enum {
119     CACHED_DEVICE_DIRECTION_IN,
120     CACHED_DEVICE_DIRECTION_OUT,
121     CACHED_DEVICE_DIRECTION_MAX,
122 };
123
124 static int cached_connected_devices[DEVICE_MAX][CACHED_DEVICE_DIRECTION_MAX];
125
126 static device_type_t convert_device_type_str(const char *device)
127 {
128     if (pa_safe_streq(device, DEVICE_TYPE_SPEAKER))
129         return DEVICE_BUILTIN_SPEAKER;
130     else if (pa_safe_streq(device, DEVICE_TYPE_RECEIVER))
131         return DEVICE_BUILTIN_RECEIVER;
132     else if (pa_safe_streq(device, DEVICE_TYPE_MIC))
133         return DEVICE_BUILTIN_MIC;
134     else if (pa_safe_streq(device, DEVICE_TYPE_AUDIO_JACK))
135         return DEVICE_AUDIO_JACK;
136     else if (pa_safe_streq(device, DEVICE_TYPE_BT_A2DP))
137         return DEVICE_BT_A2DP;
138     else if (pa_safe_streq(device, DEVICE_TYPE_BT_SCO))
139         return DEVICE_BT_SCO;
140     else if (pa_safe_streq(device, DEVICE_TYPE_HDMI))
141         return DEVICE_HDMI;
142     else if (pa_safe_streq(device, DEVICE_TYPE_FORWARDING))
143         return DEVICE_FORWARDING;
144     else if (pa_safe_streq(device, DEVICE_TYPE_USB_AUDIO))
145         return DEVICE_USB_AUDIO;
146     else if (pa_safe_streq(device, DEVICE_TYPE_NETWORK))
147         return DEVICE_NETWORK;
148
149     pa_log_warn("unknown device (%s)", device);
150     return DEVICE_UNKNOWN;
151 }
152
153 struct userdata {
154     pa_core *core;
155     pa_module *module;
156
157     struct {
158         pa_communicator *comm;
159         pa_hook_slot *comm_hook_select_proper_sink_or_source_slot;
160         pa_hook_slot *comm_hook_change_route_slot;
161         pa_hook_slot *comm_hook_device_connection_changed_slot;
162         pa_hook_slot *comm_hook_update_info_slot;
163     } communicator;
164
165     pa_hal_interface *hal_interface;
166     pa_stream_manager *stream_manager;
167     pa_device_manager *device_manager;
168
169     pa_module *module_combine_sink;
170     pa_module *module_combine_sink_for_ex;
171     uint32_t module_null_sink_index;
172     uint32_t module_null_source_index;
173     pa_module *module_loopback;
174     struct {
175         int32_t latency_msec;
176         int32_t adjust_sec;
177         pa_sink *sink;
178         pa_source *source;
179     } loopback_args;
180     pa_time_event *time_event_bt_sco_close;
181 };
182
183 static void __load_dump_config(struct userdata *u)
184 {
185     dictionary * dict = NULL;
186
187     dict = iniparser_load(PA_DUMP_INI_DEFAULT_PATH);
188     if (!dict) {
189         pa_log_debug("%s load failed. Use temporary file", PA_DUMP_INI_DEFAULT_PATH);
190         dict = iniparser_load(PA_DUMP_INI_TEMP_PATH);
191         if (!dict) {
192             pa_log_warn("%s load failed", PA_DUMP_INI_TEMP_PATH);
193             return;
194         }
195     }
196
197     u->core->pcm_dump |= (bool)iniparser_getboolean(dict, "pcm_dump:pa_sink_input", 0) ? PA_PCM_DUMP_SINK_INPUT : 0;
198     u->core->pcm_dump |= (bool)iniparser_getboolean(dict, "pcm_dump:pa_sink", 0) ? PA_PCM_DUMP_SINK : 0;
199     u->core->pcm_dump |= (bool)iniparser_getboolean(dict, "pcm_dump:pa_source", 0) ? PA_PCM_DUMP_SOURCE : 0;
200     u->core->pcm_dump |= (bool)iniparser_getboolean(dict, "pcm_dump:pa_source_output", 0) ? PA_PCM_DUMP_SOURCE_OUTPUT : 0;
201
202     iniparser_freedict(dict);
203 }
204
205 /* threre is only one sco connected device */
206 static pa_tz_device* _get_sco_connected_device(pa_device_manager *dm) {
207     pa_idxset *device_list;
208     pa_tz_device *device;
209     uint32_t device_idx;
210
211     pa_assert(dm);
212
213     device_list = pa_device_manager_get_device_list(dm);
214
215     PA_IDXSET_FOREACH(device, device_list, device_idx) {
216         if (pa_safe_streq(device->type, DEVICE_TYPE_BT_SCO)) {
217             return device;
218         }
219     }
220     return NULL;
221 }
222
223 static bool is_bt_sco_connected(pa_device_manager *dm) {
224     pa_tz_device *bt_device;
225
226     pa_assert(dm);
227
228     if ((bt_device = _get_sco_connected_device(dm)))
229         return true;
230
231     return false;
232 }
233
234 static bool is_bt_a2dp_connected(pa_device_manager *dm) {
235     pa_idxset *device_list;
236     pa_tz_device *device;
237     uint32_t device_idx;
238
239     pa_assert(dm);
240
241     device_list = pa_device_manager_get_device_list(dm);
242
243     PA_IDXSET_FOREACH(device, device_list, device_idx) {
244         if (pa_safe_streq(device->type, DEVICE_TYPE_BT_A2DP)) {
245             return true;
246         }
247     }
248
249     return false;
250 }
251
252 static bool is_bt_sco_opened(pa_device_manager *dm) {
253     dm_device_bt_sco_status_t sco_status;
254     pa_tz_device *bt_device;
255
256     pa_assert(dm);
257
258     bt_device = _get_sco_connected_device(dm);
259     if (bt_device == NULL) {
260         pa_log_debug("No SCO connected bt device");
261         return false;
262     }
263     if (pa_tz_device_sco_get_status(bt_device, &sco_status) < 0) {
264         pa_log_error("get BT SCO status failed");
265         return false;
266     }
267     if (sco_status != DM_DEVICE_BT_SCO_STATUS_OPENED) {
268         pa_log_error("SCO is not opened");
269         return false;
270     }
271     pa_log_info("SCO is opened");
272
273     return true;
274 }
275
276 static void timed_bt_sco_close_cb(pa_mainloop_api *a, pa_time_event *e, const struct timeval *t, void *userdata) {
277     struct userdata *u = userdata;
278     pa_tz_device *bt_device;
279     dm_device_bt_sco_status_t sco_status;
280
281     pa_assert(u);
282     pa_assert(u->time_event_bt_sco_close == e);
283
284     pa_log_info("timed_bt_sco_close_cb is called");
285
286     u->core->mainloop->time_free(u->time_event_bt_sco_close);
287     u->time_event_bt_sco_close = NULL;
288
289     bt_device = _get_sco_connected_device(u->device_manager);
290     if (bt_device == NULL) {
291         pa_log_debug("No SCO connected bt device");
292         return;
293     }
294     if (pa_tz_device_sco_get_status(bt_device, &sco_status) < 0) {
295         pa_log_error("get BT SCO status failed");
296         return;
297     }
298     if (pa_tz_device_sco_close(bt_device) < 0) {
299         pa_log_error("BT SCO was opened, but failed to close SCO");
300         return;
301     }
302     pa_log_info("BT SCO is now closed in timed callback");
303 }
304
305
306 static int bt_sco_open(struct userdata *u, const char *role) {
307     dm_device_bt_sco_status_t sco_status;
308     pa_tz_device *bt_device;
309
310     pa_assert(u);
311     pa_assert(role);
312
313     if (u->time_event_bt_sco_close) {
314         u->core->mainloop->time_free(u->time_event_bt_sco_close);
315         u->time_event_bt_sco_close = NULL;
316     }
317
318     bt_device = _get_sco_connected_device(u->device_manager);
319     if (bt_device == NULL) {
320         pa_log_debug("No SCO connected bt device");
321         return 0;
322     }
323     pa_log_info("Got BT SCO connected device(%u)", bt_device->id);
324
325     if (pa_tz_device_sco_get_status(bt_device, &sco_status) < 0) {
326         pa_log_error("get BT SCO status failed");
327         return -1;
328     }
329     if (sco_status == DM_DEVICE_BT_SCO_STATUS_OPENED) {
330         pa_log_warn("BT SCO is already opened for this BT device");
331         return 0;
332     }
333
334     if (pa_safe_streq(role, STREAM_ROLE_VOICE_RECOGNITION) ||
335         pa_safe_streq(role, STREAM_ROLE_VOICE_RECOGNITION_SERVICE))
336         pa_tz_device_sco_enable_pcm(bt_device, true);
337
338     if (pa_tz_device_sco_open(bt_device) < 0) {
339         pa_log_error("failed to open BT SCO");
340         return -1;
341     }
342     pa_log_debug("BT SCO is now opened");
343
344     return 0;
345 }
346
347 static int bt_sco_close(struct userdata *u, bool delayed_close) {
348     dm_device_bt_sco_status_t sco_status;
349     pa_tz_device *bt_device;
350
351     pa_assert(u);
352
353     if (!u->device_manager) {
354         pa_log_error("device_manager is null");
355         return -1;
356     }
357
358     bt_device = _get_sco_connected_device(u->device_manager);
359     if (bt_device == NULL) {
360         pa_log_debug("No SCO connected bt device");
361         return 0;
362     }
363     pa_log_info("Got BT SCO connected device(%u)", bt_device->id);
364
365     if (pa_tz_device_sco_get_status(bt_device, &sco_status) < 0) {
366         pa_log_error("get BT SCO status failed");
367         return -1;
368     }
369     if (sco_status == DM_DEVICE_BT_SCO_STATUS_CONNECTED) {
370         pa_log_warn("BT SCO is already closed for this BT device");
371         return 0;
372     }
373
374     pa_tz_device_sco_enable_pcm(bt_device, false);
375
376     if (delayed_close) {
377         /* request to close SCO after 3 sec. */
378         if (!u->time_event_bt_sco_close) {
379             u->time_event_bt_sco_close = pa_core_rttime_new(u->core, pa_rtclock_now() + TIMED_BT_SCO_CLOSE_USEC, timed_bt_sco_close_cb, u);
380             pa_log_debug("Append time event to close BT SCO");
381         }
382     } else {
383         if (u->time_event_bt_sco_close) {
384             u->core->mainloop->time_free(u->time_event_bt_sco_close);
385             u->time_event_bt_sco_close = NULL;
386         }
387         if (pa_tz_device_sco_close(bt_device) < 0) {
388             pa_log_error("BT SCO was opened, but failed to close SCO");
389             return -1;
390         }
391         pa_log_debug("BT SCO is now closed");
392     }
393
394     return 0;
395 }
396
397 /* Open/Close BT SCO if it is possible */
398 static int update_bt_sco_state(struct userdata *u, bool open, bool delayed_close, const char *role) {
399     pa_assert(u);
400
401     if (open)
402         return bt_sco_open(u, role);
403     else
404         return bt_sco_close(u, delayed_close);
405 }
406
407 static int get_bt_property(pa_device_manager *dm, bool *is_wb, bool *is_nrec) {
408     dm_device_bt_sco_status_t sco_status;
409     pa_tz_device *bt_device;
410
411     pa_assert(dm);
412     pa_assert(is_wb);
413     pa_assert(is_nrec);
414
415     bt_device = _get_sco_connected_device(dm);
416     if (bt_device == NULL) {
417         pa_log_error("No SCO connected bt device");
418         return -1;
419     }
420     if (pa_tz_device_sco_get_status(bt_device, &sco_status) < 0) {
421         pa_log_error("get BT SCO status failed");
422         return -1;
423     }
424
425     pa_log_info("Got BT SCO connected device(%u), status(%d)", bt_device->id, sco_status);
426     if (sco_status == DM_DEVICE_BT_SCO_STATUS_CONNECTED)
427         return -1;
428
429     return pa_tz_device_sco_get_property(bt_device, is_wb, is_nrec);
430 }
431
432 static void update_bt_sco_option(struct userdata *u, const char* role) {
433     bool is_wb = false;
434     bool is_nrec = false;
435
436     pa_assert(u);
437     pa_assert(role);
438
439     if (get_bt_property(u->device_manager, &is_wb, &is_nrec) == 0) {
440         pa_log_info("bt property : wideband(%d), nrec(%d)", is_wb, is_nrec);
441         UPDATE_HAL_ROUTE_OPTION(u->hal_interface, role, "bt-wideband", (int)is_wb);
442         UPDATE_HAL_ROUTE_OPTION(u->hal_interface, role, "bt-nrec", (int)is_nrec);
443     } else {
444         pa_log_warn("Failed to get property for wideband / nrec....");
445     }
446 }
447
448 /* Load/Unload module-loopback */
449 static void update_loopback_module(struct userdata *u, bool load) {
450     char *args = NULL;
451     const char *volume_type;
452
453     pa_assert(u);
454
455     if (load && u->loopback_args.sink && u->loopback_args.source) {
456         if (!u->loopback_args.latency_msec)
457             u->loopback_args.latency_msec = LOOPBACK_DEFAULT_LATENCY_MSEC;
458         if (!u->loopback_args.adjust_sec)
459             u->loopback_args.adjust_sec = LOOPBACK_DEFAULT_ADJUST_SEC;
460
461         volume_type = pa_stream_manager_get_volume_type(u->stream_manager, STREAM_SINK_INPUT, STREAM_ROLE_LOOPBACK);
462         args = pa_sprintf_malloc("sink=%s source=%s latency_msec=%d adjust_time=%d sink_input_properties=%s=%s",
463                                  u->loopback_args.sink->name, u->loopback_args.source->name,
464                                  u->loopback_args.latency_msec, u->loopback_args.adjust_sec,
465                                  PA_PROP_MEDIA_TIZEN_VOLUME_TYPE, volume_type);
466         if (u->module_loopback)
467             pa_module_unload(u->module_loopback, true);
468
469         if (pa_module_load(&u->module_loopback, u->core, MODULE_LOOPBACK, args))
470             pa_log_error("failed to load module-loopback with (%s)", args);
471         else
472             pa_log_info("  -- load module-loopback with (%s)", args);
473         pa_xfree(args);
474
475     } else if (!load) {
476         if (u->module_loopback) {
477             pa_module_unload(u->module_loopback, true);
478             u->module_loopback = NULL;
479             u->loopback_args.sink = NULL;
480             u->loopback_args.source = NULL;
481             pa_log_info("  -- unload module-loopback");
482         }
483     } else {
484         pa_log_error("  -- failed to update loopback module");
485     }
486 }
487
488 static pa_sink *load_combine_sink_module(struct userdata *u, const char *combine_sink_name, pa_sink *sink1, pa_sink *sink2, pa_sink_input *stream)
489 {
490     pa_module **combine_sink_module = NULL;
491     pa_sink *sink;
492     pa_sink_input *i;
493
494     pa_assert(u);
495     pa_assert(combine_sink_name);
496     pa_assert(sink1);
497     pa_assert(sink2);
498
499     if (pa_safe_streq(combine_sink_name, SINK_NAME_COMBINED)) {
500         combine_sink_module = &u->module_combine_sink;
501     } else if (pa_safe_streq(combine_sink_name, SINK_NAME_COMBINED_EX)) {
502         combine_sink_module = &u->module_combine_sink_for_ex;
503     } else {
504         pa_log_error("unknown combine_sink_name(%s)", combine_sink_name);
505         return NULL;
506     }
507
508     if (!*combine_sink_module) {
509         char *args = pa_sprintf_malloc("sink_name=%s slaves=\"%s,%s\"", combine_sink_name, sink1->name, sink2->name);
510         pa_log_info("load combine sink module[%s]", args);
511         /* FIXME: load combine module per each stream role. */
512         if (pa_module_load(combine_sink_module, u->core, MODULE_COMBINE_SINK, args))
513             pa_log_error("failed to load module-combine-sink with args(%s)", args);
514         pa_xfree(args);
515     }
516
517     sink = (pa_sink *)pa_namereg_get(u->core, combine_sink_name, PA_NAMEREG_SINK);
518     if (!sink) {
519         pa_log_error("failed to pa_namereg_get() for [%s]", combine_sink_name);
520         return NULL;
521     }
522
523     sink->use_internal_codec = pa_safe_streq(combine_sink_name, SINK_NAME_COMBINED);
524
525     if (stream) {
526         if ((i = pa_idxset_get_by_data(sink1->inputs, stream, NULL)) ||
527             (i = pa_idxset_get_by_data(sink2->inputs, stream, NULL))) {
528             pa_sink_input_move_to(i, sink, false);
529             pa_log_info("*** sink-input(%p,%u) moves to sink(%p,%s)", i, i->index, sink, sink->name);
530         }
531     }
532
533     return sink;
534 }
535
536 static void unload_combine_sink_module(struct userdata *u, const char *combine_sink_name, pa_sink *dst_sink)
537 {
538     pa_module **combine_sink_module = NULL;
539     pa_sink *combine_sink = NULL;
540     pa_sink_input *s = NULL;
541     uint32_t idx = 0;
542
543     pa_assert(u);
544     pa_assert(combine_sink_name);
545     pa_assert(dst_sink);
546
547     if (pa_safe_streq(combine_sink_name, SINK_NAME_COMBINED)) {
548         combine_sink_module = &u->module_combine_sink;
549     } else if (pa_safe_streq(combine_sink_name, SINK_NAME_COMBINED_EX)) {
550         combine_sink_module = &u->module_combine_sink_for_ex;
551     } else {
552         pa_log_error("unknown combine_sink_name(%s)", combine_sink_name);
553         return;
554     }
555
556     if (!*combine_sink_module) {
557         pa_log_warn("module combine sink(%s) has been already unloaded", combine_sink_name);
558         return;
559     }
560
561     combine_sink = (pa_sink*)pa_namereg_get(u->core, combine_sink_name, PA_NAMEREG_SINK);
562     if (!combine_sink) {
563         pa_log_error("could not get combine_sink(%s)", combine_sink_name);
564     } else {
565         PA_IDXSET_FOREACH(s, combine_sink->inputs, idx) {
566             pa_sink_input_move_to(s, dst_sink, false);
567             pa_log_info("*** sink-input(%p,%u) of (%s) moves to another sink(%p,%s)",
568                             s, ((pa_sink_input*)s)->index, combine_sink_name, dst_sink, dst_sink->name);
569         }
570         pa_sink_suspend(combine_sink, true, PA_SUSPEND_USER);
571     }
572
573     pa_log_info("unload combine sink module[%s]", combine_sink_name);
574     pa_module_unload(*combine_sink_module, true);
575     *combine_sink_module = NULL;
576 }
577
578 static bool skip_device(const char *stream_role, const char *device_type)
579 {
580     int sound_on = 1;
581
582     if (pa_safe_streq(device_type, DEVICE_TYPE_FORWARDING))
583         return true;
584
585     /* get sound profile */
586     if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &sound_on) < 0) {
587         pa_log_error("failed to get vconf - sound status");
588         return false;
589     }
590
591     if (!sound_on && IS_ROLE_RINGTONE(stream_role) && pa_safe_streq(device_type, DEVICE_TYPE_SPEAKER)) {
592         pa_log_info("sound status is 0 with ringtone-call stream, skip built-in speaker");
593         return true;
594     }
595
596     return false;
597 }
598
599 static bool skip_bt_sco_device(struct userdata *u, const char *stream_role, const char *device_type) {
600     pa_assert(u);
601     pa_assert(stream_role);
602     pa_assert(device_type);
603
604     if (pa_safe_streq(stream_role, STREAM_ROLE_VOICE_INFORMATION) && pa_safe_streq(device_type, DEVICE_TYPE_BT_SCO)) {
605         if (!is_bt_sco_connected(u->device_manager)) {
606             pa_log_warn("It is VOICE_INFORMATION, BT SCO is not connected, skip this device");
607             return true;
608         }
609         if (is_bt_sco_opened(u->device_manager)) {
610             /* remove the request of closing SCO */
611             if (u->time_event_bt_sco_close) {
612                 u->core->mainloop->time_free(u->time_event_bt_sco_close);
613                 u->time_event_bt_sco_close = NULL;
614             }
615             pa_log_info("It is VOICE_INFORMATION, BT SCO is already opened, use BT SCO");
616             return false;
617         } else if (!is_bt_a2dp_connected(u->device_manager)) {
618             pa_log_info("It is VOICE_INFORMATION, BT SCO is connected, BT A2DP is not available, use BT SCO");
619             return false;
620         } else {
621             pa_log_info("It is VOICE_INFORMATION, BT SCO is not opened, skip this device");
622             return true;
623         }
624     }
625
626     return false;
627 }
628
629 static bool is_supported_stream_role_for_usb(const char *role) {
630     pa_assert(role);
631
632     if (pa_safe_streq(STREAM_ROLE_MEDIA, role))
633         return true;
634
635     pa_log_error("not supported role for usb(%s)", role);
636
637     return false;
638 }
639
640 static bool skip_usb_device(const char *stream_role, pa_tz_device *device) {
641     char *specified_stream_role;
642
643     pa_assert(stream_role);
644     pa_assert(device);
645
646     if (!pa_safe_streq(pa_tz_device_get_type(device), DEVICE_TYPE_USB_AUDIO))
647         return false;
648
649     if (!(specified_stream_role = pa_tz_device_get_specified_stream_role(device)))
650         return false;
651
652     if (is_supported_stream_role_for_usb(specified_stream_role) &&
653         pa_safe_streq(stream_role, specified_stream_role))
654         return false;
655
656     pa_log_info("skip this usb device, stream role(%s), specified stream role(%s)", stream_role, specified_stream_role);
657
658     return true;
659 }
660
661 static inline bool is_cached_device_connected(const char* device_type, stream_type_t stream_type) {
662     if (cached_connected_devices[convert_device_type_str(device_type)][CONVERT_TO_DEVICE_DIRECTION(stream_type)-1] > 0)
663         return true;
664     return false;
665 }
666
667 static int32_t select_device_by_preemptive_device(struct userdata *u, pa_stream_manager_hook_data_for_select *data) {
668     uint32_t dm_device_id = 0;
669     pa_tz_device *device = NULL;
670     const char *device_type;
671
672     pa_assert(u);
673     pa_assert(data);
674
675     if (pa_stream_manager_get_preemptive_device_id(u->stream_manager, data->stream_type, data->stream_role, &dm_device_id))
676         return -1;
677
678     device = pa_device_manager_get_device_by_id(u->device_manager, dm_device_id);
679     device_type = pa_tz_device_get_type(device);
680     pa_log_debug("preemptive device is type:[%s] id:[%u]", device_type, dm_device_id);
681     if (data->stream_type == STREAM_SINK_INPUT)
682         *(data->proper_sink) = pa_tz_device_get_sink(device, data->device_role);
683     else
684         *(data->proper_source) = pa_tz_device_get_source(device, data->device_role);
685
686     if (data->origins_from_new_data)
687         pa_proplist_sets(GET_STREAM_NEW_PROPLIST(data->stream, data->stream_type),
688                          PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, device_type);
689     else
690         pa_proplist_sets(GET_STREAM_PROPLIST(data->stream, data->stream_type),
691                          PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, device_type);
692
693     return 0;
694 }
695
696 static void select_device_by_auto_or_auto_all_routing(struct userdata *u, pa_stream_manager_hook_data_for_select *data, pa_idxset *conn_devices)  {
697     const char *device_type = NULL;
698     uint32_t idx = 0;
699     uint32_t conn_idx = 0;
700     uint32_t dm_device_id = 0;
701     const char *dm_device_type = NULL;
702     dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
703     pa_tz_device *device = NULL;
704
705     pa_assert(u);
706     pa_assert(data);
707     pa_assert(conn_devices);
708
709     if (data->route_type == STREAM_ROUTE_TYPE_AUTO) {
710         if (!select_device_by_preemptive_device(u, data))
711             return;
712     }
713
714     PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
715         pa_log_debug("[SELECT][AUTO(_ALL)] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
716         if (!is_cached_device_connected(device_type, data->stream_type))
717             continue;
718
719         PA_IDXSET_FOREACH(device, conn_devices, conn_idx) {
720             dm_device_type = pa_tz_device_get_type(device);
721             dm_device_direction = pa_tz_device_get_direction(device);
722             dm_device_id = pa_tz_device_get_id(device);
723             pa_log_debug("  -- type[%-16s], direction[0x%x], id[%u]",
724                             dm_device_type, dm_device_direction, dm_device_id);
725             if (!pa_safe_streq(device_type, dm_device_type) || !IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction))
726                 continue;
727             pa_log_info("  ** found a matched device: type[%-16s], direction[0x%x]", dm_device_type, dm_device_direction);
728             if (skip_bt_sco_device(u, data->stream_role, dm_device_type))
729                 continue;
730             if (skip_usb_device(data->stream_role, device))
731                 continue;
732
733             if (data->stream_type == STREAM_SINK_INPUT) {
734                 if (data->origins_from_new_data) {
735                     if (data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL && u->module_combine_sink) {
736                         *(data->proper_sink) = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK);
737                         pa_log_info("  -- found the combine-sink, set it to the sink");
738                     } else {
739                         *(data->proper_sink) = pa_tz_device_get_sink(device, data->device_role);
740                     }
741                 } else {
742                     if (data->route_type == STREAM_ROUTE_TYPE_AUTO)
743                         data->new_sink = pa_tz_device_get_sink(device, data->device_role);
744                 }
745             } else {
746                 if (data->origins_from_new_data) {
747                     *(data->proper_source) = pa_tz_device_get_source(device, data->device_role);
748                 } else {
749                     if (data->route_type == STREAM_ROUTE_TYPE_AUTO)
750                         data->new_source = pa_tz_device_get_source(device, data->device_role);
751                 }
752             }
753             if (data->route_type == STREAM_ROUTE_TYPE_AUTO) {
754                 if (data->origins_from_new_data)
755                     pa_proplist_sets(GET_STREAM_NEW_PROPLIST(data->stream, data->stream_type),
756                                      PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type);
757                 else
758                     pa_proplist_sets(GET_STREAM_PROPLIST(data->stream, data->stream_type),
759                                      PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type);
760                 return;
761             }
762         }
763     }
764 }
765
766 static void select_device_by_auto_last_connected_routing(struct userdata *u, pa_stream_manager_hook_data_for_select *data, pa_idxset *conn_devices) {
767     const char *device_type = NULL;
768     pa_tz_device *latest_device = NULL;
769     const char *latest_device_type = NULL;
770     pa_tz_device *device = NULL;
771     uint32_t idx = 0;
772     uint32_t conn_idx = 0;
773     uint32_t dm_device_id = 0;
774     const char *dm_device_type = NULL;
775     dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
776     pa_usec_t creation_time = 0;
777     pa_usec_t latest_creation_time = 0;
778
779     pa_assert(u);
780     pa_assert(data);
781     pa_assert(conn_devices);
782
783     if (!select_device_by_preemptive_device(u, data))
784         return;
785
786     PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
787         pa_log_debug("[SELECT][AUTO_LAST_CONN] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
788         if (!is_cached_device_connected(device_type, data->stream_type))
789             continue;
790
791         PA_IDXSET_FOREACH(device, conn_devices, conn_idx) {
792             dm_device_type = pa_tz_device_get_type(device);
793             dm_device_direction = pa_tz_device_get_direction(device);
794             dm_device_id = pa_tz_device_get_id(device);
795             creation_time = pa_tz_device_get_creation_time(device);
796             pa_log_debug("  -- type[%-16s], direction[0x%x], id[%u], creation_time[%llu]",
797                             dm_device_type, dm_device_direction, dm_device_id, creation_time);
798             if (!pa_safe_streq(device_type, dm_device_type) || !IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction))
799                 continue;
800             if (skip_bt_sco_device(u, data->stream_role, dm_device_type))
801                 continue;
802             if (skip_usb_device(data->stream_role, device))
803                 continue;
804
805             if (!latest_device || (latest_creation_time <= creation_time)) {
806                 if (device_type_is_builtin(dm_device_type) && pa_safe_streq(latest_device_type, dm_device_type)) {
807                     pa_log_info("%s %s", latest_device_type, dm_device_type);
808                     if (data->stream_type == STREAM_SINK_INPUT ?
809                                                     (void*)pa_tz_device_get_sink(latest_device, data->device_role) :
810                                                     (void*)pa_tz_device_get_source(latest_device, data->device_role))
811                         continue;
812                 }
813                 latest_device = device;
814                 latest_creation_time = creation_time;
815                 latest_device_type = dm_device_type;
816                 pa_log_info("  ** updated the last connected device: type[%-16s], direction[0x%x]", dm_device_type, dm_device_direction);
817             }
818         }
819     }
820     /* update active device info. */
821     if (latest_device) {
822         dm_device_type = pa_tz_device_get_type(latest_device);
823         if (data->origins_from_new_data) {
824             if (data->stream_type == STREAM_SINK_INPUT)
825                 *(data->proper_sink) = pa_tz_device_get_sink(latest_device, data->device_role);
826             else
827                 *(data->proper_source) = pa_tz_device_get_source(latest_device, data->device_role);
828         } else {
829             if (data->stream_type == STREAM_SINK_INPUT)
830                 data->new_sink = pa_tz_device_get_sink(latest_device, data->device_role);
831             else
832                 data->new_source = pa_tz_device_get_source(latest_device, data->device_role);
833         }
834         if (data->origins_from_new_data)
835             pa_proplist_sets(GET_STREAM_NEW_PROPLIST(data->stream, data->stream_type),
836                                 PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type);
837         else
838             pa_proplist_sets(GET_STREAM_PROPLIST(data->stream, data->stream_type),
839                                 PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type);
840     }
841 }
842
843 static void select_device_by_manual_routing(struct userdata *u, pa_stream_manager_hook_data_for_select *data, pa_sink *null_sink, pa_source *null_source) {
844     const char *device_type = NULL;
845     pa_tz_device *device = NULL;
846     uint32_t *device_id = NULL;
847     uint32_t idx = 0;
848     uint32_t m_idx = 0;
849     const char *dm_device_type = NULL;
850     dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
851
852     pa_assert(u);
853     pa_assert(data);
854     pa_assert(null_sink);
855     pa_assert(null_source);
856
857     PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
858         pa_log_info("[SELECT][MANUAL] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
859         if (!is_cached_device_connected(device_type, data->stream_type))
860             continue;
861
862         PA_IDXSET_FOREACH(device_id, data->idx_manual_devices, m_idx) {
863             if (!(device = pa_device_manager_get_device_by_id(u->device_manager, *device_id)))
864                 continue;
865             dm_device_type = pa_tz_device_get_type(device);
866             dm_device_direction = pa_tz_device_get_direction(device);
867             pa_log_debug("  -- type[%-16s], direction[0x%x], device id[%u]",
868                             dm_device_type, dm_device_direction, *device_id);
869             if (!pa_safe_streq(device_type, dm_device_type) || !IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction))
870                 continue;
871             pa_log_info("  ** found a matched device: type[%-16s], direction[0x%x]", device_type, dm_device_direction);
872             if (data->stream_type == STREAM_SINK_INPUT) {
873                 if ((*(data->proper_sink)) == null_sink)
874                     pa_sink_input_move_to((pa_sink_input*)(data->stream), pa_tz_device_get_sink(device, data->device_role), false);
875                 else
876                     *(data->proper_sink) = pa_tz_device_get_sink(device, data->device_role);
877             } else {
878                 if ((*(data->proper_source)) == null_source)
879                     pa_source_output_move_to((pa_source_output*)(data->stream), pa_tz_device_get_source(device, data->device_role), false);
880                 else
881                     *(data->proper_source) = pa_tz_device_get_source(device, data->device_role);
882             }
883         }
884     }
885 }
886
887 static void select_device_by_manual_external_routing(struct userdata *u, pa_stream_manager_hook_data_for_select *data) {
888     const char *device_type = NULL;
889     pa_tz_device *device = NULL;
890     uint32_t *device_id = NULL;
891     uint32_t idx = 0;
892     uint32_t m_idx = 0;
893     const char *dm_device_type = NULL;
894     dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
895     pa_sink *sink = NULL;
896     pa_source *source = NULL;
897     pa_sink *combine_sink_arg1 = NULL;
898     pa_sink *combine_sink_arg2 = NULL;
899
900     pa_assert(u);
901     pa_assert(data);
902
903     PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
904         pa_log_info("[SELECT][MANUAL_EXT] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
905         if (!is_cached_device_connected(device_type, data->stream_type))
906             continue;
907
908         PA_IDXSET_FOREACH(device_id, data->idx_manual_devices, m_idx) {
909             if (!(device = pa_device_manager_get_device_by_id(u->device_manager, *device_id)))
910                 continue;
911             dm_device_type = pa_tz_device_get_type(device);
912             dm_device_direction = pa_tz_device_get_direction(device);
913             pa_log_debug("  -- type[%-16s], direction[0x%x], device id[%u]", dm_device_type, dm_device_direction, *device_id);
914             if (!pa_safe_streq(device_type, dm_device_type) || !IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction))
915                 continue;
916             pa_log_info("  ** found a matched device: type[%-16s], direction[0x%x]", device_type, dm_device_direction);
917             /* currently, we support two sinks for combining */
918             if (data->stream_type == STREAM_SINK_INPUT) {
919                 if (!combine_sink_arg1) {
920                     if ((sink = combine_sink_arg1 = pa_tz_device_get_sink(device, NULL)))
921                         pa_log_info("  -- combine_sink_arg1[%s], combine_sink_arg2[%p]", sink->name, combine_sink_arg2);
922                     else
923                         pa_log_warn("  -- could not get combine_sink_arg1");
924                 } else if (!combine_sink_arg2) {
925                     sink = combine_sink_arg2 = pa_tz_device_get_sink(device, NULL);
926                     if (sink && !pa_safe_streq(sink->name, combine_sink_arg1->name)) {
927                         pa_log_info("  -- combine_sink_arg2[%s]", sink->name);
928                         sink = load_combine_sink_module(u, SINK_NAME_COMBINED_EX, combine_sink_arg1, combine_sink_arg2, data->stream);
929
930                     } else if (!sink) {
931                         pa_log_warn("  -- could not get combine_sink_arg2");
932                     }
933                 }
934                 if (data->origins_from_new_data)
935                     *(data->proper_sink) = sink;
936                 else {
937                     if (((pa_sink_input*)(data->stream))->sink != sink)
938                         pa_sink_input_move_to(data->stream, sink, false);
939                 }
940                 continue;
941             }
942             /* source-output case */
943             if ((source = pa_tz_device_get_source(device, NULL))) {
944                 if (data->origins_from_new_data)
945                     *(data->proper_source) = source;
946                 else {
947                     if (((pa_source_output*)(data->stream))->source != source)
948                         pa_source_output_move_to(data->stream, source, false);
949                 }
950             }
951         }
952     }
953 }
954
955 /* Set the proper sink(source) according to the data of the parameter.
956  * - ROUTE_TYPE_AUTO(_ALL)
957  *     1. Find the proper sink/source comparing between avail_devices
958  *       and current connected devices.
959  *     2. If not found, set it to null sink/source.
960  * - ROUTE_TYPE_MANUAL(_EXT)
961  *     1. Find the proper sink/source comparing between avail_devices
962  *        and manual_devices that have been set by user.
963  *     2. If not found, set it to null sink/source. */
964 static pa_hook_result_t select_proper_sink_or_source_hook_cb(pa_core *c, pa_stream_manager_hook_data_for_select *data, struct userdata *u) {
965     pa_idxset *conn_devices = NULL;
966     pa_sink *null_sink = NULL;
967     pa_source *null_source = NULL;
968
969     pa_assert(c);
970     pa_assert(data);
971     pa_assert(u);
972
973     pa_log_info("[SELECT] data(%p), stream_type(%d), stream_role(%s), device_role(%s), route_type(%d)",
974                 data, data->stream_type, data->stream_role, data->device_role, data->route_type);
975
976     null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_NULL, PA_NAMEREG_SINK);
977     null_source = (pa_source*)pa_namereg_get(u->core, SOURCE_NAME_NULL, PA_NAMEREG_SOURCE);
978     if (!null_sink || !null_source) {
979         pa_log_error("[SELECT] could not get null_sink(%p) or null_source(%p)", null_sink, null_source);
980         return PA_HOOK_OK;
981     }
982
983     /* check if the current occupying role is related to call.
984      * some targets use several pcm card as per their purpose.
985      * e.g) using a specific pcm card during voice call. */
986     if (data->occupying_role) {
987         if (IS_ROLE_COMMUNICATION(data->occupying_role)) {
988             CONVERT_TO_DEVICE_ROLE(data->occupying_role, data->device_role);
989             pa_log_info("[SELECT] current occupying stream role is [%s], set device role to [%s]", data->occupying_role, data->device_role);
990         }
991     }
992
993     if (!data->idx_avail_devices) {
994         pa_log_error("[SELECT] available devices is NULL, set it to null sink/source");
995         goto not_found;
996     }
997
998     if (IS_MANUAL_ROUTE_TYPE_SERIES(data->route_type) && !data->idx_manual_devices) {
999         pa_log_error("[SELECT] manual devices is NULL, set it to null sink/source");
1000         goto not_found;
1001     }
1002
1003     if (IS_AUTO_ROUTE_TYPE_SERIES(data->route_type)) {
1004         /* get current connected devices */
1005         conn_devices = pa_device_manager_get_device_list(u->device_manager);
1006         if (data->route_type == STREAM_ROUTE_TYPE_AUTO || data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL)
1007             select_device_by_auto_or_auto_all_routing(u, data, conn_devices);
1008         else if (data->route_type == STREAM_ROUTE_TYPE_AUTO_LAST_CONNECTED)
1009             select_device_by_auto_last_connected_routing(u, data, conn_devices);
1010
1011     } else if (data->route_type == STREAM_ROUTE_TYPE_MANUAL) {
1012         select_device_by_manual_routing(u, data, null_sink, null_source);
1013
1014     } else if (data->route_type == STREAM_ROUTE_TYPE_MANUAL_EXT) {
1015         select_device_by_manual_external_routing(u, data);
1016     }
1017
1018 not_found:
1019     if (data->origins_from_new_data) {
1020         if ((data->stream_type == STREAM_SINK_INPUT) ? !(*(data->proper_sink)) : !(*(data->proper_source))) {
1021             pa_log_warn("[SELECT] could not find a proper sink/source, set it to null sink/source");
1022             if (data->stream_type == STREAM_SINK_INPUT)
1023                 *(data->proper_sink) = null_sink;
1024             else
1025                 *(data->proper_source) = null_source;
1026         }
1027     }
1028
1029     return PA_HOOK_OK;
1030 }
1031
1032 static void reset_route(struct userdata *u, stream_type_t stream_type) {
1033     hal_route_info route_info = {NULL, NULL, 0};
1034     pa_sink *null_sink = NULL;
1035
1036     pa_assert(u);
1037
1038     if (u->module_loopback) {
1039         if (stream_type == STREAM_SINK_INPUT && u->loopback_args.sink->use_internal_codec)
1040             update_loopback_module(u, false);
1041         else if (stream_type == STREAM_SOURCE_OUTPUT && u->loopback_args.source->use_internal_codec)
1042             update_loopback_module(u, false);
1043     }
1044
1045     /* update BT SCO: close */
1046     update_bt_sco_state(u, false, true, NULL);
1047
1048     /* unload combine sink */
1049     if (stream_type == STREAM_SINK_INPUT) {
1050         if (null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_NULL, PA_NAMEREG_SINK))
1051             unload_combine_sink_module(u, SINK_NAME_COMBINED, null_sink);
1052     }
1053
1054     route_info.role = "reset";
1055     route_info.num_of_devices = 1;
1056     route_info.device_infos = pa_xmalloc0(sizeof(hal_device_info)*route_info.num_of_devices);
1057     route_info.device_infos[0].direction = CONVERT_TO_HAL_DIRECTION(stream_type);
1058
1059     /* send information to HAL to update route */
1060     if (pa_hal_interface_update_route(u->hal_interface, &route_info))
1061         pa_log_error("[ROUTE] Failed to pa_hal_interface_update_route()");
1062
1063     pa_xfree(route_info.device_infos);
1064 }
1065
1066 /* Some H/W can have several alsa cards to serve various purposes. Therefore,
1067  * a particular stream may have to use a specific card, e.g) during voice call.
1068  * Here are codes to move streams to the specific device according to device role.
1069  * It has to be set only when the new_data is true - start routing of the new
1070  * highest priority stream. */
1071 static void route_change_move_streams(struct userdata *u, pa_stream_manager_hook_data_for_route *data, pa_tz_device *device) {
1072     const char *device_role;
1073     void *s = NULL;
1074     uint32_t idx = 0;
1075     pa_idxset *streams = NULL;
1076     pa_sink *sink = NULL;
1077     pa_sink *dst_sink = NULL;
1078     pa_source *source = NULL;
1079     pa_source *dst_source = NULL;
1080
1081     pa_assert(u);
1082     pa_assert(data);
1083
1084     /* if it's NOT from new_data, return here */
1085     if (!device || !data->origins_from_new_data)
1086         return;
1087     if (!data->stream)
1088         return;
1089     if (!IS_ROLE_COMMUNICATION(data->stream_role))
1090         return;
1091
1092     CONVERT_TO_DEVICE_ROLE(data->stream_role, device_role);
1093     pa_log_info("[ROUTE][MOVE] stream_role[%s], device role[%s]", data->stream_role, device_role);
1094     if (data->stream_type == STREAM_SINK_INPUT) {
1095         if (!(sink = pa_tz_device_get_sink(device, NULL)) ||
1096             !(dst_sink = pa_tz_device_get_sink(device, device_role)) ||
1097             sink == dst_sink) {
1098             pa_log_info("[ROUTE][MOVE][%s] no need to move streams, sink(%p), dst_sink(%p)", data->stream_role, sink, dst_sink);
1099             return;
1100         }
1101         streams = sink->inputs;
1102     } else if (data->stream_type == STREAM_SOURCE_OUTPUT) {
1103         if (!(source = pa_tz_device_get_source(device, NULL)) ||
1104             !(dst_source = pa_tz_device_get_source(device, device_role)) ||
1105             source == dst_source) {
1106             pa_log_info("[ROUTE][MOVE][%s] no need to move streams, source(%p), dst_source(%p)", data->stream_role, source, dst_source);
1107             return;
1108         }
1109         streams = source->outputs;
1110     }
1111
1112     if (!streams || (pa_idxset_size(streams) == 0))
1113         return;
1114
1115     /* move other streams that belong to the device of NORMAL role */
1116     PA_IDXSET_FOREACH(s, streams, idx) {
1117         if (data->stream_type == STREAM_SINK_INPUT) {
1118             pa_sink_input_move_to(s, dst_sink, false);
1119             pa_log_info("[ROUTE][MOVE][%s] *** sink-input(%p,%u) moves to sink(%p,%s)",
1120                          data->stream_role, s, ((pa_sink_input*)s)->index, dst_sink, dst_sink->name);
1121         } else if (data->stream_type == STREAM_SOURCE_OUTPUT) {
1122             pa_source_output_move_to(s, dst_source, false);
1123             pa_log_info("[ROUTE][MOVE][%s] *** source-output(%p,%u) moves to source(%p,%s)",
1124                          data->stream_role, s, ((pa_source_output*)s)->index, dst_source, dst_source->name);
1125         }
1126     }
1127     /* make sure the previous device is closed */
1128     if (data->stream_type == STREAM_SINK_INPUT)
1129         pa_sink_suspend(sink, true, PA_SUSPEND_INTERNAL);
1130     else if (data->stream_type == STREAM_SOURCE_OUTPUT)
1131         pa_source_suspend(source, true, PA_SUSPEND_INTERNAL);
1132 }
1133
1134 /* Some H/W can have several alsa cards to serve various purposes. Therefore,
1135  * a particular stream may have to use a specific card, e.g) during voice call.
1136  * Here are codes to depart from the above situation and move streams to the device
1137  * for rollback if needed only when the new_data is false - end of stream or
1138  * start routing of the new highest priority stream. */
1139 static void route_change_rollback_streams(struct userdata *u, pa_stream_manager_hook_data_for_route *data, pa_tz_device *device) {
1140     pa_sink *sink = NULL;
1141     pa_source *source = NULL;
1142     uint32_t idx = 0;
1143     void *s = NULL;
1144     pa_sink *combine_sink = NULL;
1145
1146     pa_assert(u);
1147     pa_assert(data);
1148
1149     /* if it's from new_data, return here */
1150     if (!device || data->origins_from_new_data)
1151         return;
1152     if (!data->stream || !data->idx_streams || pa_idxset_size(data->idx_streams) == 0)
1153         return;
1154     if (!IS_AUTO_ROUTE_TYPE_SERIES(data->route_type))
1155         return;
1156     if (data->stream_type == STREAM_SINK_INPUT) {
1157         if (!(sink = pa_tz_device_get_sink(device, data->device_role)))
1158             return;
1159         pa_sink_suspend(sink, false, PA_SUSPEND_INTERNAL);
1160     } else if (data->stream_type == STREAM_SOURCE_OUTPUT) {
1161         if (!(source = pa_tz_device_get_source(device, data->device_role)))
1162             return;
1163         pa_source_suspend(source, false, PA_SUSPEND_INTERNAL);
1164     }
1165
1166     PA_IDXSET_FOREACH(s, data->idx_streams, idx) {
1167         if (sink && sink != ((pa_sink_input*)s)->sink) {
1168             if ((pa_stream_manager_check_name_is_vstream(s, STREAM_SINK_INPUT, false)))
1169                 continue;
1170             if (((combine_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK)) &&
1171                 ((pa_sink_input*)s)->sink == combine_sink))
1172                 break;
1173             if ((pa_stream_manager_check_filter_apply_stream(s, STREAM_SINK_INPUT)))
1174                 continue;
1175             pa_sink_input_move_to(s, sink, false);
1176             pa_log_info("[ROUTE][ROLLBACK] *** sink-input(%p,%u) moves to sink(%p,%s)",
1177                          s, ((pa_sink_input*)s)->index, sink, sink->name);
1178         } else if (source && source != ((pa_source_output*)s)->source) {
1179             pa_source_output_move_to(s, source, false);
1180             pa_log_info("[ROUTE][ROLLBACK] *** source-output(%p,%u) moves to source(%p,%s)",
1181                          s, ((pa_source_output*)s)->index, source, source->name);
1182         }
1183     }
1184 }
1185
1186 static void fill_device_info(hal_route_info *route_info, const char *type, uint32_t direction, uint32_t id) {
1187     pa_assert(route_info);
1188     pa_assert(type);
1189
1190     route_info->num_of_devices++;
1191     route_info->device_infos = pa_xrealloc(route_info->device_infos, sizeof(hal_device_info)*route_info->num_of_devices);
1192     route_info->device_infos[route_info->num_of_devices-1].type = type;
1193     route_info->device_infos[route_info->num_of_devices-1].direction = direction;
1194     route_info->device_infos[route_info->num_of_devices-1].id = id;
1195     pa_log_info("  ** filled a matched device to device_infos[%d]: type[%-16s], direction[0x%x], id[%u]",
1196                 route_info->num_of_devices -1, type, direction, id);
1197 }
1198
1199 static pa_hook_result_t update_combine_sink_and_bt_sco(struct userdata *u, pa_stream_manager_hook_data_for_route *data,
1200                                                     pa_tz_device *device, const char *stream_role, const char *dm_device_type,
1201                                                     pa_sink **combine_sink_arg1, pa_sink **combine_sink_arg2) {
1202     pa_sink *sink = NULL;
1203
1204     pa_assert(u);
1205     pa_assert(data);
1206     pa_assert(device);
1207
1208     switch (data->route_type) {
1209     case STREAM_ROUTE_TYPE_AUTO: {
1210         /* unload combine sink */
1211         if (data->stream_type == STREAM_SINK_INPUT) {
1212             if ((sink = pa_tz_device_get_sink(device, data->device_role)))
1213                 unload_combine_sink_module(u, SINK_NAME_COMBINED, sink);
1214             else
1215                 pa_log_error("[ROUTE][AUTO] could not get sink");
1216         }
1217         if (pa_safe_streq(dm_device_type, DEVICE_TYPE_BT_SCO)) {
1218             if (IS_ROLE_AVAILABLE_BT_SCO_OPEN(stream_role)) {
1219                 if (update_bt_sco_state(u, true, false, stream_role)) {
1220                     pa_log_error("  ** could not open BT SCO");
1221                     return PA_HOOK_CANCEL;
1222                 }
1223                 update_bt_sco_option(u, stream_role);
1224             }
1225             return PA_HOOK_OK;
1226         }
1227         update_bt_sco_state(u, false, false, NULL);
1228         break;
1229     }
1230     case STREAM_ROUTE_TYPE_AUTO_ALL: {
1231         pa_source *source = NULL;
1232         uint32_t s_idx = 0;
1233         void *s = NULL;
1234         stream_route_type_t route_type;
1235
1236         update_bt_sco_state(u, false, false, NULL);
1237
1238         /* find the proper sink/source */
1239         /* currently, we support two sinks for combining */
1240         if (data->stream_type == STREAM_SINK_INPUT && u->module_combine_sink) {
1241             sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK);
1242             pa_log_info("[ROUTE][AUTO_ALL] found the combine_sink already existed");
1243
1244         } else if (data->stream_type == STREAM_SINK_INPUT && !*combine_sink_arg1) {
1245             sink = *combine_sink_arg1 = pa_tz_device_get_sink(device, data->device_role);
1246             if (sink)
1247                 pa_log_info("[ROUTE][AUTO_ALL] combine_sink_arg1[%s], combine_sink_arg2[%p]", sink->name, *combine_sink_arg2);
1248
1249         } else if (data->stream_type == STREAM_SINK_INPUT && !*combine_sink_arg2) {
1250             sink = *combine_sink_arg2 = pa_tz_device_get_sink(device, data->device_role);
1251             if (sink && !pa_safe_streq(sink->name, (*combine_sink_arg1)->name)) {
1252                 pa_log_info("[ROUTE][AUTO_ALL] combine_sink_arg2[%s]", sink->name);
1253                 sink = load_combine_sink_module(u, SINK_NAME_COMBINED, *combine_sink_arg1, *combine_sink_arg2, data->stream);
1254             }
1255
1256         } else if (data->stream_type == STREAM_SOURCE_OUTPUT) {
1257             source = pa_tz_device_get_source(device, data->device_role);
1258         }
1259
1260         if (data->origins_from_new_data) {
1261             if (data->stream_type == STREAM_SINK_INPUT)
1262                 *(data->proper_sink) = sink;
1263             else
1264                 *(data->proper_source) = source;
1265             break;
1266         }
1267         /* move sink-inputs/source-outputs if needed */
1268         if (!data->idx_streams)
1269             break;
1270         PA_IDXSET_FOREACH(s, data->idx_streams, s_idx) { /* data->idx_streams: null_sink */
1271             if (pa_stream_manager_get_route_type(s, data->stream_type, false, &route_type) ||
1272                 (route_type != STREAM_ROUTE_TYPE_AUTO_ALL))
1273                 continue;
1274             if ((data->stream_type == STREAM_SINK_INPUT) && (sink && (sink != ((pa_sink_input*)s)->sink))) {
1275                 pa_sink_input_move_to(s, sink, false);
1276                 pa_log_info("[ROUTE][AUTO_ALL] *** sink-input(%p,%u) moves to sink(%p,%s)",
1277                             s, ((pa_sink_input*)s)->index, sink, sink->name);
1278             } else if ((data->stream_type == STREAM_SOURCE_OUTPUT) && (source && (source != ((pa_source_output*)s)->source))) {
1279                 pa_source_output_move_to(s, source, false);
1280                 pa_log_info("[ROUTE][AUTO_ALL] *** source-output(%p,%u) moves to source(%p,%s)",
1281                             s, ((pa_source_output*)s)->index, source, source->name);
1282             }
1283         }
1284         break;
1285     }
1286     default:
1287         pa_log_error("it can not be here, route_type(%d)", data->route_type);
1288         break;
1289     }
1290     return PA_HOOK_OK;
1291 }
1292
1293 static int32_t update_route_by_preemptive_device(struct userdata *u, pa_stream_manager_hook_data_for_route *data, hal_route_info *route_info, pa_tz_device **device) {
1294     uint32_t dm_device_id = 0;
1295     const char *dm_device_type = NULL;
1296     bool use_internal_codec = false;
1297
1298     pa_assert(u);
1299     pa_assert(data);
1300     pa_assert(route_info);
1301     pa_assert(device);
1302
1303     if (pa_stream_manager_get_preemptive_device_id(u->stream_manager, data->stream_type, data->stream_role, &dm_device_id))
1304         return -1;
1305
1306     /* if this device id is no longer valid - disconnected. */
1307     if (!(*device = pa_device_manager_get_device_by_id(u->device_manager, dm_device_id)))
1308         return -1;
1309
1310     dm_device_type = pa_tz_device_get_type(*device);
1311     pa_log_debug("preemptive device is type:[%s] id:[%u]", dm_device_type, dm_device_id);
1312
1313     if (skip_usb_device(data->stream_role, *device))
1314         return -1;
1315
1316     if ((use_internal_codec = pa_tz_device_is_use_internal_codec(*device))) {
1317         /* if it needs to skip it, keep going to next device for proper UCM setting */
1318         if (skip_device(data->stream_role, dm_device_type))
1319             return -1;
1320         if (skip_bt_sco_device(u, data->stream_role, dm_device_type))
1321             return -1;
1322         fill_device_info(route_info, dm_device_type, CONVERT_TO_HAL_DIRECTION(data->stream_type), dm_device_id);
1323         return 0;
1324     }
1325
1326     return -1;
1327 }
1328
1329 static pa_hook_result_t handle_auto_or_auto_all_routing(struct userdata *u, pa_stream_manager_hook_data_for_route *data,
1330                                                         hal_route_info *route_info, pa_idxset *conn_devices, pa_tz_device **device) {
1331     const char *device_type = NULL;
1332     const char *dm_device_type = NULL;
1333     dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
1334     uint32_t dm_device_id = 0;
1335     uint32_t idx = 0;
1336     uint32_t conn_idx = 0;
1337     bool use_internal_codec = false;
1338     pa_sink *combine_sink_arg1 = NULL;
1339     pa_sink *combine_sink_arg2 = NULL;
1340
1341     pa_assert(u);
1342     pa_assert(data);
1343     pa_assert(route_info);
1344     pa_assert(conn_devices);
1345     pa_assert(device);
1346
1347     if (data->route_type == STREAM_ROUTE_TYPE_AUTO) {
1348         if (!update_route_by_preemptive_device(u, data, route_info, device)) {
1349             dm_device_type = pa_tz_device_get_type(*device);
1350             goto update_auto_active_dev;
1351         }
1352     }
1353
1354     PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
1355         pa_log_debug("[ROUTE][AUTO(_ALL)] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, route_info->role, device_type);
1356         if (!is_cached_device_connected(device_type, data->stream_type))
1357             continue;
1358
1359         PA_IDXSET_FOREACH(*device, conn_devices, conn_idx) {
1360             dm_device_type = pa_tz_device_get_type(*device);
1361             dm_device_direction = pa_tz_device_get_direction(*device);
1362             dm_device_id = pa_tz_device_get_id(*device);
1363             pa_log_debug("  -- type[%-16s], direction[0x%x], id[%u]",
1364                             dm_device_type, dm_device_direction, dm_device_id);
1365             if (!pa_safe_streq(device_type, dm_device_type) || !IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction))
1366                 continue;
1367             pa_log_debug("  ** found a matched device: type[%-16s], direction[0x%x]", dm_device_type, dm_device_direction);
1368             if (skip_usb_device(data->stream_role, *device))
1369                 continue;
1370             if ((use_internal_codec = pa_tz_device_is_use_internal_codec(*device))) {
1371                 /* if it needs to skip it, keep going to next device for proper UCM setting */
1372                 if (skip_device(data->stream_role, dm_device_type))
1373                     continue;
1374                 if (skip_bt_sco_device(u, data->stream_role, dm_device_type))
1375                     continue;
1376                 fill_device_info(route_info, dm_device_type, CONVERT_TO_HAL_DIRECTION(data->stream_type), dm_device_id);
1377                 break;
1378             }
1379             pa_log_debug("  -- it does not use internal audio codec, skip it");
1380             break;
1381         }
1382         if (*device == NULL)
1383             continue;
1384
1385         if (data->route_type == STREAM_ROUTE_TYPE_AUTO) {
1386 update_auto_active_dev:
1387             if (data->origins_from_new_data)
1388                 pa_proplist_sets(GET_STREAM_NEW_PROPLIST(data->stream, data->stream_type),
1389                                 PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type);
1390             else
1391                 pa_proplist_sets(GET_STREAM_PROPLIST(data->stream, data->stream_type),
1392                                 PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type);
1393             return update_combine_sink_and_bt_sco(u, data, *device, route_info->role, dm_device_type, NULL, NULL);
1394
1395         } else if (data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL) {
1396             update_combine_sink_and_bt_sco(u, data, *device, NULL, NULL, &combine_sink_arg1, &combine_sink_arg2);
1397         }
1398     }
1399     return PA_HOOK_OK;
1400 }
1401
1402 static pa_hook_result_t handle_auto_last_connected_routing(struct userdata *u, pa_stream_manager_hook_data_for_route *data,
1403                                                         hal_route_info *route_info, pa_idxset *conn_devices, pa_tz_device **device) {
1404     pa_tz_device *latest_device = NULL;
1405     const char *device_type = NULL;
1406     const char *latest_device_type = NULL;
1407     const char *dm_device_type = NULL;
1408     dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
1409     uint32_t dm_device_id = 0;
1410     uint32_t idx = 0;
1411     uint32_t conn_idx = 0;
1412     pa_usec_t creation_time = 0;
1413     pa_usec_t latest_creation_time = 0;
1414     bool use_internal_codec = false;
1415     pa_sink *sink = NULL;
1416
1417     pa_assert(u);
1418     pa_assert(data);
1419     pa_assert(route_info);
1420     pa_assert(conn_devices);
1421     pa_assert(device);
1422
1423     if (!update_route_by_preemptive_device(u, data, route_info, device)) {
1424         latest_device = *device;
1425         dm_device_type = pa_tz_device_get_type(*device);
1426         goto update_auto_active_dev;
1427     }
1428
1429     PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
1430         pa_log_debug("[ROUTE][AUTO_LAST_CONN] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
1431         if (!is_cached_device_connected(device_type, data->stream_type))
1432             continue;
1433
1434         PA_IDXSET_FOREACH(*device, conn_devices, conn_idx) {
1435             dm_device_type = pa_tz_device_get_type(*device);
1436             dm_device_direction = pa_tz_device_get_direction(*device);
1437             dm_device_id = pa_tz_device_get_id(*device);
1438             creation_time = pa_tz_device_get_creation_time(*device);
1439             pa_log_debug("  -- type[%-16s], direction[0x%x], id[%u], creation_time[%llu]",
1440                             dm_device_type, dm_device_direction, dm_device_id, creation_time);
1441             if (!pa_safe_streq(device_type, dm_device_type) || !IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction))
1442                 continue;
1443             if (skip_usb_device(data->stream_role, *device))
1444                 continue;
1445             if ((use_internal_codec = pa_tz_device_is_use_internal_codec(*device))) {
1446                 /* if it needs to skip it, keep going to next device for proper UCM setting */
1447                 if (skip_device(data->stream_role, dm_device_type) ||
1448                     skip_bt_sco_device(u, data->stream_role, dm_device_type))
1449                     continue;
1450             }
1451             if (!latest_device || (latest_creation_time <= creation_time)) {
1452                 if (device_type_is_builtin(dm_device_type) && pa_safe_streq(latest_device_type, dm_device_type)) {
1453                     if (data->stream_type == STREAM_SINK_INPUT ?
1454                                                     (void*)pa_tz_device_get_sink(latest_device, data->device_role) :
1455                                                     (void*)pa_tz_device_get_source(latest_device, data->device_role))
1456                         continue;
1457                 }
1458                 latest_device = *device;
1459                 latest_creation_time = creation_time;
1460                 latest_device_type = dm_device_type;
1461                 pa_log_info("  ** updated the last connected device: type[%-16s], direction[0x%x]", dm_device_type, dm_device_direction);
1462             }
1463         }
1464     }
1465     /* update activated device if it is found */
1466     if (latest_device) {
1467         dm_device_type = pa_tz_device_get_type(latest_device);
1468         dm_device_id = pa_tz_device_get_id(latest_device);
1469         if ((use_internal_codec = pa_tz_device_is_use_internal_codec(latest_device)))
1470             fill_device_info(route_info, dm_device_type, CONVERT_TO_HAL_DIRECTION(data->stream_type), dm_device_id);
1471         else
1472             pa_log_debug("  -- it does not use internal audio codec, skip it");
1473
1474 update_auto_active_dev:
1475         if (data->origins_from_new_data)
1476             pa_proplist_sets(GET_STREAM_NEW_PROPLIST(data->stream, data->stream_type),
1477                             PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type);
1478         else
1479             pa_proplist_sets(GET_STREAM_PROPLIST(data->stream, data->stream_type),
1480                             PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type);
1481
1482         /* unload combine sink */
1483         if (data->stream_type == STREAM_SINK_INPUT) {
1484             if ((sink = pa_tz_device_get_sink(latest_device, data->device_role)))
1485                 unload_combine_sink_module(u, SINK_NAME_COMBINED, sink);
1486             else
1487                 pa_log_error("[ROUTE][AUTO_LAST_CONN] could not get sink");
1488         }
1489
1490         if (pa_safe_streq(dm_device_type, DEVICE_TYPE_BT_SCO)) {
1491             if (IS_ROLE_AVAILABLE_BT_SCO_OPEN(route_info->role)) {
1492                 if (update_bt_sco_state(u, true, false, route_info->role)) {
1493                     pa_log_error("  ** could not open BT SCO");
1494                     return PA_HOOK_CANCEL;
1495                 }
1496                 update_bt_sco_option(u, route_info->role);
1497             }
1498         } else {
1499             update_bt_sco_state(u, false, false, NULL);
1500         }
1501
1502         /* Update device with latest_device to use be used later in this function */
1503         *device = latest_device;
1504     }
1505
1506     return PA_HOOK_OK;
1507 }
1508
1509 static pa_hook_result_t handle_manual_routing(struct userdata *u, pa_stream_manager_hook_data_for_route *data,
1510                                 hal_route_info *route_info, pa_tz_device **device) {
1511     const char *device_type = NULL;
1512     const char *dm_device_type = NULL;
1513     dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
1514     bool use_internal_codec = false;
1515     uint32_t idx = 0;
1516     uint32_t d_idx = 0;
1517     uint32_t *device_id = NULL;
1518
1519     pa_assert(u);
1520     pa_assert(data);
1521     pa_assert(route_info);
1522     pa_assert(device);
1523
1524     PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
1525         pa_log_info("[ROUTE][MANUAL] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
1526         if (!is_cached_device_connected(device_type, data->stream_type))
1527             continue;
1528
1529         PA_IDXSET_FOREACH(device_id, data->idx_manual_devices, d_idx) {
1530             pa_log_debug("  -- manual_device[%u] for this role[%-16s]: device_id(%u)", idx, data->stream_role, *device_id);
1531             if (!(*device = pa_device_manager_get_device_by_id(u->device_manager, *device_id)))
1532                 continue;
1533             dm_device_type = pa_tz_device_get_type(*device);
1534             if (!pa_safe_streq(device_type, dm_device_type))
1535                 continue;
1536             dm_device_direction = pa_tz_device_get_direction(*device);
1537             pa_log_debug("  ** found a matched device: type[%-16s], direction[0x%x]",
1538                             dm_device_type, dm_device_direction);
1539             /* Check for availability for opening Bluetooth SCO */
1540             if (pa_safe_streq(dm_device_type, DEVICE_TYPE_BT_SCO) && IS_ROLE_AVAILABLE_BT_SCO_OPEN(route_info->role)) {
1541                 /* update BT SCO: open */
1542                 if (update_bt_sco_state(u, true, false, route_info->role)) {
1543                     pa_log_error("  ** could not open BT SCO");
1544                     return PA_HOOK_CANCEL;
1545                 }
1546                 update_bt_sco_option(u, route_info->role);
1547             } else {
1548                 /* update BT SCO: close */
1549                 update_bt_sco_state(u, false, false, NULL);
1550             }
1551             /* Check for in/out devices in case of loopback */
1552             if (pa_safe_streq(data->stream_role, STREAM_ROLE_LOOPBACK)) {
1553                 if ((data->stream_type == STREAM_SINK_INPUT) && (dm_device_direction & DM_DEVICE_DIRECTION_OUT))
1554                     u->loopback_args.sink = pa_tz_device_get_sink(*device, NULL);
1555                 else if ((data->stream_type == STREAM_SOURCE_OUTPUT) && (dm_device_direction & DM_DEVICE_DIRECTION_IN))
1556                     u->loopback_args.source = pa_tz_device_get_source(*device, NULL);
1557             }
1558
1559             if (IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction)) {
1560                 if ((use_internal_codec = pa_tz_device_is_use_internal_codec(*device)))
1561                     fill_device_info(route_info, dm_device_type, CONVERT_TO_HAL_DIRECTION(data->stream_type), *device_id);
1562                 else
1563                     pa_log_debug("  -- it does not use internal audio codec, skip it");
1564             }
1565         }
1566     }
1567     if (pa_safe_streq(data->stream_role, STREAM_ROLE_LOOPBACK)) {
1568         /* load module-loopback */
1569         if (u->loopback_args.sink && u->loopback_args.source)
1570             update_loopback_module(u, true);
1571     }
1572
1573     return PA_HOOK_OK;
1574 }
1575
1576 /* Change the route setting according to the data from argument.
1577  * This function is called only when it needs to change routing path via HAL.
1578  * - stream is null
1579  *     1. It will be received when it is needed to terminate playback
1580  *       or capture routing path.
1581  *     2. Update the state of the device to be deactivated.
1582  *     3. Call HAL API to "reset" routing.
1583  * - ROUTE_TYPE_AUTO
1584  *     1. Find the proper sink/source comparing between avail_devices
1585  *       and current connected devices.
1586  *      : Need to check the priority of the device list by order of receipt.
1587  *     2. Update the state of devices.
1588  *     3. Call HAL API to apply the routing setting
1589  * - ROUTE_TYPE_AUTO_ALL
1590  *     1. Find the proper sink/source comparing between avail_devices
1591  *       and current connected devices.
1592  *      : Might use combine-sink according to the conditions.
1593  *     2. Update the state of devices.
1594  *     3. Call HAL API to apply the routing setting
1595  * - ROUTE_TYPE_MANUAL
1596  *     1. Find the proper sink/source comparing between avail_devices
1597  *        and manual_devices that have been set by user.
1598  *     2. Update the state of devices.
1599  *     3. Call HAL API to apply the routing setting. */
1600 static pa_hook_result_t route_change_hook_cb(pa_core *c, pa_stream_manager_hook_data_for_route *data, struct userdata *u) {
1601     hal_route_info route_info = {NULL, NULL, 0};
1602     pa_tz_device *device = NULL;
1603     pa_hook_result_t result;
1604
1605     pa_assert(c);
1606     pa_assert(data);
1607     pa_assert(u);
1608
1609     pa_log_info("[ROUTE] data(%p), stream_type(%d), stream_role(%s), route_type(%d)",
1610                 data, data->stream_type, data->stream_role, data->route_type);
1611
1612     if (data->stream == NULL) {
1613         reset_route(u, data->stream_type);
1614         pa_device_manager_update_device_running_state(u->device_manager,
1615                                                       0,
1616                                                       NULL,
1617                                                       (data->stream_type == STREAM_SINK_INPUT) ? true : false);
1618         return PA_HOOK_OK;
1619     }
1620
1621     if (!data->idx_avail_devices) {
1622         pa_log_error("[ROUTE] available devices is NULL, do nothing...");
1623         return PA_HOOK_OK;
1624     }
1625
1626     if (IS_MANUAL_ROUTE_TYPE_SERIES(data->route_type) && !data->idx_manual_devices) {
1627         pa_log_error("[ROUTE] manual devices is NULL, do nothing...");
1628         return PA_HOOK_OK;
1629     }
1630
1631     route_info.role = data->stream_role;
1632
1633     if (IS_AUTO_ROUTE_TYPE_SERIES(data->route_type)) {
1634         pa_idxset *conn_devices = NULL;
1635
1636         /* unload module-loopback */
1637         if (u->module_loopback) {
1638             if (data->stream_type == STREAM_SINK_INPUT && u->loopback_args.sink->use_internal_codec)
1639                 update_loopback_module(u, false);
1640             else if (data->stream_type == STREAM_SOURCE_OUTPUT && u->loopback_args.source->use_internal_codec)
1641                 update_loopback_module(u, false);
1642         }
1643
1644         /* get current connected devices */
1645         conn_devices = pa_device_manager_get_device_list(u->device_manager);
1646         if (data->route_type == STREAM_ROUTE_TYPE_AUTO || data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL) {
1647             if ((result = handle_auto_or_auto_all_routing(u, data, &route_info, conn_devices, &device)))
1648                 return result;
1649
1650         } else if (data->route_type == STREAM_ROUTE_TYPE_AUTO_LAST_CONNECTED) {
1651             if ((result = handle_auto_last_connected_routing(u, data, &route_info, conn_devices, &device)))
1652                 return result;
1653         }
1654
1655     } else if (data->route_type == STREAM_ROUTE_TYPE_MANUAL) {
1656         if ((result = handle_manual_routing(u, data, &route_info, &device)))
1657             return result;
1658     }
1659
1660     route_change_move_streams(u, data, device);
1661
1662     if (route_info.device_infos) {
1663         /* send information to HAL to update route */
1664         if (pa_hal_interface_update_route(u->hal_interface, &route_info))
1665             pa_log_error("[ROUTE] Failed to pa_hal_interface_update_route()");
1666         pa_device_manager_update_device_running_state(u->device_manager,
1667                                                       route_info.num_of_devices,
1668                                                       (pa_device_info*)route_info.device_infos,
1669                                                       (data->stream_type == STREAM_SINK_INPUT) ? true : false);
1670         pa_xfree(route_info.device_infos);
1671     }
1672
1673     route_change_rollback_streams(u, data, device);
1674
1675     return PA_HOOK_OK;
1676 }
1677
1678 static pa_hook_result_t update_info_hook_cb(pa_core *c, pa_stream_manager_hook_data_for_update_info *data, struct userdata *u) {
1679     pa_assert(c);
1680     pa_assert(data);
1681     pa_assert(u);
1682
1683     if (pa_safe_streq(data->stream_role, STREAM_ROLE_LOOPBACK)) {
1684         pa_log_info("[UPDATE] stream_role(%s) [name(%s)/value(%d)]", data->stream_role, data->name, data->value);
1685         if (pa_safe_streq(data->name, MSG_FOR_LOOPBACK_ARG_LATENCY))
1686             u->loopback_args.latency_msec = data->value;
1687         else if (pa_safe_streq(data->name, MSG_FOR_LOOPBACK_ARG_ADJUST_TIME))
1688             u->loopback_args.adjust_sec = data->value;
1689     }
1690
1691     return PA_HOOK_OK;
1692 }
1693
1694 /* Update ref. count of each connected device */
1695 static void update_cached_connected_devices(const char *device_type, dm_device_direction_t direction, bool is_connected) {
1696     int32_t val = 0;
1697     int* ptr_in = NULL;
1698     int* ptr_out = NULL;
1699
1700     ptr_in = &cached_connected_devices[convert_device_type_str(device_type)][CACHED_DEVICE_DIRECTION_IN];
1701     ptr_out = &cached_connected_devices[convert_device_type_str(device_type)][CACHED_DEVICE_DIRECTION_OUT];
1702     val = (is_connected) ? 1 : -1;
1703
1704     if (direction & DM_DEVICE_DIRECTION_IN)
1705         *ptr_in += val;
1706     if (direction & DM_DEVICE_DIRECTION_OUT)
1707         *ptr_out += val;
1708
1709     if (*ptr_in < 0)
1710         *ptr_in = 0;
1711     if (*ptr_out < 0)
1712         *ptr_out = 0;
1713 }
1714
1715 static void dump_connected_devices()
1716 {
1717 #if 0
1718     int32_t i = 0;
1719
1720     pa_log_debug("== dump cached current device ==");
1721     for (i = 0; i < DEVICE_MAX-1; i++)
1722         pa_log_debug("in: %d, out: %d", cached_connected_devices[i][CACHED_DEVICE_DIRECTION_IN], cached_connected_devices[i][CACHED_DEVICE_DIRECTION_OUT]);
1723     pa_log_debug("================================");
1724 #endif
1725 }
1726
1727 /* Reorganize routing when a device has been connected or disconnected */
1728 static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_tz_device_hook_data_for_conn_changed *conn, struct userdata *u) {
1729     uint32_t idx = 0;
1730     dm_device_direction_t device_direction = DM_DEVICE_DIRECTION_OUT;
1731     pa_sink *sink = NULL;
1732     pa_sink *null_sink = NULL;
1733     bool use_internal_codec = false;
1734     pa_idxset* conn_devices = NULL;
1735     pa_tz_device *device = NULL;
1736
1737     pa_assert(c);
1738     pa_assert(conn);
1739     pa_assert(u);
1740
1741     device_direction = pa_tz_device_get_direction(conn->device);
1742
1743     pa_log_info("[CONN] conn(%p), is_connected(%d), device(%p), direction(0x%x)",
1744                 conn, conn->is_connected, conn->device, device_direction);
1745
1746     update_cached_connected_devices(pa_tz_device_get_type(conn->device), device_direction, conn->is_connected);
1747     dump_connected_devices();
1748
1749     sink = null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_NULL, PA_NAMEREG_SINK);
1750     if (!null_sink) {
1751         pa_log_error("[CONN] could not get null_sink(%p)", null_sink);
1752         return PA_HOOK_OK;
1753     }
1754
1755     use_internal_codec = pa_tz_device_is_use_internal_codec(conn->device);
1756     /* update for unloading modules when external device is disconnected */
1757     if (!use_internal_codec && !conn->is_connected) {
1758         if (device_direction & DM_DEVICE_DIRECTION_OUT) {
1759            /* unload combine sink */
1760            conn_devices = pa_device_manager_get_device_list(u->device_manager);
1761             PA_IDXSET_FOREACH(device, conn_devices, idx) {
1762                 device_direction = pa_tz_device_get_direction(device);
1763                 if (device_direction == DM_DEVICE_DIRECTION_OUT) {
1764                     if ((use_internal_codec = pa_tz_device_is_use_internal_codec(device))) {
1765                         sink = pa_tz_device_get_sink(device, NULL);
1766                         break;
1767                     }
1768                 }
1769             }
1770             unload_combine_sink_module(u, SINK_NAME_COMBINED, sink);
1771
1772             /* unload combine sink for external devices */
1773             unload_combine_sink_module(u, SINK_NAME_COMBINED_EX, null_sink);
1774
1775             /* unload loopback module */
1776             if (u->module_loopback)
1777                 if (u->loopback_args.sink == pa_tz_device_get_sink(conn->device, NULL))
1778                     update_loopback_module(u, false);
1779         }
1780     if (device_direction & DM_DEVICE_DIRECTION_IN) {
1781         /* unload loopback module */
1782         if (u->module_loopback)
1783             if (u->loopback_args.source == pa_tz_device_get_source(conn->device, NULL))
1784                 update_loopback_module(u, false);
1785         }
1786     }
1787
1788     return PA_HOOK_OK;
1789 }
1790
1791 int pa__init(pa_module *m)
1792 {
1793     pa_modargs *ma = NULL;
1794     struct userdata *u;
1795     char *args = NULL;
1796     pa_module *module_loaded;
1797
1798     pa_assert(m);
1799
1800     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
1801         pa_log("Failed to parse module arguments");
1802         goto fail;
1803     }
1804
1805     m->userdata = u = pa_xnew0(struct userdata, 1);
1806     u->core = m->core;
1807     u->module = m;
1808     u->module_null_sink_index = PA_INVALID_INDEX;
1809     u->module_null_source_index = PA_INVALID_INDEX;
1810
1811     if (!(u->hal_interface = pa_hal_interface_get(u->core))) {
1812         pa_log("Failed to get hal interface");
1813         pa_modargs_free(ma);
1814         goto fail;
1815     }
1816
1817     if ((u->communicator.comm = pa_communicator_get(u->core))) {
1818         u->communicator.comm_hook_select_proper_sink_or_source_slot = pa_hook_connect(
1819                 pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_SELECT_INIT_SINK_OR_SOURCE),
1820                 PA_HOOK_EARLY, (pa_hook_cb_t)select_proper_sink_or_source_hook_cb, u);
1821         u->communicator.comm_hook_change_route_slot = pa_hook_connect(
1822                 pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_CHANGE_ROUTE),
1823                 PA_HOOK_EARLY, (pa_hook_cb_t)route_change_hook_cb, u);
1824         u->communicator.comm_hook_device_connection_changed_slot = pa_hook_connect(
1825                 pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_DEVICE_CONNECTION_CHANGED),
1826                 PA_HOOK_EARLY, (pa_hook_cb_t)device_connection_changed_hook_cb, u);
1827         u->communicator.comm_hook_update_info_slot = pa_hook_connect(
1828                 pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_UPDATE_INFORMATION),
1829                 PA_HOOK_EARLY, (pa_hook_cb_t)update_info_hook_cb, u);
1830     }
1831     u->device_manager = pa_device_manager_get(u->core);
1832     u->stream_manager = pa_stream_manager_get(u->core);
1833
1834     /* load null sink/source */
1835     args = pa_sprintf_malloc("sink_name=%s norewinds=1", SINK_NAME_NULL);
1836     if (pa_module_load(&module_loaded, u->core, MODULE_NULL_SINK, args))
1837         pa_log_error("failed to load module-null-sink");
1838     else
1839         u->module_null_sink_index = module_loaded->index;
1840     pa_xfree(args);
1841
1842     args = pa_sprintf_malloc("source_name=%s max_latency_msec=100", SOURCE_NAME_NULL);
1843     if (pa_module_load(&module_loaded, u->core, MODULE_NULL_SOURCE, args))
1844         pa_log_error("failed to load module-null-source");
1845     else
1846         u->module_null_source_index = module_loaded->index;
1847     pa_xfree(args);
1848
1849     __load_dump_config(u);
1850
1851     pa_log_info("Tizen Audio Policy module is loaded\n");
1852
1853     if (ma)
1854         pa_modargs_free(ma);
1855
1856     return 0;
1857
1858 fail:
1859     pa__done(m);
1860
1861     return -1;
1862 }
1863
1864 void pa__done(pa_module *m)
1865 {
1866     struct userdata* u;
1867
1868     pa_assert(m);
1869
1870     if (!(u = m->userdata))
1871         return;
1872
1873     bt_sco_close(u, false);
1874
1875     if (u->module_null_sink_index != PA_INVALID_INDEX)
1876         pa_module_unload_by_index(m->core, u->module_null_sink_index, true);
1877
1878     if (u->module_null_source_index != PA_INVALID_INDEX)
1879         pa_module_unload_by_index(m->core, u->module_null_source_index, true);
1880
1881     if (u->device_manager)
1882         pa_device_manager_unref(u->device_manager);
1883
1884     if (u->stream_manager)
1885         pa_stream_manager_unref(u->stream_manager);
1886
1887     if (u->communicator.comm) {
1888         if (u->communicator.comm_hook_select_proper_sink_or_source_slot)
1889             pa_hook_slot_free(u->communicator.comm_hook_select_proper_sink_or_source_slot);
1890         if (u->communicator.comm_hook_change_route_slot)
1891             pa_hook_slot_free(u->communicator.comm_hook_change_route_slot);
1892         if (u->communicator.comm_hook_device_connection_changed_slot)
1893             pa_hook_slot_free(u->communicator.comm_hook_device_connection_changed_slot);
1894         if (u->communicator.comm_hook_update_info_slot)
1895             pa_hook_slot_free(u->communicator.comm_hook_update_info_slot);
1896         pa_communicator_unref(u->communicator.comm);
1897     }
1898
1899     if (u->hal_interface)
1900         pa_hal_interface_unref(u->hal_interface);
1901
1902     pa_xfree(u);
1903
1904     pa_log_info("Tizen Audio Policy module is unloaded\n");
1905 }