OLD | NEW |
---|---|
(Empty) | |
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 | |
5 package org.chromium.device.sensors; | |
6 | |
7 import android.hardware.Sensor; | |
8 import android.hardware.SensorEvent; | |
9 import android.hardware.SensorEventListener; | |
10 import android.os.Build; | |
11 | |
12 import org.chromium.base.annotations.CalledByNative; | |
13 import org.chromium.base.annotations.JNINamespace; | |
14 import org.chromium.mojom.device.mojom.ReportingMode; | |
15 | |
16 import java.nio.BufferOverflowException; | |
17 import java.nio.ByteBuffer; | |
18 import java.nio.ByteOrder; | |
19 | |
20 import java.util.List; | |
21 | |
22 /** | |
23 * Implementation of PlatformSensor that uses Android Sensor Framework. Lifetime is controlled by | |
24 * the device::PlatformSensorAndroid. | |
25 */ | |
26 @JNINamespace("device") | |
27 public class PlatformSensor implements SensorEventListener, PlatformSensorNotifi er { | |
28 private static final double MICROSECONDS_IN_SECOND = 1000000; | |
29 private static final double MILLISECONDS_IN_NANOSECOND = 0.000001d; | |
30 | |
31 /** | |
32 * The SENSOR_FREQUENCY_NORMAL is defined as 5Hz which corresponds to a poll ing delay | |
33 * @see android.hardware.SensorManager.SENSOR_DELAY_NORMAL value that is def ined as 200000 | |
34 * microseconds. | |
35 */ | |
36 private static final double SENSOR_FREQUENCY_NORMAL = 5.0d; | |
37 | |
38 /** | |
39 * Identifier of device::PlatformSensorAndroid instance. | |
40 */ | |
41 private long mNativePlatformSensorAndroid; | |
42 | |
43 /** | |
44 * Shared buffer that is used to return data to the client. | |
45 */ | |
46 private ByteBuffer mBuffer; | |
47 | |
48 /** | |
49 * Buffer that is filled with sensor reading data and swapped into mBuffer. | |
50 */ | |
51 private ByteBuffer mSensorReadingData; | |
52 | |
53 /** | |
54 * Used for fetching sensor reading values and obtaining information about t he sensor. | |
55 * @see android.hardware.Sensor | |
56 */ | |
57 private final Sensor mSensor; | |
58 | |
59 /** | |
60 * The minimum delay between two readings in microseconds that is supported by the sensor. | |
61 */ | |
62 private final int mMinDelayUsec; | |
63 | |
64 /** | |
65 * The number of sensor reading values required from the sensor. | |
66 */ | |
67 private final int mReadingCount; | |
68 | |
69 /** | |
70 * Frequncy that is currently used by the sensor for polling. | |
71 */ | |
72 private double mCurrentPollingFrequency; | |
73 | |
74 /** | |
75 * Provides shared SensorManager and event processing thread Handler to Plat formSensor objects. | |
76 */ | |
77 private final PlatformSensorProvider mProvider; | |
78 | |
79 /** | |
80 * Provides methods to notify native PlatformSensorAndroid. | |
81 */ | |
82 private PlatformSensorNotifier mNotifier; | |
83 | |
84 /** | |
85 * Creates new PlatformSensor. | |
86 * | |
87 * @param sensorType type of the sensor to be constructed. @see android.hard ware.Sensor.TYPE_* | |
88 * @param readingCount number of sensor reading values required from the sen sor. | |
89 * @param provider object that shares SensorManager and polling thread Handl er with sensors. | |
90 */ | |
91 public static PlatformSensor create( | |
92 int sensorType, int readingCount, PlatformSensorProvider provider) { | |
93 List<Sensor> sensors = provider.getSensorManager().getSensorList(sensorT ype); | |
94 if (sensors.isEmpty()) return null; | |
95 return new PlatformSensor(sensors.get(0), readingCount, provider); | |
96 } | |
97 | |
98 protected PlatformSensor(Sensor sensor, int readingCount, PlatformSensorProv ider provider) { | |
99 mReadingCount = readingCount; | |
100 mProvider = provider; | |
101 mSensor = sensor; | |
102 mMinDelayUsec = mSensor.getMinDelay(); | |
103 } | |
104 | |
105 /** | |
106 * Initializes PlatformSensor, called by native code. | |
107 * | |
108 * @param nativePlatformSensorAndroid identifier of device::PlatformSensorAn droid instance. | |
109 * @param buffer shared buffer that is used to return data to the client. | |
110 */ | |
111 @CalledByNative | |
112 protected void initPlatformSensorAndroid(long nativePlatformSensorAndroid, B yteBuffer buffer) { | |
Ted C
2016/09/07 18:12:23
looks like this one could be private
shalamov
2016/09/08 13:40:49
I'm using it for unit tests, is there a way to mak
| |
113 initPlatformSensorAndroid(this, nativePlatformSensorAndroid, buffer); | |
114 } | |
115 | |
116 /** | |
117 * Initializes PlatformSensor. | |
118 * | |
119 * @param notifier object that is used to notify native device::PlatformSens orAndroid. | |
120 * @param nativePlatformSensorAndroid identifier of device::PlatformSensorAn droid instance. | |
121 * @param buffer shared buffer that is used to return data to the client. | |
122 */ | |
123 protected void initPlatformSensorAndroid( | |
124 PlatformSensorNotifier notifier, long nativePlatformSensorAndroid, B yteBuffer buffer) { | |
125 assert nativePlatformSensorAndroid != 0; | |
126 assert buffer != null; | |
127 mNativePlatformSensorAndroid = nativePlatformSensorAndroid; | |
128 mNotifier = notifier; | |
129 mBuffer = buffer; | |
130 mSensorReadingData = ByteBuffer.allocate(mBuffer.capacity()); | |
131 mSensorReadingData.order(ByteOrder.nativeOrder()); | |
132 } | |
133 | |
134 /** | |
135 * Fills shared buffer with sensor reading data, throws exception if number of received values | |
136 * is less than the number required for the PlatformSensor. | |
137 */ | |
138 private void fillSensorReadingData(SensorEvent event, ByteBuffer buffer) | |
139 throws IllegalStateException { | |
140 if (event.values.length < mReadingCount) throw new IllegalStateException (); | |
141 for (int i = 0; i < mReadingCount; ++i) { | |
142 buffer.putDouble(event.values[i]); | |
143 } | |
144 } | |
145 | |
146 /** | |
147 * Returns reporting mode supported by the sensor. | |
148 * | |
149 * @return ReportingMode reporting mode. | |
150 */ | |
151 @CalledByNative | |
152 protected int getReportingMode() { | |
153 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | |
154 return mSensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOU S | |
155 ? ReportingMode.CONTINUOUS | |
156 : ReportingMode.ON_CHANGE; | |
157 } | |
158 return ReportingMode.CONTINUOUS; | |
159 } | |
160 | |
161 /** | |
162 * Returns default configuration supported by the sensor. Currently only fre quency is supported. | |
163 * | |
164 * @return double frequency. | |
165 */ | |
166 @CalledByNative | |
167 protected double getDefaultConfiguration() { | |
168 return SENSOR_FREQUENCY_NORMAL; | |
169 } | |
170 | |
171 /** | |
172 * Requests sensor to start polling for data. | |
173 * | |
174 * @return boolean true if successful, false otherwise. | |
175 */ | |
176 @CalledByNative | |
177 protected boolean startSensor(double frequency) { | |
Ted C
2016/09/07 18:12:23
just to make sure the frequency is sanity checked
shalamov
2016/09/07 18:49:18
It is checked on native side, during mojo type co
| |
178 // If we already polling hw with same frequency, do not restart the sens or. | |
179 if (mCurrentPollingFrequency == frequency) return true; | |
180 | |
181 // Unregister old listener if polling frequency has changed. | |
182 unregisterListener(); | |
183 mProvider.sensorStarted(this); | |
184 boolean sensorStarted = mProvider.getSensorManager().registerListener( | |
185 this, mSensor, getSamplingPeriod(frequency), mProvider.getHandle r()); | |
186 | |
187 if (!sensorStarted) { | |
188 stopSensor(); | |
189 return sensorStarted; | |
190 } | |
191 | |
192 mCurrentPollingFrequency = frequency; | |
Ted C
2016/09/07 18:12:23
any reason this is under the !sensorStarted check
shalamov
2016/09/07 18:49:18
If sensor failed to start with given configuration
| |
193 return sensorStarted; | |
194 } | |
195 | |
196 private void unregisterListener() { | |
197 // Do not unregister if current polling frequency is 0, not polling for data. | |
198 if (mCurrentPollingFrequency == 0) return; | |
Ted C
2016/09/07 18:12:23
should we not be registering if frequency is 0 abo
shalamov
2016/09/07 18:49:18
Native side will never provide 0 frequency, but I
| |
199 mProvider.getSensorManager().unregisterListener(this, mSensor); | |
200 } | |
201 | |
202 /** | |
203 * Requests sensor to stop polling for data. | |
204 */ | |
205 @CalledByNative | |
206 protected void stopSensor() { | |
207 unregisterListener(); | |
208 mProvider.sensorStopped(this); | |
209 mCurrentPollingFrequency = 0; | |
210 } | |
211 | |
212 /** | |
213 * Checks whether configuration is supported by the sensor. Currently only f requency is | |
214 * supported. | |
215 * | |
216 * @return boolean true if configuration is supported, false otherwise. | |
217 */ | |
218 @CalledByNative | |
219 protected boolean checkSensorConfiguration(double frequency) { | |
220 return mMinDelayUsec <= getSamplingPeriod(frequency); | |
221 } | |
222 | |
223 /** | |
224 * Converts frequency to sampling period in microseconds. | |
225 */ | |
226 private int getSamplingPeriod(double frequency) { | |
227 return (int) ((1 / frequency) * MICROSECONDS_IN_SECOND); | |
228 } | |
229 | |
230 @Override | |
231 public void sensorReadingChanged() { | |
232 nativeNotifyPlatformSensorReadingChanged(mNativePlatformSensorAndroid); | |
233 } | |
234 | |
235 @Override | |
236 public void sensorError() { | |
237 nativeNotifyPlatformSensorError(mNativePlatformSensorAndroid); | |
238 } | |
239 | |
240 /** | |
241 * Notifies native device::PlatformSensorAndroid when reading is changed. | |
242 */ | |
243 protected native void nativeNotifyPlatformSensorReadingChanged( | |
Ted C
2016/09/07 18:12:23
Should these be private?
Also, we put native meth
shalamov
2016/09/08 13:40:49
Done.
| |
244 long nativePlatformSensorAndroid); | |
245 | |
246 /** | |
247 * Notifies native device::PlatformSensorAndroid when there is an error. | |
248 */ | |
249 protected native void nativeNotifyPlatformSensorError(long nativePlatformSen sorAndroid); | |
250 | |
251 @Override | |
252 public void onAccuracyChanged(Sensor sensor, int accuracy) {} | |
253 | |
254 @Override | |
255 public void onSensorChanged(SensorEvent event) { | |
256 try { | |
257 mSensorReadingData.mark(); | |
258 // Convert timestamp from nanoseconds to milliseconds. | |
259 mSensorReadingData.putDouble(event.timestamp * MILLISECONDS_IN_NANOS ECOND); | |
260 fillSensorReadingData(event, mSensorReadingData); | |
261 | |
262 mSensorReadingData.reset(); | |
263 | |
264 mBuffer.mark(); | |
265 mBuffer.put(mSensorReadingData); | |
266 mSensorReadingData.reset(); | |
267 mBuffer.reset(); | |
268 | |
269 if (getReportingMode() == ReportingMode.ON_CHANGE) { | |
270 mNotifier.sensorReadingChanged(); | |
271 } | |
272 } catch (BufferOverflowException | IllegalStateException e) { | |
273 mNotifier.sensorError(); | |
274 stopSensor(); | |
275 } | |
276 } | |
277 } | |
OLD | NEW |