Merge pull request #11332 from jdgleaver/android-sensors

(Sensors API) Android (crash-)fixes/improvements + add option to disable sensor input
This commit is contained in:
Autechre 2020-09-14 19:16:58 +02:00 committed by GitHub
commit 0cb0635ddc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 249 additions and 35 deletions

View File

@ -1151,6 +1151,16 @@ static const unsigned turbo_default_btn = RETRO_DEVICE_ID_JOYPAD_B;
* gamepads, plug-and-play style. */
static const bool input_autodetect_enable = true;
/* Enables accelerometer/gyroscope/illuminance
* sensor input, if supported */
#if defined(ANDROID)
/* Hardware sensors cause substantial battery
* drain on Android... */
#define DEFAULT_INPUT_SENSORS_ENABLE false
#else
#define DEFAULT_INPUT_SENSORS_ENABLE true
#endif
/* Show the input descriptors set by the core instead
* of the default ones. */
static const bool input_descriptor_label_show = true;

View File

@ -1707,6 +1707,7 @@ static struct config_bool_setting *populate_settings_bool(
SETTING_BOOL("config_save_on_exit", &settings->bools.config_save_on_exit, true, DEFAULT_CONFIG_SAVE_ON_EXIT, false);
SETTING_BOOL("show_hidden_files", &settings->bools.show_hidden_files, true, DEFAULT_SHOW_HIDDEN_FILES, false);
SETTING_BOOL("input_autodetect_enable", &settings->bools.input_autodetect_enable, true, input_autodetect_enable, false);
SETTING_BOOL("input_sensors_enable", &settings->bools.input_sensors_enable, true, DEFAULT_INPUT_SENSORS_ENABLE, false);
SETTING_BOOL("audio_rate_control", &settings->bools.audio_rate_control, true, DEFAULT_RATE_CONTROL, false);
#ifdef HAVE_WASAPI
SETTING_BOOL("audio_wasapi_exclusive_mode", &settings->bools.audio_wasapi_exclusive_mode, true, DEFAULT_WASAPI_EXCLUSIVE_MODE, false);

View File

@ -496,6 +496,7 @@ typedef struct settings
/* Input */
bool input_remap_binds_enable;
bool input_autodetect_enable;
bool input_sensors_enable;
bool input_overlay_enable;
bool input_overlay_enable_autopreferred;
bool input_overlay_hide_in_menu;

View File

@ -138,9 +138,11 @@ struct android_app
/* Below are "private" implementation of RA code. */
bool unfocused;
unsigned accelerometer_event_rate;
unsigned gyroscope_event_rate;
ASensorManager *sensorManager;
ASensorEventQueue *sensorEventQueue;
const ASensor* accelerometerSensor;
const ASensor* gyroscopeSensor;
uint64_t sensor_state_mask;
char current_ime[PATH_MAX_LENGTH];
bool input_alive;

View File

@ -47,6 +47,7 @@
#define MAX_TOUCH 16
#define MAX_NUM_KEYBOARDS 3
#define DEFAULT_ASENSOR_EVENT_RATE 60
/* If using an SDK lower than 14 then add missing mouse button codes */
#if __ANDROID_API__ < 14
@ -153,6 +154,7 @@ typedef struct android_input
unsigned pads_connected;
unsigned pointer_count;
sensor_t accelerometer_state; /* float alignment */
sensor_t gyroscope_state; /* float alignment */
float mouse_x_prev, mouse_y_prev;
struct input_pointer pointer[MAX_TOUCH]; /* int16_t alignment */
char device_model[256];
@ -370,18 +372,27 @@ static void android_input_poll_main_cmd(void)
case APP_CMD_GAINED_FOCUS:
{
bool boolean = false;
bool boolean = false;
bool enable_accelerometer = (android_app->sensor_state_mask &
(UINT64_C(1) << RETRO_SENSOR_ACCELEROMETER_ENABLE)) &&
!android_app->accelerometerSensor;
bool enable_gyroscope = (android_app->sensor_state_mask &
(UINT64_C(1) << RETRO_SENSOR_GYROSCOPE_ENABLE)) &&
!android_app->gyroscopeSensor;
rarch_ctl(RARCH_CTL_SET_PAUSED, &boolean);
rarch_ctl(RARCH_CTL_SET_IDLE, &boolean);
video_driver_unset_stub_frame();
if ((android_app->sensor_state_mask
& (UINT64_C(1) << RETRO_SENSOR_ACCELEROMETER_ENABLE))
&& !android_app->accelerometerSensor)
if (enable_accelerometer)
input_sensor_set_state(0,
RETRO_SENSOR_ACCELEROMETER_ENABLE,
android_app->accelerometer_event_rate);
if (enable_gyroscope)
input_sensor_set_state(0,
RETRO_SENSOR_GYROSCOPE_ENABLE,
android_app->gyroscope_event_rate);
}
slock_lock(android_app->mutex);
android_app->unfocused = false;
@ -390,20 +401,28 @@ static void android_input_poll_main_cmd(void)
break;
case APP_CMD_LOST_FOCUS:
{
bool boolean = true;
bool boolean = true;
bool disable_accelerometer = (android_app->sensor_state_mask &
(UINT64_C(1) << RETRO_SENSOR_ACCELEROMETER_ENABLE)) &&
android_app->accelerometerSensor;
bool disable_gyroscope = (android_app->sensor_state_mask &
(UINT64_C(1) << RETRO_SENSOR_GYROSCOPE_ENABLE)) &&
android_app->gyroscopeSensor;
rarch_ctl(RARCH_CTL_SET_PAUSED, &boolean);
rarch_ctl(RARCH_CTL_SET_IDLE, &boolean);
video_driver_set_stub_frame();
/* Avoid draining battery while app is not being used. */
if ((android_app->sensor_state_mask
& (UINT64_C(1) << RETRO_SENSOR_ACCELEROMETER_ENABLE))
&& android_app->accelerometerSensor != NULL
)
if (disable_accelerometer)
input_sensor_set_state(0,
RETRO_SENSOR_ACCELEROMETER_DISABLE,
android_app->accelerometer_event_rate);
if (disable_gyroscope)
input_sensor_set_state(0,
RETRO_SENSOR_GYROSCOPE_DISABLE,
android_app->gyroscope_event_rate);
}
slock_lock(android_app->mutex);
android_app->unfocused = true;
@ -1225,18 +1244,44 @@ static void android_input_poll_input(android_input_t *android,
static void android_input_poll_user(android_input_t *android)
{
struct android_app *android_app = (struct android_app*)g_android;
bool poll_accelerometer = false;
bool poll_gyroscope = false;
if ((android_app->sensor_state_mask & (UINT64_C(1) <<
RETRO_SENSOR_ACCELEROMETER_ENABLE))
&& android_app->accelerometerSensor)
if (!android_app->sensorEventQueue)
return;
poll_accelerometer = (android_app->sensor_state_mask &
(UINT64_C(1) << RETRO_SENSOR_ACCELEROMETER_ENABLE)) &&
android_app->accelerometerSensor;
poll_gyroscope = (android_app->sensor_state_mask &
(UINT64_C(1) << RETRO_SENSOR_GYROSCOPE_ENABLE)) &&
android_app->gyroscopeSensor;
if (poll_accelerometer || poll_gyroscope)
{
ASensorEvent event;
while (ASensorEventQueue_getEvents(
android_app->sensorEventQueue, &event, 1) > 0)
android_app->sensorEventQueue, &event, 1) > 0)
{
android->accelerometer_state.x = event.acceleration.x;
android->accelerometer_state.y = event.acceleration.y;
android->accelerometer_state.z = event.acceleration.z;
switch (event.type)
{
case ASENSOR_TYPE_ACCELEROMETER:
android->accelerometer_state.x = event.acceleration.x;
android->accelerometer_state.y = event.acceleration.y;
android->accelerometer_state.z = event.acceleration.z;
break;
case ASENSOR_TYPE_GYROSCOPE:
/* ASensorEvent struct is mysterious - have to
* read the raw 'data' field to get rate of
* rotation... */
android->gyroscope_state.x = event.data[0];
android->gyroscope_state.y = event.data[1];
android->gyroscope_state.z = event.data[2];
break;
default:
break;
}
}
}
}
@ -1462,10 +1507,16 @@ static void android_input_free_input(void *data)
if (!android)
return;
if (android_app->sensorManager)
if (android_app->sensorManager &&
android_app->sensorEventQueue)
ASensorManager_destroyEventQueue(android_app->sensorManager,
android_app->sensorEventQueue);
android_app->sensorEventQueue = NULL;
android_app->accelerometerSensor = NULL;
android_app->gyroscopeSensor = NULL;
android_app->sensorManager = NULL;
android_app->input_alive = false;
#ifdef HAVE_DYNAMIC
@ -1489,22 +1540,39 @@ static uint64_t android_input_get_capabilities(void *data)
static void android_input_enable_sensor_manager(struct android_app *android_app)
{
android_app->sensorManager = ASensorManager_getInstance();
android_app->accelerometerSensor =
ASensorManager_getDefaultSensor(android_app->sensorManager,
ASENSOR_TYPE_ACCELEROMETER);
android_app->sensorEventQueue =
ASensorManager_createEventQueue(android_app->sensorManager,
android_app->looper, LOOPER_ID_USER, NULL, NULL);
if (!android_app->sensorManager)
android_app->sensorManager = ASensorManager_getInstance();
if (android_app->sensorManager)
{
if (!android_app->accelerometerSensor)
android_app->accelerometerSensor =
ASensorManager_getDefaultSensor(android_app->sensorManager,
ASENSOR_TYPE_ACCELEROMETER);
if (!android_app->gyroscopeSensor)
android_app->gyroscopeSensor =
ASensorManager_getDefaultSensor(android_app->sensorManager,
ASENSOR_TYPE_GYROSCOPE);
if (!android_app->sensorEventQueue)
android_app->sensorEventQueue =
ASensorManager_createEventQueue(android_app->sensorManager,
android_app->looper, LOOPER_ID_USER, NULL, NULL);
}
}
static bool android_input_set_sensor_state(void *data, unsigned port,
enum retro_sensor_action action, unsigned event_rate)
{
struct android_app *android_app = (struct android_app*)g_android;
android_input_t *android = (android_input_t*)data;
if (port > 0)
return false;
if (event_rate == 0)
event_rate = 60;
event_rate = DEFAULT_ASENSOR_EVENT_RATE;
switch (action)
{
@ -1512,28 +1580,74 @@ static bool android_input_set_sensor_state(void *data, unsigned port,
if (!android_app->accelerometerSensor)
android_input_enable_sensor_manager(android_app);
if (android_app->accelerometerSensor)
if (android_app->sensorEventQueue &&
android_app->accelerometerSensor)
{
ASensorEventQueue_enableSensor(android_app->sensorEventQueue,
android_app->accelerometerSensor);
/* Events per second (in microseconds). */
if (android_app->accelerometerSensor)
/* Events per second (in microseconds). */
ASensorEventQueue_setEventRate(android_app->sensorEventQueue,
android_app->accelerometerSensor, (1000L / event_rate)
* 1000);
}
android_app->accelerometer_event_rate = event_rate;
BIT64_CLEAR(android_app->sensor_state_mask, RETRO_SENSOR_ACCELEROMETER_DISABLE);
BIT64_SET(android_app->sensor_state_mask, RETRO_SENSOR_ACCELEROMETER_ENABLE);
return true;
case RETRO_SENSOR_ACCELEROMETER_DISABLE:
if (android_app->accelerometerSensor)
if (android_app->sensorEventQueue &&
android_app->accelerometerSensor)
ASensorEventQueue_disableSensor(android_app->sensorEventQueue,
android_app->accelerometerSensor);
android->accelerometer_state.x = 0.0f;
android->accelerometer_state.y = 0.0f;
android->accelerometer_state.z = 0.0f;
BIT64_CLEAR(android_app->sensor_state_mask, RETRO_SENSOR_ACCELEROMETER_ENABLE);
BIT64_SET(android_app->sensor_state_mask, RETRO_SENSOR_ACCELEROMETER_DISABLE);
return true;
case RETRO_SENSOR_GYROSCOPE_ENABLE:
if (!android_app->gyroscopeSensor)
android_input_enable_sensor_manager(android_app);
if (android_app->sensorEventQueue &&
android_app->gyroscopeSensor)
{
ASensorEventQueue_enableSensor(android_app->sensorEventQueue,
android_app->gyroscopeSensor);
/* Events per second (in microseconds). */
ASensorEventQueue_setEventRate(android_app->sensorEventQueue,
android_app->gyroscopeSensor, (1000L / event_rate)
* 1000);
}
android_app->gyroscope_event_rate = event_rate;
BIT64_CLEAR(android_app->sensor_state_mask, RETRO_SENSOR_GYROSCOPE_DISABLE);
BIT64_SET(android_app->sensor_state_mask, RETRO_SENSOR_GYROSCOPE_ENABLE);
return true;
case RETRO_SENSOR_GYROSCOPE_DISABLE:
if (android_app->sensorEventQueue &&
android_app->gyroscopeSensor)
ASensorEventQueue_disableSensor(android_app->sensorEventQueue,
android_app->gyroscopeSensor);
android->gyroscope_state.x = 0.0f;
android->gyroscope_state.y = 0.0f;
android->gyroscope_state.z = 0.0f;
BIT64_CLEAR(android_app->sensor_state_mask, RETRO_SENSOR_GYROSCOPE_ENABLE);
BIT64_SET(android_app->sensor_state_mask, RETRO_SENSOR_GYROSCOPE_DISABLE);
return true;
default:
break;
}
@ -1542,10 +1656,13 @@ static bool android_input_set_sensor_state(void *data, unsigned port,
}
static float android_input_get_sensor_input(void *data,
unsigned port,unsigned id)
unsigned port, unsigned id)
{
android_input_t *android = (android_input_t*)data;
if (port > 0)
return 0.0f;
switch (id)
{
case RETRO_SENSOR_ACCELEROMETER_X:
@ -1554,9 +1671,15 @@ static float android_input_get_sensor_input(void *data,
return android->accelerometer_state.y;
case RETRO_SENSOR_ACCELEROMETER_Z:
return android->accelerometer_state.z;
case RETRO_SENSOR_GYROSCOPE_X:
return android->gyroscope_state.x;
case RETRO_SENSOR_GYROSCOPE_Y:
return android->gyroscope_state.y;
case RETRO_SENSOR_GYROSCOPE_Z:
return android->gyroscope_state.z;
}
return 0;
return 0.0f;
}
input_driver_t input_android = {

View File

@ -1302,6 +1302,10 @@ MSG_HASH(
MENU_ENUM_LABEL_INPUT_AUTODETECT_ENABLE,
"input_autodetect_enable"
)
MSG_HASH(
MENU_ENUM_LABEL_INPUT_SENSORS_ENABLE,
"input_sensors_enable"
)
MSG_HASH(
MENU_ENUM_LABEL_INPUT_BUTTON_AXIS_THRESHOLD,
"input_axis_threshold"

View File

@ -2010,6 +2010,14 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_AUTODETECT_ENABLE,
"Automatically configures controllers that have a profile, Plug-and-Play style."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_SENSORS_ENABLE,
"Auxiliary Sensor Input"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_SENSORS_ENABLE,
"Enables input from accelerometer, gyroscope and illuminance sensors, if supported by the current hardware. May have a performance impact and/or increase power drain on some platforms."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_BUTTON_AXIS_THRESHOLD,
"Input Button Axis Threshold"

View File

@ -487,6 +487,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_savestate_file_compression, MENU_
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_autosave_interval, MENU_ENUM_SUBLABEL_AUTOSAVE_INTERVAL)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_remap_binds_enable, MENU_ENUM_SUBLABEL_INPUT_REMAP_BINDS_ENABLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_autodetect_enable, MENU_ENUM_SUBLABEL_INPUT_AUTODETECT_ENABLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_sensors_enable, MENU_ENUM_SUBLABEL_INPUT_SENSORS_ENABLE)
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)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_savestate_resume, MENU_ENUM_SUBLABEL_MENU_SAVESTATE_RESUME)
@ -2818,6 +2819,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_INPUT_AUTODETECT_ENABLE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_autodetect_enable);
break;
case MENU_ENUM_LABEL_INPUT_SENSORS_ENABLE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_sensors_enable);
break;
case MENU_ENUM_LABEL_INPUT_REMAP_BINDS_ENABLE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_remap_binds_enable);
break;

