tizenaudio-policy: Fix to select a valid device if a device role is specified 16/210416/6
authorSangchul Lee <sc11.lee@samsung.com>
Fri, 19 Jul 2019 02:15:44 +0000 (11:15 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Wed, 24 Jul 2019 06:41:43 +0000 (15:41 +0900)
[Version] 11.1.62
[Issue type] Bug fix

Change-Id: Icbb61235e2431f8c078c823551507fc5da94252b
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
packaging/pulseaudio-modules-tizen.spec
src/device-manager.c
src/module-tizenaudio-policy.c
src/stream-manager.c
src/tizen-device.c

index 496ef6f..990bfd6 100644 (file)
@@ -1,6 +1,6 @@
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          11.1.61
+Version:          11.1.62
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index 3c80ee6..22d9845 100644 (file)
@@ -1515,30 +1515,30 @@ static void handle_internal_pulse_device(pa_object *pdevice, bool is_loaded, pa_
         /* Put this pulse_device to already loaded devices */
         for (int i = 0; i < pa_dynarray_size(ctypes); i++) {
             ctype = pa_dynarray_get(ctypes, i);
-            pa_log_info("Found belongs type %s %s", ctype->type, ctype->role);
-            if ((device = device_list_get_device(dm, ctype->type, NULL, NULL))) {
+            pa_log_info("Found belongs type %s.%s", ctype->type, ctype->role);
+            if ((device = device_list_get_device(dm, ctype->type, ctype->role, NULL))) {
                 pa_log_info("Add this pulse_device to device(%u)", pa_tz_device_get_id(device));
                 if (direction == DM_DEVICE_DIRECTION_OUT)
                     pa_tz_device_add_sink(device, ctype->role, PA_SINK(pdevice));
                 else
                     pa_tz_device_add_source(device, ctype->role, PA_SOURCE(pdevice));
             } else {
-                pa_log_info("No device for %s", ctype->type);
+                pa_log_info("No device for %s.%s", ctype->type, ctype->role);
             }
         }
     } else {
         /* Remove this pulse_device from already loaded devices */
         for (int i = 0; i < pa_dynarray_size(ctypes); i++) {
             ctype = pa_dynarray_get(ctypes, i);
-            pa_log_info("Found belongs type %s %s", ctype->type, ctype->role);
-            if ((device = device_list_get_device(dm, ctype->type, NULL, NULL))) {
+            pa_log_info("Found belongs type %s.%s", ctype->type, ctype->role);
+            if ((device = device_list_get_device(dm, ctype->type, ctype->role, NULL))) {
                 pa_log_info("Remove this pulse_device from device(%u)", pa_tz_device_get_id(device));
                 if (direction == DM_DEVICE_DIRECTION_OUT)
                     pa_tz_device_remove_sink(device, PA_SINK(pdevice));
                 else
                     pa_tz_device_remove_source(device, PA_SOURCE(pdevice));
             } else {
-                pa_log_info("No device for %s", ctype->type);
+                pa_log_info("No device for %s.%s", ctype->type, ctype->role);
             }
         }
     }
@@ -1844,6 +1844,7 @@ static int _load_type_devices(device_type_info *type_info, bool is_playback, pa_
             pa_log_warn("load device failed %s %s", device_string, params);
             continue;
         }
+
         if (first_one && !pa_streq(role, DEVICE_ROLE_NORMAL)) {
             /* NOTE: If the first role is not NORMAL, handle it as external devices.
              * Because it's not ready to pass this information to audio HAL for now. */
@@ -1853,6 +1854,7 @@ static int _load_type_devices(device_type_info *type_info, bool is_playback, pa_
                 PA_SOURCE(device)->use_internal_codec = false;
             first_one = false;
         }
+        pa_log_info("load device success %s %s %s", device_string, params, role);
     }
 
     return 0;
index 19602ff..c869a1f 100644 (file)
@@ -713,10 +713,16 @@ 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_ALL && u->module_combine_sink) {
                                 *(data->proper_sink) = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK);
                                 pa_log_info("  -- found the combine-sink, set it to the sink");
-                            } else
+                            } else {
                                 *(data->proper_sink) = pa_tz_device_get_sink(device, data->device_role);
-                        } else
+                            }
+                            if (*(data->proper_sink) == NULL)
+                                continue;
+                        } else {
                             *(data->proper_source) = pa_tz_device_get_source(device, data->device_role);
+                            if (*(data->proper_source) == NULL)
+                                continue;
+                        }
 
                         if (data->route_type == STREAM_ROUTE_TYPE_AUTO) {
                             if (data->origins_from_new_data)
index 9cf90e3..2b534d0 100644 (file)
@@ -1123,6 +1123,34 @@ static void update_preferred_device_role(pa_stream_manager *m, void *stream, str
                         sp->preferred_device.roles[type]);
 }
 
