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

Commit f354c67b authored by Dave Mankoff's avatar Dave Mankoff
Browse files

Prevent NPE in ProximitySensor.

There was a pseudo-race in ProximitySensor where, if a listener
tried to cancel its proximity sensor, the sensor would then add
a delayed runnable _after_ being canceled, causing it to NPE the
next time it ran. This only occured on phones using a dual-sensor
approach to proximity. It happened particularly regularly with the
ProxCheck utility class.

Fixes: 155183913
Test: atest SystemUITests && manual.
Change-Id: Id399c6d577e3c43f91a3d3a2e3b49fd4fa1918e4
parent 06de1911
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -92,11 +92,11 @@ public class ProximitySensor implements ThresholdSensor {
            }
            logDebug("Secondary sensor event: " + event.getBelow() + ".");

            onSensorEvent(event);

            // Check this sensor again in a moment.
            mCancelSecondaryRunnable = mDelayableExecutor.executeDelayed(
                    mSecondaryThresholdSensor::resume, SECONDARY_PING_INTERVAL_MS);

            onSensorEvent(event);
        }
    };

+31 −0
Original line number Diff line number Diff line
@@ -262,6 +262,37 @@ public class ProximitySensorDualTest extends SysuiTestCase {
        mProximitySensor.unregister(listener);
    }

    @Test
    public void testSecondaryCancelsSecondary() {
        TestableListener listener = new TestableListener();
        ThresholdSensor.Listener cancelingListener = new ThresholdSensor.Listener() {
            @Override
            public void onThresholdCrossed(ThresholdSensor.ThresholdSensorEvent event) {
                mProximitySensor.pause();
            }
        };

        mProximitySensor.register(listener);
        mProximitySensor.register(cancelingListener);
        assertNull(listener.mLastEvent);
        assertEquals(0, listener.mCallCount);

        mThresholdSensorPrimary.triggerEvent(true, 0);
        assertNull(listener.mLastEvent);
        assertEquals(0, listener.mCallCount);
        mThresholdSensorSecondary.triggerEvent(true, 0);
        assertTrue(listener.mLastEvent.getBelow());
        assertEquals(1, listener.mCallCount);

        // The proximity sensor should now be canceled. Advancing the clock should do nothing.
        assertEquals(0, mFakeExecutor.numPending());
        mThresholdSensorSecondary.triggerEvent(false, 1);
        assertTrue(listener.mLastEvent.getBelow());
        assertEquals(1, listener.mCallCount);

        mProximitySensor.unregister(listener);
    }

    private static class TestableListener implements ThresholdSensor.Listener {
        ThresholdSensor.ThresholdSensorEvent mLastEvent;
        int mCallCount = 0;