View File

@ -5986,6 +5986,10 @@ unsigned menu_displaylist_build_list(
MENU_ENUM_LABEL_INPUT_BIND_MODE,
PARSE_ONLY_UINT, false) == 0)
count++;
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_INPUT_SENSORS_ENABLE,
PARSE_ONLY_BOOL, false) == 0)
count++;
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
MENU_ENUM_LABEL_INPUT_HAPTIC_FEEDBACK_SETTINGS,
PARSE_ACTION, false) == 0)

View File

@ -7296,6 +7296,26 @@ static void general_write_handler(rarch_setting_t *setting)
audio_driver_load_system_sounds();
#endif
break;
case MENU_ENUM_LABEL_INPUT_SENSORS_ENABLE:
/* When toggling sensor input off, ensure
* that all sensors are actually disabled */
if (!*setting->value.target.boolean)
{
size_t i;
for (i = 0; i < DEFAULT_MAX_PADS; i++)
{
/* Event rate does not matter when disabling
* sensors - set to zero */
input_sensor_set_state(i,
RETRO_SENSOR_ACCELEROMETER_DISABLE, 0);
input_sensor_set_state(i,
RETRO_SENSOR_GYROSCOPE_DISABLE, 0);
input_sensor_set_state(i,
RETRO_SENSOR_ILLUMINANCE_DISABLE, 0);
}
}
break;
default:
break;
}
@ -11714,6 +11734,22 @@ static bool setting_append_list(
SD_FLAG_ADVANCED
);
CONFIG_BOOL(
list, list_info,
&settings->bools.input_sensors_enable,
MENU_ENUM_LABEL_INPUT_SENSORS_ENABLE,
MENU_ENUM_LABEL_VALUE_INPUT_SENSORS_ENABLE,
DEFAULT_INPUT_SENSORS_ENABLE,
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
);
#if 0
CONFIG_BOOL(
list, list_info,

View File

@ -909,6 +909,7 @@ enum msg_hash_enums
MENU_LABEL(INPUT_USER_BINDS),
MENU_LABEL(INPUT_DUTY_CYCLE),
MENU_LABEL(INPUT_AUTODETECT_ENABLE),
MENU_LABEL(INPUT_SENSORS_ENABLE),
MENU_LABEL(INPUT_DESCRIPTOR_LABEL_SHOW),
MENU_LABEL(INPUT_DESCRIPTOR_HIDE_UNBOUND),
MENU_LABEL(INPUT_BUTTON_AXIS_THRESHOLD),

View File

@ -19587,10 +19587,15 @@ static bool rarch_environment_cb(unsigned cmd, void *data)
case RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE:
{
struct retro_sensor_interface *iface =
(struct retro_sensor_interface*)data;
settings_t *settings = p_rarch->configuration_settings;
bool input_sensors_enable = settings->bools.input_sensors_enable;
struct retro_sensor_interface *iface = (struct retro_sensor_interface*)data;
RARCH_LOG("[Environ]: GET_SENSOR_INTERFACE.\n");
if (!input_sensors_enable)
return false;
iface->set_sensor_state = input_sensor_set_state;
iface->get_sensor_input = input_sensor_get_input;
break;
@ -23840,6 +23845,17 @@ bool input_sensor_set_state(unsigned port,
enum retro_sensor_action action, unsigned rate)
{
struct rarch_state *p_rarch = &rarch_st;
settings_t *settings = p_rarch->configuration_settings;
bool input_sensors_enable = settings->bools.input_sensors_enable;
/* If sensors are disabled, inhibit any enable
* actions (but always allow disable actions) */
if (!input_sensors_enable &&
((action == RETRO_SENSOR_ACCELEROMETER_ENABLE) ||
(action == RETRO_SENSOR_GYROSCOPE_ENABLE) ||
(action == RETRO_SENSOR_ILLUMINANCE_ENABLE)))
return false;
if (p_rarch->current_input_data &&
p_rarch->current_input->set_sensor_state)
return p_rarch->current_input->set_sensor_state(p_rarch->current_input_data,
@ -23850,8 +23866,12 @@ bool input_sensor_set_state(unsigned port,
float input_sensor_get_input(unsigned port, unsigned id)
{
struct rarch_state *p_rarch = &rarch_st;
if (p_rarch->current_input_data &&
p_rarch->current_input->get_sensor_input)
settings_t *settings = p_rarch->configuration_settings;
bool input_sensors_enable = settings->bools.input_sensors_enable;
if (input_sensors_enable &&
p_rarch->current_input_data &&
p_rarch->current_input->get_sensor_input)
return p_rarch->current_input->get_sensor_input(p_rarch->current_input_data,
port, id);
return 0.0f;