diff options
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/hardware/FlushCompleteListener.java | 35 | ||||
| -rw-r--r-- | core/java/android/hardware/Sensor.java | 22 | ||||
| -rw-r--r-- | core/java/android/hardware/SensorManager.java | 165 | ||||
| -rw-r--r-- | core/java/android/hardware/SystemSensorManager.java | 116 |
4 files changed, 291 insertions, 47 deletions
diff --git a/core/java/android/hardware/FlushCompleteListener.java b/core/java/android/hardware/FlushCompleteListener.java new file mode 100644 index 0000000..cb5b9e3 --- /dev/null +++ b/core/java/android/hardware/FlushCompleteListener.java @@ -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); +} diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java index 9bffdbe..bbede57 100644 --- a/core/java/android/hardware/Sensor.java +++ b/core/java/android/hardware/Sensor.java @@ -319,6 +319,8 @@ public final class Sensor { private float mResolution; private float mPower; private int mMinDelay; + private int mFifoReservedEventCount; + private int mFifoMaxEventCount; Sensor() { } @@ -381,6 +383,26 @@ public final class Sensor { 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 */ public int getHandle() { return mHandle; diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index 30118f9..6839f9a 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -608,8 +608,74 @@ public abstract class SensorManager { } /** - * Registers a {@link android.hardware.SensorEventListener - * SensorEventListener} for the given sensor. + * Enables batch mode for a sensor with the given rate and maxBatchReportLatency. If the + * 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> * 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 #unregisterListener(SensorEventListener) * @see #unregisterListener(SensorEventListener, Sensor) + * @see #registerListener(SensorEventListener, Sensor, int, int, int, FlushCompleteListener) * * @throws IllegalArgumentException when sensor is null or a trigger sensor */ @@ -655,31 +722,55 @@ public abstract class SensorManager { return false; } - 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; - } + int delay = getDelay(rate); + return registerListenerImpl(listener, sensor, delay, handler, 0, 0, null); + } - 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 */ 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> @@ -1079,15 +1170,15 @@ public abstract class SensorManager { * <p> * All three angles above are in <b>radians</b> and <b>positive</b> in the * <b>counter-clockwise</b> direction. - * + * * @param R * rotation matrix see {@link #getRotationMatrix}. - * + * * @param values * an array of 3 floats to hold the result. - * + * * @return The array values passed as argument. - * + * * @see #getRotationMatrix(float[], float[], float[], float[]) * @see GeomagneticField */ @@ -1407,4 +1498,26 @@ public abstract class SensorManager { 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; + } } diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index 852cf4a..9747f0d 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -93,30 +93,35 @@ public class SystemSensorManager extends SensorManager { /** @hide */ @Override 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: // - one Looper per SensorEventListener // - one Looper per SensorEventQueue // 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) { SensorEventQueue queue = mSensorListeners.get(listener); if (queue == null) { Looper looper = (handler != null) ? handler.getLooper() : mMainLooper; - queue = new SensorEventQueue(listener, looper, this); - if (!queue.addSensor(sensor, delay)) { + queue = new SensorEventQueue(listener, looper, this, flushCompleteListener); + if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags)) { queue.dispose(); return false; } mSensorListeners.put(listener, queue); return true; } 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); if (queue == null) { queue = new TriggerEventQueue(listener, mMainLooper, this); - if (!queue.addSensor(sensor, 0)) { + if (!queue.addSensor(sensor, 0, 0, 0)) { queue.dispose(); return false; } mTriggerListeners.put(listener, queue); return true; } 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, * 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 native int nativeInitBaseEventQueue(BaseEventQueue eventQ, MessageQueue msgQ, - 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 void nativeDestroySensorEventQueue(int eventQ); + private static native int nativeFlushSensor(int eventQ, int handle); private int nSensorEventQueue; private final SparseBooleanArray mActiveSensors = new SparseBooleanArray(); protected final SparseIntArray mSensorAccuracies = new SparseIntArray(); @@ -225,7 +243,8 @@ public class SystemSensorManager extends SensorManager { dispose(false); } - public boolean addSensor(Sensor sensor, int delay) { + public boolean addSensor( + Sensor sensor, int delayUs, int maxBatchReportLatencyUs, int reservedFlags) { // Check if already present. int handle = sensor.getHandle(); if (mActiveSensors.get(handle)) return false; @@ -233,9 +252,13 @@ public class SystemSensorManager extends SensorManager { // Get ready to receive events before calling enable. mActiveSensors.put(handle, true); addSensorEvent(sensor); - if (enableSensor(sensor, delay) != 0) { - removeSensor(sensor, false); - return false; + if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags) != 0) { + // Try continuous mode if batching fails. + if (maxBatchReportLatencyUs == 0 || + maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0, 0) != 0) { + removeSensor(sensor, false); + return false; + } } return true; } @@ -268,6 +291,12 @@ public class SystemSensorManager extends SensorManager { 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() { // no more sensors are set 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 (sensor == null) throw new NullPointerException(); - return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), us); + return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), rateUs, + maxBatchReportLatencyUs, reservedFlags); } + private int disableSensor(Sensor sensor) { if (nSensorEventQueue == 0) 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, long timestamp); + protected abstract void dispatchFlushCompleteEvent(int handle); protected abstract void addSensorEvent(Sensor sensor); protected abstract void removeSensorEvent(Sensor sensor); @@ -314,12 +347,14 @@ public class SystemSensorManager extends SensorManager { static final class SensorEventQueue extends BaseEventQueue { private final SensorEventListener mListener; + private final FlushCompleteListener mFlushCompleteListener; private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>(); public SensorEventQueue(SensorEventListener listener, Looper looper, - SystemSensorManager manager) { + SystemSensorManager manager, FlushCompleteListener flushCompleteListener) { super(looper, manager); mListener = listener; + mFlushCompleteListener = flushCompleteListener; } public void addSensorEvent(Sensor sensor) { @@ -370,6 +405,15 @@ public class SystemSensorManager extends SensorManager { } 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 { @@ -415,5 +459,35 @@ public class SystemSensorManager extends SensorManager { 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) { + } } } |
