ControllerInterface/Android: Implement sensor input for InputDevices

This functionality was added in Android 12 to let apps get motion data
for gamepads.
This commit is contained in:
JosJuice
2022-09-16 23:02:30 +02:00
parent 5e51b56d72
commit 36acb17700
5 changed files with 118 additions and 37 deletions

View File

@ -67,7 +67,8 @@ public final class ControllerInterface
/**
* {@link DolphinSensorEventListener} calls this for each axis of a received SensorEvent.
*/
public static native void dispatchSensorEvent(String axisName, float value);
public static native void dispatchSensorEvent(String deviceQualifier, String axisName,
float value);
/**
* Enables delivering sensor events to native code.

View File

@ -6,6 +6,7 @@ import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.view.InputDevice;
import android.view.Surface;
import androidx.annotation.Keep;
@ -55,6 +56,10 @@ public class DolphinSensorEventListener implements SensorEventListener
private final HashMap<Sensor, SensorDetails> mSensorDetails = new HashMap<>();
private final boolean mRotateCoordinatesForScreenOrientation;
private String mDeviceQualifier = "";
private SensorEventRequester mRequester = null;
// The fastest sampling rate Android lets us use without declaring the HIGH_SAMPLING_RATE_SENSORS
@ -66,10 +71,28 @@ public class DolphinSensorEventListener implements SensorEventListener
{
mSensorManager = (SensorManager)
DolphinApplication.getAppContext().getSystemService(Context.SENSOR_SERVICE);
mRotateCoordinatesForScreenOrientation = true;
addSensors();
}
@Keep
public DolphinSensorEventListener(InputDevice inputDevice)
{
mRotateCoordinatesForScreenOrientation = false;
if (Build.VERSION.SDK_INT >= 31)
{
mSensorManager = inputDevice.getSensorManager();
addSensors();
}
else
{
mSensorManager = null;
}
}
private void addSensors()
{
tryAddSensor(Sensor.TYPE_ACCELEROMETER, new String[]{"Accel Right", "Accel Left",
@ -201,7 +224,8 @@ public class DolphinSensorEventListener implements SensorEventListener
axisSetDetails[detailsAxisSetIndex].firstAxisOfSet == eventAxisIndex)
{
int rotation = Surface.ROTATION_0;
if (axisSetDetails[detailsAxisSetIndex].axisSetType == AXIS_SET_TYPE_DEVICE_COORDINATES)
if (mRotateCoordinatesForScreenOrientation &&
axisSetDetails[detailsAxisSetIndex].axisSetType == AXIS_SET_TYPE_DEVICE_COORDINATES)
{
rotation = mRequester.getDisplay().getRotation();
}
@ -230,12 +254,17 @@ public class DolphinSensorEventListener implements SensorEventListener
float z = values[eventAxisIndex + 2];
ControllerInterface.dispatchSensorEvent(axisNames[detailsAxisIndex], x);
ControllerInterface.dispatchSensorEvent(axisNames[detailsAxisIndex + 1], x);
ControllerInterface.dispatchSensorEvent(axisNames[detailsAxisIndex + 2], y);
ControllerInterface.dispatchSensorEvent(axisNames[detailsAxisIndex + 3], y);
ControllerInterface.dispatchSensorEvent(axisNames[detailsAxisIndex + 4], z);
ControllerInterface.dispatchSensorEvent(axisNames[detailsAxisIndex + 5], z);
ControllerInterface.dispatchSensorEvent(mDeviceQualifier, axisNames[detailsAxisIndex], x);
ControllerInterface.dispatchSensorEvent(mDeviceQualifier, axisNames[detailsAxisIndex + 1],
x);
ControllerInterface.dispatchSensorEvent(mDeviceQualifier, axisNames[detailsAxisIndex + 2],
y);
ControllerInterface.dispatchSensorEvent(mDeviceQualifier, axisNames[detailsAxisIndex + 3],
y);
ControllerInterface.dispatchSensorEvent(mDeviceQualifier, axisNames[detailsAxisIndex + 4],
z);
ControllerInterface.dispatchSensorEvent(mDeviceQualifier, axisNames[detailsAxisIndex + 5],
z);
eventAxisIndex += 3;
detailsAxisIndex += 6;
@ -243,7 +272,7 @@ public class DolphinSensorEventListener implements SensorEventListener
}
else
{
ControllerInterface.dispatchSensorEvent(axisNames[detailsAxisIndex],
ControllerInterface.dispatchSensorEvent(mDeviceQualifier, axisNames[detailsAxisIndex],
values[eventAxisIndex]);
eventAxisIndex++;
@ -258,6 +287,16 @@ public class DolphinSensorEventListener implements SensorEventListener
// We don't care about this
}
/**
* The device qualifier set here will be passed on to native code,
* for the purpose of letting native code identify which device this object belongs to.
*/
@Keep
public void setDeviceQualifier(String deviceQualifier)
{
mDeviceQualifier = deviceQualifier;
}
/**
* Enables delivering sensor events to native code.
*
@ -275,9 +314,12 @@ public class DolphinSensorEventListener implements SensorEventListener
mRequester = requester;
for (Sensor sensor : mSensorDetails.keySet())
if (mSensorManager != null)
{
mSensorManager.registerListener(this, sensor, SAMPLING_PERIOD_US);
for (Sensor sensor : mSensorDetails.keySet())
{
mSensorManager.registerListener(this, sensor, SAMPLING_PERIOD_US);
}
}
}
@ -291,7 +333,10 @@ public class DolphinSensorEventListener implements SensorEventListener
{
mRequester = null;
mSensorManager.unregisterListener(this);
if (mSensorManager != null)
{
mSensorManager.unregisterListener(this);
}
}
@Keep