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

Commit 63027a63 authored by Dave Mankoff's avatar Dave Mankoff
Browse files

Ensure ProxCheck doesn't unregister ProxSensor

If the ProximitySensor passed into ProximityCheck is shared with other
clients, the ProximityCheck was causing the ProximitySensor to be
paused which, in turn, meant other clients would miss out on events.

Specifically, this manifested itself in AOD/Doze where one part of
Doze wanted the proximity sensor registered, but another part used
ProximityCheck with the same sensor, causing the sensor to be
paused. The screen would either not turn off when covered, or would
not turn back on when uncovered.

Fixes: 155365422
Test: atest SystemUITests and manual
Change-Id: I3c3faf79ba6d3915b0cfecec7861f6065ae689e8
parent 3233e504
Loading
Loading
Loading
Loading
+21 −13
Original line number Diff line number Diff line
@@ -297,22 +297,15 @@ public class ProximitySensor implements ThresholdSensor {
        private final ProximitySensor mSensor;
        private final DelayableExecutor mDelayableExecutor;
        private List<Consumer<Boolean>> mCallbacks = new ArrayList<>();
        private final ThresholdSensor.Listener mListener;
        private final AtomicBoolean mRegistered = new AtomicBoolean();

        @Inject
        public ProximityCheck(ProximitySensor sensor, DelayableExecutor delayableExecutor) {
            mSensor = sensor;
            mSensor.setTag("prox_check");
            mDelayableExecutor = delayableExecutor;
            mSensor.pause();
            ThresholdSensor.Listener listener = proximityEvent -> {
                mCallbacks.forEach(
                        booleanConsumer ->
                                booleanConsumer.accept(
                                        proximityEvent == null ? null : proximityEvent.getBelow()));
                mCallbacks.clear();
                mSensor.pause();
            };
            mSensor.register(listener);
            mListener = this::onProximityEvent;
        }

        /** Set a descriptive tag for the sensors registration. */
@@ -322,7 +315,7 @@ public class ProximitySensor implements ThresholdSensor {

        @Override
        public void run() {
            mSensor.pause();
            unregister();
            mSensor.alertListeners();
        }

@@ -334,11 +327,26 @@ public class ProximitySensor implements ThresholdSensor {
                callback.accept(null);
            }
            mCallbacks.add(callback);
            if (!mSensor.isRegistered()) {
                mSensor.resume();
            if (!mRegistered.getAndSet(true)) {
                mSensor.register(mListener);
                mDelayableExecutor.executeDelayed(this, timeoutMs);
            }
        }

        private void unregister() {
            mSensor.unregister(mListener);
            mRegistered.set(false);
        }

        private void onProximityEvent(ThresholdSensorEvent proximityEvent) {
            mCallbacks.forEach(
                    booleanConsumer ->
                            booleanConsumer.accept(
                                    proximityEvent == null ? null : proximityEvent.getBelow()));
            mCallbacks.clear();
            unregister();
            mRegistered.set(false);
        }
    }

    private void logDebug(String msg) {
+26 −0
Original line number Diff line number Diff line
@@ -82,6 +82,32 @@ public class ProximityCheckTest extends SysuiTestCase {
        assertFalse(mFakeProximitySensor.isRegistered());
    }

    @Test
    public void testProxDoesntCancelOthers() {
        assertFalse(mFakeProximitySensor.isRegistered());
        // We don't need our "other" listener to do anything. Just ensure our sensor is registered.
        ThresholdSensor.Listener emptyListener = event -> { };
        mFakeProximitySensor.register(emptyListener);
        assertTrue(mFakeProximitySensor.isRegistered());

        // Now run a basic check. This is just like testCheck()
        mProximityCheck.check(100, mTestableCallback);

        assertNull(mTestableCallback.mLastResult);

        mFakeProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(true, 0));
        mFakeProximitySensor.alertListeners();

        assertTrue(mTestableCallback.mLastResult);

        // We should still be registered, since we have another listener.
        assertTrue(mFakeProximitySensor.isRegistered());

        mFakeProximitySensor.unregister(emptyListener);
        assertFalse(mFakeProximitySensor.isRegistered());

    }

    private static class TestableCallback implements Consumer<Boolean> {
        Boolean mLastResult;
        @Override