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

Commit ae6c4b4e authored by Kweku Adams's avatar Kweku Adams
Browse files

Fix locking in AnyMotionDetector.

1. Make sure we appropriately lock around mState when accessing and
   changing it.
2. Annotate lock requirements around variables
3. Don't call the callback with the lock held. This could have resulted
   in a deadlock, though I have no evidence that one did occur.

Bug: 199191752
Test: atest DeviceIdleTest
Test: atest FrameworksMockingServicesTests:DeviceIdleControllerTest
Change-Id: I689145822462202afb2d4ba24ffd9e73cc1917ee
parent 616c2cac
Loading
Loading
Loading
Loading
+37 −20
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server;

import android.annotation.Nullable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
@@ -26,6 +27,8 @@ import android.os.PowerManager;
import android.os.SystemClock;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;

/**
 * Determines if the device has been set upon a stationary object.
 */
@@ -54,6 +57,7 @@ public class AnyMotionDetector {
    private static final int STATE_ACTIVE = 1;

    /** Current measurement state. */
    @GuardedBy("mLock")
    private int mState;

    /** Threshold energy above which the device is considered moving. */
@@ -82,38 +86,47 @@ public class AnyMotionDetector {

    private final Handler mHandler;
    private final Object mLock = new Object();
    private Sensor mAccelSensor;
    private SensorManager mSensorManager;
    private PowerManager.WakeLock mWakeLock;
    private final Sensor mAccelSensor;
    private final SensorManager mSensorManager;
    private final PowerManager.WakeLock mWakeLock;

    /** Threshold angle in degrees beyond which the device is considered moving. */
    private final float mThresholdAngle;

    /** The minimum number of samples required to detect AnyMotion. */
    @GuardedBy("mLock")
    private int mNumSufficientSamples;

    /** True if an orientation measurement is in progress. */
    @GuardedBy("mLock")
    private boolean mMeasurementInProgress;

    /** True if sendMessageDelayed() for the mMeasurementTimeout callback has been scheduled */
    @GuardedBy("mLock")
    private boolean mMeasurementTimeoutIsActive;

    /** True if sendMessageDelayed() for the mWakelockTimeout callback has been scheduled */
    private boolean mWakelockTimeoutIsActive;
    private volatile boolean mWakelockTimeoutIsActive;

    /** True if sendMessageDelayed() for the mSensorRestart callback has been scheduled */
    @GuardedBy("mLock")
    private boolean mSensorRestartIsActive;

    /** The most recent gravity vector. */
    @Nullable
    @GuardedBy("mLock")
    private Vector3 mCurrentGravityVector = null;

    /** The second most recent gravity vector. */
    @Nullable
    @GuardedBy("mLock")
    private Vector3 mPreviousGravityVector = null;

    /** Running sum of squared errors. */
    private RunningSignalStats mRunningStats;
    @GuardedBy("mLock")
    private final RunningSignalStats mRunningStats;

    private DeviceIdleCallback mCallback = null;
    private final DeviceIdleCallback mCallback;

    public AnyMotionDetector(PowerManager pm, Handler handler, SensorManager sm,
            DeviceIdleCallback callback, float thresholdAngle) {
@@ -149,11 +162,11 @@ public class AnyMotionDetector {
     * Acquire accel data until we determine AnyMotion status.
     */
    public void checkForAnyMotion() {
        synchronized (mLock) {
            if (DEBUG) {
                Slog.d(TAG, "checkForAnyMotion(). mState = " + mState);
            }
            if (mState != STATE_ACTIVE) {
            synchronized (mLock) {
                mState = STATE_ACTIVE;
                if (DEBUG) {
                    Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_ACTIVE.");
@@ -193,6 +206,7 @@ public class AnyMotionDetector {
        }
    }

    @GuardedBy("mLock")
    private void startOrientationMeasurementLocked() {
        if (DEBUG) Slog.d(TAG, "startOrientationMeasurementLocked: mMeasurementInProgress=" +
            mMeasurementInProgress + ", (mAccelSensor != null)=" + (mAccelSensor != null));
@@ -208,6 +222,7 @@ public class AnyMotionDetector {
        }
    }

    @GuardedBy("mLock")
    private int stopOrientationMeasurementLocked() {
        if (DEBUG) Slog.d(TAG, "stopOrientationMeasurement. mMeasurementInProgress=" +
                mMeasurementInProgress);
@@ -231,7 +246,7 @@ public class AnyMotionDetector {
                Slog.d(TAG, "mCurrentGravityVector = " + currentGravityVectorString);
                Slog.d(TAG, "mPreviousGravityVector = " + previousGravityVectorString);
            }
            status = getStationaryStatus();
            status = getStationaryStatusLocked();
            mRunningStats.reset();
            if (DEBUG) Slog.d(TAG, "getStationaryStatus() returned " + status);
            if (status != RESULT_UNKNOWN) {
@@ -261,9 +276,10 @@ public class AnyMotionDetector {
    }

    /*
     * Updates mStatus to the current AnyMotion status.
     * Returns the current AnyMotion status.
     */
    public int getStationaryStatus() {
    @GuardedBy("mLock")
    private int getStationaryStatusLocked() {
        if ((mPreviousGravityVector == null) || (mCurrentGravityVector == null)) {
            return RESULT_UNKNOWN;
        }
@@ -341,14 +357,14 @@ public class AnyMotionDetector {
                          "data within " + ACCELEROMETER_DATA_TIMEOUT_MILLIS + " ms. Stopping " +
                          "orientation measurement.");
                    status = stopOrientationMeasurementLocked();
                }
            }
            if (status != RESULT_UNKNOWN) {
                mHandler.removeCallbacks(mWakelockTimeout);
                mWakelockTimeoutIsActive = false;
                mCallback.onAnyMotionResult(status);
            }
        }
            }
        }
    };

    private final Runnable mWakelockTimeout = new Runnable() {
@@ -488,9 +504,10 @@ public class AnyMotionDetector {
            }
        }

        @Nullable
        public Vector3 getRunningAverage() {
            if (sampleCount > 0) {
              return runningSum.times((float)(1.0f / sampleCount));
                return runningSum.times(1.0f / sampleCount);
            }
            return null;
        }