Loading core/java/android/provider/Settings.java +0 −1 Original line number Diff line number Diff line Loading @@ -50,7 +50,6 @@ import android.speech.tts.TextToSpeech; import android.text.TextUtils; import android.util.AndroidException; import android.util.Log; import android.view.WindowOrientationListener; import com.android.internal.widget.ILockSettings; Loading policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +7 −5 Original line number Diff line number Diff line Loading @@ -84,7 +84,6 @@ import android.view.Window; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicy; import android.view.WindowOrientationListener; import android.view.accessibility.AccessibilityEvent; import android.view.animation.Animation; import android.view.animation.AnimationUtils; Loading Loading @@ -555,8 +554,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } class MyOrientationListener extends WindowOrientationListener { MyOrientationListener(Context context) { super(context); MyOrientationListener(Context context, Handler handler) { super(context, handler); } @Override Loading Loading @@ -854,7 +853,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mKeyguardMediator = new KeyguardViewMediator(context, null); } mHandler = new PolicyHandler(); mOrientationListener = new MyOrientationListener(mContext); mOrientationListener = new MyOrientationListener(mContext, mHandler); try { mOrientationListener.setCurrentRotation(windowManager.getRotation()); } catch (RemoteException ex) { } Loading Loading @@ -3760,14 +3759,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { } BroadcastReceiver mDockReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED); } updateRotation(true); synchronized (mLock) { updateOrientationListenerLp(); } } }; BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { Loading core/java/android/view/WindowOrientationListener.java→policy/src/com/android/internal/policy/impl/WindowOrientationListener.java +213 −195 Original line number Diff line number Diff line Loading @@ -14,13 +14,14 @@ * limitations under the License. */ package android.view; package com.android.internal.policy.impl; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Handler; import android.os.SystemProperties; import android.util.FloatMath; import android.util.Log; Loading @@ -47,26 +48,31 @@ public abstract class WindowOrientationListener { private static final boolean USE_GRAVITY_SENSOR = false; private Handler mHandler; private SensorManager mSensorManager; private boolean mEnabled; private int mRate; private Sensor mSensor; private SensorEventListenerImpl mSensorEventListener; int mCurrentRotation = -1; private int mCurrentRotation = -1; private final Object mLock = new Object(); /** * Creates a new WindowOrientationListener. * * @param context for the WindowOrientationListener. * @param handler Provides the Looper for receiving sensor updates. */ public WindowOrientationListener(Context context) { this(context, SensorManager.SENSOR_DELAY_UI); public WindowOrientationListener(Context context, Handler handler) { this(context, handler, SensorManager.SENSOR_DELAY_UI); } /** * Creates a new WindowOrientationListener. * * @param context for the WindowOrientationListener. * @param handler Provides the Looper for receiving sensor updates. * @param rate at which sensor events are processed (see also * {@link android.hardware.SensorManager SensorManager}). Use the default * value of {@link android.hardware.SensorManager#SENSOR_DELAY_NORMAL Loading @@ -74,22 +80,24 @@ public abstract class WindowOrientationListener { * * This constructor is private since no one uses it. */ private WindowOrientationListener(Context context, int rate) { private WindowOrientationListener(Context context, Handler handler, int rate) { mHandler = handler; mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE); mRate = rate; mSensor = mSensorManager.getDefaultSensor(USE_GRAVITY_SENSOR ? Sensor.TYPE_GRAVITY : Sensor.TYPE_ACCELEROMETER); if (mSensor != null) { // Create listener only if sensors do exist mSensorEventListener = new SensorEventListenerImpl(this); mSensorEventListener = new SensorEventListenerImpl(); } } /** * Enables the WindowOrientationListener so it will monitor the sensor and call * {@link #onOrientationChanged} when the device orientation changes. * {@link #onProposedRotationChanged(int)} when the device orientation changes. */ public void enable() { synchronized (mLock) { if (mSensor == null) { Log.w(TAG, "Cannot detect sensors. Not enabled"); return; Loading @@ -98,16 +106,18 @@ public abstract class WindowOrientationListener { if (LOG) { Log.d(TAG, "WindowOrientationListener enabled"); } mSensorEventListener.reset(); mSensorManager.registerListener(mSensorEventListener, mSensor, mRate); mSensorEventListener.resetLocked(); mSensorManager.registerListener(mSensorEventListener, mSensor, mRate, mHandler); mEnabled = true; } } } /** * Disables the WindowOrientationListener. */ public void disable() { synchronized (mLock) { if (mSensor == null) { Log.w(TAG, "Cannot detect sensors. Invalid disable"); return; Loading @@ -120,6 +130,7 @@ public abstract class WindowOrientationListener { mEnabled = false; } } } /** * Sets the current rotation. Loading @@ -127,8 +138,10 @@ public abstract class WindowOrientationListener { * @param rotation The current rotation. */ public void setCurrentRotation(int rotation) { synchronized (mLock) { mCurrentRotation = rotation; } } /** * Gets the proposed rotation. Loading @@ -139,18 +152,22 @@ public abstract class WindowOrientationListener { * @return The proposed rotation, or -1 if unknown. */ public int getProposedRotation() { synchronized (mLock) { if (mEnabled) { return mSensorEventListener.getProposedRotation(); return mSensorEventListener.getProposedRotationLocked(); } return -1; } } /** * Returns true if sensor is enabled and false otherwise */ public boolean canDetectOrientation() { synchronized (mLock) { return mSensor != null; } } /** * Called when the rotation view of the device has changed. Loading @@ -160,7 +177,7 @@ public abstract class WindowOrientationListener { * uncertain to being certain again, even if it is the same orientation as before. * * @param rotation The new orientation of the device, one of the Surface.ROTATION_* constants. * @see Surface * @see android.view.Surface */ public abstract void onProposedRotationChanged(int rotation); Loading Loading @@ -202,7 +219,7 @@ public abstract class WindowOrientationListener { * See http://en.wikipedia.org/wiki/Low-pass_filter#Discrete-time_realization for * signal processing background. */ static final class SensorEventListenerImpl implements SensorEventListener { final class SensorEventListenerImpl implements SensorEventListener { // We work with all angles in degrees in this class. private static final float RADIANS_TO_DEGREES = (float) (180 / Math.PI); Loading @@ -214,8 +231,6 @@ public abstract class WindowOrientationListener { private static final int ACCELEROMETER_DATA_Y = 1; private static final int ACCELEROMETER_DATA_Z = 2; private final WindowOrientationListener mOrientationListener; // The minimum amount of time that a predicted rotation must be stable before it // is accepted as a valid rotation proposal. This value can be quite small because // the low-pass filter already suppresses most of the noise so we're really just Loading Loading @@ -320,7 +335,7 @@ public abstract class WindowOrientationListener { // facing up (resting on a table). // The ideal tilt angle is 0 (when the device is vertical) so the limits establish // how close to vertical the device must be in order to change orientation. private static final int[][] TILT_TOLERANCE = new int[][] { private final int[][] TILT_TOLERANCE = new int[][] { /* ROTATION_0 */ { -25, 70 }, /* ROTATION_90 */ { -25, 65 }, /* ROTATION_180 */ { -25, 60 }, Loading Loading @@ -362,12 +377,7 @@ public abstract class WindowOrientationListener { private long[] mTiltHistoryTimestampNanos = new long[TILT_HISTORY_SIZE]; private int mTiltHistoryIndex; public SensorEventListenerImpl(WindowOrientationListener orientationListener) { mOrientationListener = orientationListener; reset(); } public int getProposedRotation() { public int getProposedRotationLocked() { return mProposedRotation; } Loading @@ -377,8 +387,13 @@ public abstract class WindowOrientationListener { @Override public void onSensorChanged(SensorEvent event) { // The vector given in the SensorEvent points straight up (towards the sky) under ideal // conditions (the phone is not accelerating). I'll call this up vector elsewhere. int proposedRotation; int oldProposedRotation; synchronized (mLock) { // The vector given in the SensorEvent points straight up (towards the sky) under // ideal conditions (the phone is not accelerating). I'll call this up vector // elsewhere. float x = event.values[ACCELEROMETER_DATA_X]; float y = event.values[ACCELEROMETER_DATA_Y]; float z = event.values[ACCELEROMETER_DATA_Z]; Loading @@ -403,7 +418,7 @@ public abstract class WindowOrientationListener { if (LOG) { Slog.v(TAG, "Resetting orientation listener."); } reset(); resetLocked(); skipSample = true; } else { final float alpha = timeDeltaMS / (FILTER_TIME_CONSTANT_MS + timeDeltaMS); Loading Loading @@ -432,10 +447,11 @@ public abstract class WindowOrientationListener { if (LOG) { Slog.v(TAG, "Ignoring sensor data, magnitude too close to zero."); } clearPredictedRotation(); clearPredictedRotationLocked(); } else { // Determine whether the device appears to be undergoing external acceleration. if (isAccelerating(magnitude)) { // Determine whether the device appears to be undergoing external // acceleration. if (isAcceleratingLocked(magnitude)) { isAccelerating = true; mAccelerationTimestampNanos = now; } Loading @@ -448,14 +464,14 @@ public abstract class WindowOrientationListener { // 90 degrees: screen horizontal and facing the sky (on table) final int tiltAngle = (int) Math.round( Math.asin(z / magnitude) * RADIANS_TO_DEGREES); addTiltHistoryEntry(now, tiltAngle); addTiltHistoryEntryLocked(now, tiltAngle); // Determine whether the device appears to be flat or swinging. if (isFlat(now)) { if (isFlatLocked(now)) { isFlat = true; mFlatTimestampNanos = now; } if (isSwinging(now, tiltAngle)) { if (isSwingingLocked(now, tiltAngle)) { isSwinging = true; mSwingTimestampNanos = now; } Loading @@ -467,7 +483,7 @@ public abstract class WindowOrientationListener { Slog.v(TAG, "Ignoring sensor data, tilt angle too high: " + "tiltAngle=" + tiltAngle); } clearPredictedRotation(); clearPredictedRotationLocked(); } else { // Calculate the orientation angle. // This is the angle between the x-y projection of the up vector onto Loading @@ -486,10 +502,10 @@ public abstract class WindowOrientationListener { } // Determine the predicted orientation. if (isTiltAngleAcceptable(nearestRotation, tiltAngle) && isOrientationAngleAcceptable(nearestRotation, if (isTiltAngleAcceptableLocked(nearestRotation, tiltAngle) && isOrientationAngleAcceptableLocked(nearestRotation, orientationAngle)) { updatePredictedRotation(now, nearestRotation); updatePredictedRotationLocked(now, nearestRotation); if (LOG) { Slog.v(TAG, "Predicted: " + "tiltAngle=" + tiltAngle Loading @@ -505,22 +521,23 @@ public abstract class WindowOrientationListener { + "tiltAngle=" + tiltAngle + ", orientationAngle=" + orientationAngle); } clearPredictedRotation(); clearPredictedRotationLocked(); } } } } // Determine new proposed rotation. final int oldProposedRotation = mProposedRotation; if (mPredictedRotation < 0 || isPredictedRotationAcceptable(now)) { oldProposedRotation = mProposedRotation; if (mPredictedRotation < 0 || isPredictedRotationAcceptableLocked(now)) { mProposedRotation = mPredictedRotation; } proposedRotation = mProposedRotation; // Write final statistics about where we are in the orientation detection process. if (LOG) { Slog.v(TAG, "Result: currentRotation=" + mOrientationListener.mCurrentRotation + ", proposedRotation=" + mProposedRotation Slog.v(TAG, "Result: currentRotation=" + mCurrentRotation + ", proposedRotation=" + proposedRotation + ", predictedRotation=" + mPredictedRotation + ", timeDeltaMS=" + timeDeltaMS + ", isAccelerating=" + isAccelerating Loading @@ -535,21 +552,22 @@ public abstract class WindowOrientationListener { + ", timeUntilSwingDelayExpiredMS=" + remainingMS(now, mSwingTimestampNanos + PROPOSAL_MIN_TIME_SINCE_SWING_ENDED_NANOS)); } } // Tell the listener. if (mProposedRotation != oldProposedRotation && mProposedRotation >= 0) { if (proposedRotation != oldProposedRotation && proposedRotation >= 0) { if (LOG) { Slog.v(TAG, "Proposed rotation changed! proposedRotation=" + mProposedRotation Slog.v(TAG, "Proposed rotation changed! proposedRotation=" + proposedRotation + ", oldProposedRotation=" + oldProposedRotation); } mOrientationListener.onProposedRotationChanged(mProposedRotation); onProposedRotationChanged(proposedRotation); } } /** * Returns true if the tilt angle is acceptable for a given predicted rotation. */ private boolean isTiltAngleAcceptable(int rotation, int tiltAngle) { private boolean isTiltAngleAcceptableLocked(int rotation, int tiltAngle) { return tiltAngle >= TILT_TOLERANCE[rotation][0] && tiltAngle <= TILT_TOLERANCE[rotation][1]; } Loading @@ -560,11 +578,11 @@ public abstract class WindowOrientationListener { * This function takes into account the gap between adjacent orientations * for hysteresis. */ private boolean isOrientationAngleAcceptable(int rotation, int orientationAngle) { private boolean isOrientationAngleAcceptableLocked(int rotation, int orientationAngle) { // If there is no current rotation, then there is no gap. // The gap is used only to introduce hysteresis among advertised orientation // changes to avoid flapping. final int currentRotation = mOrientationListener.mCurrentRotation; final int currentRotation = mCurrentRotation; if (currentRotation >= 0) { // If the specified rotation is the same or is counter-clockwise adjacent // to the current rotation, then we set a lower bound on the orientation angle. Loading Loading @@ -611,7 +629,7 @@ public abstract class WindowOrientationListener { * Returns true if the predicted rotation is ready to be advertised as a * proposed rotation. */ private boolean isPredictedRotationAcceptable(long now) { private boolean isPredictedRotationAcceptableLocked(long now) { // The predicted rotation must have settled long enough. if (now < mPredictedRotationTimestampNanos + PROPOSAL_SETTLE_TIME_NANOS) { return false; Loading @@ -638,47 +656,47 @@ public abstract class WindowOrientationListener { return true; } private void reset() { private void resetLocked() { mLastFilteredTimestampNanos = Long.MIN_VALUE; mProposedRotation = -1; mFlatTimestampNanos = Long.MIN_VALUE; mSwingTimestampNanos = Long.MIN_VALUE; mAccelerationTimestampNanos = Long.MIN_VALUE; clearPredictedRotation(); clearTiltHistory(); clearPredictedRotationLocked(); clearTiltHistoryLocked(); } private void clearPredictedRotation() { private void clearPredictedRotationLocked() { mPredictedRotation = -1; mPredictedRotationTimestampNanos = Long.MIN_VALUE; } private void updatePredictedRotation(long now, int rotation) { private void updatePredictedRotationLocked(long now, int rotation) { if (mPredictedRotation != rotation) { mPredictedRotation = rotation; mPredictedRotationTimestampNanos = now; } } private boolean isAccelerating(float magnitude) { private boolean isAcceleratingLocked(float magnitude) { return magnitude < MIN_ACCELERATION_MAGNITUDE || magnitude > MAX_ACCELERATION_MAGNITUDE; } private void clearTiltHistory() { private void clearTiltHistoryLocked() { mTiltHistoryTimestampNanos[0] = Long.MIN_VALUE; mTiltHistoryIndex = 1; } private void addTiltHistoryEntry(long now, float tilt) { private void addTiltHistoryEntryLocked(long now, float tilt) { mTiltHistory[mTiltHistoryIndex] = tilt; mTiltHistoryTimestampNanos[mTiltHistoryIndex] = now; mTiltHistoryIndex = (mTiltHistoryIndex + 1) % TILT_HISTORY_SIZE; mTiltHistoryTimestampNanos[mTiltHistoryIndex] = Long.MIN_VALUE; } private boolean isFlat(long now) { for (int i = mTiltHistoryIndex; (i = nextTiltHistoryIndex(i)) >= 0; ) { private boolean isFlatLocked(long now) { for (int i = mTiltHistoryIndex; (i = nextTiltHistoryIndexLocked(i)) >= 0; ) { if (mTiltHistory[i] < FLAT_ANGLE) { break; } Loading @@ -690,8 +708,8 @@ public abstract class WindowOrientationListener { return false; } private boolean isSwinging(long now, float tilt) { for (int i = mTiltHistoryIndex; (i = nextTiltHistoryIndex(i)) >= 0; ) { private boolean isSwingingLocked(long now, float tilt) { for (int i = mTiltHistoryIndex; (i = nextTiltHistoryIndexLocked(i)) >= 0; ) { if (mTiltHistoryTimestampNanos[i] + SWING_TIME_NANOS < now) { break; } Loading @@ -703,12 +721,12 @@ public abstract class WindowOrientationListener { return false; } private int nextTiltHistoryIndex(int index) { private int nextTiltHistoryIndexLocked(int index) { index = (index == 0 ? TILT_HISTORY_SIZE : index) - 1; return mTiltHistoryTimestampNanos[index] != Long.MIN_VALUE ? index : -1; } private static float remainingMS(long now, long until) { private float remainingMS(long now, long until) { return now >= until ? 0 : (until - now) * 0.000001f; } } Loading Loading
core/java/android/provider/Settings.java +0 −1 Original line number Diff line number Diff line Loading @@ -50,7 +50,6 @@ import android.speech.tts.TextToSpeech; import android.text.TextUtils; import android.util.AndroidException; import android.util.Log; import android.view.WindowOrientationListener; import com.android.internal.widget.ILockSettings; Loading
policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +7 −5 Original line number Diff line number Diff line Loading @@ -84,7 +84,6 @@ import android.view.Window; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicy; import android.view.WindowOrientationListener; import android.view.accessibility.AccessibilityEvent; import android.view.animation.Animation; import android.view.animation.AnimationUtils; Loading Loading @@ -555,8 +554,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } class MyOrientationListener extends WindowOrientationListener { MyOrientationListener(Context context) { super(context); MyOrientationListener(Context context, Handler handler) { super(context, handler); } @Override Loading Loading @@ -854,7 +853,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mKeyguardMediator = new KeyguardViewMediator(context, null); } mHandler = new PolicyHandler(); mOrientationListener = new MyOrientationListener(mContext); mOrientationListener = new MyOrientationListener(mContext, mHandler); try { mOrientationListener.setCurrentRotation(windowManager.getRotation()); } catch (RemoteException ex) { } Loading Loading @@ -3760,14 +3759,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { } BroadcastReceiver mDockReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED); } updateRotation(true); synchronized (mLock) { updateOrientationListenerLp(); } } }; BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { Loading
core/java/android/view/WindowOrientationListener.java→policy/src/com/android/internal/policy/impl/WindowOrientationListener.java +213 −195 Original line number Diff line number Diff line Loading @@ -14,13 +14,14 @@ * limitations under the License. */ package android.view; package com.android.internal.policy.impl; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Handler; import android.os.SystemProperties; import android.util.FloatMath; import android.util.Log; Loading @@ -47,26 +48,31 @@ public abstract class WindowOrientationListener { private static final boolean USE_GRAVITY_SENSOR = false; private Handler mHandler; private SensorManager mSensorManager; private boolean mEnabled; private int mRate; private Sensor mSensor; private SensorEventListenerImpl mSensorEventListener; int mCurrentRotation = -1; private int mCurrentRotation = -1; private final Object mLock = new Object(); /** * Creates a new WindowOrientationListener. * * @param context for the WindowOrientationListener. * @param handler Provides the Looper for receiving sensor updates. */ public WindowOrientationListener(Context context) { this(context, SensorManager.SENSOR_DELAY_UI); public WindowOrientationListener(Context context, Handler handler) { this(context, handler, SensorManager.SENSOR_DELAY_UI); } /** * Creates a new WindowOrientationListener. * * @param context for the WindowOrientationListener. * @param handler Provides the Looper for receiving sensor updates. * @param rate at which sensor events are processed (see also * {@link android.hardware.SensorManager SensorManager}). Use the default * value of {@link android.hardware.SensorManager#SENSOR_DELAY_NORMAL Loading @@ -74,22 +80,24 @@ public abstract class WindowOrientationListener { * * This constructor is private since no one uses it. */ private WindowOrientationListener(Context context, int rate) { private WindowOrientationListener(Context context, Handler handler, int rate) { mHandler = handler; mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE); mRate = rate; mSensor = mSensorManager.getDefaultSensor(USE_GRAVITY_SENSOR ? Sensor.TYPE_GRAVITY : Sensor.TYPE_ACCELEROMETER); if (mSensor != null) { // Create listener only if sensors do exist mSensorEventListener = new SensorEventListenerImpl(this); mSensorEventListener = new SensorEventListenerImpl(); } } /** * Enables the WindowOrientationListener so it will monitor the sensor and call * {@link #onOrientationChanged} when the device orientation changes. * {@link #onProposedRotationChanged(int)} when the device orientation changes. */ public void enable() { synchronized (mLock) { if (mSensor == null) { Log.w(TAG, "Cannot detect sensors. Not enabled"); return; Loading @@ -98,16 +106,18 @@ public abstract class WindowOrientationListener { if (LOG) { Log.d(TAG, "WindowOrientationListener enabled"); } mSensorEventListener.reset(); mSensorManager.registerListener(mSensorEventListener, mSensor, mRate); mSensorEventListener.resetLocked(); mSensorManager.registerListener(mSensorEventListener, mSensor, mRate, mHandler); mEnabled = true; } } } /** * Disables the WindowOrientationListener. */ public void disable() { synchronized (mLock) { if (mSensor == null) { Log.w(TAG, "Cannot detect sensors. Invalid disable"); return; Loading @@ -120,6 +130,7 @@ public abstract class WindowOrientationListener { mEnabled = false; } } } /** * Sets the current rotation. Loading @@ -127,8 +138,10 @@ public abstract class WindowOrientationListener { * @param rotation The current rotation. */ public void setCurrentRotation(int rotation) { synchronized (mLock) { mCurrentRotation = rotation; } } /** * Gets the proposed rotation. Loading @@ -139,18 +152,22 @@ public abstract class WindowOrientationListener { * @return The proposed rotation, or -1 if unknown. */ public int getProposedRotation() { synchronized (mLock) { if (mEnabled) { return mSensorEventListener.getProposedRotation(); return mSensorEventListener.getProposedRotationLocked(); } return -1; } } /** * Returns true if sensor is enabled and false otherwise */ public boolean canDetectOrientation() { synchronized (mLock) { return mSensor != null; } } /** * Called when the rotation view of the device has changed. Loading @@ -160,7 +177,7 @@ public abstract class WindowOrientationListener { * uncertain to being certain again, even if it is the same orientation as before. * * @param rotation The new orientation of the device, one of the Surface.ROTATION_* constants. * @see Surface * @see android.view.Surface */ public abstract void onProposedRotationChanged(int rotation); Loading Loading @@ -202,7 +219,7 @@ public abstract class WindowOrientationListener { * See http://en.wikipedia.org/wiki/Low-pass_filter#Discrete-time_realization for * signal processing background. */ static final class SensorEventListenerImpl implements SensorEventListener { final class SensorEventListenerImpl implements SensorEventListener { // We work with all angles in degrees in this class. private static final float RADIANS_TO_DEGREES = (float) (180 / Math.PI); Loading @@ -214,8 +231,6 @@ public abstract class WindowOrientationListener { private static final int ACCELEROMETER_DATA_Y = 1; private static final int ACCELEROMETER_DATA_Z = 2; private final WindowOrientationListener mOrientationListener; // The minimum amount of time that a predicted rotation must be stable before it // is accepted as a valid rotation proposal. This value can be quite small because // the low-pass filter already suppresses most of the noise so we're really just Loading Loading @@ -320,7 +335,7 @@ public abstract class WindowOrientationListener { // facing up (resting on a table). // The ideal tilt angle is 0 (when the device is vertical) so the limits establish // how close to vertical the device must be in order to change orientation. private static final int[][] TILT_TOLERANCE = new int[][] { private final int[][] TILT_TOLERANCE = new int[][] { /* ROTATION_0 */ { -25, 70 }, /* ROTATION_90 */ { -25, 65 }, /* ROTATION_180 */ { -25, 60 }, Loading Loading @@ -362,12 +377,7 @@ public abstract class WindowOrientationListener { private long[] mTiltHistoryTimestampNanos = new long[TILT_HISTORY_SIZE]; private int mTiltHistoryIndex; public SensorEventListenerImpl(WindowOrientationListener orientationListener) { mOrientationListener = orientationListener; reset(); } public int getProposedRotation() { public int getProposedRotationLocked() { return mProposedRotation; } Loading @@ -377,8 +387,13 @@ public abstract class WindowOrientationListener { @Override public void onSensorChanged(SensorEvent event) { // The vector given in the SensorEvent points straight up (towards the sky) under ideal // conditions (the phone is not accelerating). I'll call this up vector elsewhere. int proposedRotation; int oldProposedRotation; synchronized (mLock) { // The vector given in the SensorEvent points straight up (towards the sky) under // ideal conditions (the phone is not accelerating). I'll call this up vector // elsewhere. float x = event.values[ACCELEROMETER_DATA_X]; float y = event.values[ACCELEROMETER_DATA_Y]; float z = event.values[ACCELEROMETER_DATA_Z]; Loading @@ -403,7 +418,7 @@ public abstract class WindowOrientationListener { if (LOG) { Slog.v(TAG, "Resetting orientation listener."); } reset(); resetLocked(); skipSample = true; } else { final float alpha = timeDeltaMS / (FILTER_TIME_CONSTANT_MS + timeDeltaMS); Loading Loading @@ -432,10 +447,11 @@ public abstract class WindowOrientationListener { if (LOG) { Slog.v(TAG, "Ignoring sensor data, magnitude too close to zero."); } clearPredictedRotation(); clearPredictedRotationLocked(); } else { // Determine whether the device appears to be undergoing external acceleration. if (isAccelerating(magnitude)) { // Determine whether the device appears to be undergoing external // acceleration. if (isAcceleratingLocked(magnitude)) { isAccelerating = true; mAccelerationTimestampNanos = now; } Loading @@ -448,14 +464,14 @@ public abstract class WindowOrientationListener { // 90 degrees: screen horizontal and facing the sky (on table) final int tiltAngle = (int) Math.round( Math.asin(z / magnitude) * RADIANS_TO_DEGREES); addTiltHistoryEntry(now, tiltAngle); addTiltHistoryEntryLocked(now, tiltAngle); // Determine whether the device appears to be flat or swinging. if (isFlat(now)) { if (isFlatLocked(now)) { isFlat = true; mFlatTimestampNanos = now; } if (isSwinging(now, tiltAngle)) { if (isSwingingLocked(now, tiltAngle)) { isSwinging = true; mSwingTimestampNanos = now; } Loading @@ -467,7 +483,7 @@ public abstract class WindowOrientationListener { Slog.v(TAG, "Ignoring sensor data, tilt angle too high: " + "tiltAngle=" + tiltAngle); } clearPredictedRotation(); clearPredictedRotationLocked(); } else { // Calculate the orientation angle. // This is the angle between the x-y projection of the up vector onto Loading @@ -486,10 +502,10 @@ public abstract class WindowOrientationListener { } // Determine the predicted orientation. if (isTiltAngleAcceptable(nearestRotation, tiltAngle) && isOrientationAngleAcceptable(nearestRotation, if (isTiltAngleAcceptableLocked(nearestRotation, tiltAngle) && isOrientationAngleAcceptableLocked(nearestRotation, orientationAngle)) { updatePredictedRotation(now, nearestRotation); updatePredictedRotationLocked(now, nearestRotation); if (LOG) { Slog.v(TAG, "Predicted: " + "tiltAngle=" + tiltAngle Loading @@ -505,22 +521,23 @@ public abstract class WindowOrientationListener { + "tiltAngle=" + tiltAngle + ", orientationAngle=" + orientationAngle); } clearPredictedRotation(); clearPredictedRotationLocked(); } } } } // Determine new proposed rotation. final int oldProposedRotation = mProposedRotation; if (mPredictedRotation < 0 || isPredictedRotationAcceptable(now)) { oldProposedRotation = mProposedRotation; if (mPredictedRotation < 0 || isPredictedRotationAcceptableLocked(now)) { mProposedRotation = mPredictedRotation; } proposedRotation = mProposedRotation; // Write final statistics about where we are in the orientation detection process. if (LOG) { Slog.v(TAG, "Result: currentRotation=" + mOrientationListener.mCurrentRotation + ", proposedRotation=" + mProposedRotation Slog.v(TAG, "Result: currentRotation=" + mCurrentRotation + ", proposedRotation=" + proposedRotation + ", predictedRotation=" + mPredictedRotation + ", timeDeltaMS=" + timeDeltaMS + ", isAccelerating=" + isAccelerating Loading @@ -535,21 +552,22 @@ public abstract class WindowOrientationListener { + ", timeUntilSwingDelayExpiredMS=" + remainingMS(now, mSwingTimestampNanos + PROPOSAL_MIN_TIME_SINCE_SWING_ENDED_NANOS)); } } // Tell the listener. if (mProposedRotation != oldProposedRotation && mProposedRotation >= 0) { if (proposedRotation != oldProposedRotation && proposedRotation >= 0) { if (LOG) { Slog.v(TAG, "Proposed rotation changed! proposedRotation=" + mProposedRotation Slog.v(TAG, "Proposed rotation changed! proposedRotation=" + proposedRotation + ", oldProposedRotation=" + oldProposedRotation); } mOrientationListener.onProposedRotationChanged(mProposedRotation); onProposedRotationChanged(proposedRotation); } } /** * Returns true if the tilt angle is acceptable for a given predicted rotation. */ private boolean isTiltAngleAcceptable(int rotation, int tiltAngle) { private boolean isTiltAngleAcceptableLocked(int rotation, int tiltAngle) { return tiltAngle >= TILT_TOLERANCE[rotation][0] && tiltAngle <= TILT_TOLERANCE[rotation][1]; } Loading @@ -560,11 +578,11 @@ public abstract class WindowOrientationListener { * This function takes into account the gap between adjacent orientations * for hysteresis. */ private boolean isOrientationAngleAcceptable(int rotation, int orientationAngle) { private boolean isOrientationAngleAcceptableLocked(int rotation, int orientationAngle) { // If there is no current rotation, then there is no gap. // The gap is used only to introduce hysteresis among advertised orientation // changes to avoid flapping. final int currentRotation = mOrientationListener.mCurrentRotation; final int currentRotation = mCurrentRotation; if (currentRotation >= 0) { // If the specified rotation is the same or is counter-clockwise adjacent // to the current rotation, then we set a lower bound on the orientation angle. Loading Loading @@ -611,7 +629,7 @@ public abstract class WindowOrientationListener { * Returns true if the predicted rotation is ready to be advertised as a * proposed rotation. */ private boolean isPredictedRotationAcceptable(long now) { private boolean isPredictedRotationAcceptableLocked(long now) { // The predicted rotation must have settled long enough. if (now < mPredictedRotationTimestampNanos + PROPOSAL_SETTLE_TIME_NANOS) { return false; Loading @@ -638,47 +656,47 @@ public abstract class WindowOrientationListener { return true; } private void reset() { private void resetLocked() { mLastFilteredTimestampNanos = Long.MIN_VALUE; mProposedRotation = -1; mFlatTimestampNanos = Long.MIN_VALUE; mSwingTimestampNanos = Long.MIN_VALUE; mAccelerationTimestampNanos = Long.MIN_VALUE; clearPredictedRotation(); clearTiltHistory(); clearPredictedRotationLocked(); clearTiltHistoryLocked(); } private void clearPredictedRotation() { private void clearPredictedRotationLocked() { mPredictedRotation = -1; mPredictedRotationTimestampNanos = Long.MIN_VALUE; } private void updatePredictedRotation(long now, int rotation) { private void updatePredictedRotationLocked(long now, int rotation) { if (mPredictedRotation != rotation) { mPredictedRotation = rotation; mPredictedRotationTimestampNanos = now; } } private boolean isAccelerating(float magnitude) { private boolean isAcceleratingLocked(float magnitude) { return magnitude < MIN_ACCELERATION_MAGNITUDE || magnitude > MAX_ACCELERATION_MAGNITUDE; } private void clearTiltHistory() { private void clearTiltHistoryLocked() { mTiltHistoryTimestampNanos[0] = Long.MIN_VALUE; mTiltHistoryIndex = 1; } private void addTiltHistoryEntry(long now, float tilt) { private void addTiltHistoryEntryLocked(long now, float tilt) { mTiltHistory[mTiltHistoryIndex] = tilt; mTiltHistoryTimestampNanos[mTiltHistoryIndex] = now; mTiltHistoryIndex = (mTiltHistoryIndex + 1) % TILT_HISTORY_SIZE; mTiltHistoryTimestampNanos[mTiltHistoryIndex] = Long.MIN_VALUE; } private boolean isFlat(long now) { for (int i = mTiltHistoryIndex; (i = nextTiltHistoryIndex(i)) >= 0; ) { private boolean isFlatLocked(long now) { for (int i = mTiltHistoryIndex; (i = nextTiltHistoryIndexLocked(i)) >= 0; ) { if (mTiltHistory[i] < FLAT_ANGLE) { break; } Loading @@ -690,8 +708,8 @@ public abstract class WindowOrientationListener { return false; } private boolean isSwinging(long now, float tilt) { for (int i = mTiltHistoryIndex; (i = nextTiltHistoryIndex(i)) >= 0; ) { private boolean isSwingingLocked(long now, float tilt) { for (int i = mTiltHistoryIndex; (i = nextTiltHistoryIndexLocked(i)) >= 0; ) { if (mTiltHistoryTimestampNanos[i] + SWING_TIME_NANOS < now) { break; } Loading @@ -703,12 +721,12 @@ public abstract class WindowOrientationListener { return false; } private int nextTiltHistoryIndex(int index) { private int nextTiltHistoryIndexLocked(int index) { index = (index == 0 ? TILT_HISTORY_SIZE : index) - 1; return mTiltHistoryTimestampNanos[index] != Long.MIN_VALUE ? index : -1; } private static float remainingMS(long now, long until) { private float remainingMS(long now, long until) { return now >= until ? 0 : (until - now) * 0.000001f; } } Loading