Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4c76b18 authored by Aravind Akella's avatar Aravind Akella
Browse files

Sensor batching. Implementation for registerListener(with batch support) and flush APIs.

Bug: 10109508
Change-Id: I6dfdd986bd8c3368cb568fa7d90abf9c03de9aef
parent a861245f
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
/*
 * 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);
}
+22 −0
Original line number Diff line number Diff line
@@ -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;
+139 −26
Original line number Diff line number Diff line
@@ -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>
@@ -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;
    }
}
+95 −21
Original line number Diff line number Diff line
@@ -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,10 +252,14 @@ public class SystemSensorManager extends SensorManager {
            // Get ready to receive events before calling enable.
            mActiveSensors.put(handle, true);
            addSensorEvent(sensor);
            if (enableSensor(sensor, delay) != 0) {
            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) {
        }
    }
}
+41 −11
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
static struct {
    jclass clazz;
    jmethodID dispatchSensorEvent;
    jmethodID dispatchFlushCompleteEvent;
} gBaseEventQueueClassInfo;

namespace android {
@@ -46,6 +47,8 @@ struct SensorOffsets
    jfieldID    resolution;
    jfieldID    power;
    jfieldID    minDelay;
    jfieldID    fifoReservedEventCount;
    jfieldID    fifoMaxEventCount;
} gSensorOffsets;


@@ -67,6 +70,9 @@ nativeClassInit (JNIEnv *_env, jclass _this)
    sensorOffsets.resolution  = _env->GetFieldID(sensorClass, "mResolution","F");
    sensorOffsets.power       = _env->GetFieldID(sensorClass, "mPower",     "F");
    sensorOffsets.minDelay    = _env->GetFieldID(sensorClass, "mMinDelay",  "I");
    sensorOffsets.fifoReservedEventCount =
            _env->GetFieldID(sensorClass, "mFifoReservedEventCount",  "I");
    sensorOffsets.fifoMaxEventCount = _env->GetFieldID(sensorClass, "mFifoMaxEventCount",  "I");
}

static jint
@@ -92,7 +98,9 @@ nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next)
    env->SetFloatField(sensor, sensorOffsets.resolution, list->getResolution());
    env->SetFloatField(sensor, sensorOffsets.power,      list->getPowerUsage());
    env->SetIntField(sensor, sensorOffsets.minDelay,     list->getMinDelay());
    
    env->SetIntField(sensor, sensorOffsets.fifoReservedEventCount,
                     list->getFifoReservedEventCount());
    env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount, list->getFifoMaxEventCount());
    next++;
    return size_t(next) < count ? next : 0;
}
@@ -150,12 +158,20 @@ private:
                    env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);
                }

                if (buffer[i].type == SENSOR_TYPE_META_DATA) {
                    // This is a flush complete sensor event. Call dispatchFlushCompleteEvent
                    // method.
                    env->CallVoidMethod(mReceiverObject,
                                        gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
                                        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()) {
                    ALOGE("Exception dispatching input event.");
@@ -186,9 +202,11 @@ static jint nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQ
    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));
    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) {
@@ -202,6 +220,10 @@ static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jint eventQ
    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 },

    {"nativeEnableSensor",
            "(III)I",
            "(IIIII)I",
            (void*)nativeEnableSensor },

    {"nativeDisableSensor",
@@ -231,6 +253,10 @@ static JNINativeMethod gBaseEventQueueMethods[] = {
    {"nativeDestroySensorEventQueue",
            "(I)V",
            (void*)nativeDestroySensorEventQueue },

    {"nativeFlushSensor",
            "(II)I",
            (void*)nativeFlushSensor },
};

}; // namespace android
@@ -260,5 +286,9 @@ int register_android_hardware_SensorManager(JNIEnv *env)
            gBaseEventQueueClassInfo.clazz,
            "dispatchSensorEvent", "(I[FIJ)V");

    GET_METHOD_ID(gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
                  gBaseEventQueueClassInfo.clazz,
                  "dispatchFlushCompleteEvent", "(I)V");

    return 0;
}