Merge "Sensor values changes." into jb-mr2-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
651f99cb55
@@ -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() {
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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>
|
||||
* 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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user