Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Side by Side Diff: device/generic_sensor/android/junit/src/org/chromium/device/sensors/PlatformSensorAndProviderTest.java

Issue 2284613002: [sensors] Android platform adaptation for Generic Sensor API (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase to master. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 static org.junit.Assert.assertEquals;
8 import static org.junit.Assert.assertNotNull;
9 import static org.junit.Assert.assertNull;
10 import static org.mockito.ArgumentMatchers.any;
11 import static org.mockito.ArgumentMatchers.anyInt;
12 import static org.mockito.Mockito.doAnswer;
13 import static org.mockito.Mockito.doReturn;
14 import static org.mockito.Mockito.mock;
15 import static org.mockito.Mockito.never;
16 import static org.mockito.Mockito.spy;
17 import static org.mockito.Mockito.times;
18 import static org.mockito.Mockito.verify;
19
20 import android.content.Context;
21 import android.hardware.Sensor;
22 import android.hardware.SensorEvent;
23 import android.hardware.SensorEventListener;
24 import android.hardware.SensorManager;
25 import android.os.Handler;
26 import android.util.SparseArray;
27
28 import org.chromium.base.test.util.Feature;
29 import org.chromium.mojom.device.mojom.ReportingMode;
30 import org.chromium.mojom.device.mojom.SensorInitParams;
31 import org.chromium.mojom.device.mojom.SensorType;
32 import org.chromium.testing.local.LocalRobolectricTestRunner;
33
34 import org.junit.Before;
35 import org.junit.Test;
36 import org.junit.runner.RunWith;
37 import org.mockito.Mock;
38 import org.mockito.MockitoAnnotations;
39 import org.mockito.invocation.InvocationOnMock;
40 import org.mockito.stubbing.Answer;
41 import org.robolectric.annotation.Config;
42
43 import java.lang.reflect.Constructor;
44 import java.lang.reflect.InvocationTargetException;
45 import java.nio.ByteBuffer;
46 import java.nio.ByteOrder;
47 import java.util.ArrayList;
48 import java.util.List;
49
50 /**
51 * Unit tests for PlatformSensor and PlatformSensorProvider.
52 */
53 @RunWith(LocalRobolectricTestRunner.class)
54 @Config(manifest = Config.NONE)
55 public class PlatformSensorAndProviderTest {
56 @Mock
57 private Context mContext;
58 @Mock
59 private SensorManager mSensorManager;
60 @Mock
61 private PlatformSensorProvider mPlatformSensorProvider;
62 private ByteBuffer mSharedBuffer;
63 private final SparseArray<List<Sensor>> mMockSensors = new SparseArray<>();
64 private static final long PLATFORM_SENSOR_ANDROID = 123456789L;
65 private static final long PLATFORM_SENSOR_TIMESTAMP = 314159265358979L;
66 private static final double MILLISECONDS_IN_NANOSECOND = 0.000001d;
67
68 /**
69 * Class that overrides thread management callbacks for testing purposes.
70 */
71 private static class TestPlatformSensorProvider extends PlatformSensorProvid er {
72 public TestPlatformSensorProvider(Context context) {
73 super(context);
74 }
75
76 @Override
77 public Handler getHandler() {
78 return new Handler();
79 }
80
81 @Override
82 protected void startSensorThread() {}
83
84 @Override
85 protected void stopSensorThread() {}
86 }
87
88 /**
89 * Class that overrides native callbacks for testing purposes.
90 */
91 private static class TestPlatformSensor extends PlatformSensor {
92 public TestPlatformSensor(
93 Sensor sensor, int readingCount, PlatformSensorProvider provider ) {
94 super(sensor, readingCount, provider);
95 }
96
97 @Override
98 protected void sensorReadingChanged() {}
99 @Override
100 protected void sensorError() {}
101 }
102
103 @Before
104 public void setUp() {
105 MockitoAnnotations.initMocks(this);
106 // Remove all mock sensors before the test.
107 mMockSensors.clear();
108 doReturn(mSensorManager).when(mContext).getSystemService(Context.SENSOR_ SERVICE);
109 doAnswer(
110 new Answer<List<Sensor>>() {
111 @Override
112 public List<Sensor> answer(final InvocationOnMock invocation )
113 throws Throwable {
114 return getMockSensors((int) (Integer) (invocation.getArg uments())[0]);
115 }
116 })
117 .when(mSensorManager)
118 .getSensorList(anyInt());
119 doReturn(mSensorManager).when(mPlatformSensorProvider).getSensorManager( );
120 doReturn(new Handler()).when(mPlatformSensorProvider).getHandler();
121 // By default, allow successful registration of SensorEventListeners.
122 doReturn(true)
123 .when(mSensorManager)
124 .registerListener(any(SensorEventListener.class), any(Sensor.cla ss), anyInt(),
125 any(Handler.class));
126 }
127
128 /**
129 * Test that PlatformSensorProvider cannot create sensors if sensor manager is null.
130 */
131 @Test
132 @Feature({"PlatformSensorProvider"})
133 public void testNullSensorManager() {
134 doReturn(null).when(mContext).getSystemService(Context.SENSOR_SERVICE);
135 PlatformSensorProvider provider = PlatformSensorProvider.create(mContext );
136 PlatformSensor sensor = provider.createSensor(SensorType.AMBIENT_LIGHT);
137 assertNull(sensor);
138 }
139
140 /**
141 * Test that PlatformSensorProvider cannot create sensors that are not suppo rted.
142 */
143 @Test
144 @Feature({"PlatformSensorProvider"})
145 public void testSensorNotSupported() {
146 PlatformSensorProvider provider = PlatformSensorProvider.create(mContext );
147 PlatformSensor sensor = provider.createSensor(SensorType.AMBIENT_LIGHT);
148 assertNull(sensor);
149 }
150
151 /**
152 * Test that PlatformSensorProvider maps device::SensorType to android.hardw are.Sensor.TYPE_*.
153 */
154 @Test
155 @Feature({"PlatformSensorProvider"})
156 public void testSensorTypeMappings() {
157 PlatformSensorProvider provider = PlatformSensorProvider.create(mContext );
158 provider.createSensor(SensorType.AMBIENT_LIGHT);
159 verify(mSensorManager).getSensorList(Sensor.TYPE_LIGHT);
160 provider.createSensor(SensorType.ACCELEROMETER);
161 verify(mSensorManager).getSensorList(Sensor.TYPE_ACCELEROMETER);
162 provider.createSensor(SensorType.LINEAR_ACCELERATION);
163 verify(mSensorManager).getSensorList(Sensor.TYPE_LINEAR_ACCELERATION);
164 provider.createSensor(SensorType.GYROSCOPE);
165 verify(mSensorManager).getSensorList(Sensor.TYPE_GYROSCOPE);
166 provider.createSensor(SensorType.MAGNETOMETER);
167 verify(mSensorManager).getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
168 }
169
170 /**
171 * Test that PlatformSensorProvider can create sensors that are supported.
172 */
173 @Test
174 @Feature({"PlatformSensorProvider"})
175 public void testSensorSupported() {
176 PlatformSensor sensor = createPlatformSensor(50000, Sensor.TYPE_LIGHT,
177 SensorType.AMBIENT_LIGHT, Sensor.REPORTING_MODE_ON_CHANGE);
178 assertNotNull(sensor);
179 }
180
181 /**
182 * Test that PlatformSensor notifies PlatformSensorProvider when it starts ( stops) polling,
183 * and SensorEventListener is registered (unregistered) to sensor manager.
184 */
185 @Test
186 @Feature({"PlatformSensor"})
187 public void testSensorStartStop() {
188 addMockSensor(50000, Sensor.TYPE_ACCELEROMETER, Sensor.REPORTING_MODE_CO NTINUOUS);
189 PlatformSensor sensor =
190 PlatformSensor.create(Sensor.TYPE_ACCELEROMETER, 3, mPlatformSen sorProvider);
191 assertNotNull(sensor);
192
193 sensor.startSensor(5);
194 sensor.stopSensor();
195
196 // Multiple start invocations.
197 sensor.startSensor(1);
198 sensor.startSensor(2);
199 sensor.startSensor(3);
200 // Same frequency, should not restart sensor
201 sensor.startSensor(3);
202
203 // Started polling with 5, 1, 2 and 3 Hz frequency.
204 verify(mPlatformSensorProvider, times(4)).getHandler();
205 verify(mPlatformSensorProvider, times(4)).sensorStarted(sensor);
206 verify(mSensorManager, times(4))
207 .registerListener(any(SensorEventListener.class), any(Sensor.cla ss), anyInt(),
208 any(Handler.class));
209
210 sensor.stopSensor();
211 sensor.stopSensor();
212 verify(mPlatformSensorProvider, times(3)).sensorStopped(sensor);
213 verify(mSensorManager, times(4))
214 .unregisterListener(any(SensorEventListener.class), any(Sensor.c lass));
215 }
216
217 /**
218 * Test that PlatformSensorProvider is notified when PlatformSensor starts a nd in case of
219 * failure, tells PlatformSensorProvider that the sensor is stopped, so that polling thread
220 * can be stopped.
221 */
222 @Test
223 @Feature({"PlatformSensor"})
224 public void testSensorStartFails() {
225 addMockSensor(50000, Sensor.TYPE_ACCELEROMETER, Sensor.REPORTING_MODE_CO NTINUOUS);
226 PlatformSensor sensor =
227 PlatformSensor.create(Sensor.TYPE_ACCELEROMETER, 3, mPlatformSen sorProvider);
228 assertNotNull(sensor);
229
230 doReturn(false)
231 .when(mSensorManager)
232 .registerListener(any(SensorEventListener.class), any(Sensor.cla ss), anyInt(),
233 any(Handler.class));
234
235 sensor.startSensor(5);
236 verify(mPlatformSensorProvider, times(1)).sensorStarted(sensor);
237 verify(mPlatformSensorProvider, times(1)).sensorStopped(sensor);
238 verify(mPlatformSensorProvider, times(1)).getHandler();
239 }
240
241 /**
242 * Test that PlatformSensor correctly checks supported configuration.
243 */
244 @Test
245 @Feature({"PlatformSensor"})
246 public void testSensorConfiguration() {
247 // 5Hz min delay
248 PlatformSensor sensor = createPlatformSensor(200000, Sensor.TYPE_ACCELER OMETER,
249 SensorType.ACCELEROMETER, Sensor.REPORTING_MODE_CONTINUOUS);
250 assertEquals(true, sensor.checkSensorConfiguration(5));
251 assertEquals(false, sensor.checkSensorConfiguration(6));
252 }
253
254 /**
255 * Test that PlatformSensor correctly returns its reporting mode.
256 */
257 @Test
258 @Feature({"PlatformSensor"})
259 public void testSensorOnChangeReportingMode() {
260 PlatformSensor sensor = createPlatformSensor(50000, Sensor.TYPE_LIGHT,
261 SensorType.AMBIENT_LIGHT, Sensor.REPORTING_MODE_ON_CHANGE);
262 assertEquals(ReportingMode.ON_CHANGE, sensor.getReportingMode());
263 }
264
265 /**
266 * Test that PlatformSensor doesn't notify client about sensor reading chang es when
267 * sensor reporting mode is ReportingMode.CONTINUOUS.
268 */
269 @Test
270 @Feature({"PlatformSensor"})
271 public void testSensorNotifierIsNotCalled() {
272 TestPlatformSensor sensor = createTestPlatformSensor(
273 50000, Sensor.TYPE_ACCELEROMETER, 3, Sensor.REPORTING_MODE_CONTI NUOUS);
274 initPlatformSensor(sensor, SensorInitParams.READ_BUFFER_SIZE);
275 TestPlatformSensor spySensor = spy(sensor);
276 SensorEvent event = createFakeEvent(3);
277 assertNotNull(event);
278 spySensor.onSensorChanged(event);
279 verify(spySensor, never()).sensorReadingChanged();
280 }
281
282 /**
283 * Test that shared buffer is correctly populated from SensorEvent.
284 */
285 @Test
286 @Feature({"PlatformSensor"})
287 public void testSensorBufferFromEvent() {
288 TestPlatformSensor sensor = createTestPlatformSensor(
289 50000, Sensor.TYPE_LIGHT, 1, Sensor.REPORTING_MODE_ON_CHANGE);
290 initPlatformSensor(sensor, SensorInitParams.READ_BUFFER_SIZE);
291 TestPlatformSensor spySensor = spy(sensor);
292 SensorEvent event = createFakeEvent(1);
293 assertNotNull(event);
294 spySensor.onSensorChanged(event);
295 verify(spySensor, times(1)).sensorReadingChanged();
296 // Verify that timestamp correctly stored in buffer.
297 assertEquals(MILLISECONDS_IN_NANOSECOND * PLATFORM_SENSOR_TIMESTAMP,
298 mSharedBuffer.getDouble(), MILLISECONDS_IN_NANOSECOND);
299 // Verify illuminance value is correctly stored in buffer and precision is not lost.
300 assertEquals(1.0d + MILLISECONDS_IN_NANOSECOND, mSharedBuffer.getDouble( ),
301 MILLISECONDS_IN_NANOSECOND);
302 }
303
304 /**
305 * Test that PlatformSensor notifies client when there is an error.
306 */
307 @Test
308 @Feature({"PlatformSensor"})
309 public void testSensorInvalidReadingSize() {
310 TestPlatformSensor sensor = createTestPlatformSensor(
311 50000, Sensor.TYPE_ACCELEROMETER, 3, Sensor.REPORTING_MODE_CONTI NUOUS);
312 initPlatformSensor(sensor, SensorInitParams.READ_BUFFER_SIZE);
313 TestPlatformSensor spySensor = spy(sensor);
314 // Accelerometer requires 3 reading values x,y and z, create fake event with 1 reading
315 // value.
316 SensorEvent event = createFakeEvent(1);
317 assertNotNull(event);
318 spySensor.onSensorChanged(event);
319 verify(spySensor, times(1)).sensorError();
320 }
321
322 /**
323 * Test that PlatformSensor notifies client when there is an error.
324 */
325 @Test
326 @Feature({"PlatformSensor"})
327 public void testSensorInvalidBufferSize() {
328 TestPlatformSensor sensor = createTestPlatformSensor(
329 50000, Sensor.TYPE_ACCELEROMETER, 3, Sensor.REPORTING_MODE_CONTI NUOUS);
330 // Create buffer that doesn't have enough capacity to hold sensor readin g values.
331 initPlatformSensor(sensor, 2);
332 TestPlatformSensor spySensor = spy(sensor);
333 SensorEvent event = createFakeEvent(3);
334 assertNotNull(event);
335 spySensor.onSensorChanged(event);
336 verify(spySensor, times(1)).sensorError();
337 }
338
339 /**
340 * Test that multiple PlatformSensor instances correctly register (unregiste r) to
341 * sensor manager and notify PlatformSensorProvider when they start (stop) p olling for data.
342 */
343 @Test
344 @Feature({"PlatformSensor"})
345 public void testMultipleSensorTypeInstances() {
346 addMockSensor(200000, Sensor.TYPE_LIGHT, Sensor.REPORTING_MODE_ON_CHANGE );
347 addMockSensor(50000, Sensor.TYPE_ACCELEROMETER, Sensor.REPORTING_MODE_CO NTINUOUS);
348
349 TestPlatformSensorProvider spyProvider = spy(new TestPlatformSensorProvi der(mContext));
350 PlatformSensor lightSensor = PlatformSensor.create(Sensor.TYPE_LIGHT, 1, spyProvider);
351 assertNotNull(lightSensor);
352
353 PlatformSensor accelerometerSensor =
354 PlatformSensor.create(Sensor.TYPE_ACCELEROMETER, 3, spyProvider) ;
355 assertNotNull(accelerometerSensor);
356
357 lightSensor.startSensor(3);
358 accelerometerSensor.startSensor(10);
359 lightSensor.stopSensor();
360 accelerometerSensor.stopSensor();
361
362 verify(spyProvider, times(2)).getHandler();
363 verify(spyProvider, times(1)).sensorStarted(lightSensor);
364 verify(spyProvider, times(1)).sensorStarted(accelerometerSensor);
365 verify(spyProvider, times(1)).sensorStopped(lightSensor);
366 verify(spyProvider, times(1)).sensorStopped(accelerometerSensor);
367 verify(spyProvider, times(1)).startSensorThread();
368 verify(spyProvider, times(1)).stopSensorThread();
369 verify(mSensorManager, times(2))
370 .registerListener(any(SensorEventListener.class), any(Sensor.cla ss), anyInt(),
371 any(Handler.class));
372 verify(mSensorManager, times(2))
373 .unregisterListener(any(SensorEventListener.class), any(Sensor.c lass));
374 }
375
376 /**
377 * Creates fake event. The SensorEvent constructor is not accessible outside android.hardware
378 * package, therefore, java reflection is used to make constructor accessibl e to construct
379 * SensorEvent instance.
380 */
381 private SensorEvent createFakeEvent(int readingValuesNum) {
382 try {
383 Constructor<SensorEvent> sensorEventConstructor =
384 SensorEvent.class.getDeclaredConstructor(Integer.TYPE);
385 sensorEventConstructor.setAccessible(true);
386 SensorEvent event = sensorEventConstructor.newInstance(readingValues Num);
387 event.timestamp = PLATFORM_SENSOR_TIMESTAMP;
388 for (int i = 0; i < readingValuesNum; ++i) {
389 event.values[i] = (float) (i + 1.0f + MILLISECONDS_IN_NANOSECOND );
390 }
391 return event;
392 } catch (InvocationTargetException | NoSuchMethodException | Instantiati onException
393 | IllegalAccessException e) {
394 return null;
395 }
396 }
397
398 private void initPlatformSensor(PlatformSensor sensor, long readingSize) {
399 mSharedBuffer = ByteBuffer.allocate((int) readingSize);
400 mSharedBuffer.order(ByteOrder.nativeOrder());
401 sensor.initPlatformSensorAndroid(PLATFORM_SENSOR_ANDROID, mSharedBuffer) ;
402 }
403
404 private void addMockSensor(long minDelayUsec, int sensorType, int reportingM ode) {
405 List<Sensor> mockSensorList = new ArrayList<Sensor>();
406 mockSensorList.add(createMockSensor(minDelayUsec, sensorType, reportingM ode));
407 mMockSensors.put(sensorType, mockSensorList);
408 }
409
410 private Sensor createMockSensor(long minDelayUsec, int sensorType, int repor tingMode) {
411 Sensor mockSensor = mock(Sensor.class);
412 doReturn((int) minDelayUsec).when(mockSensor).getMinDelay();
413 doReturn(reportingMode).when(mockSensor).getReportingMode();
414 doReturn(sensorType).when(mockSensor).getType();
415 return mockSensor;
416 }
417
418 private List<Sensor> getMockSensors(int sensorType) {
419 if (mMockSensors.indexOfKey(sensorType) >= 0) {
420 return mMockSensors.get(sensorType);
421 }
422 return new ArrayList<Sensor>();
423 }
424
425 private PlatformSensor createPlatformSensor(
426 long minDelayUsec, int androidSensorType, int mojoSensorType, int re portingMode) {
427 addMockSensor(minDelayUsec, androidSensorType, reportingMode);
428 PlatformSensorProvider provider = PlatformSensorProvider.create(mContext );
429 return provider.createSensor(mojoSensorType);
430 }
431
432 private TestPlatformSensor createTestPlatformSensor(
433 long minDelayUsec, int androidSensorType, int readingCount, int repo rtingMode) {
434 return new TestPlatformSensor(
435 createMockSensor(minDelayUsec, androidSensorType, reportingMode) , readingCount,
436 mPlatformSensorProvider);
437 }
438 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698