Merge "Sensor values changes." into jb-mr2-dev

This commit is contained in:
Jaikumar Ganesh
2013-04-11 17:51:24 +00:00
committed by Android (Google) Code Review
5 changed files with 160 additions and 83 deletions

View File

@@ -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() {

View File

@@ -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.
*/

View File

@@ -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>
* 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.
* 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>
* 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];
}
}

View File

@@ -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);
}
}
}

View File

@@ -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.