diff options
author | Jaikumar Ganesh <jaikumar@google.com> | 2013-03-27 17:41:33 -0700 |
---|---|---|
committer | Jaikumar Ganesh <jaikumar@google.com> | 2013-04-11 10:25:35 -0700 |
commit | 6d0c1d78f121d4f1b72973740e8b120c7def1dc0 (patch) | |
tree | c65f4cc5738443bc80bdd4cbcb42e12e08b94376 | |
parent | 9a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5 (diff) | |
download | frameworks_base-6d0c1d78f121d4f1b72973740e8b120c7def1dc0.zip frameworks_base-6d0c1d78f121d4f1b72973740e8b120c7def1dc0.tar.gz frameworks_base-6d0c1d78f121d4f1b72973740e8b120c7def1dc0.tar.bz2 |
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
-rw-r--r-- | core/java/android/app/ContextImpl.java | 3 | ||||
-rw-r--r-- | core/java/android/hardware/Sensor.java | 32 | ||||
-rw-r--r-- | core/java/android/hardware/SensorEvent.java | 59 | ||||
-rw-r--r-- | core/java/android/hardware/SystemSensorManager.java | 147 | ||||
-rw-r--r-- | services/java/com/android/server/power/PowerManagerService.java | 2 |
5 files changed, 160 insertions, 83 deletions
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 19d495b..3fc82fa 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -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() { diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java index af4c074..074f8fe 100644 --- a/core/java/android/hardware/Sensor.java +++ b/core/java/android/hardware/Sensor.java @@ -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. */ diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java index 84c9131..012ae7e 100644 --- a/core/java/android/hardware/SensorEvent.java +++ b/core/java/android/hardware/SensorEvent.java @@ -290,8 +290,12 @@ public class SensorEvent { * <li> values[0]: x*sin(θ/2) </li> * <li> values[1]: y*sin(θ/2) </li> * <li> values[2]: z*sin(θ/2) </li> - * <li> values[3]: cos(θ/2) <i>(optional: only if value.length = 4)</i> </li> + * <li> values[3]: cos(θ/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]; } } diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index 3c231e5..c6c999b 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -1,4 +1,4 @@ -/* + /* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -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,91 +302,104 @@ 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. - System.arraycopy(values, 0, t.values, 0, t.values.length); - t.timestamp = timestamp; - t.accuracy = inAccuracy; - t.sensor = sensor; - switch (t.sensor.getType()) { - // Only report accuracy for sensors that support it. - case Sensor.TYPE_MAGNETIC_FIELD: - case Sensor.TYPE_ORIENTATION: - // call onAccuracyChanged() only if the value changes - final int accuracy = mSensorAccuracies.get(handle); - if ((t.accuracy >= 0) && (accuracy != t.accuracy)) { - mSensorAccuracies.put(handle, t.accuracy); - mListener.onAccuracyChanged(t.sensor, t.accuracy); - } - break; - default: - // For other sensors, just report the accuracy once - if (mFirstEvent.get(handle) == false) { - mFirstEvent.put(handle, true); - mListener.onAccuracyChanged( - t.sensor, SENSOR_STATUS_ACCURACY_HIGH); - } - break; - } - mListener.onSensorChanged(t); - } finally { - sSensorEventPool.release(t); + 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; + t.sensor = sensor; + switch (t.sensor.getType()) { + // Only report accuracy for sensors that support it. + case Sensor.TYPE_MAGNETIC_FIELD: + case Sensor.TYPE_ORIENTATION: + // call onAccuracyChanged() only if the value changes + final int accuracy = mSensorAccuracies.get(handle); + if ((t.accuracy >= 0) && (accuracy != t.accuracy)) { + mSensorAccuracies.put(handle, t.accuracy); + mListener.onAccuracyChanged(t.sensor, t.accuracy); + } + break; + default: + // For other sensors, just report the accuracy once + if (mFirstEvent.get(handle) == false) { + mFirstEvent.put(handle, true); + mListener.onAccuracyChanged( + t.sensor, SENSOR_STATUS_ACCURACY_HIGH); + } + break; } + mListener.onSensorChanged(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. - System.arraycopy(values, 0, t.values, 0, t.values.length); - t.timestamp = timestamp; - t.sensor = sensor; + // Copy from the values array. + System.arraycopy(values, 0, t.values, 0, t.values.length); + t.timestamp = timestamp; + t.sensor = sensor; - // A trigger sensor should be auto disabled. - mManager.cancelTriggerSensorImpl(mListener, sensor); + // A trigger sensor should be auto disabled. + mManager.cancelTriggerSensorImpl(mListener, sensor); - mListener.onTrigger(t); - } finally { - sTriggerEventPool.release(t); - } + mListener.onTrigger(t); } } } diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java index 2652739..1203e02 100644 --- a/services/java/com/android/server/power/PowerManagerService.java +++ b/services/java/com/android/server/power/PowerManagerService.java @@ -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. |