From 4bdc37d315a6dbdcf2425e70423ec43d7b74e102 Mon Sep 17 00:00:00 2001 From: Aravind Akella Date: Tue, 1 Oct 2013 17:58:35 -0700 Subject: [PATCH] Fix registerListener and flush bugs. 1) Fix registerListener to return false when called with a Trigger sensor. Correct java documentation. 2) Remove reservedFlags and FlushCompleteListener parameters from the public API. 3) Create SensorEventListener2 which extends SensorEventListener and has the onFlushCompleted callback. 3) Change flush(Sensor) API to flush(SensorEventListener). Change-Id: I56ce4e0b6e329483e129a14ad7e8a0cd35665ffe Bug: 10894703 --- api/current.txt | 14 +-- ...leteListener.java => SensorEventListener2.java} | 4 +- core/java/android/hardware/SensorManager.java | 109 +++++++++++---------- .../java/android/hardware/SystemSensorManager.java | 85 ++++++---------- core/jni/android_hardware_SensorManager.cpp | 6 +- 5 files changed, 99 insertions(+), 119 deletions(-) rename core/java/android/hardware/{FlushCompleteListener.java => SensorEventListener2.java} (89%) diff --git a/api/current.txt b/api/current.txt index 548433e762d5..a3e6fbcbd1fa 100644 --- a/api/current.txt +++ b/api/current.txt @@ -10691,10 +10691,6 @@ package android.hardware { method public int getMinFrequency(); } - public abstract interface FlushCompleteListener { - method public abstract void onFlushCompleted(android.hardware.Sensor); - } - public class GeomagneticField { ctor public GeomagneticField(float, float, float, long); method public float getDeclination(); @@ -10752,6 +10748,10 @@ package android.hardware { method public abstract void onSensorChanged(android.hardware.SensorEvent); } + public abstract interface SensorEventListener2 implements android.hardware.SensorEventListener { + method public abstract void onFlushCompleted(android.hardware.Sensor); + } + public abstract deprecated interface SensorListener { method public abstract void onAccuracyChanged(int, int); method public abstract void onSensorChanged(int, float[]); @@ -10759,7 +10759,7 @@ package android.hardware { public abstract class SensorManager { method public boolean cancelTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor); - method public boolean flush(android.hardware.Sensor); + method public boolean flush(android.hardware.SensorEventListener); method public static float getAltitude(float, float); method public static void getAngleChange(float[], float[], float[]); method public android.hardware.Sensor getDefaultSensor(int); @@ -10773,9 +10773,9 @@ package android.hardware { method public deprecated boolean registerListener(android.hardware.SensorListener, int); method public deprecated boolean registerListener(android.hardware.SensorListener, int, int); method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int); - method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, int, android.hardware.FlushCompleteListener); + method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int); method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, android.os.Handler); - method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, int, android.os.Handler, android.hardware.FlushCompleteListener); + method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, android.os.Handler); method public static boolean remapCoordinateSystem(float[], int, int, float[]); method public boolean requestTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor); method public deprecated void unregisterListener(android.hardware.SensorListener); diff --git a/core/java/android/hardware/FlushCompleteListener.java b/core/java/android/hardware/SensorEventListener2.java similarity index 89% rename from core/java/android/hardware/FlushCompleteListener.java rename to core/java/android/hardware/SensorEventListener2.java index fbdf4c811e72..4c3b42908b01 100644 --- a/core/java/android/hardware/FlushCompleteListener.java +++ b/core/java/android/hardware/SensorEventListener2.java @@ -19,7 +19,7 @@ package android.hardware; /** * Used for receiving a notification when a flush() has been successfully completed. */ -public interface FlushCompleteListener { +public interface SensorEventListener2 extends SensorEventListener { /** * 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 @@ -28,7 +28,7 @@ public interface FlushCompleteListener { * * @param sensor The {@link android.hardware.Sensor Sensor} on which flush was called. * - * @see android.hardware.SensorManager#flush(Sensor) + * @see android.hardware.SensorManager#flush(SensorEventListener) */ public void onFlushCompleted(Sensor sensor); } diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index 8a4aa1df1df8..b93131308316 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -533,8 +533,6 @@ public abstract class SensorManager { * * @see #unregisterListener(SensorEventListener) * @see #registerListener(SensorEventListener, Sensor, int) - * - * @throws IllegalArgumentException when sensor is a trigger sensor. */ public void unregisterListener(SensorEventListener listener, Sensor sensor) { if (listener == null || sensor == null) { @@ -601,7 +599,6 @@ public abstract class SensorManager { * @see #unregisterListener(SensorEventListener) * @see #unregisterListener(SensorEventListener, Sensor) * - * @throws IllegalArgumentException when sensor is null or a trigger sensor */ public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs) { return registerListener(listener, sensor, rateUs, null); @@ -638,7 +635,9 @@ public abstract class SensorManager { * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead.

* * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object - * that will receive the sensor events. + * that will receive the sensor events. If the application is interested in receiving + * flush complete notifications, it should register with + * {@link android.hardware.SensorEventListener SensorEventListener2} instead. * @param sensor The {@link android.hardware.Sensor Sensor} to register to. * @param rateUs 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 @@ -651,30 +650,23 @@ public abstract class SensorManager { * 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. + * @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. + * @see #flush(SensorEventListener) */ public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs, - int maxBatchReportLatencyUs, int reservedFlags, - FlushCompleteListener flushCompleteListener) { + int maxBatchReportLatencyUs) { int delay = getDelay(rateUs); - return registerListenerImpl(listener, sensor, delay, null, maxBatchReportLatencyUs, - reservedFlags, flushCompleteListener); + return registerListenerImpl(listener, sensor, delay, null, maxBatchReportLatencyUs, 0); } /** * 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)} which enables batch mode for the sensor. + * battery usage, use {@link #registerListener(SensorEventListener, Sensor, int, int)} which + * enables batch mode for the sensor. * *

* Note: Don't use this method with a one shot trigger sensor such as @@ -706,67 +698,80 @@ public abstract class SensorManager { * {@link android.hardware.SensorEvent sensor events} will be * delivered to. * - * @return true if the sensor is supported and successfully enabled. + * @return true if the sensor is supported and successfully enabled. * * @see #registerListener(SensorEventListener, Sensor, int) * @see #unregisterListener(SensorEventListener) * @see #unregisterListener(SensorEventListener, Sensor) - * - * @throws IllegalArgumentException when sensor is null or a trigger sensor */ public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs, Handler handler) { - if (listener == null || sensor == null) { - return false; - } - int delay = getDelay(rateUs); - return registerListenerImpl(listener, sensor, delay, handler, 0, 0, null); + return registerListenerImpl(listener, sensor, delay, handler, 0, 0); } /** * 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. + * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object + * that will receive the sensor events. If the application is interested in receiving + * flush complete notifications, it should register with + * {@link android.hardware.SensorEventListener SensorEventListener2} instead. + * @param sensor The {@link android.hardware.Sensor Sensor} to register to. + * @param rateUs 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 maxBatchReportLatencyUs 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 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) + * @return true if batch mode is successfully enabled for this sensor, + * false otherwise. + * @see #registerListener(SensorEventListener, Sensor, int, int) */ public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs, - int maxBatchReportLatencyUs, int reservedFlags, Handler handler, - FlushCompleteListener flushCompleteListener) { + int maxBatchReportLatencyUs, Handler handler) { int delayUs = getDelay(rateUs); - return registerListenerImpl(listener, sensor, delayUs, handler, maxBatchReportLatencyUs, - reservedFlags, flushCompleteListener); + return registerListenerImpl(listener, sensor, delayUs, handler, maxBatchReportLatencyUs, 0); } /** @hide */ protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, - int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags, - FlushCompleteListener flushCompleteListener); + int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags); /** - * 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. + * Flushes the batch FIFO of all the sensors registered for this listener. If there are events + * in the FIFO of the sensor, they are returned as if the batch timeout in the FIFO of the + * sensors had expired. Events are returned in the usual way through the SensorEventListener. + * This call doesn't affect the batch timeout for this sensor. This call is asynchronous and + * returns immediately. + * {@link android.hardware.SensorEventListener2#onFlushCompleted onFlushCompleted} is called + * after all the events in the batch at the time of calling this method have been delivered + * successfully. If the hardware doesn't support flush, it still returns true and a trivial + * flush complete event is sent after the current event for all the clients registered for this + * sensor. + * + * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object + * which was previously used in a registerListener call. + * @return true if the flush is initiated successfully on all the sensors + * registered for this listener, false if no sensor is previously registered for this + * listener or flush on one of the sensors fails. + * @see #registerListener(SensorEventListener, Sensor, int, int) + * @throws IllegalArgumentException when listener is null. */ - public boolean flush(Sensor sensor) { - return flushImpl(sensor); + public boolean flush(SensorEventListener listener) { + return flushImpl(listener); } /** @hide */ - protected abstract boolean flushImpl(Sensor sensor); + protected abstract boolean flushImpl(SensorEventListener listener); /** *

diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index 9747f0d9c80e..14f67c582894 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -93,17 +93,20 @@ public class SystemSensorManager extends SensorManager { /** @hide */ @Override protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, - 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"); + int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) { + if (listener == null || sensor == null) { + Log.e(TAG, "sensor or listener is null"); + return false; + } // Trigger Sensors should use the requestTriggerSensor call. - if (Sensor.getReportingMode(sensor) == Sensor.REPORTING_MODE_ONE_SHOT) - throw new IllegalArgumentException("Trigger Sensors cannot use registerListener"); + if (Sensor.getReportingMode(sensor) == Sensor.REPORTING_MODE_ONE_SHOT) { + Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor."); + return false; + } + if (maxBatchReportLatencyUs < 0 || delayUs < 0) { + Log.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative"); + return false; + } // Invariants to preserve: // - one Looper per SensorEventListener @@ -113,7 +116,7 @@ public class SystemSensorManager extends SensorManager { SensorEventQueue queue = mSensorListeners.get(listener); if (queue == null) { Looper looper = (handler != null) ? handler.getLooper() : mMainLooper; - queue = new SensorEventQueue(listener, looper, this, flushCompleteListener); + queue = new SensorEventQueue(listener, looper, this); if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags)) { queue.dispose(); return false; @@ -200,16 +203,17 @@ 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"); + protected boolean flushImpl(SensorEventListener listener) { + if (listener == null) throw new IllegalArgumentException("listener cannot be null"); - FlushEventQueue queue = new FlushEventQueue(mMainLooper, this); - if (queue.flushSensor(sensor) != 0) { - return false; + synchronized (mSensorListeners) { + SensorEventQueue queue = mSensorListeners.get(listener); + if (queue == null) { + return false; + } else { + return (queue.flush() == 0); + } } - return true; } /* @@ -224,7 +228,7 @@ public class SystemSensorManager extends SensorManager { 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 static native int nativeFlushSensor(int eventQ); private int nSensorEventQueue; private final SparseBooleanArray mActiveSensors = new SparseBooleanArray(); protected final SparseIntArray mSensorAccuracies = new SparseIntArray(); @@ -291,10 +295,9 @@ public class SystemSensorManager extends SensorManager { return false; } - public int flushSensor(Sensor sensor) { + public int flush() { if (nSensorEventQueue == 0) throw new NullPointerException(); - if (sensor == null) throw new NullPointerException(); - return nativeFlushSensor(nSensorEventQueue, sensor.getHandle()); + return nativeFlushSensor(nSensorEventQueue); } public boolean hasSensors() { @@ -347,14 +350,12 @@ public class SystemSensorManager extends SensorManager { static final class SensorEventQueue extends BaseEventQueue { private final SensorEventListener mListener; - private final FlushCompleteListener mFlushCompleteListener; private final SparseArray mSensorsEvents = new SparseArray(); public SensorEventQueue(SensorEventListener listener, Looper looper, - SystemSensorManager manager, FlushCompleteListener flushCompleteListener) { + SystemSensorManager manager) { super(looper, manager); mListener = listener; - mFlushCompleteListener = flushCompleteListener; } public void addSensorEvent(Sensor sensor) { @@ -408,9 +409,9 @@ public class SystemSensorManager extends SensorManager { @SuppressWarnings("unused") protected void dispatchFlushCompleteEvent(int handle) { - final Sensor sensor = sHandleToSensor.get(handle); - if (mFlushCompleteListener != null) { - mFlushCompleteListener.onFlushCompleted(sensor); + if (mListener instanceof SensorEventListener2) { + final Sensor sensor = sHandleToSensor.get(handle); + ((SensorEventListener2)mListener).onFlushCompleted(sensor); } return; } @@ -464,30 +465,4 @@ public class SystemSensorManager extends SensorManager { 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) { - } - } } diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp index 4290a6ed6bfc..793d1bf93a99 100644 --- a/core/jni/android_hardware_SensorManager.cpp +++ b/core/jni/android_hardware_SensorManager.cpp @@ -220,9 +220,9 @@ static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jint eventQ receiver->decStrong((void*)nativeInitSensorEventQueue); } -static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle) { +static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jint eventQ) { sp receiver(reinterpret_cast(eventQ)); - return receiver->getSensorEventQueue()->flushSensor(handle); + return receiver->getSensorEventQueue()->flush(); } //---------------------------------------------------------------------------- @@ -255,7 +255,7 @@ static JNINativeMethod gBaseEventQueueMethods[] = { (void*)nativeDestroySensorEventQueue }, {"nativeFlushSensor", - "(II)I", + "(I)I", (void*)nativeFlushSensor }, }; -- 2.11.0