Open janusw opened 4 years ago
After doing some git archeology, I found that the iOS numbers were first introduced with the OrientationSensor
implementation (#249). Btw, the OrientationSensor is also where I noticed the differences.
The OrientationSensor
was initially implemented with commit 3432c0e65929a445acaa71f0b9bdf972a8d03ed6, which includes a revealing comment in OrientationSensor.ios.cs
:
// Timing intervales to match android sensor speeds in seconds
// https://stackoverflow.com/questions/10044158/android-sensors
So, first of all I'm glad that there was the desire to match the Android sensor speeds :)
However, looking at https://stackoverflow.com/questions/10044158/android-sensors, the Xamarin iOS values apparently come from the top-rated answer, which only has approximations based on test results. Also it's from 2013.
The second answer also quotes the numbers from https://developer.android.com/guide/topics/sensors/sensors_overview, which I could even verify by measurement (for the fastest interval I actually get values around 5ms on my Zenfone 6 with Android 10).
So I assume the numbers in the Stackoverflow thread are simply wrong (either measured incorrectly, or outdated).
It seems that one should not use an actual zero for the sensor interval (at least not on UWP, where a zero is used to turn off the sensor, see #419).
UWP used even other values originally (neither agreeing with Android nor iOS), but after the values were unified in 1806eb9f7544f54f19ffc02e32cc110c8ba134bb, UWP uses the same values as iOS.
Tizen still uses yet another set of values, but some of them actually agree with Android already :)
The biggest problem here, apart from the sensor rates simply differing across platforms, is that the rates on iOS are systematically lower than on Android, and in some cases just loo low.
In particular the interval of 20ms for SensorSpeed.Fastest corresponds to an update rate of 50 Hz, which is even lower than the typical screen refresh rates of modern devices (often 60 Hz or even above).
While it's always possible to down-sample a high rate to something lower (e.g. via Reactive Observables), the opposite is impossible, of course.
Let's say we're aiming at a sensor rate of 60 Hz, matching a device's screen refresh rate (in order to achieve a visual appearance that's as smooth as possible, e.g. for an augmented-reality display that relies on OrientationSensor data) ...
SensorSpeed.Fastest
, providing a rate of 200 Hz or more, and down-sample that to the desired 60 Hz (in order to avoid wasting CPU cycles for more frequent updates that can not even be displayed).SensorSpeed.Fastest
only provides 50 Hz, and this is the highest we can get from Xamarin.Essentials, so we'll never get up to 60 Hz.By that argument, SensorSpeed.Fastest
should really correspond to the highest rate possible. The 5 ms interval used in my patch (see above) is already a big improvement over the 20 ms that XE uses for iOS and UWP right now, and it would even be sufficient for the latest devices with a 120 Hz screen.
However, one should probably check whether it's possible to achieve even higher sampling rates on iOS (as a reminder: the 5 ms were the maximum I could achieve on an Android 10 device).
However, one should probably check whether it's possible to achieve even higher sampling rates on iOS (as a reminder: the 5 ms were the maximum I could achieve on an Android 10 device).
On iOS, the smallest interval I can measure is roughly 9 ms, which is about double of the value on Android (roughly 4.5 ms).
I verified that the interval with SensorSpeed.Fastest
is 4 - 4.5 ms not only on Android 10, but also on also on an older device with Android 6.
Also I have extended the XE samples app to measure the interval of the OrientationSensor (see #1439).
Description
Looking at https://github.com/xamarin/Essentials/blob/main/Xamarin.Essentials/Types/SensorSpeed.ios.tvos.watchos.cs, one can see the following SensorSpeed intervals for iOS:
SensorSpeed.Default
: 225msSensorSpeed.UI
: 80msSensorSpeed.Game
: 40msSensorSpeed.Fastest
: 20ms(The source code does not give any hint as to where these numbers come from.)
On Android, in contrast, there are no hard-coded numbers, but instead one relies on
Android.Hardware.SensorDelay
. According to https://developer.android.com/guide/topics/sensors/sensors_overview, the Android intervals are defined like this:SENSOR_DELAY_NORMAL
: 200msSENSOR_DELAY_UI
: 60msSENSOR_DELAY_GAME
: 20msSENSOR_DELAY_FASTEST
: 0msIdeally the sensor intervals should be the same on all platforms, I guess. However, as one can see above, they differ considerably between Android and iOS (in particular the smaller intervals).
Basic Information