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 AxisSetDetails(val firstAxisOfSet: Int, val axisSetType: Int)
|
||||||
|
|
||||||
private class SensorDetails(
|
private class SensorDetails(
|
||||||
|
val sensor: Sensor,
|
||||||
val sensorType: Int,
|
val sensorType: Int,
|
||||||
val axisNames: Array<String>,
|
val axisNames: Array<String>,
|
||||||
val axisSetDetails: Array<AxisSetDetails>
|
val axisSetDetails: Array<AxisSetDetails>
|
||||||
|
@ -28,7 +29,7 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
|
|
||||||
private val sensorManager: SensorManager?
|
private val sensorManager: SensorManager?
|
||||||
|
|
||||||
private val sensorDetails = HashMap<Sensor, SensorDetails>()
|
private val sensorDetails = ArrayList<SensorDetails>()
|
||||||
|
|
||||||
private val rotateCoordinatesForScreenOrientation: Boolean
|
private val rotateCoordinatesForScreenOrientation: Boolean
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
.getSystemService(Context.SENSOR_SERVICE) as SensorManager?
|
.getSystemService(Context.SENSOR_SERVICE) as SensorManager?
|
||||||
rotateCoordinatesForScreenOrientation = true
|
rotateCoordinatesForScreenOrientation = true
|
||||||
addSensors()
|
addSensors()
|
||||||
|
sortSensorDetails()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
|
@ -58,6 +60,7 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
sortSensorDetails()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addSensors() {
|
private fun addSensors() {
|
||||||
|
@ -254,15 +257,22 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
) {
|
) {
|
||||||
val sensor = sensorManager!!.getDefaultSensor(sensorType)
|
val sensor = sensorManager!!.getDefaultSensor(sensorType)
|
||||||
if (sensor != null) {
|
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) {
|
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 values = sensorEvent.values
|
||||||
val axisNames = sensorDetails!!.axisNames
|
val axisNames = sensorDetails.axisNames
|
||||||
val axisSetDetails = sensorDetails.axisSetDetails
|
val axisSetDetails = sensorDetails.axisSetDetails
|
||||||
|
|
||||||
var eventAxisIndex = 0
|
var eventAxisIndex = 0
|
||||||
|
@ -356,7 +366,7 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!keepSensorAlive) {
|
if (!keepSensorAlive) {
|
||||||
setSensorSuspended(sensorEvent.sensor, sensorDetails, true)
|
setSensorSuspended(sensorDetails, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,18 +391,14 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
*/
|
*/
|
||||||
@Keep
|
@Keep
|
||||||
fun requestUnsuspendSensor(axisName: String) {
|
fun requestUnsuspendSensor(axisName: String) {
|
||||||
for ((key, value) in sensorDetails) {
|
for (sd in sensorDetails) {
|
||||||
if (listOf(*value.axisNames).contains(axisName)) {
|
if (listOf(*sd.axisNames).contains(axisName)) {
|
||||||
setSensorSuspended(key, value, false)
|
setSensorSuspended(sd, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setSensorSuspended(
|
private fun setSensorSuspended(sensorDetails: SensorDetails, suspend: Boolean) {
|
||||||
sensor: Sensor,
|
|
||||||
sensorDetails: SensorDetails,
|
|
||||||
suspend: Boolean
|
|
||||||
) {
|
|
||||||
var changeOccurred = false
|
var changeOccurred = false
|
||||||
|
|
||||||
synchronized(sensorDetails) {
|
synchronized(sensorDetails) {
|
||||||
|
@ -404,9 +410,9 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
)
|
)
|
||||||
|
|
||||||
if (suspend)
|
if (suspend)
|
||||||
sensorManager!!.unregisterListener(this, sensor)
|
sensorManager!!.unregisterListener(this, sensorDetails.sensor)
|
||||||
else
|
else
|
||||||
sensorManager!!.registerListener(this, sensor, SAMPLING_PERIOD_US)
|
sensorManager!!.registerListener(this, sensorDetails.sensor, SAMPLING_PERIOD_US)
|
||||||
|
|
||||||
sensorDetails.isSuspended = suspend
|
sensorDetails.isSuspended = suspend
|
||||||
|
|
||||||
|
@ -415,14 +421,14 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changeOccurred) {
|
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
|
@Keep
|
||||||
fun getAxisNames(): Array<String> {
|
fun getAxisNames(): Array<String> {
|
||||||
val axisNames = ArrayList<String>()
|
val axisNames = ArrayList<String>()
|
||||||
for (sensorDetails in sensorDetailsSorted) {
|
for (sensorDetails in sensorDetails) {
|
||||||
sensorDetails.axisNames.forEach { axisNames.add(it) }
|
sensorDetails.axisNames.forEach { axisNames.add(it) }
|
||||||
}
|
}
|
||||||
return axisNames.toArray(arrayOf())
|
return axisNames.toArray(arrayOf())
|
||||||
|
@ -432,7 +438,7 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
fun getNegativeAxes(): BooleanArray {
|
fun getNegativeAxes(): BooleanArray {
|
||||||
val negativeAxes = ArrayList<Boolean>()
|
val negativeAxes = ArrayList<Boolean>()
|
||||||
|
|
||||||
for (sensorDetails in sensorDetailsSorted) {
|
for (sensorDetails in sensorDetails) {
|
||||||
var eventAxisIndex = 0
|
var eventAxisIndex = 0
|
||||||
var detailsAxisIndex = 0
|
var detailsAxisIndex = 0
|
||||||
var detailsAxisSetIndex = 0
|
var detailsAxisSetIndex = 0
|
||||||
|
@ -467,22 +473,13 @@ class DolphinSensorEventListener : SensorEventListener {
|
||||||
return result
|
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 {
|
companion object {
|
||||||
// Set of three axes. Creates a negative companion to each axis, and corrects for device rotation.
|
// 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
|
private const val AXIS_SET_TYPE_DEVICE_COORDINATES = 0
|
||||||
|
|
||||||
// Set of three axes. Creates a negative companion to each axis.
|
// Set of three axes. Creates a negative companion to each axis.
|
||||||
private const val AXIS_SET_TYPE_OTHER_COORDINATES = 1
|
private const val AXIS_SET_TYPE_OTHER_COORDINATES = 1
|
||||||
|
|
||||||
private var deviceRotation = Surface.ROTATION_0
|
private var deviceRotation = Surface.ROTATION_0
|
||||||
|
|
||||||
// The fastest sampling rate Android lets us use without declaring the HIGH_SAMPLING_RATE_SENSORS
|
// 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) {
|
fun setDeviceRotation(deviceRotation: Int) {
|
||||||
this.deviceRotation = deviceRotation
|
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