| 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();
|
| + }
|
| + }
|
| + }
|
| +};
|
|
|