+static void get_preferred_device_type_and_role(pa_stream_manager *m, void *stream, stream_type_t stream_type, const char **type, const char **role) {
+    const char *p_idx_str;
+    uint32_t parent_idx = 100;
+    stream_parent *sp = NULL;
+
+    pa_assert(m);
+    pa_assert(stream);
+    pa_assert(type);
+    pa_assert(role);
+
+    p_idx_str = pa_proplist_gets(GET_STREAM_PROPLIST(stream, stream_type), PA_PROP_MEDIA_PARENT_ID);
+    if (!p_idx_str || pa_atou(p_idx_str, &parent_idx)) {
+        return;
+    }
+    if (!(sp = pa_hashmap_get(m->stream_parents, (const void*)parent_idx))) {
+        pa_log_warn("could not find matching client for this parent_id(%u)", parent_idx);
+        return;
+    }
+
+    *type = sp->preferred_device.types[stream_type];
+    *role = sp->preferred_device.roles[stream_type];
+
+    pa_log_debug("%s(%u), parent_id(%u), preferred type(%s), role(%s)",
+            stream_type == STREAM_SINK_INPUT ? "sink-input" : "source-output",
+            stream_type == STREAM_SINK_INPUT ? PA_SINK_INPUT(stream)->index : PA_SOURCE_OUTPUT(stream)->index,
+            parent_idx, *type, *role);
+}
+
 static bool update_stream_parent_info(pa_stream_manager *m, process_command_type_t command, stream_type_t type, void *stream) {
     const char *p_idx;
     uint32_t parent_idx;
@@ -1784,6 +1812,24 @@ static void set_new_data_stream_to_null_sink_source(pa_stream_manager *m, void *
     }
 }
 
