Android: Add workaround for AOSP input device sensor suspend bug
This commit is contained in:
parent
7b0a7f15b0
commit
59cbe5a843
|
@ -25,6 +25,7 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
val axisSetDetails: Array<AxisSetDetails>
|
val axisSetDetails: Array<AxisSetDetails>
|
||||||
) {
|
) {
|
||||||
var isSuspended = true
|
var isSuspended = true
|
||||||
|
var hasRegisteredListener = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private val sensorManager: SensorManager?
|
private val sensorManager: SensorManager?
|
||||||
|
@ -33,6 +34,16 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
|
|
||||||
private val rotateCoordinatesForScreenOrientation: Boolean
|
private val rotateCoordinatesForScreenOrientation: Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AOSP has a bug in InputDeviceSensorManager where
|
||||||
|
* InputSensorEventListenerDelegate.removeSensor attempts to modify an ArrayList it's iterating
|
||||||
|
* through in a way that throws a ConcurrentModificationException. Because of this, we can't
|
||||||
|
* suspend individual sensors for InputDevices, but we can suspend all sensors at once.
|
||||||
|
*/
|
||||||
|
private val canSuspendSensorsIndividually: Boolean
|
||||||
|
|
||||||
|
private var unsuspendedSensors = 0
|
||||||
|
|
||||||
private var deviceQualifier = ""
|
private var deviceQualifier = ""
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
|
@ -40,6 +51,7 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
sensorManager = DolphinApplication.getAppContext()
|
sensorManager = DolphinApplication.getAppContext()
|
||||||
.getSystemService(Context.SENSOR_SERVICE) as SensorManager?
|
.getSystemService(Context.SENSOR_SERVICE) as SensorManager?
|
||||||
rotateCoordinatesForScreenOrientation = true
|
rotateCoordinatesForScreenOrientation = true
|
||||||
|
canSuspendSensorsIndividually = true
|
||||||
addSensors()
|
addSensors()
|
||||||
sortSensorDetails()
|
sortSensorDetails()
|
||||||
}
|
}
|
||||||
|
@ -47,6 +59,7 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
@Keep
|
@Keep
|
||||||
constructor(inputDevice: InputDevice) {
|
constructor(inputDevice: InputDevice) {
|
||||||
rotateCoordinatesForScreenOrientation = false
|
rotateCoordinatesForScreenOrientation = false
|
||||||
|
canSuspendSensorsIndividually = false
|
||||||
sensorManager = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
sensorManager = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
inputDevice.sensorManager
|
inputDevice.sensorManager
|
||||||
|
|
||||||
|
@ -409,10 +422,46 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
suspend
|
suspend
|
||||||
)
|
)
|
||||||
|
|
||||||
if (suspend)
|
if (suspend) {
|
||||||
|
unsuspendedSensors -= 1
|
||||||
|
} else {
|
||||||
|
unsuspendedSensors += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canSuspendSensorsIndividually) {
|
||||||
|
if (suspend) {
|
||||||
sensorManager!!.unregisterListener(this, sensorDetails.sensor)
|
sensorManager!!.unregisterListener(this, sensorDetails.sensor)
|
||||||
else
|
} else {
|
||||||
sensorManager!!.registerListener(this, sensorDetails.sensor, SAMPLING_PERIOD_US)
|
sensorManager!!.registerListener(
|
||||||
|
this,
|
||||||
|
sensorDetails.sensor,
|
||||||
|
SAMPLING_PERIOD_US
|
||||||
|
)
|
||||||
|
}
|
||||||
|
sensorDetails.hasRegisteredListener = !suspend
|
||||||
|
} else {
|
||||||
|
if (suspend) {
|
||||||
|
// If there are no unsuspended sensors left, unregister them all.
|
||||||
|
// Otherwise, leave unregistering for later. A possible alternative could be
|
||||||
|
// to unregister everything and then re-register the sensors we still want,
|
||||||
|
// but I fear this could lead to dropped inputs.
|
||||||
|
if (unsuspendedSensors == 0) {
|
||||||
|
sensorManager!!.unregisterListener(this)
|
||||||
|
for (sd in this.sensorDetails) {
|
||||||
|
sd.hasRegisteredListener = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!sensorDetails.hasRegisteredListener) {
|
||||||
|
sensorManager!!.registerListener(
|
||||||
|
this,
|
||||||
|
sensorDetails.sensor,
|
||||||
|
SAMPLING_PERIOD_US
|
||||||
|
)
|
||||||
|
sensorDetails.hasRegisteredListener = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sensorDetails.isSuspended = suspend
|
sensorDetails.isSuspended = suspend
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue