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

Unified Diff: device/sensors/android/java/src/org/chromium/device/sensors/SensorBase.java

Issue 2051083002: WIP : Generic Sensor API implementation Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: Created 4 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: device/sensors/android/java/src/org/chromium/device/sensors/SensorBase.java
diff --git a/device/sensors/android/java/src/org/chromium/device/sensors/SensorBase.java b/device/sensors/android/java/src/org/chromium/device/sensors/SensorBase.java
new file mode 100644
index 0000000000000000000000000000000000000000..f72a1e89db64b5370d3fd6624cc0dddce51a147a
--- /dev/null
+++ b/device/sensors/android/java/src/org/chromium/device/sensors/SensorBase.java
@@ -0,0 +1,233 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.device.sensors;
+
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Build;
+import android.os.Handler;
+
+import org.chromium.mojo.system.SharedBufferHandle;
+import org.chromium.mojom.device.sensors.SensorConfiguration;
+import org.chromium.mojom.device.sensors.ReportingMode;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.BufferOverflowException;
+
+/**
+ * Base interface for Sensors
+ */
+public abstract class SensorBase implements SensorEventListener {
+ private static final double MICROSECONDS_PER_SECOND = 1000000;
+ private final Sensor mSensor;
+ private final SensorManager mSensorManager;
+ private final SensorStateObserver mSensorStateObserver;
+ private final Map<SensorProxy, Boolean> mSensorProxies = new HashMap<SensorProxy, Boolean>();
+ private final SharedBufferHandle mSharedBufferHandle;
+ private final Handler mHandler;
+ private final long mSize;
+ private final long mOffset;
+ private final int mMinDelay;
+ private SensorConfiguration mCurrentConfiguration;
+ private ByteBuffer mSharedBuffer;
+ private ByteBuffer mSensorReadingData;
+
+ protected SensorBase(int sensorType, SensorManager manager, Handler handler,
+ SharedBufferHandle handle, long offset, long size, SensorStateObserver observer)
+ throws SensorException {
+ if (handle == null || !handle.isValid()) throw new SensorException();
+ mSensorManager = manager;
+ mHandler = handler;
+ mSensorStateObserver = observer;
+ mSharedBufferHandle = handle;
+ mSize = size;
+ mOffset = offset;
+ List<Sensor> sensors = mSensorManager.getSensorList(sensorType);
+ if (sensors.isEmpty()) throw new SensorException();
+ mSensor = sensors.get(0);
+ mMinDelay = mSensor.getMinDelay();
+ }
+
+ public int reportingMode() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ return mSensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS ?
+ ReportingMode.CONTINUOUS : ReportingMode.ON_CHANGE;
+ }
+ return ReportingMode.CONTINUOUS;
+ }
+
+ public abstract int getType();
+ protected abstract void fillSensorReadingData(SensorEvent event, ByteBuffer buffer)
+ throws SensorException;
+
+ public boolean startListening(SensorProxy proxy) {
+ if (proxy == null) return false;
+
+ if (!mapSharedBuffer()) {
+ return false;
+ }
+
+ setSensorListening(proxy);
+ SensorConfiguration configuration = optimalConfiguration();
+ return restartIfNeeded(configuration);
+ }
+
+ private SensorConfiguration optimalConfiguration() {
+ SensorConfigurations configurations = new SensorConfigurations();
+ for (Map.Entry<SensorProxy, Boolean> entry : mSensorProxies.entrySet()) {
+ if (entry.getValue() == true) {
+ configurations.add(entry.getKey().getCurrentConfiguration());
+ }
+ }
+ if (!configurations.isEmpty())
+ return configurations.get(0);
+ return null;
+ }
+
+ public boolean stopListening(SensorProxy proxy) {
+ if (proxy == null) return false;
+
+ SensorConfiguration configuration = optimalConfiguration();
+ setSensorNotListening(proxy);
+
+ if (hasListeners()) {
+ return restartIfNeeded(configuration);
+ } else {
+ stopListening();
+ }
+
+ return true;
+ }
+
+ public boolean configuratoinUpdated() {
+ return restartIfNeeded(optimalConfiguration());
+ }
+
+ public boolean restartIfNeeded(SensorConfiguration configuration) {
+ boolean restarted = true;
+ if (configuration != null && configuration != mCurrentConfiguration) {
+ SensorConfiguration oldConfiguration = mCurrentConfiguration;
+ mCurrentConfiguration = configuration;
+ stopListening();
+ restarted = startListening();
+ if (!restarted) {
+ mCurrentConfiguration = oldConfiguration;
+ startListening();
+ }
+ }
+ return restarted;
+ }
+
+ private boolean startListening() {
+ int samplingFrequency = getSamplingFrequency();
+ if (samplingFrequency < mMinDelay) return false;
+ return mSensorManager.registerListener(this, mSensor, samplingFrequency, mHandler);
+ }
+
+ private void stopListening() {
+ mSensorManager.unregisterListener(this);
+ }
+
+ public void addSensorProxy(SensorProxy proxy) {
+ mSensorProxies.put(proxy, false);
+ }
+
+ public void removeSensorProxy(SensorProxy proxy) {
+ mSensorProxies.remove(proxy);
+ if (mSensorProxies.isEmpty()) {
+ stopListening();
+ mSensorStateObserver.onSensorNotInUse(this);
+ }
+ }
+
+ private int getSamplingFrequency() {
+ if (mCurrentConfiguration == null)
+ return getDefaultSamplingFrequency();
+
+ if (mCurrentConfiguration.frequency > 0) {
+ return (int)((1 / mCurrentConfiguration.frequency) * MICROSECONDS_PER_SECOND);
+ } else {
+ return getDefaultSamplingFrequency();
+ }
+ }
+
+ private int getDefaultSamplingFrequency() {
+ return SensorManager.SENSOR_DELAY_NORMAL;
+ }
+
+ private void setSensorListening(SensorProxy proxy) {
+ setSensorFlag(proxy, true);
+ }
+
+ private void setSensorNotListening(SensorProxy proxy) {
+ setSensorFlag(proxy, false);
+ }
+
+ private void setSensorFlag(SensorProxy proxy, boolean listening) {
+ if (mSensorProxies.containsKey(proxy)) {
+ mSensorProxies.put(proxy, listening);
+ }
+ }
+
+ protected boolean hasListeners() {
+ for (Map.Entry<SensorProxy, Boolean> entry : mSensorProxies.entrySet()) {
+ if (entry.getValue() == true) return true;
+ }
+ return false;
+ }
+
+ private boolean isValidConfiguration(SensorConfiguration configuration) {
+ return true;
+ }
+
+ private boolean mapSharedBuffer() {
+ if (mSharedBuffer == null) {
+ mSharedBuffer = mSharedBufferHandle.map(mOffset, mSize, SharedBufferHandle.MapFlags.none());
+ mSensorReadingData = ByteBuffer.allocate(mSharedBuffer.capacity());
+ mSensorReadingData.order(ByteOrder.nativeOrder());
+ }
+
+ return mSharedBuffer != null;
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) { }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ try {
+ mSensorReadingData.mark();
+ // Timestamp in milliseconds
+ mSensorReadingData.putDouble(event.timestamp * 0.000001d);
+ fillSensorReadingData(event, mSensorReadingData);
+
+ mSensorReadingData.reset();
+
+ mSharedBuffer.mark();
+ mSharedBuffer.put(mSensorReadingData);
+ mSensorReadingData.reset();
+ mSharedBuffer.reset();
+
+ if (reportingMode() == ReportingMode.ON_CHANGE) {
+ for (Map.Entry<SensorProxy, Boolean> entry : mSensorProxies.entrySet()) {
+ if (entry.getValue() == true) {
+ entry.getKey().reportSensorReadingChaned();
+ }
+ }
+ }
+ } catch (BufferOverflowException | SensorException e) {
+ for (SensorProxy proxy : mSensorProxies.keySet()) {
+ proxy.reportError();
+ }
+ }
+ }
+};

Powered by Google App Engine
This is Rietveld 408576698