From 5dd80edde4f42db4e69313783ceb5b73513a43f0 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 7 Oct 2023 21:07:02 -0500 Subject: [PATCH] Wait 1 second after input device reconfiguration to enable motion sensors --- .../binding/input/ControllerHandler.java | 59 +++++++++++++------ 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/limelight/binding/input/ControllerHandler.java b/app/src/main/java/com/limelight/binding/input/ControllerHandler.java index 84e87fef..5d1c5026 100644 --- a/app/src/main/java/com/limelight/binding/input/ControllerHandler.java +++ b/app/src/main/java/com/limelight/binding/input/ControllerHandler.java @@ -2099,6 +2099,21 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD InputDeviceContext deviceContext = inputDeviceContexts.valueAt(i); if (deviceContext.controllerNumber == controllerNumber) { + // Store the desired report rate even if we don't have sensors. In some cases, + // input devices can be reconfigured at runtime which results in a change where + // sensors disappear and reappear. By storing the desired report rate, we can + // reapply the desired motion sensor configuration after they reappear. + switch (motionType) { + case MoonBridge.LI_MOTION_TYPE_ACCEL: + deviceContext.accelReportRateHz = reportRateHz; + break; + case MoonBridge.LI_MOTION_TYPE_GYRO: + deviceContext.gyroReportRateHz = reportRateHz; + break; + } + + backgroundThreadHandler.removeCallbacks(deviceContext.enableSensorRunnable); + SensorManager sm = deviceContext.sensorManager; if (sm == null) { continue; @@ -2116,10 +2131,6 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD if (reportRateHz != 0 && accelSensor != null) { deviceContext.accelListener = createSensorListener(controllerNumber, motionType, sm == deviceSensorManager); sm.registerListener(deviceContext.accelListener, accelSensor, 1000000 / reportRateHz); - deviceContext.accelReportRateHz = reportRateHz; - } - else { - deviceContext.accelReportRateHz = 0; } break; case MoonBridge.LI_MOTION_TYPE_GYRO: @@ -2133,10 +2144,6 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD if (reportRateHz != 0 && gyroSensor != null) { deviceContext.gyroListener = createSensorListener(controllerNumber, motionType, sm == deviceSensorManager); sm.registerListener(deviceContext.gyroListener, gyroSensor, 1000000 / reportRateHz); - deviceContext.gyroReportRateHz = reportRateHz; - } - else { - deviceContext.gyroReportRateHz = 0; } break; } @@ -2829,6 +2836,19 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD } }; + public final Runnable enableSensorRunnable = new Runnable() { + @Override + public void run() { + // Turn back on any sensors that should be reporting but are currently unregistered + if (accelReportRateHz != 0 && accelListener == null) { + handleSetMotionEventState(controllerNumber, MoonBridge.LI_MOTION_TYPE_ACCEL, accelReportRateHz); + } + if (gyroReportRateHz != 0 && gyroListener == null) { + handleSetMotionEventState(controllerNumber, MoonBridge.LI_MOTION_TYPE_GYRO, gyroReportRateHz); + } + } + }; + @Override public void destroy() { super.destroy(); @@ -2840,6 +2860,8 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD vibrator.cancel(); } + backgroundThreadHandler.removeCallbacks(enableSensorRunnable); + if (gyroListener != null) { sensorManager.unregisterListener(gyroListener); } @@ -2984,12 +3006,8 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD this.lightsSession = oldContext.lightsSession; oldContext.lightsSession = null; } - this.gyroListener = oldContext.gyroListener; - this.accelListener = oldContext.accelListener; this.gyroReportRateHz = oldContext.gyroReportRateHz; this.accelReportRateHz = oldContext.accelReportRateHz; - oldContext.gyroListener = null; - oldContext.accelListener = null; // Don't release the controller number, because we will carry it over if it is present. // We also want to make sure the change is invisible to the host PC to avoid an add/remove @@ -3006,11 +3024,17 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD this.sensorManager = deviceSensorManager; } + // Re-enable sensors on the new context + enableSensors(); + // Refresh battery state and start the battery state polling again backgroundThreadHandler.post(batteryStateUpdateRunnable); } public void disableSensors() { + // Stop any pending enablement + backgroundThreadHandler.removeCallbacks(enableSensorRunnable); + // Unregister all sensor listeners if (gyroListener != null) { sensorManager.unregisterListener(gyroListener); @@ -3028,13 +3052,10 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD } public void enableSensors() { - // Turn back on any sensors that should be reporting but are currently unregistered - if (accelReportRateHz != 0 && accelListener == null) { - handleSetMotionEventState(controllerNumber, MoonBridge.LI_MOTION_TYPE_ACCEL, accelReportRateHz); - } - if (gyroReportRateHz != 0 && gyroListener == null) { - handleSetMotionEventState(controllerNumber, MoonBridge.LI_MOTION_TYPE_GYRO, gyroReportRateHz); - } + // We allow 1 second for the input device to settle before re-enabling sensors. + // Pointer capture can cause the input device to change, which can cause + // InputDeviceSensorManager to crash due to missing null checks on the InputDevice. + backgroundThreadHandler.postDelayed(enableSensorRunnable, 1000); } }