am 14abafa1
: Merge "Sensor batching. Implementation for registerListener(with batch support) and flush APIs." into klp-dev
* commit '14abafa10853d979d184e2e934253aaded105137': Sensor batching. Implementation for registerListener(with batch support) and flush APIs.
This commit is contained in:
35
core/java/android/hardware/FlushCompleteListener.java
Normal file
35
core/java/android/hardware/FlushCompleteListener.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.hardware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for receiving a notification when a flush() has been successfully completed.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public interface FlushCompleteListener {
|
||||||
|
/**
|
||||||
|
* Called after flush() is completed. This flush() could have been initiated by this application
|
||||||
|
* or some other application. All the events in the batch at the point when the flush was called
|
||||||
|
* have been delivered to the applications registered for those sensor events.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @param sensor The {@link android.hardware.Sensor Sensor} on which flush was called.
|
||||||
|
*
|
||||||
|
* @see android.hardware.SensorManager#flush(Sensor)
|
||||||
|
*/
|
||||||
|
public void onFlushCompleted(Sensor sensor);
|
||||||
|
}
|
@ -319,6 +319,8 @@ public final class Sensor {
|
|||||||
private float mResolution;
|
private float mResolution;
|
||||||
private float mPower;
|
private float mPower;
|
||||||
private int mMinDelay;
|
private int mMinDelay;
|
||||||
|
private int mFifoReservedEventCount;
|
||||||
|
private int mFifoMaxEventCount;
|
||||||
|
|
||||||
Sensor() {
|
Sensor() {
|
||||||
}
|
}
|
||||||
@ -381,6 +383,26 @@ public final class Sensor {
|
|||||||
return mMinDelay;
|
return mMinDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Number of events reserved for this sensor in the batch mode FIFO. This gives a
|
||||||
|
* guarantee on the minimum number of events that can be batched
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public int getFifoReservedEventCount() {
|
||||||
|
return mFifoReservedEventCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Maximum number of events of this sensor that could be batched. If this value is zero
|
||||||
|
* it indicates that batch mode is not supported for this sensor. If other applications
|
||||||
|
* registered to batched sensors, the actual number of events that can be batched might be
|
||||||
|
* smaller because the hardware FiFo will be partially used to batch the other sensors.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public int getFifoMaxEventCount() {
|
||||||
|
return mFifoMaxEventCount;
|
||||||
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public int getHandle() {
|
public int getHandle() {
|
||||||
return mHandle;
|
return mHandle;
|
||||||
|
@ -608,8 +608,74 @@ public abstract class SensorManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a {@link android.hardware.SensorEventListener
|
* Enables batch mode for a sensor with the given rate and maxBatchReportLatency. If the
|
||||||
* SensorEventListener} for the given sensor.
|
* underlying hardware does not support batch mode, this defaults to
|
||||||
|
* {@link #registerListener(SensorEventListener, Sensor, int)} and other parameters are are
|
||||||
|
* ignored. In non-batch mode, all sensor events must be reported as soon as they are detected.
|
||||||
|
* While in batch mode, sensor events do not need to be reported as soon as they are detected.
|
||||||
|
* They can be temporarily stored in batches and reported in batches, as long as no event is
|
||||||
|
* delayed by more than "maxBatchReportLatency" microseconds. That is, all events since the
|
||||||
|
* previous batch are recorded and returned all at once. This allows to reduce the amount of
|
||||||
|
* interrupts sent to the SoC, and allows the SoC to switch to a lower power state (Idle) while
|
||||||
|
* the sensor is capturing and batching data.
|
||||||
|
* <p>
|
||||||
|
* Registering to a sensor in batch mode will not prevent the SoC from going to suspend mode. In
|
||||||
|
* this case, the sensor will continue to gather events and store it in a hardware FIFO. If the
|
||||||
|
* FIFO gets full before the AP wakes up again, some events will be lost, as the older events
|
||||||
|
* get overwritten by new events in the hardware FIFO. This can be avoided by holding a wake
|
||||||
|
* lock. If the application holds a wake lock, the SoC will not go to suspend mode, so no events
|
||||||
|
* will be lost, as the events will be reported before the FIFO gets full.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Batching is always best effort. If a different application requests updates in continuous
|
||||||
|
* mode, this application will also get events in continuous mode. Batch mode updates can be
|
||||||
|
* unregistered by calling {@link #unregisterListener(SensorEventListener)}.
|
||||||
|
* </p>
|
||||||
|
* <p class="note">
|
||||||
|
* </p>
|
||||||
|
* Note: Don't use this method with a one shot trigger sensor such as
|
||||||
|
* {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use
|
||||||
|
* {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p>
|
||||||
|
*
|
||||||
|
* @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
|
||||||
|
* that will receive the sensor events.
|
||||||
|
* @param sensor The {@link android.hardware.Sensor Sensor} to register to.
|
||||||
|
* @param rate The desired delay between two consecutive events in microseconds. This is only a
|
||||||
|
* hint to the system. Events may be received faster or slower than the specified
|
||||||
|
* rate. Usually events are received faster. Can be one of
|
||||||
|
* {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
|
||||||
|
* {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in
|
||||||
|
* microseconds.
|
||||||
|
* @param maxBatchReportLatency An event in the batch can be delayed by at most
|
||||||
|
* maxBatchReportLatency microseconds. More events can be batched if this value is
|
||||||
|
* large. If this is set to zero, batch mode is disabled and events are delivered in
|
||||||
|
* continuous mode as soon as they are available which is equivalent to calling
|
||||||
|
* {@link #registerListener(SensorEventListener, Sensor, int)}.
|
||||||
|
* @param reservedFlags Always set to Zero.
|
||||||
|
* @param flushCompleteListener A {@link android.hardware.FlushCompleteListener
|
||||||
|
* FlushCompleteListener} object which is called when any application calls flush()
|
||||||
|
* on this sensor and all the events in the batch at the time of calling flush() are
|
||||||
|
* successfully delivered to the listeners.
|
||||||
|
* @return true if batch mode is successfully enabled for this sensor, false otherwise.
|
||||||
|
* @see #registerListener(SensorEventListener, Sensor, int)
|
||||||
|
* @see #unregisterListener(SensorEventListener)
|
||||||
|
* @see #flush(Sensor)
|
||||||
|
* @throws IllegalArgumentException when sensor or listener is null or a trigger sensor.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs,
|
||||||
|
int maxBatchReportLatencyUs, int reservedFlags,
|
||||||
|
FlushCompleteListener flushCompleteListener) {
|
||||||
|
int delay = getDelay(rateUs);
|
||||||
|
return registerListenerImpl(listener, sensor, delay, null, maxBatchReportLatencyUs,
|
||||||
|
reservedFlags, flushCompleteListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
|
||||||
|
* sensor. Events are delivered in continuous mode as soon as they are available. To reduce the
|
||||||
|
* battery usage, use {@link #registerListener(SensorEventListener, Sensor, int, int, int,
|
||||||
|
* FlushCompleteListener)}
|
||||||
*
|
*
|
||||||
* <p class="note"></p>
|
* <p class="note"></p>
|
||||||
* Note: Don't use this method with a one shot trigger sensor such as
|
* Note: Don't use this method with a one shot trigger sensor such as
|
||||||
@ -646,6 +712,7 @@ public abstract class SensorManager {
|
|||||||
* @see #registerListener(SensorEventListener, Sensor, int)
|
* @see #registerListener(SensorEventListener, Sensor, int)
|
||||||
* @see #unregisterListener(SensorEventListener)
|
* @see #unregisterListener(SensorEventListener)
|
||||||
* @see #unregisterListener(SensorEventListener, Sensor)
|
* @see #unregisterListener(SensorEventListener, Sensor)
|
||||||
|
* @see #registerListener(SensorEventListener, Sensor, int, int, int, FlushCompleteListener)
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException when sensor is null or a trigger sensor
|
* @throws IllegalArgumentException when sensor is null or a trigger sensor
|
||||||
*/
|
*/
|
||||||
@ -655,31 +722,55 @@ public abstract class SensorManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int delay = -1;
|
int delay = getDelay(rate);
|
||||||
switch (rate) {
|
return registerListenerImpl(listener, sensor, delay, handler, 0, 0, null);
|
||||||
case SENSOR_DELAY_FASTEST:
|
}
|
||||||
delay = 0;
|
|
||||||
break;
|
|
||||||
case SENSOR_DELAY_GAME:
|
|
||||||
delay = 20000;
|
|
||||||
break;
|
|
||||||
case SENSOR_DELAY_UI:
|
|
||||||
delay = 66667;
|
|
||||||
break;
|
|
||||||
case SENSOR_DELAY_NORMAL:
|
|
||||||
delay = 200000;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
delay = rate;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return registerListenerImpl(listener, sensor, delay, handler);
|
/**
|
||||||
|
* Enables batch mode for a sensor with the given rate and maxBatchReportLatency.
|
||||||
|
* @param handler
|
||||||
|
* The {@link android.os.Handler Handler} the
|
||||||
|
* {@link android.hardware.SensorEvent sensor events} will be
|
||||||
|
* delivered to.
|
||||||
|
*
|
||||||
|
* @see #registerListener(SensorEventListener, Sensor, int, int, int, FlushCompleteListener)
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs,
|
||||||
|
int maxBatchReportLatencyUs, int reservedFlags, Handler handler,
|
||||||
|
FlushCompleteListener flushCompleteListener) {
|
||||||
|
int delayUs = getDelay(rateUs);
|
||||||
|
return registerListenerImpl(listener, sensor, delayUs, handler, maxBatchReportLatencyUs,
|
||||||
|
reservedFlags, flushCompleteListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
|
protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
|
||||||
int delay, Handler handler);
|
int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags,
|
||||||
|
FlushCompleteListener flushCompleteListener);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flushes the batch FIFO of the given sensor. If there are events in the FIFO of this sensor,
|
||||||
|
* they are returned as if the batch timeout has expired. Events are returned in the
|
||||||
|
* usual way through the SensorEventListener. This call doesn't effect the batch timeout for
|
||||||
|
* this sensor. This call is asynchronous and returns immediately. FlushCompleteListener is
|
||||||
|
* called after all the events in the batch at the time of calling this method have been
|
||||||
|
* delivered successfully.
|
||||||
|
* @param sensor
|
||||||
|
* The {@link android.hardware.Sensor Sensor} to flush.
|
||||||
|
* @return true if the flush is initiated successfully. false if the sensor isn't active
|
||||||
|
* i.e no application is registered for updates from this sensor.
|
||||||
|
* @see #registerListener(SensorEventListener, Sensor, int, int, int, FlushCompleteListener)
|
||||||
|
* @throws IllegalArgumentException when sensor is null or a trigger sensor.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean flush(Sensor sensor) {
|
||||||
|
return flushImpl(sensor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
protected abstract boolean flushImpl(Sensor sensor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@ -1079,15 +1170,15 @@ public abstract class SensorManager {
|
|||||||
* <p>
|
* <p>
|
||||||
* All three angles above are in <b>radians</b> and <b>positive</b> in the
|
* All three angles above are in <b>radians</b> and <b>positive</b> in the
|
||||||
* <b>counter-clockwise</b> direction.
|
* <b>counter-clockwise</b> direction.
|
||||||
*
|
*
|
||||||
* @param R
|
* @param R
|
||||||
* rotation matrix see {@link #getRotationMatrix}.
|
* rotation matrix see {@link #getRotationMatrix}.
|
||||||
*
|
*
|
||||||
* @param values
|
* @param values
|
||||||
* an array of 3 floats to hold the result.
|
* an array of 3 floats to hold the result.
|
||||||
*
|
*
|
||||||
* @return The array values passed as argument.
|
* @return The array values passed as argument.
|
||||||
*
|
*
|
||||||
* @see #getRotationMatrix(float[], float[], float[], float[])
|
* @see #getRotationMatrix(float[], float[], float[], float[])
|
||||||
* @see GeomagneticField
|
* @see GeomagneticField
|
||||||
*/
|
*/
|
||||||
@ -1407,4 +1498,26 @@ public abstract class SensorManager {
|
|||||||
return mLegacySensorManager;
|
return mLegacySensorManager;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int getDelay(int rate) {
|
||||||
|
int delay = -1;
|
||||||
|
switch (rate) {
|
||||||
|
case SENSOR_DELAY_FASTEST:
|
||||||
|
delay = 0;
|
||||||
|
break;
|
||||||
|
case SENSOR_DELAY_GAME:
|
||||||
|
delay = 20000;
|
||||||
|
break;
|
||||||
|
case SENSOR_DELAY_UI:
|
||||||
|
delay = 66667;
|
||||||
|
break;
|
||||||
|
case SENSOR_DELAY_NORMAL:
|
||||||
|
delay = 200000;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
delay = rate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return delay;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,30 +93,35 @@ public class SystemSensorManager extends SensorManager {
|
|||||||
/** @hide */
|
/** @hide */
|
||||||
@Override
|
@Override
|
||||||
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
|
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
|
||||||
int delay, Handler handler)
|
int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags,
|
||||||
{
|
FlushCompleteListener flushCompleteListener) {
|
||||||
|
if (sensor == null) throw new IllegalArgumentException("sensor cannot be null");
|
||||||
|
if (listener == null) throw new IllegalArgumentException("listener cannot be null");
|
||||||
|
if (reservedFlags != 0) throw new IllegalArgumentException("reservedFlags should be zero");
|
||||||
|
if (delayUs < 0) throw new IllegalArgumentException("rateUs should be positive");
|
||||||
|
if (maxBatchReportLatencyUs < 0)
|
||||||
|
throw new IllegalArgumentException("maxBatchReportLatencyUs should be positive");
|
||||||
|
// Trigger Sensors should use the requestTriggerSensor call.
|
||||||
|
if (Sensor.getReportingMode(sensor) == Sensor.REPORTING_MODE_ONE_SHOT)
|
||||||
|
throw new IllegalArgumentException("Trigger Sensors cannot use registerListener");
|
||||||
|
|
||||||
// Invariants to preserve:
|
// Invariants to preserve:
|
||||||
// - one Looper per SensorEventListener
|
// - one Looper per SensorEventListener
|
||||||
// - one Looper per SensorEventQueue
|
// - one Looper per SensorEventQueue
|
||||||
// We map SensorEventListener to a SensorEventQueue, which holds the looper
|
// We map SensorEventListener to a SensorEventQueue, which holds the looper
|
||||||
if (sensor == null) throw new IllegalArgumentException("sensor cannot be null");
|
|
||||||
|
|
||||||
// Trigger Sensors should use the requestTriggerSensor call.
|
|
||||||
if (Sensor.getReportingMode(sensor) == Sensor.REPORTING_MODE_ONE_SHOT) return false;
|
|
||||||
|
|
||||||
synchronized (mSensorListeners) {
|
synchronized (mSensorListeners) {
|
||||||
SensorEventQueue queue = mSensorListeners.get(listener);
|
SensorEventQueue queue = mSensorListeners.get(listener);
|
||||||
if (queue == null) {
|
if (queue == null) {
|
||||||
Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
|
Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
|
||||||
queue = new SensorEventQueue(listener, looper, this);
|
queue = new SensorEventQueue(listener, looper, this, flushCompleteListener);
|
||||||
if (!queue.addSensor(sensor, delay)) {
|
if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags)) {
|
||||||
queue.dispose();
|
queue.dispose();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mSensorListeners.put(listener, queue);
|
mSensorListeners.put(listener, queue);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return queue.addSensor(sensor, delay);
|
return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,14 +162,14 @@ public class SystemSensorManager extends SensorManager {
|
|||||||
TriggerEventQueue queue = mTriggerListeners.get(listener);
|
TriggerEventQueue queue = mTriggerListeners.get(listener);
|
||||||
if (queue == null) {
|
if (queue == null) {
|
||||||
queue = new TriggerEventQueue(listener, mMainLooper, this);
|
queue = new TriggerEventQueue(listener, mMainLooper, this);
|
||||||
if (!queue.addSensor(sensor, 0)) {
|
if (!queue.addSensor(sensor, 0, 0, 0)) {
|
||||||
queue.dispose();
|
queue.dispose();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mTriggerListeners.put(listener, queue);
|
mTriggerListeners.put(listener, queue);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return queue.addSensor(sensor, 0);
|
return queue.addSensor(sensor, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,6 +200,18 @@ public class SystemSensorManager extends SensorManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean flushImpl(Sensor sensor) {
|
||||||
|
if (sensor == null) throw new IllegalArgumentException("sensor cannot be null");
|
||||||
|
if(Sensor.getReportingMode(sensor) == Sensor.REPORTING_MODE_ONE_SHOT)
|
||||||
|
throw new IllegalArgumentException("Trigger Sensors cannot call flush");
|
||||||
|
|
||||||
|
FlushEventQueue queue = new FlushEventQueue(mMainLooper, this);
|
||||||
|
if (queue.flushSensor(sensor) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BaseEventQueue is the communication channel with the sensor service,
|
* BaseEventQueue is the communication channel with the sensor service,
|
||||||
* SensorEventQueue, TriggerEventQueue are subclases and there is one-to-one mapping between
|
* SensorEventQueue, TriggerEventQueue are subclases and there is one-to-one mapping between
|
||||||
@ -202,11 +219,12 @@ public class SystemSensorManager extends SensorManager {
|
|||||||
*/
|
*/
|
||||||
private static abstract class BaseEventQueue {
|
private static abstract class BaseEventQueue {
|
||||||
private native int nativeInitBaseEventQueue(BaseEventQueue eventQ, MessageQueue msgQ,
|
private native int nativeInitBaseEventQueue(BaseEventQueue eventQ, MessageQueue msgQ,
|
||||||
|
|
||||||
float[] scratch);
|
float[] scratch);
|
||||||
private static native int nativeEnableSensor(int eventQ, int handle, int us);
|
private static native int nativeEnableSensor(int eventQ, int handle, int rateUs,
|
||||||
|
int maxBatchReportLatencyUs, int reservedFlags);
|
||||||
private static native int nativeDisableSensor(int eventQ, int handle);
|
private static native int nativeDisableSensor(int eventQ, int handle);
|
||||||
private static native void nativeDestroySensorEventQueue(int eventQ);
|
private static native void nativeDestroySensorEventQueue(int eventQ);
|
||||||
|
private static native int nativeFlushSensor(int eventQ, int handle);
|
||||||
private int nSensorEventQueue;
|
private int nSensorEventQueue;
|
||||||
private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
|
private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
|
||||||
protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
|
protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
|
||||||
@ -225,7 +243,8 @@ public class SystemSensorManager extends SensorManager {
|
|||||||
dispose(false);
|
dispose(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addSensor(Sensor sensor, int delay) {
|
public boolean addSensor(
|
||||||
|
Sensor sensor, int delayUs, int maxBatchReportLatencyUs, int reservedFlags) {
|
||||||
// Check if already present.
|
// Check if already present.
|
||||||
int handle = sensor.getHandle();
|
int handle = sensor.getHandle();
|
||||||
if (mActiveSensors.get(handle)) return false;
|
if (mActiveSensors.get(handle)) return false;
|
||||||
@ -233,9 +252,13 @@ public class SystemSensorManager extends SensorManager {
|
|||||||
// Get ready to receive events before calling enable.
|
// Get ready to receive events before calling enable.
|
||||||
mActiveSensors.put(handle, true);
|
mActiveSensors.put(handle, true);
|
||||||
addSensorEvent(sensor);
|
addSensorEvent(sensor);
|
||||||
if (enableSensor(sensor, delay) != 0) {
|
if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags) != 0) {
|
||||||
removeSensor(sensor, false);
|
// Try continuous mode if batching fails.
|
||||||
return false;
|
if (maxBatchReportLatencyUs == 0 ||
|
||||||
|
maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0, 0) != 0) {
|
||||||
|
removeSensor(sensor, false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -268,6 +291,12 @@ public class SystemSensorManager extends SensorManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int flushSensor(Sensor sensor) {
|
||||||
|
if (nSensorEventQueue == 0) throw new NullPointerException();
|
||||||
|
if (sensor == null) throw new NullPointerException();
|
||||||
|
return nativeFlushSensor(nSensorEventQueue, sensor.getHandle());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasSensors() {
|
public boolean hasSensors() {
|
||||||
// no more sensors are set
|
// no more sensors are set
|
||||||
return mActiveSensors.indexOfValue(true) >= 0;
|
return mActiveSensors.indexOfValue(true) >= 0;
|
||||||
@ -295,11 +324,14 @@ public class SystemSensorManager extends SensorManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int enableSensor(Sensor sensor, int us) {
|
private int enableSensor(
|
||||||
|
Sensor sensor, int rateUs, int maxBatchReportLatencyUs, int reservedFlags) {
|
||||||
if (nSensorEventQueue == 0) throw new NullPointerException();
|
if (nSensorEventQueue == 0) throw new NullPointerException();
|
||||||
if (sensor == null) throw new NullPointerException();
|
if (sensor == null) throw new NullPointerException();
|
||||||
return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), us);
|
return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), rateUs,
|
||||||
|
maxBatchReportLatencyUs, reservedFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int disableSensor(Sensor sensor) {
|
private int disableSensor(Sensor sensor) {
|
||||||
if (nSensorEventQueue == 0) throw new NullPointerException();
|
if (nSensorEventQueue == 0) throw new NullPointerException();
|
||||||
if (sensor == null) throw new NullPointerException();
|
if (sensor == null) throw new NullPointerException();
|
||||||
@ -307,6 +339,7 @@ public class SystemSensorManager extends SensorManager {
|
|||||||
}
|
}
|
||||||
protected abstract void dispatchSensorEvent(int handle, float[] values, int accuracy,
|
protected abstract void dispatchSensorEvent(int handle, float[] values, int accuracy,
|
||||||
long timestamp);
|
long timestamp);
|
||||||
|
protected abstract void dispatchFlushCompleteEvent(int handle);
|
||||||
|
|
||||||
protected abstract void addSensorEvent(Sensor sensor);
|
protected abstract void addSensorEvent(Sensor sensor);
|
||||||
protected abstract void removeSensorEvent(Sensor sensor);
|
protected abstract void removeSensorEvent(Sensor sensor);
|
||||||
@ -314,12 +347,14 @@ public class SystemSensorManager extends SensorManager {
|
|||||||
|
|
||||||
static final class SensorEventQueue extends BaseEventQueue {
|
static final class SensorEventQueue extends BaseEventQueue {
|
||||||
private final SensorEventListener mListener;
|
private final SensorEventListener mListener;
|
||||||
|
private final FlushCompleteListener mFlushCompleteListener;
|
||||||
private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();
|
private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();
|
||||||
|
|
||||||
public SensorEventQueue(SensorEventListener listener, Looper looper,
|
public SensorEventQueue(SensorEventListener listener, Looper looper,
|
||||||
SystemSensorManager manager) {
|
SystemSensorManager manager, FlushCompleteListener flushCompleteListener) {
|
||||||
super(looper, manager);
|
super(looper, manager);
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
|
mFlushCompleteListener = flushCompleteListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addSensorEvent(Sensor sensor) {
|
public void addSensorEvent(Sensor sensor) {
|
||||||
@ -370,6 +405,15 @@ public class SystemSensorManager extends SensorManager {
|
|||||||
}
|
}
|
||||||
mListener.onSensorChanged(t);
|
mListener.onSensorChanged(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
protected void dispatchFlushCompleteEvent(int handle) {
|
||||||
|
final Sensor sensor = sHandleToSensor.get(handle);
|
||||||
|
if (mFlushCompleteListener != null) {
|
||||||
|
mFlushCompleteListener.onFlushCompleted(sensor);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class TriggerEventQueue extends BaseEventQueue {
|
static final class TriggerEventQueue extends BaseEventQueue {
|
||||||
@ -415,5 +459,35 @@ public class SystemSensorManager extends SensorManager {
|
|||||||
|
|
||||||
mListener.onTrigger(t);
|
mListener.onTrigger(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
protected void dispatchFlushCompleteEvent(int handle) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class FlushEventQueue extends BaseEventQueue {
|
||||||
|
public FlushEventQueue(Looper looper, SystemSensorManager manager) {
|
||||||
|
super(looper, manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@Override
|
||||||
|
protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
|
||||||
|
long timestamp) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
protected void addSensorEvent(Sensor sensor) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
protected void removeSensorEvent(Sensor sensor) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
protected void dispatchFlushCompleteEvent(int handle) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
static struct {
|
static struct {
|
||||||
jclass clazz;
|
jclass clazz;
|
||||||
jmethodID dispatchSensorEvent;
|
jmethodID dispatchSensorEvent;
|
||||||
|
jmethodID dispatchFlushCompleteEvent;
|
||||||
} gBaseEventQueueClassInfo;
|
} gBaseEventQueueClassInfo;
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
@ -46,6 +47,8 @@ struct SensorOffsets
|
|||||||
jfieldID resolution;
|
jfieldID resolution;
|
||||||
jfieldID power;
|
jfieldID power;
|
||||||
jfieldID minDelay;
|
jfieldID minDelay;
|
||||||
|
jfieldID fifoReservedEventCount;
|
||||||
|
jfieldID fifoMaxEventCount;
|
||||||
} gSensorOffsets;
|
} gSensorOffsets;
|
||||||
|
|
||||||
|
|
||||||
@ -67,6 +70,9 @@ nativeClassInit (JNIEnv *_env, jclass _this)
|
|||||||
sensorOffsets.resolution = _env->GetFieldID(sensorClass, "mResolution","F");
|
sensorOffsets.resolution = _env->GetFieldID(sensorClass, "mResolution","F");
|
||||||
sensorOffsets.power = _env->GetFieldID(sensorClass, "mPower", "F");
|
sensorOffsets.power = _env->GetFieldID(sensorClass, "mPower", "F");
|
||||||
sensorOffsets.minDelay = _env->GetFieldID(sensorClass, "mMinDelay", "I");
|
sensorOffsets.minDelay = _env->GetFieldID(sensorClass, "mMinDelay", "I");
|
||||||
|
sensorOffsets.fifoReservedEventCount =
|
||||||
|
_env->GetFieldID(sensorClass, "mFifoReservedEventCount", "I");
|
||||||
|
sensorOffsets.fifoMaxEventCount = _env->GetFieldID(sensorClass, "mFifoMaxEventCount", "I");
|
||||||
}
|
}
|
||||||
|
|
||||||
static jint
|
static jint
|
||||||
@ -78,7 +84,7 @@ nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next)
|
|||||||
size_t count = mgr.getSensorList(&sensorList);
|
size_t count = mgr.getSensorList(&sensorList);
|
||||||
if (size_t(next) >= count)
|
if (size_t(next) >= count)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
Sensor const* const list = sensorList[next];
|
Sensor const* const list = sensorList[next];
|
||||||
const SensorOffsets& sensorOffsets(gSensorOffsets);
|
const SensorOffsets& sensorOffsets(gSensorOffsets);
|
||||||
jstring name = env->NewStringUTF(list->getName().string());
|
jstring name = env->NewStringUTF(list->getName().string());
|
||||||
@ -92,7 +98,9 @@ nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next)
|
|||||||
env->SetFloatField(sensor, sensorOffsets.resolution, list->getResolution());
|
env->SetFloatField(sensor, sensorOffsets.resolution, list->getResolution());
|
||||||
env->SetFloatField(sensor, sensorOffsets.power, list->getPowerUsage());
|
env->SetFloatField(sensor, sensorOffsets.power, list->getPowerUsage());
|
||||||
env->SetIntField(sensor, sensorOffsets.minDelay, list->getMinDelay());
|
env->SetIntField(sensor, sensorOffsets.minDelay, list->getMinDelay());
|
||||||
|
env->SetIntField(sensor, sensorOffsets.fifoReservedEventCount,
|
||||||
|
list->getFifoReservedEventCount());
|
||||||
|
env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount, list->getFifoMaxEventCount());
|
||||||
next++;
|
next++;
|
||||||
return size_t(next) < count ? next : 0;
|
return size_t(next) < count ? next : 0;
|
||||||
}
|
}
|
||||||
@ -150,12 +158,20 @@ private:
|
|||||||
env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);
|
env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);
|
||||||
}
|
}
|
||||||
|
|
||||||
env->CallVoidMethod(mReceiverObject,
|
if (buffer[i].type == SENSOR_TYPE_META_DATA) {
|
||||||
gBaseEventQueueClassInfo.dispatchSensorEvent,
|
// This is a flush complete sensor event. Call dispatchFlushCompleteEvent
|
||||||
buffer[i].sensor,
|
// method.
|
||||||
mScratch,
|
env->CallVoidMethod(mReceiverObject,
|
||||||
buffer[i].vector.status,
|
gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
|
||||||
buffer[i].timestamp);
|
buffer[i].meta_data.sensor);
|
||||||
|
} else {
|
||||||
|
env->CallVoidMethod(mReceiverObject,
|
||||||
|
gBaseEventQueueClassInfo.dispatchSensorEvent,
|
||||||
|
buffer[i].sensor,
|
||||||
|
mScratch,
|
||||||
|
buffer[i].vector.status,
|
||||||
|
buffer[i].timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
if (env->ExceptionCheck()) {
|
if (env->ExceptionCheck()) {
|
||||||
ALOGE("Exception dispatching input event.");
|
ALOGE("Exception dispatching input event.");
|
||||||
@ -186,9 +202,11 @@ static jint nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQ
|
|||||||
return jint(receiver.get());
|
return jint(receiver.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle, jint us) {
|
static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle, jint rate_us,
|
||||||
|
jint maxBatchReportLatency, jint reservedFlags) {
|
||||||
sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
|
sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
|
||||||
return receiver->getSensorEventQueue()->enableSensor(handle, us);
|
return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,
|
||||||
|
reservedFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle) {
|
static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle) {
|
||||||
@ -202,6 +220,10 @@ static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jint eventQ
|
|||||||
receiver->decStrong((void*)nativeInitSensorEventQueue);
|
receiver->decStrong((void*)nativeInitSensorEventQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle) {
|
||||||
|
sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
|
||||||
|
return receiver->getSensorEventQueue()->flushSensor(handle);
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -221,7 +243,7 @@ static JNINativeMethod gBaseEventQueueMethods[] = {
|
|||||||
(void*)nativeInitSensorEventQueue },
|
(void*)nativeInitSensorEventQueue },
|
||||||
|
|
||||||
{"nativeEnableSensor",
|
{"nativeEnableSensor",
|
||||||
"(III)I",
|
"(IIIII)I",
|
||||||
(void*)nativeEnableSensor },
|
(void*)nativeEnableSensor },
|
||||||
|
|
||||||
{"nativeDisableSensor",
|
{"nativeDisableSensor",
|
||||||
@ -231,6 +253,10 @@ static JNINativeMethod gBaseEventQueueMethods[] = {
|
|||||||
{"nativeDestroySensorEventQueue",
|
{"nativeDestroySensorEventQueue",
|
||||||
"(I)V",
|
"(I)V",
|
||||||
(void*)nativeDestroySensorEventQueue },
|
(void*)nativeDestroySensorEventQueue },
|
||||||
|
|
||||||
|
{"nativeFlushSensor",
|
||||||
|
"(II)I",
|
||||||
|
(void*)nativeFlushSensor },
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
@ -260,5 +286,9 @@ int register_android_hardware_SensorManager(JNIEnv *env)
|
|||||||
gBaseEventQueueClassInfo.clazz,
|
gBaseEventQueueClassInfo.clazz,
|
||||||
"dispatchSensorEvent", "(I[FIJ)V");
|
"dispatchSensorEvent", "(I[FIJ)V");
|
||||||
|
|
||||||
|
GET_METHOD_ID(gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
|
||||||
|
gBaseEventQueueClassInfo.clazz,
|
||||||
|
"dispatchFlushCompleteEvent", "(I)V");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user