Add a configurable workaround for Android reconnecting devices

Closes https://github.com/libretro/RetroArch/issues/3414

I have investigated the issue. The crux of the problem is that on Android there
is no way distinguishing 2 scenarios:
1) 2 identical bluetooth controllers A and B and first there are button presses
only on controller A and then on controller B
2) the same controller disconnects and reconnects.
Android doesn't give bluetooth mac address of where the touch came from, only
opaque ID and this opaque ID changes after reconnect. Hence without changes to
android this is infeasible without giving up the ability for 2 users to play on
identical controllers.

I guess that this sacrifice makes sense for affected users
This commit is contained in:
Vladimir Serbinenko 2022-02-21 14:13:02 +01:00
parent 5e85d22d8f
commit 2ef2ff1b36
8 changed files with 66 additions and 2 deletions

View file

@ -2023,6 +2023,10 @@ static struct config_bool_setting *populate_settings_bool(
SETTING_BOOL("wifi_enabled", &settings->bools.wifi_enabled, true, DEFAULT_WIFI_ENABLE, false);
SETTING_BOOL("gamemode_enable", &settings->bools.gamemode_enable, true, DEFAULT_GAMEMODE_ENABLE, false);
#ifdef ANDROID
SETTING_BOOL("android_input_disconnect_workaround", &settings->bools.android_input_disconnect_workaround, true, false, false);
#endif
*size = count;
return tmp;

View file

@ -940,6 +940,10 @@ typedef struct settings
#ifdef _3DS
bool new3ds_speedup_enable;
#endif
#ifdef ANDROID
bool android_input_disconnect_workaround;
#endif
} bools;
} settings_t;

View file

@ -838,7 +838,6 @@ static int android_input_get_id_port(android_input_t *android, int id,
return ret;
}
#ifdef HAVE_DYNAMIC
/* Returns the index inside android->pad_state */
static int android_input_get_id_index_from_name(android_input_t *android,
const char *name)
@ -852,7 +851,25 @@ static int android_input_get_id_index_from_name(android_input_t *android,
return -1;
}
#endif
static int android_input_recover_port(android_input_t *android, int id)
{
char device_name[256] = { 0 };
int vendorId = 0;
int productId = 0;
settings_t *settings = config_get_ptr();
if (!settings->bools.android_input_disconnect_workaround)
return -1;
if (!engine_lookup_name(device_name, &vendorId,
&productId, sizeof(device_name), id))
return -1;
int ret = android_input_get_id_index_from_name(android, device_name);
if (ret >= 0)
android->pad_states[ret].id = id;
return ret;
}
static void handle_hotplug(android_input_t *android,
struct android_app *android_app, int *port, int id,
@ -1195,6 +1212,9 @@ static void android_input_poll_input(android_input_t *android,
int id = android_input_get_id(event);
int port = android_input_get_id_port(android, id, source);
if (port < 0 && !android_is_keyboard_id(id))
port = android_input_recover_port(android, id);
if (port < 0 && !android_is_keyboard_id(id))
handle_hotplug(android, android_app,
&port, id, source);

View file

@ -2597,6 +2597,15 @@ MSG_HASH(
"Allow any user to control the menu. If disabled, only User 1 can control the menu."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_ANDROID_INPUT_DISCONNECT_WORKAROUND,
"Android disconnect workaround"
)
MSG_HASH(
MENU_ENUM_LABEL_ANDROID_INPUT_DISCONNECT_WORKAROUND,
"Workaround for controllers disconnecting and reconnecting. Impedes 2 players with the identical controllers."
)
/* Settings > Input > Hotkeys */
MSG_HASH(

View file

@ -681,6 +681,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_nowinkey_enable, MENU_
#endif
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_sensors_enable, MENU_ENUM_SUBLABEL_INPUT_SENSORS_ENABLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_auto_mouse_grab, MENU_ENUM_SUBLABEL_INPUT_AUTO_MOUSE_GRAB)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_android_input_disconnect_workaround, MENU_ENUM_SUBLABEL_ANDROID_INPUT_DISCONNECT_WORKAROUND)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_auto_game_focus, MENU_ENUM_SUBLABEL_INPUT_AUTO_GAME_FOCUS)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_swap_ok_cancel, MENU_ENUM_SUBLABEL_MENU_INPUT_SWAP_OK_CANCEL)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_pause_libretro, MENU_ENUM_SUBLABEL_PAUSE_LIBRETRO)

View file

@ -6940,6 +6940,12 @@ unsigned menu_displaylist_build_list(
MENU_ENUM_LABEL_INPUT_AUTO_MOUSE_GRAB,
PARSE_ONLY_BOOL, false) == 0)
count++;
#ifdef ANDROID
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_ANDROID_INPUT_DISCONNECT_WORKAROUND,
PARSE_ONLY_BOOL, false) == 0)
count++;
#endif
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_INPUT_AUTO_GAME_FOCUS,
PARSE_ONLY_UINT, false) == 0)

View file

@ -13618,6 +13618,24 @@ static bool setting_append_list(
SD_FLAG_NONE
);
#ifdef ANDROID
CONFIG_BOOL(
list, list_info,
&settings->bools.android_input_disconnect_workaround,
MENU_ENUM_LABEL_ANDROID_INPUT_DISCONNECT_WORKAROUND,
MENU_ENUM_LABEL_VALUE_ANDROID_INPUT_DISCONNECT_WORKAROUND,
false,
MENU_ENUM_LABEL_VALUE_OFF,
MENU_ENUM_LABEL_VALUE_ON,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler,
SD_FLAG_NONE
);
#endif
CONFIG_UINT(
list, list_info,
&settings->uints.input_auto_game_focus,

View file

@ -1058,6 +1058,8 @@ enum msg_hash_enums
MENU_LABEL(QUIT_PRESS_TWICE),
MENU_LABEL(QUIT_ON_CLOSE_CONTENT),
MENU_LABEL(ANDROID_INPUT_DISCONNECT_WORKAROUND),
MENU_ENUM_LABEL_VALUE_QUIT_ON_CLOSE_CONTENT_DISABLED,
MENU_ENUM_LABEL_VALUE_QUIT_ON_CLOSE_CONTENT_ENABLED,
MENU_ENUM_LABEL_VALUE_QUIT_ON_CLOSE_CONTENT_CLI,