Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 005f6f60 authored by Craig Mautner's avatar Craig Mautner Committed by Android (Google) Code Review
Browse files

Merge "Reset SensorEventListener when listener reenabled."

parents ea2f8029 eee29c44
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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;

+7 −5
Original line number Diff line number Diff line
@@ -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;
@@ -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
@@ -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) { }
@@ -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() {
+213 −195
Original line number Diff line number Diff line
@@ -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;
@@ -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 
@@ -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;
@@ -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;
@@ -120,6 +130,7 @@ public abstract class WindowOrientationListener {
                mEnabled = false;
            }
        }
    }

    /**
     * Sets the current rotation.
@@ -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.
@@ -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.
@@ -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);

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

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

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