Merge "fix CloseGuard usage in Surface" into jb-mr2-dev
diff --git a/api/current.txt b/api/current.txt
index be104a0..1668170 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10045,20 +10045,16 @@
field public static final int TYPE_ACCELEROMETER = 1; // 0x1
field public static final int TYPE_ALL = -1; // 0xffffffff
field public static final int TYPE_AMBIENT_TEMPERATURE = 13; // 0xd
- field public static final int TYPE_GAME_ROTATION_VECTOR = 15; // 0xf
field public static final int TYPE_GRAVITY = 9; // 0x9
field public static final int TYPE_GYROSCOPE = 4; // 0x4
- field public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16; // 0x10
field public static final int TYPE_LIGHT = 5; // 0x5
field public static final int TYPE_LINEAR_ACCELERATION = 10; // 0xa
field public static final int TYPE_MAGNETIC_FIELD = 2; // 0x2
- field public static final int TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14; // 0xe
field public static final deprecated int TYPE_ORIENTATION = 3; // 0x3
field public static final int TYPE_PRESSURE = 6; // 0x6
field public static final int TYPE_PROXIMITY = 8; // 0x8
field public static final int TYPE_RELATIVE_HUMIDITY = 12; // 0xc
field public static final int TYPE_ROTATION_VECTOR = 11; // 0xb
- field public static final int TYPE_SIGNIFICANT_MOTION = 17; // 0x11
field public static final deprecated int TYPE_TEMPERATURE = 7; // 0x7
}
@@ -10080,7 +10076,6 @@
}
public abstract class SensorManager {
- method public boolean cancelTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
method public static float getAltitude(float, float);
method public static void getAngleChange(float[], float[], float[]);
method public android.hardware.Sensor getDefaultSensor(int);
@@ -10096,7 +10091,6 @@
method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int);
method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, android.os.Handler);
method public static boolean remapCoordinateSystem(float[], int, int, float[]);
- method public boolean requestTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
method public deprecated void unregisterListener(android.hardware.SensorListener);
method public deprecated void unregisterListener(android.hardware.SensorListener, int);
method public void unregisterListener(android.hardware.SensorEventListener, android.hardware.Sensor);
@@ -10160,17 +10154,6 @@
field public static final float STANDARD_GRAVITY = 9.80665f;
}
- public final class TriggerEvent {
- field public android.hardware.Sensor sensor;
- field public long timestamp;
- field public final float[] values;
- }
-
- public abstract class TriggerEventListener {
- ctor public TriggerEventListener();
- method public abstract void onTrigger(android.hardware.TriggerEvent);
- }
-
}
package android.hardware.display {
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 8aef405..4968268 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -1256,6 +1256,13 @@
* interfaces that are cheaper and/or unnatural for a table-like
* model.
*
+ * <p class="note"><strong>WARNING:</strong> The framework does no permission checking
+ * on this entry into the content provider besides the basic ability for the application
+ * to get access to the provider at all. For example, it has no idea whether the call
+ * being executed may read or write data in the provider, so can't enforce those
+ * individual permissions. Any implementation of this method <strong>must</strong>
+ * do its own permission checks on incoming calls to make sure they are allowed.</p>
+ *
* @param method method name to call. Opaque to framework, but should not be {@code null}.
* @param arg provider-defined String argument. May be {@code null}.
* @param extras provider-defined Bundle argument. May be {@code null}.
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index af4c074..41384d2 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -114,90 +114,11 @@
/** A constant describing an ambient temperature sensor type */
public static final int TYPE_AMBIENT_TEMPERATURE = 13;
- /**
- * A constant describing a magnetic field uncalibrated sensor type. See
- * {@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.
- * </p>
- */
- public static final int TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14;
-
- /**
- * Identical to {@link #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 should report the same game rotation vector
- * (without using the earth's geomagnetic field). However, the orientation
- * may drift somewhat over time.
- * </p>
- */
-
- public static final int TYPE_GAME_ROTATION_VECTOR = 15;
-
- /**
- * A constant describing a gyroscope uncalibrated sensor type. See
- * {@link android.hardware.SensorEvent#values SensorEvent.values} for more
- * details.
- * <p>
- * No gyro-drift compensation is performed.
- * Factory calibration and temperature compensation is still applied
- * to the rate of rotation (angular speeds).
- * </p>
- */
- public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16;
-
- /**
- * A constant describing the significant motion trigger sensor.
- * See {@link android.hardware.SensorEvent#values} for more details.
- * <p>
- * It triggers when an event occurs and then automatically disables
- * itself. The sensor continues to operate while the device is asleep
- * and will automatically wake the device to notify when significant
- * motion is detected. The application does not need to hold any wake
- * locks for this sensor to trigger.
- * </p>
- */
- public static final int TYPE_SIGNIFICANT_MOTION = 17;
-
- /**
+ /**
* A constant describing all sensor types.
*/
public static final int TYPE_ALL = -1;
- /* Reporting mode constants for sensors. Each sensor will have exactly one
- reporting mode associated with it. */
- // Events are reported at a constant rate.
- static int REPORTING_MODE_CONTINUOUS = 1;
-
- // Events are reported only when the value changes.
- static int REPORTING_MODE_ON_CHANGE = 2;
-
- // Upon detection of an event, the sensor deactivates itself and then sends a single event.
- static int REPORTING_MODE_ONE_SHOT = 3;
-
- // Note: This needs to be updated, whenever a new sensor is added.
- private static int[] sSensorReportingModes = {
- REPORTING_MODE_CONTINUOUS, REPORTING_MODE_CONTINUOUS, REPORTING_MODE_CONTINUOUS,
- REPORTING_MODE_CONTINUOUS, REPORTING_MODE_ON_CHANGE, REPORTING_MODE_CONTINUOUS,
- REPORTING_MODE_ON_CHANGE, REPORTING_MODE_ON_CHANGE, REPORTING_MODE_CONTINUOUS,
- REPORTING_MODE_CONTINUOUS, REPORTING_MODE_CONTINUOUS, REPORTING_MODE_ON_CHANGE,
- REPORTING_MODE_ON_CHANGE, REPORTING_MODE_CONTINUOUS, REPORTING_MODE_CONTINUOUS,
- REPORTING_MODE_CONTINUOUS, REPORTING_MODE_ONE_SHOT };
-
- static int getReportingMode(Sensor sensor) {
- // mType starts from offset 1.
- return sSensorReportingModes[sensor.mType - 1];
- }
-
/* Some of these fields are set only by the native bindings in
* SensorManager.
*/
@@ -211,6 +132,7 @@
private float mPower;
private int mMinDelay;
+
Sensor() {
}
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 84c9131..51a17c1 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -17,9 +17,11 @@
package android.hardware;
/**
+ * <p>
* This class represents a {@link android.hardware.Sensor Sensor} event and
* holds informations such as the sensor's type, the time-stamp, accuracy and of
* course the sensor's {@link SensorEvent#values data}.
+ * </p>
*
* <p>
* <u>Definition of the coordinate system used by the SensorEvent API.</u>
@@ -65,9 +67,15 @@
* Sensor.TYPE_ACCELEROMETER}:</h4> All values are in SI units (m/s^2)
*
* <ul>
- * <li> values[0]: Acceleration minus Gx on the x-axis </li>
- * <li> values[1]: Acceleration minus Gy on the y-axis </li>
- * <li> values[2]: Acceleration minus Gz on the z-axis </li>
+ * <p>
+ * values[0]: Acceleration minus Gx on the x-axis
+ * </p>
+ * <p>
+ * values[1]: Acceleration minus Gy on the y-axis
+ * </p>
+ * <p>
+ * values[2]: Acceleration minus Gz on the z-axis
+ * </p>
* </ul>
*
* <p>
@@ -157,9 +165,15 @@
* definition of positive rotation and does not agree with the definition of
* roll given earlier.
* <ul>
- * <li> values[0]: Angular speed around the x-axis </li>
- * <li> values[1]: Angular speed around the y-axis </li>
- * <li> values[2]: Angular speed around the z-axis </li>
+ * <p>
+ * values[0]: Angular speed around the x-axis
+ * </p>
+ * <p>
+ * values[1]: Angular speed around the y-axis
+ * </p>
+ * <p>
+ * values[2]: Angular speed around the z-axis
+ * </p>
* </ul>
* <p>
* Typically the output of the gyroscope is integrated over time to
@@ -219,19 +233,22 @@
* </p>
* <h4>{@link android.hardware.Sensor#TYPE_LIGHT Sensor.TYPE_LIGHT}:</h4>
* <ul>
- * <li>values[0]: Ambient light level in SI lux units </li>
+ * <p>
+ * values[0]: Ambient light level in SI lux units
* </ul>
*
* <h4>{@link android.hardware.Sensor#TYPE_PRESSURE Sensor.TYPE_PRESSURE}:</h4>
* <ul>
- * <li>values[0]: Atmospheric pressure in hPa (millibar) </li>
+ * <p>
+ * values[0]: Atmospheric pressure in hPa (millibar)
* </ul>
*
* <h4>{@link android.hardware.Sensor#TYPE_PROXIMITY Sensor.TYPE_PROXIMITY}:
* </h4>
*
* <ul>
- * <li>values[0]: Proximity sensor distance measured in centimeters </li>
+ * <p>
+ * values[0]: Proximity sensor distance measured in centimeters
* </ul>
*
* <p>
@@ -287,23 +304,39 @@
* </p>
*
* <ul>
- * <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>
+ * <p>
+ * values[0]: x*sin(θ/2)
+ * </p>
+ * <p>
+ * values[1]: y*sin(θ/2)
+ * </p>
+ * <p>
+ * values[2]: z*sin(θ/2)
+ * </p>
+ * <p>
+ * values[3]: cos(θ/2) <i>(optional: only if value.length = 4)</i>
+ * </p>
* </ul>
*
* <h4>{@link android.hardware.Sensor#TYPE_ORIENTATION
* Sensor.TYPE_ORIENTATION}:</h4> All values are angles in degrees.
*
* <ul>
- * <li> values[0]: Azimuth, angle between the magnetic north direction and the
+ * <p>
+ * values[0]: Azimuth, angle between the magnetic north direction and the
* y-axis, around the z-axis (0 to 359). 0=North, 90=East, 180=South,
- * 270=West </li>
- * <li> values[1]: Pitch, rotation around x-axis (-180 to 180), with positive
- * values when the z-axis moves <b>toward</b> the y-axis. </li>
- * <li> values[2]: Roll, rotation around y-axis (-90 to 90), with positive values
- * when the x-axis moves <b>toward</b> the z-axis. </li>
+ * 270=West
+ * </p>
+ *
+ * <p>
+ * values[1]: Pitch, rotation around x-axis (-180 to 180), with positive
+ * values when the z-axis moves <b>toward</b> the y-axis.
+ * </p>
+ *
+ * <p>
+ * values[2]: Roll, rotation around y-axis (-90 to 90), with positive values
+ * when the x-axis moves <b>toward</b> the z-axis.
+ * </p>
* </ul>
*
* <p>
@@ -331,7 +364,9 @@
* <h4>{@link android.hardware.Sensor#TYPE_RELATIVE_HUMIDITY
* Sensor.TYPE_RELATIVE_HUMIDITY}:</h4>
* <ul>
- * <li> values[0]: Relative ambient air humidity in percent </li>
+ * <p>
+ * values[0]: Relative ambient air humidity in percent
+ * </p>
* </ul>
* <p>
* When relative ambient air humidity and ambient temperature are
@@ -388,58 +423,21 @@
* </h4>
*
* <ul>
- * <li> values[0]: ambient (room) temperature in degree Celsius.</li>
+ * <p>
+ * values[0]: ambient (room) temperature in degree Celsius.
* </ul>
*
* @see 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.
- * <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.
- * </p>
- *
- * <h4> {@link android.hardware.Sensor#TYPE_GYROSCOPE_UNCALIBRATED} </h4>
- * All values are in radians/second and measure the rate of rotation
- * around the X, Y and Z axis. An estimation of the drift on each axis is
- * reported as well.
- * <p>
- * No gyro-drift compensation is performed. Factory calibration and temperature
- * compensation is still applied to the rate of rotation (angular speeds).
- * </p>
- * <p>
- * The coordinate system is the same as is used for the
- * {@link android.hardware.Sensor#TYPE_ACCELEROMETER}
- * Rotation is positive in the counter-clockwise direction (right-hand rule).
- * That is, an observer looking from some positive location on the x, y or z axis
- * at a device positioned on the origin would report positive rotation if the device
- * appeared to be rotating counter clockwise.
- * The range would at least be 17.45 rad/s (ie: ~1000 deg/s).
- * <ul>
- * <li> values[0] : angular speed (w/o drift compensation) around the X axis in rad/s </li>
- * <li> values[1] : angular speed (w/o drift compensation) around the Y axis in rad/s </li>
- * <li> values[2] : angular speed (w/o drift compensation) around the Z axis in rad/s </li>
- * <li> values[3] : estimated drift around X axis in rad/s </li>
- * <li> values[4] : estimated drift around Y axis in rad/s </li>
- * <li> values[5] : estimated drift around Z axis in rad/s </li>
- * </ul>
- * </p>
- * <h4></h4>
- * <h4> Pro Tip: Always use the length of the values array while performing operations
- * on it. In earlier versions, this used to be always 3 which has changed now. </h4>
*/
+
public final float[] values;
/**
* The sensor that generated this event. See
* {@link android.hardware.SensorManager SensorManager} for details.
*/
- public Sensor sensor;
+ public Sensor sensor;
/**
* The accuracy of this event. See {@link android.hardware.SensorManager
@@ -447,11 +445,13 @@
*/
public int accuracy;
+
/**
* The time in nanosecond at which the event happened
*/
public long timestamp;
+
SensorEvent(int size) {
values = new float[size];
}
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index ce7bc7e..c0d2fae 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -38,11 +38,7 @@
* hours. Note that the system will <i>not</i> disable sensors automatically when
* the screen turns off.
* </p>
- * <p class="note">
- * Note: Don't use this mechanism with a Trigger Sensor, have a look
- * at {@link TriggerEventListener}. {@link Sensor#TYPE_SIGNIFICANT_MOTION}
- * is an example of a trigger sensor.
- * </p>
+ *
* <pre class="prettyprint">
* public class SensorActivity extends Activity, implements SensorEventListener {
* private final SensorManager mSensorManager;
@@ -519,12 +515,6 @@
/**
* Unregisters a listener for the sensors with which it is registered.
*
- * <p class="note"></p>
- * Note: Don't use this method with a one shot trigger sensor such as
- * {@link Sensor#TYPE_SIGNIFICANT_MOTION}.
- * Use {@link #cancelTriggerSensor(TriggerEventListener, Sensor)} instead.
- * </p>
- *
* @param listener
* a SensorEventListener object
*
@@ -534,7 +524,6 @@
* @see #unregisterListener(SensorEventListener)
* @see #registerListener(SensorEventListener, Sensor, int)
*
- * @throws IllegalArgumentException when sensor is a trigger sensor.
*/
public void unregisterListener(SensorEventListener listener, Sensor sensor) {
if (listener == null || sensor == null) {
@@ -569,12 +558,6 @@
* Registers a {@link android.hardware.SensorEventListener
* SensorEventListener} for the given sensor.
*
- * <p class="note"></p>
- * Note: Don't use this method with a one shot trigger sensor such as
- * {@link Sensor#TYPE_SIGNIFICANT_MOTION}.
- * Use {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead.
- * </p>
- *
* @param listener
* A {@link android.hardware.SensorEventListener SensorEventListener}
* object.
@@ -598,7 +581,6 @@
* @see #unregisterListener(SensorEventListener)
* @see #unregisterListener(SensorEventListener, Sensor)
*
- * @throws IllegalArgumentException when sensor is null or a trigger sensor
*/
public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {
return registerListener(listener, sensor, rate, null);
@@ -608,12 +590,6 @@
* Registers a {@link android.hardware.SensorEventListener
* SensorEventListener} for the given sensor.
*
- * <p class="note"></p>
- * Note: Don't use this method with a one shot trigger sensor such as
- * {@link Sensor#TYPE_SIGNIFICANT_MOTION}.
- * Use {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead.
- * </p>
- *
* @param listener
* A {@link android.hardware.SensorEventListener SensorEventListener}
* object.
@@ -641,7 +617,6 @@
* @see #unregisterListener(SensorEventListener)
* @see #unregisterListener(SensorEventListener, Sensor)
*
- * @throws IllegalArgumentException when sensor is null or a trigger sensor
*/
public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,
Handler handler) {
@@ -1329,68 +1304,6 @@
Q[3] = rv[2];
}
- /**
- * Requests receiving trigger events for a trigger sensor.
- *
- * <p>
- * When the sensor detects a trigger event condition, such as significant motion in
- * the case of the {@link Sensor#TYPE_SIGNIFICANT_MOTION}, the provided trigger listener
- * will be invoked once and then its request to receive trigger events will be canceled.
- * To continue receiving trigger events, the application must request to receive trigger
- * events again.
- * </p>
- *
- * @param listener The listener on which the
- * {@link TriggerEventListener#onTrigger(TriggerEvent)} will be delivered.
- * @param sensor The sensor to be enabled.
- *
- * @return true if the sensor was successfully enabled.
- *
- * @throws IllegalArgumentException when sensor is null or not a trigger sensor.
- */
- public boolean requestTriggerSensor(TriggerEventListener listener, Sensor sensor) {
- return requestTriggerSensorImpl(listener, sensor);
- }
-
- /**
- * @hide
- */
- protected abstract boolean requestTriggerSensorImpl(TriggerEventListener listener,
- Sensor sensor);
-
- /**
- * Cancels receiving trigger events for a trigger sensor.
- *
- * <p>
- * Note that a Trigger sensor will be auto disabled if
- * {@link TriggerEventListener#onTrigger(TriggerEvent)} has triggered.
- * This method is provided in case the user wants to explicitly cancel the request
- * to receive trigger events.
- * </p>
- *
- * @param listener The listener on which the
- * {@link TriggerEventListener#onTrigger(TriggerEvent)}
- * is delivered.It should be the same as the one used
- * in {@link #requestTriggerSensor(TriggerEventListener, Sensor)}
- * @param sensor The sensor for which the trigger request should be canceled.
- * If null, it cancels receiving trigger for all sensors associated
- * with the listener.
- *
- * @return true if successfully canceled.
- *
- * @throws IllegalArgumentException when sensor is a trigger sensor.
- */
- public boolean cancelTriggerSensor(TriggerEventListener listener, Sensor sensor) {
- return cancelTriggerSensorImpl(listener, sensor);
- }
-
- /**
- * @hide
- */
- protected abstract boolean cancelTriggerSensorImpl(TriggerEventListener listener,
- Sensor sensor);
-
-
private LegacySensorManager getLegacySensorManager() {
synchronized (mSensorListByType) {
if (mLegacySensorManager == null) {
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 893d701..9591631 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -16,19 +16,18 @@
package android.hardware;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+import dalvik.system.CloseGuard;
+
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;
-import dalvik.system.CloseGuard;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
/**
* Sensor manager implementation that communicates with the built-in
@@ -46,21 +45,22 @@
private static final SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
// Listener list
- private final HashMap<SensorEventListener, SensorEventQueue> mSensorListeners =
- new HashMap<SensorEventListener, SensorEventQueue>();
- private final HashMap<TriggerEventListener, TriggerEventQueue> mTriggerListeners =
- new HashMap<TriggerEventListener, TriggerEventQueue>();
+ private final ArrayList<SensorEventListenerSensorPair> mListenerDelegates = new ArrayList<SensorEventListenerSensorPair>();
- private static final int MAX_EVENTS = 16;
- private static Pools.SynchronizedPool<SensorEvent> sSensorEventPool;
- private static Pools.SynchronizedPool<TriggerEvent> sTriggerEventPool;
+ // Common pool of sensor events.
+ private static SensorEventPool sPool;
// Looper associated with the context in which this instance was created.
private final Looper mMainLooper;
+ // maps a SensorEventListener to a SensorEventQueue
+ private final Hashtable<SensorEventListener, SensorEventQueue> mSensorEventQueueMap;
+
/** {@hide} */
public SystemSensorManager(Looper mainLooper) {
mMainLooper = mainLooper;
+ mSensorEventQueueMap = new Hashtable<SensorEventListener, SensorEventQueue>();
+
synchronized(sSensorModuleLock) {
if (!sSensorModuleInitialized) {
sSensorModuleInitialized = true;
@@ -81,10 +81,7 @@
}
} while (i>0);
- sSensorEventPool = new Pools.SynchronizedPool<SensorEvent>(
- Math.max(sFullSensorsList.size()*2, 1));
- sTriggerEventPool = new Pools.SynchronizedPool<TriggerEvent>(
- Math.max(sFullSensorsList.size()*2, 1));
+ sPool = new SensorEventPool( sFullSensorsList.size()*2 );
}
}
}
@@ -105,133 +102,128 @@
// Invariants to preserve:
// - one Looper per SensorEventListener
// - one Looper per SensorEventQueue
- // We map SensorEventListener to a SensorEventQueue, which holds the looper
- if (sensor == null) throw new IllegalArgumentException("sensor cannot be null");
+ // We map SensorEventListeners to a SensorEventQueue, which holds the looper
- // Trigger Sensors should use the requestTriggerSensor call.
- if (Sensor.getReportingMode(sensor) == Sensor.REPORTING_MODE_ONE_SHOT) return false;
+ if (sensor == null) throw new NullPointerException("sensor cannot be null");
- synchronized (mSensorListeners) {
- SensorEventQueue queue = mSensorListeners.get(listener);
- if (queue == null) {
- Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
- queue = new SensorEventQueue(listener, looper);
- if (!queue.addSensor(sensor, delay)) {
- queue.dispose();
- return false;
+ boolean result;
+ synchronized (mSensorEventQueueMap) {
+ // check if we already have this SensorEventListener, Sensor pair
+ // registered -- if so, we ignore the register. This is not ideal
+ // but this is what the implementation has always been doing.
+ for (SensorEventListenerSensorPair l : mListenerDelegates) {
+ if (l.isSameListenerSensorPair(listener, sensor)) {
+ // already added, just return silently.
+ return true;
}
- mSensorListeners.put(listener, queue);
- return true;
+ }
+
+ // now find the SensorEventQueue associated to this listener
+ SensorEventQueue queue = mSensorEventQueueMap.get(listener);
+ if (queue != null) {
+ result = queue.addSensor(sensor, delay);
+ if (result) {
+ // create a new ListenerDelegate for this pair
+ mListenerDelegates.add(new SensorEventListenerSensorPair(listener, sensor));
+ }
} else {
- return queue.addSensor(sensor, delay);
+ Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
+ queue = new SensorEventQueue(listener, looper.getQueue());
+ result = queue.addSensor(sensor, delay);
+ if (result) {
+ // create a new ListenerDelegate for this pair
+ mListenerDelegates.add(new SensorEventListenerSensorPair(listener, sensor));
+ mSensorEventQueueMap.put(listener, queue);
+ } else {
+ queue.dispose();
+ }
}
}
+ return result;
}
/** @hide */
@Override
protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
- // Trigger Sensors should use the cancelTriggerSensor call.
- if (sensor != null && Sensor.getReportingMode(sensor) == Sensor.REPORTING_MODE_ONE_SHOT) {
- return;
- }
+ synchronized (mSensorEventQueueMap) {
- synchronized (mSensorListeners) {
- SensorEventQueue queue = mSensorListeners.get(listener);
- if (queue != null) {
- boolean result;
- if (sensor == null) {
- result = queue.removeAllSensors();
- } else {
- result = queue.removeSensor(sensor);
+ // remove this listener/sensor from our list
+ final ArrayList<SensorEventListenerSensorPair> copy =
+ new ArrayList<SensorEventListenerSensorPair>(mListenerDelegates);
+ int lastIndex = copy.size()-1;
+ for (int i=lastIndex ; i>= 0 ; i--) {
+ if (copy.get(i).isSameListenerSensorPair(listener, sensor)) {
+ mListenerDelegates.remove(i);
}
- if (result && !queue.hasSensors()) {
- mSensorListeners.remove(listener);
+ }
+
+ // find the SensorEventQueue associated to this SensorEventListener
+ SensorEventQueue queue = mSensorEventQueueMap.get(listener);
+ if (queue != null) {
+ if (sensor != null) {
+ queue.removeSensor(sensor);
+ } else {
+ queue.removeAllSensors();
+ }
+ if (!queue.hasSensors()) {
+ mSensorEventQueueMap.remove(listener);
queue.dispose();
}
}
}
}
- /** @hide */
- @Override
- protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
- if (sensor == null) throw new IllegalArgumentException("sensor cannot be null");
- if (Sensor.getReportingMode(sensor) != Sensor.REPORTING_MODE_ONE_SHOT) return false;
-
- synchronized (mTriggerListeners) {
- TriggerEventQueue queue = mTriggerListeners.get(listener);
- if (queue == null) {
- queue = new TriggerEventQueue(listener, mMainLooper, this);
- if (!queue.addSensor(sensor, 0)) {
- queue.dispose();
- return false;
- }
- mTriggerListeners.put(listener, queue);
- return true;
+ /*
+ * ListenerDelegate is essentially a SensorEventListener, Sensor pair
+ * and is associated with a single SensorEventQueue.
+ */
+ private static final class SensorEventListenerSensorPair {
+ private final SensorEventListener mSensorEventListener;
+ private final Sensor mSensor;
+ public SensorEventListenerSensorPair(SensorEventListener listener, Sensor sensor) {
+ mSensorEventListener = listener;
+ mSensor = sensor;
+ }
+ public boolean isSameListenerSensorPair(SensorEventListener listener, Sensor sensor) {
+ // if sensor is null, we match only on the listener
+ if (sensor != null) {
+ return (listener == mSensorEventListener) &&
+ (sensor.getHandle() == mSensor.getHandle());
} else {
- return queue.addSensor(sensor, 0);
+ return (listener == mSensorEventListener);
}
}
}
- /** @hide */
- @Override
- protected boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
- if (sensor != null && Sensor.getReportingMode(sensor) != Sensor.REPORTING_MODE_ONE_SHOT) {
- return false;
- }
- synchronized (mTriggerListeners) {
- TriggerEventQueue queue = mTriggerListeners.get(listener);
- if (queue != null) {
- boolean result;
- if (sensor == null) {
- result = queue.removeAllSensors();
- } else {
- result = queue.removeSensor(sensor);
- }
- if (result && !queue.hasSensors()) {
- mTriggerListeners.remove(listener);
- queue.dispose();
- }
- return result;
- }
- return false;
- }
- }
-
/*
- * BaseEventQueue is the communication channel with the sensor service,
- * SensorEventQueue, TriggerEventQueue are subclases and there is one-to-one mapping between
- * the queues and the listeners.
+ * SensorEventQueue is the communication channel with the sensor service,
+ * there is a one-to-one mapping between SensorEventQueue and
+ * SensorEventListener.
*/
- private static abstract class BaseEventQueue {
- private native int nativeInitBaseEventQueue(BaseEventQueue eventQ, MessageQueue msgQ,
- float[] scratch);
+ private static final class SensorEventQueue {
+ private static native int nativeInitSensorEventQueue(SensorEventQueue 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);
private static native void nativeDestroySensorEventQueue(int eventQ);
private int nSensorEventQueue;
+ private final SensorEventListener mListener;
private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
- protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
- protected final SparseBooleanArray mFirstEvent = new SparseBooleanArray();
+ private final SparseIntArray mSensorAccuracies = new SparseIntArray();
+ private final SparseBooleanArray mFirstEvent = new SparseBooleanArray();
private final CloseGuard mCloseGuard = CloseGuard.get();
private final float[] mScratch = new float[16];
- BaseEventQueue(Looper looper) {
- nSensorEventQueue = nativeInitBaseEventQueue(this, looper.getQueue(), mScratch);
+ public SensorEventQueue(SensorEventListener listener, MessageQueue msgQ) {
+ nSensorEventQueue = nativeInitSensorEventQueue(this, msgQ, mScratch);
+ mListener = listener;
mCloseGuard.open("dispose");
}
-
public void dispose() {
dispose(false);
}
public boolean addSensor(Sensor sensor, int delay) {
- // Check if already present.
- if (mActiveSensors.get(sensor.getHandle())) return false;
-
if (enableSensor(sensor, delay) == 0) {
mActiveSensors.put(sensor.getHandle(), true);
return true;
@@ -239,7 +231,7 @@
return false;
}
- public boolean removeAllSensors() {
+ public void removeAllSensors() {
for (int i=0 ; i<mActiveSensors.size(); i++) {
if (mActiveSensors.valueAt(i) == true) {
int handle = mActiveSensors.keyAt(i);
@@ -252,24 +244,21 @@
}
}
}
- return true;
}
- public boolean removeSensor(Sensor sensor) {
+ public void removeSensor(Sensor sensor) {
final int handle = sensor.getHandle();
if (mActiveSensors.get(handle)) {
disableSensor(sensor);
mActiveSensors.put(sensor.getHandle(), false);
- return true;
}
- return false;
}
public boolean hasSensors() {
// no more sensors are set
return mActiveSensors.indexOfValue(true) >= 0;
}
-
+
@Override
protected void finalize() throws Throwable {
try {
@@ -302,30 +291,17 @@
if (sensor == null) throw new NullPointerException();
return nativeDisableSensor(nSensorEventQueue, sensor.getHandle());
}
- protected abstract void dispatchSensorEvent(int handle, float[] values, int accuracy,
- long timestamp);
- }
-
- static final class SensorEventQueue extends BaseEventQueue {
- private final SensorEventListener mListener;
-
- public SensorEventQueue(SensorEventListener listener, Looper looper) {
- super(looper);
- mListener = listener;
- }
// 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);
+ private void dispatchSensorEvent(int handle, float[] values, int inAccuracy, long timestamp) {
+ // this is always called on the same thread.
+ final SensorEvent t = sPool.getFromPool();
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);
+ final Sensor sensor = sHandleToSensor.get(handle);
+ final SensorEventListener listener = mListener;
+ // FIXME: handle more than 3 values
+ System.arraycopy(values, 0, t.values, 0, 3);
t.timestamp = timestamp;
t.accuracy = inAccuracy;
t.sensor = sensor;
@@ -337,57 +313,72 @@
final int accuracy = mSensorAccuracies.get(handle);
if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
mSensorAccuracies.put(handle, t.accuracy);
- mListener.onAccuracyChanged(t.sensor, t.accuracy);
+ listener.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(
+ listener.onAccuracyChanged(
t.sensor, SENSOR_STATUS_ACCURACY_HIGH);
}
break;
}
- mListener.onSensorChanged(t);
+ listener.onSensorChanged(t);
} finally {
- sSensorEventPool.release(t);
+ sPool.returnToPool(t);
}
}
}
- static final class TriggerEventQueue extends BaseEventQueue {
- private final TriggerEventListener mListener;
- private SensorManager mManager;
+ /*
+ * A dumb pool of SensorEvent
+ */
+ private static final class SensorEventPool {
+ private final int mPoolSize;
+ private final SensorEvent mPool[];
+ private int mNumItemsInPool;
- public TriggerEventQueue(TriggerEventListener listener, Looper looper,
- SensorManager manager) {
- super(looper);
- mListener = listener;
- mManager = manager;
+ private SensorEvent createSensorEvent() {
+ // maximal size for all legacy events is 3
+ return new SensorEvent(3);
}
- // Called from native code.
- @SuppressWarnings("unused")
- @Override
- 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);
+ SensorEventPool(int poolSize) {
+ mPoolSize = poolSize;
+ mNumItemsInPool = poolSize;
+ mPool = new SensorEvent[poolSize];
+ }
- 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;
+ SensorEvent getFromPool() {
+ SensorEvent t = null;
+ synchronized (this) {
+ if (mNumItemsInPool > 0) {
+ // remove the "top" item from the pool
+ final int index = mPoolSize - mNumItemsInPool;
+ t = mPool[index];
+ mPool[index] = null;
+ mNumItemsInPool--;
+ }
+ }
+ if (t == null) {
+ // the pool was empty or this item was removed from the pool for
+ // the first time. In any case, we need to create a new item.
+ t = createSensorEvent();
+ }
+ return t;
+ }
- // A trigger sensor should be auto disabled.
- mManager.cancelTriggerSensorImpl(mListener, sensor);
-
- mListener.onTrigger(t);
- } finally {
- sTriggerEventPool.release(t);
+ void returnToPool(SensorEvent t) {
+ synchronized (this) {
+ // is there space left in the pool?
+ if (mNumItemsInPool < mPoolSize) {
+ // if so, return the item to the pool
+ mNumItemsInPool++;
+ final int index = mPoolSize - mNumItemsInPool;
+ mPool[index] = t;
+ }
}
}
}
diff --git a/core/java/android/hardware/TriggerEvent.java b/core/java/android/hardware/TriggerEvent.java
deleted file mode 100644
index bdd39f3..0000000
--- a/core/java/android/hardware/TriggerEvent.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware;
-
-/**
- * This class represents a Trigger Event - the event
- * associated with a Trigger Sensor. When the sensor detects a trigger
- * event condition, such as significant motion in the case of the
- * {@link Sensor#TYPE_SIGNIFICANT_MOTION}, the {@link TriggerEventListener}
- * is called with the TriggerEvent. The sensor is automatically canceled
- * after the trigger.
- * <p>
- * This class holds information such as the value of the sensor
- * when the trigger happened, the timestamp along with detailed
- * information regarding the Sensor itself.
- * </p>
- * @see android.hardware.SensorManager
- * @see android.hardware.TriggerEvent
- * @see android.hardware.Sensor
- */
-public final class TriggerEvent {
- /**
- * <p>
- * The length and contents of the {@link #values values} array depends on
- * which {@link android.hardware.Sensor sensor} type is being monitored (see
- * also {@link SensorEvent} for a definition of the coordinate system used).
- * </p>
- * <h4> {@link Sensor#TYPE_SIGNIFICANT_MOTION} </h4>
- * The value field is of length 1. value[0] = 1.0 when the sensor triggers.
- * 1.0 is the only allowed value.
- */
- public final float[] values;
-
- /**
- * The sensor that generated this event. See
- * {@link android.hardware.SensorManager SensorManager} for details.
- */
- public Sensor sensor;
-
- /**
- * The time in nanosecond at which the event happened
- */
- public long timestamp;
-
- TriggerEvent(int size) {
- values = new float[size];
- }
-}
diff --git a/core/java/android/hardware/TriggerEventListener.java b/core/java/android/hardware/TriggerEventListener.java
deleted file mode 100644
index 76b2796..0000000
--- a/core/java/android/hardware/TriggerEventListener.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware;
-
-/**
- * This class is the listener used to handle Trigger Sensors.
- * Trigger Sensors are sensors that trigger an event and are automatically
- * disabled. {@link Sensor#TYPE_SIGNIFICANT_MOTION} is one such example.
- * <p>
- * SensorManager lets you access the device's {@link android.hardware.Sensor
- * sensors}. Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with the argument
- * {@link android.content.Context#SENSOR_SERVICE}.
- * Usage details are explained in the example below.
- * </p>
- *
- * <pre class="prettyprint">
- * class TriggerListener extends TriggerEventListener {
- * public void onTrigger(TriggerEvent event) {
- * // Do Work.
- *
- * // As it is a one shot sensor, it will be canceled automatically.
- * // SensorManager.requestTriggerSensor(this, mSigMotion); needs to
- * // be called again, if needed.
- * }
- * }
- * public class SensorActivity extends Activity {
- * private final SensorManager mSensorManager;
- * private final Sensor mSigMotion;
- * private final TriggerEventListener mListener = new TriggerEventListener();
- *
- * public SensorActivity() {
- * mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
- * mSigMotion = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
- * }
- *
- * protected void onResume() {
- * super.onResume();
- * mSensorManager.requestTriggerSensor(mListener, mSigMotion);
- * }
- *
- * protected void onPause() {
- * super.onPause();
- * // Call disable to ensure that the trigger request has been canceled.
- * mSensorManager.cancelTriggerSensor(mListener, mSigMotion);
- * }
- *
- * }
- * </pre>
- *
- * @see TriggerEvent
- * @see Sensor
- */
-public abstract class TriggerEventListener {
- /**
- * The method that will be called when the sensor
- * is triggered. Override this method in your implementation
- * of this class.
- *
- * @param event The details of the event.
- */
- public abstract void onTrigger(TriggerEvent event);
-}
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
index fd22b10..f140282 100644
--- a/core/java/android/net/DhcpStateMachine.java
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -77,7 +77,7 @@
RENEW
};
- private String mInterfaceName;
+ private final String mInterfaceName;
private boolean mRegisteredForPreDhcpNotification = false;
private static final int BASE = Protocol.BASE_DHCP;
@@ -349,6 +349,7 @@
private boolean runDhcp(DhcpAction dhcpAction) {
boolean success = false;
DhcpResults dhcpResults = new DhcpResults();
+ dhcpResults.linkProperties.mLogMe = true;
if (dhcpAction == DhcpAction.START) {
/* Stop any existing DHCP daemon before starting new */
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 5d13a18..9292e5f 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -20,6 +20,7 @@
import android.os.Parcelable;
import android.os.Parcel;
import android.text.TextUtils;
+import android.util.Log;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -57,6 +58,7 @@
private String mDomains;
private Collection<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
private ProxyProperties mHttpProxy;
+ public boolean mLogMe;
public static class CompareResult<T> {
public Collection<T> removed = new ArrayList<T>();
@@ -75,6 +77,7 @@
public LinkProperties() {
clear();
+ mLogMe = false;
}
// copy constructor instead of clone
@@ -91,6 +94,14 @@
}
public void setInterfaceName(String iface) {
+ if (mLogMe) {
+ Log.d("LinkProperties", "setInterfaceName from " + mIfaceName +
+ " to " + iface);
+ for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
+ Log.d("LinkProperties", " " + e.toString());
+ }
+ }
+
mIfaceName = iface;
ArrayList<RouteInfo> newRoutes = new ArrayList<RouteInfo>(mRoutes.size());
for (RouteInfo route : mRoutes) {
@@ -166,6 +177,13 @@
}
public void clear() {
+ if (mLogMe) {
+ Log.d("LinkProperties", "clear from " + mIfaceName);
+ for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
+ Log.d("LinkProperties", " " + e.toString());
+ }
+ }
+
mIfaceName = null;
mLinkAddresses.clear();
mDnses.clear();
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 6374494..3083cb1 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -31,7 +31,7 @@
static struct {
jclass clazz;
jmethodID dispatchSensorEvent;
-} gBaseEventQueueClassInfo;
+} gSensorEventQueueClassInfo;
namespace android {
@@ -145,7 +145,7 @@
env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);
env->CallVoidMethod(mReceiverObject,
- gBaseEventQueueClassInfo.dispatchSensorEvent,
+ gSensorEventQueueClassInfo.dispatchSensorEvent,
buffer[i].sensor,
mScratch,
buffer[i].vector.status,
@@ -209,9 +209,9 @@
(void*)nativeGetNextSensor },
};
-static JNINativeMethod gBaseEventQueueMethods[] = {
- {"nativeInitBaseEventQueue",
- "(Landroid/hardware/SystemSensorManager$BaseEventQueue;Landroid/os/MessageQueue;[F)I",
+static JNINativeMethod gSensorEventQueueMethods[] = {
+ {"nativeInitSensorEventQueue",
+ "(Landroid/hardware/SystemSensorManager$SensorEventQueue;Landroid/os/MessageQueue;[F)I",
(void*)nativeInitSensorEventQueue },
{"nativeEnableSensor",
@@ -245,13 +245,13 @@
jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager",
gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
- jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager$BaseEventQueue",
- gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
+ jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager$SensorEventQueue",
+ gSensorEventQueueMethods, NELEM(gSensorEventQueueMethods));
- FIND_CLASS(gBaseEventQueueClassInfo.clazz, "android/hardware/SystemSensorManager$BaseEventQueue");
+ FIND_CLASS(gSensorEventQueueClassInfo.clazz, "android/hardware/SystemSensorManager$SensorEventQueue");
- GET_METHOD_ID(gBaseEventQueueClassInfo.dispatchSensorEvent,
- gBaseEventQueueClassInfo.clazz,
+ GET_METHOD_ID(gSensorEventQueueClassInfo.dispatchSensorEvent,
+ gSensorEventQueueClassInfo.clazz,
"dispatchSensorEvent", "(I[FIJ)V");
return 0;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 105f45f..4e6b552 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1169,6 +1169,7 @@
break;
}
mLocalBounds.set(x, mY + metrics.fTop, x + length, mY + metrics.fBottom);
+ memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float));
}
/*
@@ -1179,9 +1180,11 @@
virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
SkPaint* paint = getPaint(renderer);
FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
- const bool pureTranslate = state.mMatrix.isPureTranslate();
- const mat4 transform = renderer.findBestFontTransform(state.mMatrix);
- fontRenderer.precache(paint, mText, mCount, transform);
+ const mat4& transform = renderer.findBestFontTransform(state.mMatrix);
+ if (mPrecacheTransform != transform) {
+ fontRenderer.precache(paint, mText, mCount, transform);
+ mPrecacheTransform = transform;
+ }
}
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
@@ -1210,6 +1213,7 @@
float mY;
const float* mPositions;
float mLength;
+ mat4 mPrecacheTransform;
};
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 7b7357e..75e280c 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -93,6 +93,14 @@
return *this;
}
+ friend bool operator==(const Matrix4& a, const Matrix4& b) {
+ return !memcmp(&a.data[0], &b.data[0], 16 * sizeof(float));
+ }
+
+ friend bool operator!=(const Matrix4& a, const Matrix4& b) {
+ return !(a == b);
+ }
+
void loadIdentity();
void load(const float* v);
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index c932087..02c1aa1 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -15,10 +15,12 @@
*/
#define LOG_TAG "OpenGLRenderer"
+#define ATRACE_TAG ATRACE_TAG_VIEW
#include <cutils/compiler.h>
#include <utils/JenkinsHash.h>
+#include <utils/Trace.h>
#include <SkGlyph.h>
#include <SkUtils.h>
@@ -261,11 +263,8 @@
}
CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit, bool precaching) {
- CachedGlyphInfo* cachedGlyph = NULL;
- ssize_t index = mCachedGlyphs.indexOfKey(textUnit);
- if (index >= 0) {
- cachedGlyph = mCachedGlyphs.valueAt(index);
-
+ CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueFor(textUnit);
+ if (cachedGlyph) {
// Is the glyph still in texture cache?
if (!cachedGlyph->mIsValid) {
const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit,
@@ -346,11 +345,13 @@
}
void Font::precache(SkPaint* paint, const char* text, int numGlyphs) {
+ ATRACE_NAME("precacheText");
+
if (numGlyphs == 0 || text == NULL) {
return;
}
- int glyphsCount = 0;
+ int glyphsCount = 0;
while (glyphsCount < numGlyphs) {
glyph_t glyph = GET_GLYPH(text);
@@ -360,7 +361,6 @@
}
CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph, true);
-
glyphsCount++;
}
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java b/policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java
index cd7324c..c68bab5 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java
@@ -20,6 +20,7 @@
import android.content.Intent;
import android.os.PowerManager;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.telephony.TelephonyManager;
import android.util.AttributeSet;
import android.view.View;
@@ -104,7 +105,8 @@
Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- getContext().startActivity(intent);
+ getContext().startActivityAsUser(intent,
+ new UserHandle(mLockPatternUtils.getCurrentUser()));
}
}