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

Commit 6d0c1d78 authored by Jaikumar Ganesh's avatar Jaikumar Ganesh
Browse files

Sensor values changes.

1. Remove Sensor Event Pool.
2. Allocate fixed array values for each Sensor added.
   - Needed for backward compatibility.
3. Use SDK checks for backward compatibility for
   rotation vector.

b/8165631

Change-Id: I2d2cf10d3460478ed7af8e6188343f4bb033503c
parent 9a8df4dc
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -449,7 +449,8 @@ class ContextImpl extends Context {

        registerService(SENSOR_SERVICE, new ServiceFetcher() {
                public Object createService(ContextImpl ctx) {
                    return new SystemSensorManager(ctx.mMainThread.getHandler().getLooper());
                    return new SystemSensorManager(ctx.getOuterContext(),
                      ctx.mMainThread.getHandler().getLooper());
                }});

        registerService(STATUS_BAR_SERVICE, new ServiceFetcher() {
+28 −4
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@

package android.hardware;

import android.os.Build;

/**
 * Class representing a sensor. Use {@link SensorManager#getSensorList} to get
 * the list of available Sensors.
@@ -119,10 +121,12 @@ public final class Sensor {
     * {@link android.hardware.SensorEvent#values SensorEvent.values} for more
     * details.
     * <p>
     * No periodic calibration is performed (ie: there are no discontinuities
     * in the data stream while using this sensor). Assumptions that the
     * magnetic field is due to the Earth's poles is avoided. Factory calibration
     * and temperature compensation is still performed.
     * Similar to {@link #TYPE_MAGNETIC_FIELD} but the hard iron calibration (calibration
     * due to distortions that arise from magnetized iron, steel or permanenet magnets
     * on the device) is reported separately. No periodic calibration is performed
     * (i.e. there are no discontinuities in the data stream while using this sensor).
     * Assumptions that the magnetic field is due to the Earth's poles is avoided.
     * Factory calibration and temperature compensation are still performed.
     * </p>
     */
    public static final int TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14;
@@ -193,11 +197,31 @@ public final class Sensor {
            REPORTING_MODE_ON_CHANGE, REPORTING_MODE_CONTINUOUS, REPORTING_MODE_CONTINUOUS,
            REPORTING_MODE_CONTINUOUS, REPORTING_MODE_ONE_SHOT };

    // Note: This needs to be updated, whenever a new sensor is added.
    // Holds the maximum length of the values array associated with {@link SensorEvent} or
    // {@link TriggerEvent} for the Sensor
    private static int[] sMaxLengthValuesArray = {
            3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 3,
            6, 4, 6, 1 };

    static int getReportingMode(Sensor sensor) {
        // mType starts from offset 1.
        return sSensorReportingModes[sensor.mType - 1];
    }

    static int getMaxLengthValuesArray(Sensor sensor, int sdkLevel) {
        // mType starts from offset 1.
        int len = sMaxLengthValuesArray[sensor.mType - 1];

        // RotationVector length has changed to 3 to 5 for API level 18
        // Set it to 3 for backward compatibility.
        if (sensor.getType() == Sensor.TYPE_ROTATION_VECTOR &&
                sdkLevel <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            len = 3;
        }
        return len;
    }

    /* Some of these fields are set only by the native bindings in
     * SensorManager.
     */
+50 −9
Original line number Diff line number Diff line
@@ -290,8 +290,12 @@ public class SensorEvent {
     * <li> values[0]: x*sin(&#952/2) </li>
     * <li> values[1]: y*sin(&#952/2) </li>
     * <li> values[2]: z*sin(&#952/2) </li>
     * <li> values[3]: cos(&#952/2) <i>(optional: only if value.length = 4)</i> </li>
     * <li> values[3]: cos(&#952/2) </li>
     * <li> values[4]: estimated heading Accuracy (in radians) (-1 if unavailable)</li>
     * </ul>
     * <p> values[3], originally optional, will always be present from SDK Level 18 onwards.
     * values[4] is a new value that has been added in SDK Level 18.
     * </p>
     *
     * <h4>{@link android.hardware.Sensor#TYPE_ORIENTATION
     * Sensor.TYPE_ORIENTATION}:</h4> All values are angles in degrees.
@@ -395,13 +399,50 @@ public class SensorEvent {
     * @see GeomagneticField
     *
     * <h4>{@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD_UNCALIBRATED} </h4>
     * All values are in micro-Tesla (uT) and measure the ambient magnetic field
     * in the X, Y and Z axis.
     * Similar to {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD},
     * but the hard iron calibration is reported separately instead of being included
     * in the measurement. Factory calibration and temperature compensation will still
     * be applied to the "uncalibrated" measurement. Assumptions that the magnetic field
     * is due to the Earth's poles is avoided.
     * <p>
     * The values array is shown below:
     * <ul>
     * <li> values[0] = x_uncalib </li>
     * <li> values[1] = y_uncalib </li>
     * <li> values[2] = z_uncalib </li>
     * <li> values[3] = x_bias </li>
     * <li> values[4] = y_bias </li>
     * <li> values[5] = z_bias </li>
     * </ul>
     * </p>
     * <p>
     * x_uncalib, y_uncalib, z_uncalib are the measured magnetic field in X, Y, Z axes.
     * Soft iron and temperature calibrations are applied. But the hard iron
     * calibration is not applied. The values are in micro-Tesla (uT).
     * </p>
     * <p>
     * x_bias, y_bias, z_bias give the iron bias estimated in X, Y, Z axes.
     * Each field is a component of the estimated hard iron calibration.
     * The values are in micro-Tesla (uT).
     * </p>
     * <p> Hard iron - These distortions arise due to the magnetized iron, steel or permanenet
     * magnets on the device.
     * Soft iron - These distortions arise due to the interaction with the earth's magentic
     * field.
     * </p>
     * <h4> {@link android.hardware.Sensor#TYPE_GAME_ROTATION_VECTOR} </h4>
     * Identical to {@link android.hardware.Sensor#TYPE_ROTATION_VECTOR} except that it
     * doesn't use the geomagnetic field. Therefore the Y axis doesn't
     * point north, but instead to some other reference, that reference is
     * allowed to drift by the same order of magnitude as the gyroscope
     * drift around the Z axis.
     * <p>
     * No periodic calibration is performed (ie: there are no discontinuities
     * in the data stream while using this sensor). Assumptions that the the
     * magnetic field is due to the Earth's poles is avoided. Factory calibration
     * and temperature compensation is still performed.
     * In the ideal case, a phone rotated and returning to the same real-world
     * orientation will report the same game rotation vector
     * (without using the earth's geomagnetic field). However, the orientation
     * may drift somewhat over time. See {@link android.hardware.Sensor#TYPE_ROTATION_VECTOR}
     * for a detailed description of the values. This sensor will not have
     * the estimated heading accuracy value.
     * </p>
     *
     * <h4> {@link android.hardware.Sensor#TYPE_GYROSCOPE_UNCALIBRATED} </h4>
@@ -452,7 +493,7 @@ public class SensorEvent {
     */
    public long timestamp;

    SensorEvent(int size) {
        values = new float[size];
    SensorEvent(int valueSize) {
        values = new float[valueSize];
    }
}
+79 −68
Original line number Diff line number Diff line
@@ -16,11 +16,10 @@

package android.hardware;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.Log;
import android.util.Pools;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
@@ -51,16 +50,14 @@ public class SystemSensorManager extends SensorManager {
    private final HashMap<TriggerEventListener, TriggerEventQueue> mTriggerListeners =
            new HashMap<TriggerEventListener, TriggerEventQueue>();

    private static final int MAX_EVENTS = 16;
    private static Pools.SynchronizedPool<SensorEvent> sSensorEventPool;
    private static Pools.SynchronizedPool<TriggerEvent> sTriggerEventPool;

    // Looper associated with the context in which this instance was created.
    private final Looper mMainLooper;
    private final int mTargetSdkLevel;

    /** {@hide} */
    public SystemSensorManager(Looper mainLooper) {
    public SystemSensorManager(Context context, Looper mainLooper) {
        mMainLooper = mainLooper;
        mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
        synchronized(sSensorModuleLock) {
            if (!sSensorModuleInitialized) {
                sSensorModuleInitialized = true;
@@ -80,11 +77,6 @@ public class SystemSensorManager extends SensorManager {
                        sHandleToSensor.append(sensor.getHandle(), sensor);
                    }
                } while (i>0);

                sSensorEventPool = new Pools.SynchronizedPool<SensorEvent>(
                        sFullSensorsList.size()*2);
                sTriggerEventPool = new Pools.SynchronizedPool<TriggerEvent>(
                        sFullSensorsList.size()*2);
            }
        }
    }
@@ -115,7 +107,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);
                queue = new SensorEventQueue(listener, looper, this);
                if (!queue.addSensor(sensor, delay)) {
                    queue.dispose();
                    return false;
@@ -208,6 +200,7 @@ 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 nativeDisableSensor(int eventQ, int handle);
@@ -218,10 +211,12 @@ public class SystemSensorManager extends SensorManager {
        protected final SparseBooleanArray mFirstEvent = new SparseBooleanArray();
        private final CloseGuard mCloseGuard = CloseGuard.get();
        private final float[] mScratch = new float[16];
        protected final SystemSensorManager mManager;

        BaseEventQueue(Looper looper) {
        BaseEventQueue(Looper looper, SystemSensorManager manager) {
            nSensorEventQueue = nativeInitBaseEventQueue(this, looper.getQueue(), mScratch);
            mCloseGuard.open("dispose");
            mManager = manager;
        }

        public void dispose() {
@@ -234,6 +229,7 @@ public class SystemSensorManager extends SensorManager {

            if (enableSensor(sensor, delay) == 0) {
                mActiveSensors.put(sensor.getHandle(), true);
                addSensorEvent(sensor);
                return true;
            }
            return false;
@@ -247,6 +243,7 @@ public class SystemSensorManager extends SensorManager {
                    if (sensor != null) {
                        disableSensor(sensor);
                        mActiveSensors.put(handle, false);
                        removeSensorEvent(sensor);
                    } else {
                        // it should never happen -- just ignore.
                    }
@@ -260,6 +257,7 @@ public class SystemSensorManager extends SensorManager {
            if (mActiveSensors.get(handle)) {
                disableSensor(sensor);
                mActiveSensors.put(sensor.getHandle(), false);
                removeSensorEvent(sensor);
                return true;
            }
            return false;
@@ -304,27 +302,39 @@ public class SystemSensorManager extends SensorManager {
        }
        protected abstract void dispatchSensorEvent(int handle, float[] values, int accuracy,
                long timestamp);

        protected abstract void addSensorEvent(Sensor sensor);
        protected abstract void removeSensorEvent(Sensor sensor);
    }

    static final class SensorEventQueue extends BaseEventQueue {
        private final SensorEventListener mListener;
        private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();

        public SensorEventQueue(SensorEventListener listener, Looper looper) {
            super(looper);
        public SensorEventQueue(SensorEventListener listener, Looper looper,
                SystemSensorManager manager) {
            super(looper, manager);
            mListener = listener;
        }

        public void addSensorEvent(Sensor sensor) {
            SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,
                    mManager.mTargetSdkLevel));
            mSensorsEvents.put(sensor.getHandle(), t);
        }

        public void removeSensorEvent(Sensor sensor) {
            mSensorsEvents.delete(sensor.getHandle());
        }

        // Called from native code.
        @SuppressWarnings("unused")
        @Override
        protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
                long timestamp) {
            final Sensor sensor = sHandleToSensor.get(handle);
            SensorEvent t = sSensorEventPool.acquire();
            if (t == null) t = new SensorEvent(MAX_EVENTS);
            try {
                // Copy the entire values array.
                // Any changes in length will be handled at the native layer.
            SensorEvent t = mSensorsEvents.get(handle);
            // Copy from the values array.
            System.arraycopy(values, 0, t.values, 0, t.values.length);
            t.timestamp = timestamp;
            t.accuracy = inAccuracy;
@@ -350,34 +360,38 @@ public class SystemSensorManager extends SensorManager {
                    break;
            }
            mListener.onSensorChanged(t);
            } finally {
                sSensorEventPool.release(t);
            }
        }
    }

    static final class TriggerEventQueue extends BaseEventQueue {
        private final TriggerEventListener mListener;
        private SensorManager mManager;
        private final SparseArray<TriggerEvent> mTriggerEvents = new SparseArray<TriggerEvent>();

        public TriggerEventQueue(TriggerEventListener listener, Looper looper,
                SensorManager manager) {
            super(looper);
                SystemSensorManager manager) {
            super(looper, manager);
            mListener = listener;
            mManager = manager;
        }

        public void addSensorEvent(Sensor sensor) {
            TriggerEvent t = new TriggerEvent(Sensor.getMaxLengthValuesArray(sensor,
                    mManager.mTargetSdkLevel));
            mTriggerEvents.put(sensor.getHandle(), t);
        }

        public void removeSensorEvent(Sensor sensor) {
            mTriggerEvents.delete(sensor.getHandle());
        }

        // Called from native code.
        @SuppressWarnings("unused")
        @Override
        protected void dispatchSensorEvent(int handle, float[] values, int accuracy, long timestamp) {
        protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
                long timestamp) {
            final Sensor sensor = sHandleToSensor.get(handle);
            TriggerEvent t = sTriggerEventPool.acquire();
            if (t == null) t = new TriggerEvent(MAX_EVENTS);
            TriggerEvent t = mTriggerEvents.get(handle);

            try {
                // Copy the entire values array.
                // Any changes in length will be handled at the native layer.
            // Copy from the values array.
            System.arraycopy(values, 0, t.values, 0, t.values.length);
            t.timestamp = timestamp;
            t.sensor = sensor;
@@ -386,9 +400,6 @@ public class SystemSensorManager extends SensorManager {
            mManager.cancelTriggerSensorImpl(mListener, sensor);

            mListener.onTrigger(t);
            } finally {
                sTriggerEventPool.release(t);
            }
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -432,7 +432,7 @@ public final class PowerManagerService extends IPowerManager.Stub
            mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
            mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();

            SensorManager sensorManager = new SystemSensorManager(mHandler.getLooper());
            SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());

            // The notifier runs on the system server's main looper so as not to interfere
            // with the animations and other critical functions of the power manager.