+static bool check_preferred_role_of_active_device_exist(pa_stream_manager *m, void *stream, stream_type_t type, const char *preferred_role) {
+    const char *active_device_type;
+    pa_tz_device *device;
+
+    pa_assert(m);
+    pa_assert(stream);
+    pa_assert(preferred_role);
+
+    if ((active_device_type = pa_proplist_gets(GET_STREAM_PROPLIST(stream, type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV))) {
+        if ((device = pa_device_manager_get_device(m->dm, active_device_type, preferred_role))) {
+            pa_log_debug("preferred device role[%s] of active device[%s] is found", preferred_role, pa_tz_device_get_type(device));
+            return true;
+        }
+    }
+
+    return false;
+}
+
 process_stream_result_t process_stream(pa_stream_manager *m, void *stream, stream_type_t type, process_command_type_t command, bool is_new_data) {
     process_stream_result_t result = PROCESS_STREAM_RESULT_OK;
     const char *role = NULL;
@@ -1920,8 +1966,15 @@ process_stream_result_t process_stream(pa_stream_manager *m, void *stream, strea
 
         /* skip updating priority, focus status, the highest priority, ucm to HAL */
         if (preferred_device_role) {
-            pa_log_debug("preferred device role[%s] is found, skip ROUTE_START", preferred_device_role);
-            goto skip_notifying_route_start;
+            if (is_new_data) {
+                pa_log_debug("skip updating priority, focus status, the highest priority, ucm to HAL");
+                goto skip_notifying_route_start;
+            } else {
+                if (check_preferred_role_of_active_device_exist(m, stream, type, preferred_device_role)) {
+                    pa_log_debug("skip updating priority, focus status, the highest priority, ucm to HAL");
+                    goto skip_notifying_route_start;
+                }
+            }
         }
 
         /* skip roles */
@@ -1996,8 +2049,10 @@ skip_notifying_route_start:
                                                     PA_PROP_MEDIA_ROUTE_AUTO_PREFERRED_DEVICE_ROLE);
         /* skip updating the highest priority, ucm to HAL */
         if (preferred_device_role) {
-            pa_log_debug("preferred device role[%s] is found, skip ROUTE_END", preferred_device_role);
-            goto skip_notifying_route_end;
+            if (check_preferred_role_of_active_device_exist(m, stream, type, preferred_device_role)) {
+                pa_log_debug("skip updating the highest priority, ucm to HAL");
+                goto skip_notifying_route_end;
+            }
         }
 
         /* unload forwarding device */
@@ -2497,7 +2552,8 @@ static pa_hook_result_t source_output_move_finish_cb(pa_core *core, pa_source_ou
     return PA_HOOK_OK;
 }
 
-static void find_next_device_for_auto_route(pa_stream_manager *m, stream_route_type_t route_type, const char *role, stream_type_t stream_type, const char *cur_device_type, pa_tz_device **next_device) {
+static void find_next_device_for_auto_route(pa_stream_manager *m, stream_route_type_t route_type, const char *stream_role,
+                                        stream_type_t stream_type, const char *cur_device_type, const char *preferred_device_role, pa_tz_device **next_device) {
     stream_info *si = NULL;
     pa_idxset *devices = NULL;
     uint32_t idx = 0;
@@ -2509,15 +2565,15 @@ static void find_next_device_for_auto_route(pa_stream_manager *m, stream_route_t
 
     pa_assert(m);
     pa_assert(m->stream_infos);
-    pa_assert(role);
+    pa_assert(stream_role);
     pa_assert(cur_device_type);
     pa_assert(next_device);
     pa_assert((route_type == STREAM_ROUTE_TYPE_AUTO || route_type == STREAM_ROUTE_TYPE_AUTO_LAST_CONNECTED));
 
     *next_device = NULL;
 
-    if (!(si = pa_hashmap_get(m->stream_infos, role))) {
-        pa_log_warn("not support this role[%s]", role);
+    if (!(si = pa_hashmap_get(m->stream_infos, stream_role))) {
+        pa_log_warn("not support this stream_role[%s]", stream_role);
         return;
     }
     if (si->route_type != route_type) {
@@ -2526,7 +2582,7 @@ static void find_next_device_for_auto_route(pa_stream_manager *m, stream_route_t
     }
 
     if (!(devices = (stream_type == STREAM_SINK_INPUT) ? si->idx_avail_out_devices : si->idx_avail_in_devices)) {
-        pa_log_error("could not found a device list for this role[%s], stream type[%d]", role, stream_type);
+        pa_log_error("could not found a device list for this stream_role[%s], stream type[%d]", stream_role, stream_type);
         return;
     }
 
@@ -2537,8 +2593,8 @@ static void find_next_device_for_auto_route(pa_stream_manager *m, stream_route_t
                 continue;
             }
             if (ret_next) {
-                if ((*next_device = pa_device_manager_get_device(m->dm, device_type, NULL))) {
-                    pa_log_debug("found next device[%s, %p]", device_type, *next_device);
+                if ((*next_device = pa_device_manager_get_device(m->dm, device_type, preferred_device_role))) {
+                    pa_log_debug("found next device[%s, %s, %p]", device_type, preferred_device_role, *next_device);
                     break;
                 }
             }
@@ -2557,7 +2613,7 @@ static void find_next_device_for_auto_route(pa_stream_manager *m, stream_route_t
         pa_log_debug("found next device[%p], creation_time[%llu]", *next_device, latest_creation_time);
     }
 
-    pa_log_debug("next_device is [%p] for role[%s]/route_type[%d]/stream_type[%d]", *next_device, role, route_type, stream_type);
+    pa_log_debug("next_device is [%p] for stream_role[%s]/route_type[%d]/stream_type[%d]", *next_device, stream_role, route_type, stream_type);
 }
 
 static void is_available_device_for_auto_route(pa_stream_manager *m, stream_route_type_t route_type, const char *cur_device_type, const char *new_device_type, const char *role, stream_type_t stream_type, bool *available) {
@@ -2716,7 +2772,7 @@ static bool manage_filter_apply_stream(pa_stream_manager *m, pa_sink_input *si,
 
             if (is_active_device_of_stream(si, STREAM_SINK_INPUT, device_type)) {
                 pa_sink *next_sink = NULL;
-                find_next_device_for_auto_route(m, route_type, stream_role, STREAM_SINK_INPUT, cur_device_type, &next_device);
+                find_next_device_for_auto_route(m, route_type, stream_role, STREAM_SINK_INPUT, cur_device_type, NULL, &next_device);
                 if (!next_device) {
                     pa_log_error("failed to get next_device");
                     return true;
@@ -2746,7 +2802,7 @@ static void update_sink_or_source_as_device_change(pa_stream_manager *m, stream_
     } cached_device_list;
     void *s = NULL;
     uint32_t s_idx = 0;
-    const char *role = NULL;
+    const char *stream_role = NULL;
     const char *device_type = NULL;
     const char *cur_device_type = NULL;
     const char *new_device_type = NULL;
@@ -2791,13 +2847,13 @@ static void update_sink_or_source_as_device_change(pa_stream_manager *m, stream_
             if (stream_type == STREAM_SINK_INPUT && manage_filter_apply_stream(m, s, device, is_connected))
                 continue;
 
-            role = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROLE);
-            pa_log_debug("  -- idx(%u), route_type(%d), role(%s)", s_idx, route_type, role);
+            stream_role = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROLE);
+            pa_log_debug("  -- idx(%u), route_type(%d), stream_role(%s)", s_idx, route_type, stream_role);
             if (is_connected) {
                 /* CONNECTED: move a stream to the new device if possible */
                 if (sink && (sink != ((pa_sink_input*)s)->sink)) {
                     if ((cur_device_type = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV))) {
-                        is_available_device_for_auto_route(m, route_type, cur_device_type, device_type, role, stream_type, &available);
+                        is_available_device_for_auto_route(m, route_type, cur_device_type, device_type, stream_role, stream_type, &available);
                         if (available) {
                             if (check_name_is_vstream(s, STREAM_SINK_INPUT, false)) {
                                 pa_log_debug("  -- *** keep null sink for a virtual stream");
@@ -2812,7 +2868,7 @@ static void update_sink_or_source_as_device_change(pa_stream_manager *m, stream_
                         pa_log_error("  -- could not find current device type for s->sink(%p)", ((pa_sink_input*)s)->sink);
                 } else if (source && (source != ((pa_source_output*)s)->source)) {
                     if ((cur_device_type = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV))) {
-                        is_available_device_for_auto_route(m, route_type, cur_device_type, device_type, role, stream_type, &available);
+                        is_available_device_for_auto_route(m, route_type, cur_device_type, device_type, stream_role, stream_type, &available);
                         if (available) {
                             if (check_name_is_vstream(s, STREAM_SOURCE_OUTPUT, false)) {
                                 pa_log_debug("  -- *** keep null source for a virtual stream");
@@ -2834,13 +2890,23 @@ static void update_sink_or_source_as_device_change(pa_stream_manager *m, stream_
                     process_stream_as_device_change_for_auto_route(m, s, stream_type, is_connected, device);
                 }
             } else if (!is_connected) {
+                const char *pref_device_type = NULL;
+                const char *pref_device_role = NULL;
+                const char *device_role = NULL;
+
+                /* get preferred role */
+                get_preferred_device_type_and_role(m, s, stream_type, &pref_device_type, &pref_device_role);
+
                 /* DISCONNECTED: find a connected device that has the next priority */
                 if (sink && ((sink == ((pa_sink_input*)s)->sink) || check_name_is_vstream(s, STREAM_SINK_INPUT, false))) {
                     if (!is_active_device_of_stream(s, stream_type, device_type))
                         continue;
-                    find_next_device_for_auto_route(m, route_type, role, stream_type, device_type, &next_device);
+                    find_next_device_for_auto_route(m, route_type, stream_role, stream_type, device_type, pref_device_role, &next_device);
                     if (next_device) {
-                        if ((next_sink = pa_tz_device_get_sink(next_device, NULL))) {
+                        if (pref_device_type && pa_safe_streq(pa_tz_device_get_type(next_device), pref_device_type))
+                            device_role = pref_device_role;
+
+                        if ((next_sink = pa_tz_device_get_sink(next_device, device_role))) {
                             new_device_type = pa_tz_device_get_type(next_device);
                             /* update activated device */
                             pa_proplist_sets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, new_device_type);
@@ -2867,9 +2933,12 @@ static void update_sink_or_source_as_device_change(pa_stream_manager *m, stream_
                 } else if (source && ((source == ((pa_source_output*)s)->source) || check_name_is_vstream(s, STREAM_SOURCE_OUTPUT, false))) {
                     if (!is_active_device_of_stream(s, stream_type, device_type))
                         continue;
-                    find_next_device_for_auto_route(m, route_type, role, stream_type, device_type, &next_device);
+                    find_next_device_for_auto_route(m, route_type, stream_role, stream_type, device_type, pref_device_role, &next_device);
                     if (next_device) {
-                        if ((next_source = pa_tz_device_get_source(next_device, NULL))) {
+                        if (pref_device_type && pa_safe_streq(pa_tz_device_get_type(next_device), pref_device_type))
+                            device_role = pref_device_role;
+
+                        if ((next_source = pa_tz_device_get_source(next_device, device_role))) {
                             new_device_type = pa_tz_device_get_type(next_device);
                             /* update activated device */
                             pa_proplist_sets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, new_device_type);
index c1c1a83..a516201 100644 (file)
@@ -626,6 +626,8 @@ pa_sink* pa_tz_device_get_sink(pa_tz_device *device, const char *role) {
         return NULL;
     }
 
+    pa_log_info("sink name(%s)", sink->name);
+
     return sink;
 }
 
@@ -642,6 +644,8 @@ pa_source* pa_tz_device_get_source(pa_tz_device *device, const char *role) {
         return NULL;
     }
 
+    pa_log_info("source name(%s)", source->name);
+
     return source;
 }