/* 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);
}
}
}
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. */
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;
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;
}
}
+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;
/* 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 */
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 */
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;
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) {
}
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;
}
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;
}
}
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) {
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;
} 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;
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");
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");
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);
} 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);