Wait 1 second after input device reconfiguration to enable motion sensors

This commit is contained in:
Cameron Gutman 2023-10-07 21:07:02 -05:00
parent 2243cf2017
commit 5dd80edde4

View File

@ -2099,6 +2099,21 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
InputDeviceContext deviceContext = inputDeviceContexts.valueAt(i); InputDeviceContext deviceContext = inputDeviceContexts.valueAt(i);
if (deviceContext.controllerNumber == controllerNumber) { 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; SensorManager sm = deviceContext.sensorManager;
if (sm == null) { if (sm == null) {
continue; continue;
@ -2116,10 +2131,6 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
if (reportRateHz != 0 && accelSensor != null) { if (reportRateHz != 0 && accelSensor != null) {
deviceContext.accelListener = createSensorListener(controllerNumber, motionType, sm == deviceSensorManager); deviceContext.accelListener = createSensorListener(controllerNumber, motionType, sm == deviceSensorManager);
sm.registerListener(deviceContext.accelListener, accelSensor, 1000000 / reportRateHz); sm.registerListener(deviceContext.accelListener, accelSensor, 1000000 / reportRateHz);
deviceContext.accelReportRateHz = reportRateHz;
}
else {
deviceContext.accelReportRateHz = 0;
} }
break; break;
case MoonBridge.LI_MOTION_TYPE_GYRO: case MoonBridge.LI_MOTION_TYPE_GYRO:
@ -2133,10 +2144,6 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
if (reportRateHz != 0 && gyroSensor != null) { if (reportRateHz != 0 && gyroSensor != null) {
deviceContext.gyroListener = createSensorListener(controllerNumber, motionType, sm == deviceSensorManager); deviceContext.gyroListener = createSensorListener(controllerNumber, motionType, sm == deviceSensorManager);
sm.registerListener(deviceContext.gyroListener, gyroSensor, 1000000 / reportRateHz); sm.registerListener(deviceContext.gyroListener, gyroSensor, 1000000 / reportRateHz);
deviceContext.gyroReportRateHz = reportRateHz;
}
else {
deviceContext.gyroReportRateHz = 0;
} }
break; 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 @Override
public void destroy() { public void destroy() {
super.destroy(); super.destroy();
@ -2840,6 +2860,8 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
vibrator.cancel(); vibrator.cancel();
} }
backgroundThreadHandler.removeCallbacks(enableSensorRunnable);
if (gyroListener != null) { if (gyroListener != null) {
sensorManager.unregisterListener(gyroListener); sensorManager.unregisterListener(gyroListener);
} }
@ -2984,12 +3006,8 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
this.lightsSession = oldContext.lightsSession; this.lightsSession = oldContext.lightsSession;
oldContext.lightsSession = null; oldContext.lightsSession = null;
} }
this.gyroListener = oldContext.gyroListener;
this.accelListener = oldContext.accelListener;
this.gyroReportRateHz = oldContext.gyroReportRateHz; this.gyroReportRateHz = oldContext.gyroReportRateHz;
this.accelReportRateHz = oldContext.accelReportRateHz; 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. // 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 // 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; this.sensorManager = deviceSensorManager;
} }
// Re-enable sensors on the new context
enableSensors();
// Refresh battery state and start the battery state polling again // Refresh battery state and start the battery state polling again
backgroundThreadHandler.post(batteryStateUpdateRunnable); backgroundThreadHandler.post(batteryStateUpdateRunnable);
} }
public void disableSensors() { public void disableSensors() {
// Stop any pending enablement
backgroundThreadHandler.removeCallbacks(enableSensorRunnable);
// Unregister all sensor listeners // Unregister all sensor listeners
if (gyroListener != null) { if (gyroListener != null) {
sensorManager.unregisterListener(gyroListener); sensorManager.unregisterListener(gyroListener);
@ -3028,13 +3052,10 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
} }
public void enableSensors() { public void enableSensors() {
// Turn back on any sensors that should be reporting but are currently unregistered // We allow 1 second for the input device to settle before re-enabling sensors.
if (accelReportRateHz != 0 && accelListener == null) { // Pointer capture can cause the input device to change, which can cause
handleSetMotionEventState(controllerNumber, MoonBridge.LI_MOTION_TYPE_ACCEL, accelReportRateHz); // InputDeviceSensorManager to crash due to missing null checks on the InputDevice.
} backgroundThreadHandler.postDelayed(enableSensorRunnable, 1000);
if (gyroReportRateHz != 0 && gyroListener == null) {
handleSetMotionEventState(controllerNumber, MoonBridge.LI_MOTION_TYPE_GYRO, gyroReportRateHz);
}
} }
} }