Android: Use structural equality for sensorDetails
To fix the crash in input device sensor handling, we should look up Sensors using structural equality. Unfortunately, Sensor.equals implements referential equality, and HashMap doesn't let us provide a custom comparator. Because the number of sensors is relatively small, and because we have a reason to keep a sorted list of sensors around anyway, let's switch from HashMap to ArrayList.
This commit is contained in:
parent
87b7009c12
commit
7b0a7f15b0
|
@ -19,6 +19,7 @@ class DolphinSensorEventListener : SensorEventListener {
|
|||
private class AxisSetDetails(val firstAxisOfSet: Int, val axisSetType: Int)
|
||||
|
||||
private class SensorDetails(
|
||||
val sensor: Sensor,
|
||||
val sensorType: Int,
|
||||
val axisNames: Array<String>,
|
||||
val axisSetDetails: Array<AxisSetDetails>
|
||||
|
@ -28,7 +29,7 @@ class DolphinSensorEventListener : SensorEventListener {
|
|||
|
||||
private val sensorManager: SensorManager?
|
||||
|
||||
private val sensorDetails = HashMap<Sensor, SensorDetails>()
|
||||
private val sensorDetails = ArrayList<SensorDetails>()
|
||||
|
||||
private val rotateCoordinatesForScreenOrientation: Boolean
|
||||
|
||||
|
@ -40,6 +41,7 @@ class DolphinSensorEventListener : SensorEventListener {
|
|||
.getSystemService(Context.SENSOR_SERVICE) as SensorManager?
|
||||
rotateCoordinatesForScreenOrientation = true
|
||||
addSensors()
|
||||
sortSensorDetails()
|
||||
}
|
||||
|
||||
@Keep
|
||||
|
@ -58,6 +60,7 @@ class DolphinSensorEventListener : SensorEventListener {
|
|||
} else {
|
||||
null
|
||||
}
|
||||
sortSensorDetails()
|
||||
}
|
||||
|
||||
private fun addSensors() {
|
||||
|
@ -254,15 +257,22 @@ class DolphinSensorEventListener : SensorEventListener {
|
|||
) {
|
||||
val sensor = sensorManager!!.getDefaultSensor(sensorType)
|
||||
if (sensor != null) {
|
||||
sensorDetails[sensor] = SensorDetails(sensorType, axisNames, axisSetDetails)
|
||||
sensorDetails.add(SensorDetails(sensor, sensorType, axisNames, axisSetDetails))
|
||||
}
|
||||
}
|
||||
|
||||
private fun sortSensorDetails() {
|
||||
Collections.sort(
|
||||
sensorDetails,
|
||||
Comparator.comparingInt { s: SensorDetails -> s.sensorType }
|
||||
)
|
||||
}
|
||||
|
||||
override fun onSensorChanged(sensorEvent: SensorEvent) {
|
||||
val sensorDetails = sensorDetails[sensorEvent.sensor]
|
||||
val sensorDetails = sensorDetails.first{s -> sensorsAreEqual(s.sensor, sensorEvent.sensor)}
|
||||
|
||||
val values = sensorEvent.values
|
||||
val axisNames = sensorDetails!!.axisNames
|
||||
val axisNames = sensorDetails.axisNames
|
||||
val axisSetDetails = sensorDetails.axisSetDetails
|
||||
|
||||
var eventAxisIndex = 0
|
||||
|
@ -356,7 +366,7 @@ class DolphinSensorEventListener : SensorEventListener {
|
|||
}
|
||||
}
|
||||
if (!keepSensorAlive) {
|
||||
setSensorSuspended(sensorEvent.sensor, sensorDetails, true)
|
||||
setSensorSuspended(sensorDetails, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,18 +391,14 @@ class DolphinSensorEventListener : SensorEventListener {
|
|||
*/
|
||||
@Keep
|
||||
fun requestUnsuspendSensor(axisName: String) {
|
||||
for ((key, value) in sensorDetails) {
|
||||
if (listOf(*value.axisNames).contains(axisName)) {
|
||||
setSensorSuspended(key, value, false)
|
||||
for (sd in sensorDetails) {
|
||||
if (listOf(*sd.axisNames).contains(axisName)) {
|
||||
setSensorSuspended(sd, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setSensorSuspended(
|
||||
sensor: Sensor,
|
||||
sensorDetails: SensorDetails,
|
||||
suspend: Boolean
|
||||
) {
|
||||
private fun setSensorSuspended(sensorDetails: SensorDetails, suspend: Boolean) {
|
||||
var changeOccurred = false
|
||||
|
||||
synchronized(sensorDetails) {
|
||||
|
@ -404,9 +410,9 @@ class DolphinSensorEventListener : SensorEventListener {
|
|||
)
|
||||
|
||||
if (suspend)
|
||||
sensorManager!!.unregisterListener(this, sensor)
|
||||
sensorManager!!.unregisterListener(this, sensorDetails.sensor)
|
||||
else
|
||||
sensorManager!!.registerListener(this, sensor, SAMPLING_PERIOD_US)
|
||||
sensorManager!!.registerListener(this, sensorDetails.sensor, SAMPLING_PERIOD_US)
|
||||
|
||||
sensorDetails.isSuspended = suspend
|
||||
|
||||
|
@ -415,14 +421,14 @@ class DolphinSensorEventListener : SensorEventListener {
|
|||
}
|
||||
|
||||
if (changeOccurred) {
|
||||
Log.info((if (suspend) "Suspended sensor " else "Unsuspended sensor ") + sensor.name)
|
||||
Log.info((if (suspend) "Suspended sensor " else "Unsuspended sensor ") + sensorDetails.sensor.name)
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
fun getAxisNames(): Array<String> {
|
||||
val axisNames = ArrayList<String>()
|
||||
for (sensorDetails in sensorDetailsSorted) {
|
||||
for (sensorDetails in sensorDetails) {
|
||||
sensorDetails.axisNames.forEach { axisNames.add(it) }
|
||||
}
|
||||
return axisNames.toArray(arrayOf())
|
||||
|
@ -432,7 +438,7 @@ class DolphinSensorEventListener : SensorEventListener {
|
|||
fun getNegativeAxes(): BooleanArray {
|
||||
val negativeAxes = ArrayList<Boolean>()
|
||||
|
||||
for (sensorDetails in sensorDetailsSorted) {
|
||||
for (sensorDetails in sensorDetails) {
|
||||
var eventAxisIndex = 0
|
||||
var detailsAxisIndex = 0
|
||||
var detailsAxisSetIndex = 0
|
||||
|
@ -467,22 +473,13 @@ class DolphinSensorEventListener : SensorEventListener {
|
|||
return result
|
||||
}
|
||||
|
||||
private val sensorDetailsSorted: List<SensorDetails>
|
||||
get() {
|
||||
val sensorDetails = ArrayList(sensorDetails.values)
|
||||
Collections.sort(
|
||||
sensorDetails,
|
||||
Comparator.comparingInt { s: SensorDetails -> s.sensorType }
|
||||
)
|
||||
return sensorDetails
|
||||
}
|
||||
|
||||
companion object {
|
||||
// Set of three axes. Creates a negative companion to each axis, and corrects for device rotation.
|
||||
private const val AXIS_SET_TYPE_DEVICE_COORDINATES = 0
|
||||
|
||||
// Set of three axes. Creates a negative companion to each axis.
|
||||
private const val AXIS_SET_TYPE_OTHER_COORDINATES = 1
|
||||
|
||||
private var deviceRotation = Surface.ROTATION_0
|
||||
|
||||
// The fastest sampling rate Android lets us use without declaring the HIGH_SAMPLING_RATE_SENSORS
|
||||
|
@ -500,5 +497,13 @@ class DolphinSensorEventListener : SensorEventListener {
|
|||
fun setDeviceRotation(deviceRotation: Int) {
|
||||
this.deviceRotation = deviceRotation
|
||||
}
|
||||
|
||||
private fun sensorsAreEqual(s1: Sensor, s2: Sensor): Boolean {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && s1.id > 0 && s2.id > 0) {
|
||||
s1.type == s2.type && s1.id == s2.id
|
||||
} else {
|
||||
s1.type == s2.type && s1.name == s2.name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue