PlatformSensor.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. package org.chromium.device.sensors;
  5. import android.hardware.Sensor;
  6. import android.hardware.SensorEvent;
  7. import android.hardware.SensorEventListener;
  8. import android.hardware.SensorManager;
  9. import androidx.annotation.GuardedBy;
  10. import org.chromium.base.Log;
  11. import org.chromium.base.annotations.CalledByNative;
  12. import org.chromium.base.annotations.JNINamespace;
  13. import org.chromium.base.annotations.NativeMethods;
  14. import org.chromium.device.mojom.ReportingMode;
  15. import org.chromium.device.mojom.SensorType;
  16. import java.util.List;
  17. /**
  18. * Implementation of PlatformSensor that uses Android Sensor Framework. Lifetime is controlled by
  19. * the device::PlatformSensorAndroid.
  20. */
  21. @JNINamespace("device")
  22. public class PlatformSensor implements SensorEventListener {
  23. private static final double MICROSECONDS_IN_SECOND = 1000000;
  24. private static final double SECONDS_IN_MICROSECOND = 0.000001d;
  25. private static final double SECONDS_IN_NANOSECOND = 0.000000001d;
  26. private static final String TAG = "PlatformSensor";
  27. /**
  28. * The SENSOR_FREQUENCY_NORMAL is defined as 5Hz which corresponds to a polling delay
  29. * @see android.hardware.SensorManager.SENSOR_DELAY_NORMAL value that is defined as 200000
  30. * microseconds.
  31. */
  32. private static final double SENSOR_FREQUENCY_NORMAL = 5.0d;
  33. /**
  34. * Lock protecting access to mNativePlatformSensorAndroid.
  35. */
  36. private final Object mLock = new Object();
  37. /**
  38. * Identifier of device::PlatformSensorAndroid instance.
  39. */
  40. @GuardedBy("mLock")
  41. private long mNativePlatformSensorAndroid;
  42. /**
  43. * Used for fetching sensor reading values and obtaining information about the sensor.
  44. * @see android.hardware.Sensor
  45. */
  46. private final Sensor mSensor;
  47. /**
  48. * The minimum delay between two readings in microseconds that is supported by the sensor.
  49. */
  50. private final int mMinDelayUsec;
  51. /**
  52. * The number of sensor reading values required from the sensor.
  53. */
  54. private final int mReadingCount;
  55. /**
  56. * Frequncy that is currently used by the sensor for polling.
  57. */
  58. private double mCurrentPollingFrequency;
  59. /**
  60. * Provides shared SensorManager and event processing thread Handler to PlatformSensor objects.
  61. */
  62. private final PlatformSensorProvider mProvider;
  63. /**
  64. * Creates new PlatformSensor.
  65. *
  66. * @param provider object that shares SensorManager and polling thread Handler with sensors.
  67. * @param sensorType type of the sensor to be constructed. @see android.hardware.Sensor.TYPE_*
  68. * @param nativePlatformSensorAndroid identifier of device::PlatformSensorAndroid instance.
  69. */
  70. @CalledByNative
  71. public static PlatformSensor create(
  72. PlatformSensorProvider provider, int type, long nativePlatformSensorAndroid) {
  73. SensorManager sensorManager = provider.getSensorManager();
  74. if (sensorManager == null) return null;
  75. List<Sensor> sensors;
  76. int readingCount;
  77. switch (type) {
  78. case SensorType.AMBIENT_LIGHT:
  79. sensors = sensorManager.getSensorList(Sensor.TYPE_LIGHT);
  80. readingCount = 1;
  81. break;
  82. case SensorType.ACCELEROMETER:
  83. sensors = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
  84. readingCount = 3;
  85. break;
  86. case SensorType.LINEAR_ACCELERATION:
  87. sensors = sensorManager.getSensorList(Sensor.TYPE_LINEAR_ACCELERATION);
  88. readingCount = 3;
  89. break;
  90. case SensorType.GRAVITY:
  91. sensors = sensorManager.getSensorList(Sensor.TYPE_GRAVITY);
  92. readingCount = 3;
  93. break;
  94. case SensorType.GYROSCOPE:
  95. sensors = sensorManager.getSensorList(Sensor.TYPE_GYROSCOPE);
  96. readingCount = 3;
  97. break;
  98. case SensorType.MAGNETOMETER:
  99. sensors = sensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
  100. readingCount = 3;
  101. break;
  102. case SensorType.ABSOLUTE_ORIENTATION_QUATERNION:
  103. sensors = sensorManager.getSensorList(Sensor.TYPE_ROTATION_VECTOR);
  104. readingCount = 4;
  105. break;
  106. case SensorType.RELATIVE_ORIENTATION_QUATERNION:
  107. sensors = sensorManager.getSensorList(Sensor.TYPE_GAME_ROTATION_VECTOR);
  108. readingCount = 4;
  109. break;
  110. default:
  111. return null;
  112. }
  113. if (sensors.isEmpty()) return null;
  114. return new PlatformSensor(
  115. sensors.get(0), readingCount, provider, nativePlatformSensorAndroid);
  116. }
  117. /**
  118. * Constructor.
  119. */
  120. protected PlatformSensor(Sensor sensor, int readingCount, PlatformSensorProvider provider,
  121. long nativePlatformSensorAndroid) {
  122. mReadingCount = readingCount;
  123. mProvider = provider;
  124. mSensor = sensor;
  125. mNativePlatformSensorAndroid = nativePlatformSensorAndroid;
  126. mMinDelayUsec = mSensor.getMinDelay();
  127. }
  128. /**
  129. * Returns reporting mode supported by the sensor.
  130. *
  131. * @return ReportingMode reporting mode.
  132. */
  133. @CalledByNative
  134. protected int getReportingMode() {
  135. return mSensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS
  136. ? ReportingMode.CONTINUOUS
  137. : ReportingMode.ON_CHANGE;
  138. }
  139. /**
  140. * Returns default configuration supported by the sensor. Currently only frequency is supported.
  141. *
  142. * @return double frequency.
  143. */
  144. @CalledByNative
  145. protected double getDefaultConfiguration() {
  146. return SENSOR_FREQUENCY_NORMAL;
  147. }
  148. /**
  149. * Returns maximum sampling frequency supported by the sensor.
  150. *
  151. * @return double frequency in Hz.
  152. */
  153. @CalledByNative
  154. protected double getMaximumSupportedFrequency() {
  155. if (mMinDelayUsec == 0) return getDefaultConfiguration();
  156. return 1 / (mMinDelayUsec * SECONDS_IN_MICROSECOND);
  157. }
  158. /**
  159. * Requests sensor to start polling for data.
  160. *
  161. * @return boolean true if successful, false otherwise.
  162. */
  163. @CalledByNative
  164. protected boolean startSensor(double frequency) {
  165. // If we already polling hw with same frequency, do not restart the sensor.
  166. if (mCurrentPollingFrequency == frequency) return true;
  167. // Unregister old listener if polling frequency has changed.
  168. unregisterListener();
  169. mProvider.sensorStarted(this);
  170. boolean sensorStarted;
  171. try {
  172. sensorStarted = mProvider.getSensorManager().registerListener(
  173. this, mSensor, getSamplingPeriod(frequency), mProvider.getHandler());
  174. } catch (RuntimeException e) {
  175. // This can fail due to internal framework errors. https://crbug.com/884190
  176. Log.w(TAG, "Failed to register sensor listener.", e);
  177. sensorStarted = false;
  178. }
  179. if (!sensorStarted) {
  180. stopSensor();
  181. return sensorStarted;
  182. }
  183. mCurrentPollingFrequency = frequency;
  184. return sensorStarted;
  185. }
  186. private void unregisterListener() {
  187. // Do not unregister if current polling frequency is 0, not polling for data.
  188. if (mCurrentPollingFrequency == 0) return;
  189. mProvider.getSensorManager().unregisterListener(this, mSensor);
  190. }
  191. /**
  192. * Requests sensor to stop polling for data.
  193. */
  194. @CalledByNative
  195. protected void stopSensor() {
  196. unregisterListener();
  197. mProvider.sensorStopped(this);
  198. mCurrentPollingFrequency = 0;
  199. }
  200. /**
  201. * Checks whether configuration is supported by the sensor. Currently only frequency is
  202. * supported.
  203. *
  204. * @return boolean true if configuration is supported, false otherwise.
  205. */
  206. @CalledByNative
  207. protected boolean checkSensorConfiguration(double frequency) {
  208. return mMinDelayUsec <= getSamplingPeriod(frequency);
  209. }
  210. /**
  211. * Called from device::PlatformSensorAndroid destructor, so that this instance would be
  212. * notified not to deliver any updates about new sensor readings or errors.
  213. */
  214. @CalledByNative
  215. protected void sensorDestroyed() {
  216. stopSensor();
  217. synchronized (mLock) {
  218. mNativePlatformSensorAndroid = 0;
  219. }
  220. }
  221. /**
  222. * Converts frequency to sampling period in microseconds.
  223. */
  224. private int getSamplingPeriod(double frequency) {
  225. return (int) ((1 / frequency) * MICROSECONDS_IN_SECOND);
  226. }
  227. /**
  228. * Notifies native device::PlatformSensorAndroid when there is an error.
  229. */
  230. @GuardedBy("mLock")
  231. protected void sensorError() {
  232. PlatformSensorJni.get().notifyPlatformSensorError(
  233. mNativePlatformSensorAndroid, PlatformSensor.this);
  234. }
  235. /**
  236. * Updates reading at native device::PlatformSensorAndroid.
  237. */
  238. @GuardedBy("mLock")
  239. protected void updateSensorReading(
  240. double timestamp, double value1, double value2, double value3, double value4) {
  241. PlatformSensorJni.get().updatePlatformSensorReading(mNativePlatformSensorAndroid,
  242. PlatformSensor.this, timestamp, value1, value2, value3, value4);
  243. }
  244. @Override
  245. public void onAccuracyChanged(Sensor sensor, int accuracy) {}
  246. @Override
  247. public void onSensorChanged(SensorEvent event) {
  248. // Acquire mLock to ensure that mNativePlatformSensorAndroid is not reset between this check
  249. // and when it is used.
  250. synchronized (mLock) {
  251. if (mNativePlatformSensorAndroid == 0) {
  252. Log.w(TAG,
  253. "Should not get sensor events after PlatformSensorAndroid is destroyed.");
  254. return;
  255. }
  256. if (event.values.length < mReadingCount) {
  257. sensorError();
  258. stopSensor();
  259. return;
  260. }
  261. double timestamp = event.timestamp * SECONDS_IN_NANOSECOND;
  262. switch (event.values.length) {
  263. case 1:
  264. updateSensorReading(timestamp, event.values[0], 0.0, 0.0, 0.0);
  265. break;
  266. case 2:
  267. updateSensorReading(timestamp, event.values[0], event.values[1], 0.0, 0.0);
  268. break;
  269. case 3:
  270. updateSensorReading(
  271. timestamp, event.values[0], event.values[1], event.values[2], 0.0);
  272. break;
  273. default:
  274. updateSensorReading(timestamp, event.values[0], event.values[1],
  275. event.values[2], event.values[3]);
  276. }
  277. }
  278. }
  279. @NativeMethods
  280. interface Natives {
  281. void notifyPlatformSensorError(long nativePlatformSensorAndroid, PlatformSensor caller);
  282. void updatePlatformSensorReading(long nativePlatformSensorAndroid, PlatformSensor caller,
  283. double timestamp, double value1, double value2, double value3, double value4);
  284. }
  285. }