policy: Add skip logic when selecting device 58/58058/3 accepted/tizen/common/20160202.165219 accepted/tizen/ivi/20160218.023854 accepted/tizen/mobile/20160128.082837 accepted/tizen/tv/20160128.082855 accepted/tizen/wearable/20160128.082917 submit/tizen/20160128.050738 submit/tizen_common/20160201.150530 submit/tizen_ivi/20160217.000000 submit/tizen_ivi/20160217.000003
authorSangchul Lee <sc11.lee@samsung.com>
Wed, 27 Jan 2016 08:09:48 +0000 (17:09 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Thu, 28 Jan 2016 01:43:57 +0000 (10:43 +0900)
[Version] 5.0.32
[Profile] Common
[Issue Type] Optimization

Change-Id: Iab182bf01abd3fc5eaba3dd697f4bf5fa4ac76a6

packaging/pulseaudio-modules-tizen.spec
src/module-policy.c

index f5f11fded5af692b4bf2f98a72427ac2c8b1b91f..1600e7009001486c1920cce3a83813fb3fc373fd 100644 (file)
@@ -1,6 +1,6 @@
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          5.0.31
+Version:          5.0.32
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index ba0818c579f242ddf12f027ef17473c518184390..751f1ed27cae8a03e6dad0ca3d7ae98c7c0acbb1 100644 (file)
@@ -231,6 +231,50 @@ enum signal_index {
 #define PA_DUMP_PLAYBACK_RESAMPLER_OUT          0x00000010
 #define PA_DUMP_CAPTURE_ENCODER_IN              0x80000000
 
+typedef enum _device_type {
+    DEVICE_BUILTIN_SPEAKER,
+    DEVICE_BUILTIN_RECEIVER,
+    DEVICE_BUILTIN_MIC,
+    DEVICE_AUDIO_JACK,
+    DEVICE_BT,
+    DEVICE_HDMI,
+    DEVICE_FORWARDING,
+    DEVICE_USB_AUDIO,
+    DEVICE_UNKNOWN,
+    DEVICE_MAX,
+} device_type_t;
+
+enum {
+    CACHED_DEVICE_DIRECTION_IN,
+    CACHED_DEVICE_DIRECTION_OUT,
+    CACHED_DEVICE_DIRECTION_MAX,
+};
+
+int cached_connected_devices[DEVICE_MAX][CACHED_DEVICE_DIRECTION_MAX];
+
+static device_type_t convert_device_type_str(const char *device)
+{
+    if (pa_streq(device, DEVICE_TYPE_SPEAKER))
+        return DEVICE_BUILTIN_SPEAKER;
+    else if (pa_streq(device, DEVICE_TYPE_RECEIVER))
+        return DEVICE_BUILTIN_RECEIVER;
+    else if (pa_streq(device, DEVICE_TYPE_MIC))
+        return DEVICE_BUILTIN_MIC;
+    else if (pa_streq(device, DEVICE_TYPE_AUDIO_JACK))
+        return DEVICE_AUDIO_JACK;
+    else if (pa_streq(device, DEVICE_TYPE_BT))
+        return DEVICE_BT;
+    else if (pa_streq(device, DEVICE_TYPE_HDMI))
+        return DEVICE_HDMI;
+    else if (pa_streq(device, DEVICE_TYPE_FORWARDING))
+        return DEVICE_FORWARDING;
+    else if (pa_streq(device, DEVICE_TYPE_USB_AUDIO))
+        return DEVICE_USB_AUDIO;
+
+    pa_log_warn("unknown device (%s)", device);
+    return DEVICE_UNKNOWN;
+}
+
 struct userdata {
     pa_core *core;
     pa_module *module;
@@ -246,6 +290,7 @@ struct userdata {
         pa_hook_slot *comm_hook_change_route_slot;
         pa_hook_slot *comm_hook_update_route_option_slot;
         pa_hook_slot *comm_hook_device_connection_changed_slot;
+        pa_hook_slot *comm_hook_device_info_changed_slot;
     } communicator;
 
     pa_hal_manager *hal_manager;
@@ -361,6 +406,8 @@ static pa_hook_result_t select_proper_sink_or_source_hook_cb(pa_core *c, pa_stre
         if (data->route_type == STREAM_ROUTE_TYPE_AUTO || data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL) {
             PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
                 pa_log_info("[SELECT][AUTO(_ALL)] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
+                if (cached_connected_devices[convert_device_type_str(device_type)][CONVERT_TO_DEVICE_DIRECTION(data->stream_type)-1] == 0)
+                    continue;
                 PA_IDXSET_FOREACH(device, conn_devices, conn_idx) {
                     dm_device_type = pa_device_manager_get_device_type(device);
                     dm_device_subtype = pa_device_manager_get_device_subtype(device);
@@ -388,6 +435,8 @@ static pa_hook_result_t select_proper_sink_or_source_hook_cb(pa_core *c, pa_stre
         } else if (data->route_type == STREAM_ROUTE_TYPE_AUTO_LAST_CONNECTED) {
             PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
                 pa_log_info("[SELECT][AUTO_LAST_CONN] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
+                if (cached_connected_devices[convert_device_type_str(device_type)][CONVERT_TO_DEVICE_DIRECTION(data->stream_type)-1] == 0)
+                    continue;
                 PA_IDXSET_FOREACH(device, conn_devices, conn_idx) {
                     dm_device_type = pa_device_manager_get_device_type(device);
                     dm_device_subtype = pa_device_manager_get_device_subtype(device);
@@ -419,6 +468,8 @@ static pa_hook_result_t select_proper_sink_or_source_hook_cb(pa_core *c, pa_stre
     } else if (data->route_type == STREAM_ROUTE_TYPE_MANUAL && data->idx_manual_devices && data->idx_avail_devices) {
         PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
             pa_log_info("[SELECT][MANUAL] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
+            if (cached_connected_devices[convert_device_type_str(device_type)][CONVERT_TO_DEVICE_DIRECTION(data->stream_type)-1] == 0)
+                continue;
             PA_IDXSET_FOREACH(device_id, data->idx_manual_devices, m_idx) {
                 if ((device = pa_device_manager_get_device_by_id(u->device_manager, *device_id))) {
                     dm_device_type = pa_device_manager_get_device_type(device);
@@ -447,6 +498,8 @@ static pa_hook_result_t select_proper_sink_or_source_hook_cb(pa_core *c, pa_stre
     } else if (data->route_type == STREAM_ROUTE_TYPE_MANUAL_EXT && data->idx_manual_devices && data->idx_avail_devices) {
         PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
             pa_log_info("[SELECT][MANUAL_EXT] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
+            if (cached_connected_devices[convert_device_type_str(device_type)][CONVERT_TO_DEVICE_DIRECTION(data->stream_type)-1] == 0)
+                continue;
             PA_IDXSET_FOREACH(device_id, data->idx_manual_devices, m_idx) {
                 if ((device = pa_device_manager_get_device_by_id(u->device_manager, *device_id))) {
                     dm_device_type = pa_device_manager_get_device_type(device);
@@ -598,7 +651,7 @@ static void update_loopback_module(struct userdata *u, pa_bool_t load) {
             u->module_loopback = NULL;
             u->loopback_args.sink = NULL;
             u->loopback_args.source = NULL;
-            pa_log_info("  -- unload module-loopback", args);
+            pa_log_info("  -- unload module-loopback");
         }
     } else {
         pa_log_error("  -- failed to update loopback module");
@@ -739,6 +792,8 @@ static pa_hook_result_t route_change_hook_cb(pa_core *c, pa_stream_manager_hook_
         if (data->route_type == STREAM_ROUTE_TYPE_AUTO || data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL) {
             PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
                 pa_log_info("[ROUTE][AUTO(_ALL)] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, route_info.role, device_type);
+                if (cached_connected_devices[convert_device_type_str(device_type)][CONVERT_TO_DEVICE_DIRECTION(data->stream_type)-1] == 0)
+                    continue;
                 PA_IDXSET_FOREACH(device, conn_devices, conn_idx) {
                     dm_device_type = pa_device_manager_get_device_type(device);
                     dm_device_subtype = pa_device_manager_get_device_subtype(device);
@@ -873,6 +928,8 @@ static pa_hook_result_t route_change_hook_cb(pa_core *c, pa_stream_manager_hook_
         } else if (data->route_type == STREAM_ROUTE_TYPE_AUTO_LAST_CONNECTED) {
             PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
                 pa_log_info("[ROUTE][AUTO_LAST_CONN] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
+                if (cached_connected_devices[convert_device_type_str(device_type)][CONVERT_TO_DEVICE_DIRECTION(data->stream_type)-1] == 0)
+                    continue;
                 PA_IDXSET_FOREACH(device, conn_devices, conn_idx) {
                     dm_device_type = pa_device_manager_get_device_type(device);
                     dm_device_subtype = pa_device_manager_get_device_subtype(device);
@@ -961,6 +1018,8 @@ static pa_hook_result_t route_change_hook_cb(pa_core *c, pa_stream_manager_hook_
     } else if (data->route_type == STREAM_ROUTE_TYPE_MANUAL && data->idx_manual_devices && data->idx_avail_devices) {
         PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
             pa_log_info("[ROUTE][MANUAL] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
+            if (cached_connected_devices[convert_device_type_str(device_type)][CONVERT_TO_DEVICE_DIRECTION(data->stream_type)-1] == 0)
+                continue;
             PA_IDXSET_FOREACH(device_id, data->idx_manual_devices, d_idx) {
                 pa_log_debug("  -- manual_device[%u] for this role[%-16s]: device_id(%u)", idx, data->stream_role, *device_id);
                 if ((device = pa_device_manager_get_device_by_id(u->device_manager, *device_id))) {
@@ -1124,6 +1183,42 @@ static pa_hook_result_t route_option_update_hook_cb(pa_core *c, pa_stream_manage
     return PA_HOOK_OK;
 }
 
+/* Update ref. count of each connected device */
+static void update_connected_devices(const char *device_type, dm_device_direction_t direction, pa_bool_t is_connected) {
+    int32_t val = 0;
+    int* ptr_in = NULL;
+    int* ptr_out = NULL;
+
+    ptr_in = &cached_connected_devices[convert_device_type_str(device_type)][CACHED_DEVICE_DIRECTION_IN];
+    ptr_out = &cached_connected_devices[convert_device_type_str(device_type)][CACHED_DEVICE_DIRECTION_OUT];
+    val = (is_connected) ? 1 : -1;
+
+    if (direction & DM_DEVICE_DIRECTION_IN)
+        *ptr_in += val;
+    if (direction & DM_DEVICE_DIRECTION_OUT)
+        *ptr_out += val;
+
+    if (*ptr_in < 0)
+        *ptr_in = 0;
+    if (*ptr_out < 0)
+        *ptr_out = 0;
+
+    return;
+}
+
+static void dump_connected_devices()
+{
+#if 0
+    int32_t i = 0;
+
+    pa_log_debug("== dump cached current device ==");
+    for (i = 0; i < DEVICE_MAX-1; i++)
+        pa_log_debug("in: %d, out: %d", cached_connected_devices[i][CACHED_DEVICE_DIRECTION_IN], cached_connected_devices[i][CACHED_DEVICE_DIRECTION_OUT]);
+    pa_log_debug("================================");
+#endif
+    return;
+}
+
 /* Reorganize routing when a device has been connected or disconnected */
 static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_device_manager_hook_data_for_conn_changed *conn, struct userdata *u) {
     uint32_t idx = 0;
@@ -1143,7 +1238,10 @@ static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_device_
     device_direction = pa_device_manager_get_device_direction(conn->device);
 
     pa_log_info("[CONN] device_connection_changed_hook_cb is called. conn(%p), is_connected(%d), device(%p), direction(0x%x)",
-            conn, conn->is_connected, conn->device, device_direction);
+                conn, conn->is_connected, conn->device, device_direction);
+
+    update_connected_devices(pa_device_manager_get_device_type(conn->device), device_direction, conn->is_connected);
+    dump_connected_devices();
 
     null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_NULL, PA_NAMEREG_SINK);
     if (!null_sink) {
@@ -1214,6 +1312,38 @@ static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_device_
     return PA_HOOK_OK;
 }
 
+/* Update connected device list when a device's information has been changed */
+static pa_hook_result_t device_info_changed_hook_cb(pa_core *c, pa_device_manager_hook_data_for_info_changed *conn, struct userdata *u) {
+    dm_device_direction_t device_direction = DM_DEVICE_DIRECTION_OUT;
+    int* ptr_in = NULL;
+    int* ptr_out = NULL;
+
+    pa_assert(c);
+    pa_assert(conn);
+    pa_assert(u);
+
+    device_direction = pa_device_manager_get_device_direction(conn->device);
+
+    pa_log_info("[CONN] device_info_changed_hook_cb is called. conn(%p), changed_info(%d), device(%p), direction(0x%x)",
+                conn, conn->changed_info, conn->device, device_direction);
+
+    if (conn->changed_info == DM_DEVICE_CHANGED_INFO_IO_DIRECTION)
+        if (pa_streq(pa_device_manager_get_device_type(conn->device), DEVICE_TYPE_BT)) {
+            /* In case of the bluetooth, we do not maintain a ref. count of the bluetooth devices.
+             * Because bluetooth framework supports only one device simultaneously for audio profile. */
+            ptr_in = &cached_connected_devices[convert_device_type_str(DEVICE_TYPE_BT)][CACHED_DEVICE_DIRECTION_IN];
+            ptr_out = &cached_connected_devices[convert_device_type_str(DEVICE_TYPE_BT)][CACHED_DEVICE_DIRECTION_OUT];
+            *ptr_in = *ptr_out = 0;
+            if (device_direction & DM_DEVICE_DIRECTION_IN)
+                *ptr_in = 1;
+            if (device_direction & DM_DEVICE_DIRECTION_OUT)
+                *ptr_out = 1;
+            dump_connected_devices();
+        }
+
+    return PA_HOOK_OK;
+}
+
 #ifdef HAVE_DBUS
 static void _do_something1(char* arg1, int arg2, void *data)
 {
@@ -1769,6 +1899,9 @@ int pa__init(pa_module *m)
         u->communicator.comm_hook_device_connection_changed_slot = pa_hook_connect(
                 pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_DEVICE_CONNECTION_CHANGED),
                 PA_HOOK_EARLY, (pa_hook_cb_t)device_connection_changed_hook_cb, u);
+        u->communicator.comm_hook_device_info_changed_slot = pa_hook_connect(
+                pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_DEVICE_INFORMATION_CHANGED),
+                PA_HOOK_EARLY, (pa_hook_cb_t)device_info_changed_hook_cb, u);
     }
     u->device_manager = pa_device_manager_get(u->core);
 
@@ -1833,6 +1966,8 @@ void pa__done(pa_module *m)
             pa_hook_slot_free(u->communicator.comm_hook_update_route_option_slot);
         if (u->communicator.comm_hook_device_connection_changed_slot)
             pa_hook_slot_free(u->communicator.comm_hook_device_connection_changed_slot);
+        if (u->communicator.comm_hook_device_info_changed_slot)
+            pa_hook_slot_free(u->communicator.comm_hook_device_info_changed_slot);
         pa_communicator_unref(u->communicator.comm);
     }