summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaikumar Ganesh <jaikumar@google.com>2013-03-27 17:41:33 -0700
committerJaikumar Ganesh <jaikumar@google.com>2013-04-11 10:25:35 -0700
commit6d0c1d78f121d4f1b72973740e8b120c7def1dc0 (patch)
treec65f4cc5738443bc80bdd4cbcb42e12e08b94376
parent9a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5 (diff)
downloadframeworks_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.java3
-rw-r--r--core/java/android/hardware/Sensor.java32
-rw-r--r--core/java/android/hardware/SensorEvent.java59
-rw-r--r--core/java/android/hardware/SystemSensorManager.java147
-rw-r--r--services/java/com/android/server/power/PowerManagerService.java2
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(&#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];
}
}
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.