Chromium Code Reviews| 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 |