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

Commit f54f3eb2 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.

This CL is a cherry pick of an earlier CL that went into rvc-d1.
Some slight differences are seen since the proximity code in rvc-d1
has diverged from rvc, but the logic needed for the fix is the same.

Fixes: 155365422
Test: atest SystemUITests and manual
Change-Id: I3c3faf79ba6d3915b0cfecec7861f6065ae689e8
Merged-In: I3c3faf79ba6d3915b0cfecec7861f6065ae689e8
parent 3bf4ec13
Loading
Loading
Loading
Loading
+24 −14
Original line number Original line Diff line number Diff line
@@ -222,7 +222,9 @@ public class ProximitySensor {
        if (mAlerting.getAndSet(true)) {
        if (mAlerting.getAndSet(true)) {
            return;
            return;
        }
        }
        mListeners.forEach(proximitySensorListener ->

        List<ProximitySensorListener> listeners = new ArrayList<>(mListeners);
        listeners.forEach(proximitySensorListener ->
                proximitySensorListener.onSensorEvent(mLastEvent));
                proximitySensorListener.onSensorEvent(mLastEvent));
        mAlerting.set(false);
        mAlerting.set(false);
    }
    }
@@ -247,22 +249,15 @@ public class ProximitySensor {
        private final ProximitySensor mSensor;
        private final ProximitySensor mSensor;
        private final DelayableExecutor mDelayableExecutor;
        private final DelayableExecutor mDelayableExecutor;
        private List<Consumer<Boolean>> mCallbacks = new ArrayList<>();
        private List<Consumer<Boolean>> mCallbacks = new ArrayList<>();
        private final ProximitySensor.ProximitySensorListener mListener;
        private final AtomicBoolean mRegistered = new AtomicBoolean();


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


        /** Set a descriptive tag for the sensors registration. */
        /** Set a descriptive tag for the sensors registration. */
@@ -272,7 +267,7 @@ public class ProximitySensor {


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


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

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

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


    /** Implement to be notified of ProximityEvents. */
    /** Implement to be notified of ProximityEvents. */
+26 −0
Original line number Original line Diff line number Diff line
@@ -81,6 +81,32 @@ public class ProximityCheckTest extends SysuiTestCase {
        assertFalse(mFakeProximitySensor.isRegistered());
        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.
        ProximitySensor.ProximitySensorListener 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.ProximityEvent(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> {
    private static class TestableCallback implements Consumer<Boolean> {
        Boolean mLastResult;
        Boolean mLastResult;
        @Override
        @Override