From ec5da04c1a1f7df3be91942a18d795bfb270462f Mon Sep 17 00:00:00 2001 From: Joe Bolinger Date: Fri, 21 Oct 2022 13:36:08 -0700 Subject: Ensure await lux calls are completed when there is no sensor activity. Bug: 254720091 Test: atest ALSProbeTest Change-Id: Ibf2f0d21788d20ec8e869fee4d5f26b1419a5dcd --- .../android/server/biometrics/log/ALSProbe.java | 52 +++++++++++----------- .../server/biometrics/log/ALSProbeTest.java | 17 +++++++ 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/services/core/java/com/android/server/biometrics/log/ALSProbe.java b/services/core/java/com/android/server/biometrics/log/ALSProbe.java index 1a5f31c8ac90..da4361843681 100644 --- a/services/core/java/com/android/server/biometrics/log/ALSProbe.java +++ b/services/core/java/com/android/server/biometrics/log/ALSProbe.java @@ -52,16 +52,13 @@ final class ALSProbe implements Probe { private boolean mDestroyed = false; private boolean mDestroyRequested = false; private boolean mDisableRequested = false; - private volatile NextConsumer mNextConsumer = null; + private NextConsumer mNextConsumer = null; private volatile float mLastAmbientLux = -1; private final SensorEventListener mLightSensorListener = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { - mLastAmbientLux = event.values[0]; - if (mNextConsumer != null) { - completeNextConsumer(mLastAmbientLux); - } + onNext(event.values[0]); } @Override @@ -133,11 +130,29 @@ final class ALSProbe implements Probe { // if a final consumer is set it will call destroy/disable on the next value if requested if (!mDestroyed && mNextConsumer == null) { - disable(); + disableLightSensorLoggingLocked(); mDestroyed = true; } } + private synchronized void onNext(float value) { + mLastAmbientLux = value; + + final NextConsumer consumer = mNextConsumer; + mNextConsumer = null; + if (consumer != null) { + Slog.v(TAG, "Finishing next consumer"); + + if (mDestroyRequested) { + destroy(); + } else if (mDisableRequested) { + disable(); + } + + consumer.consume(value); + } + } + /** The most recent lux reading. */ public float getMostRecentLux() { return mLastAmbientLux; @@ -160,7 +175,7 @@ final class ALSProbe implements Probe { @Nullable Handler handler) { final NextConsumer nextConsumer = new NextConsumer(consumer, handler); final float current = mLastAmbientLux; - if (current > 0) { + if (current > -1f) { nextConsumer.consume(current); } else if (mDestroyed) { nextConsumer.consume(-1f); @@ -172,23 +187,6 @@ final class ALSProbe implements Probe { } } - private synchronized void completeNextConsumer(float value) { - Slog.v(TAG, "Finishing next consumer"); - - final NextConsumer consumer = mNextConsumer; - mNextConsumer = null; - - if (mDestroyRequested) { - destroy(); - } else if (mDisableRequested) { - disable(); - } - - if (consumer != null) { - consumer.consume(value); - } - } - private void enableLightSensorLoggingLocked() { if (!mEnabled) { mEnabled = true; @@ -219,9 +217,13 @@ final class ALSProbe implements Probe { } } - private void onTimeout() { + private synchronized void onTimeout() { Slog.e(TAG, "Max time exceeded for ALS logger - disabling: " + mLightSensorListener.hashCode()); + + // if consumers are waiting but there was no sensor change, complete them with the latest + // value before disabling + onNext(mLastAmbientLux); disable(); } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/ALSProbeTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/ALSProbeTest.java index 68c9ce4a9f86..0cff4f14bf23 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/log/ALSProbeTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/log/ALSProbeTest.java @@ -177,6 +177,23 @@ public class ALSProbeTest { assertThat(mProbe.getMostRecentLux()).isLessThan(0f); } + @Test + public void testWatchDogCompletesAwait() { + mProbe.enable(); + + AtomicInteger lux = new AtomicInteger(-9); + mProbe.awaitNextLux((v) -> lux.set(Math.round(v)), null /* handler */); + + verify(mSensorManager).registerListener( + mSensorEventListenerCaptor.capture(), any(), anyInt()); + + moveTimeBy(TIMEOUT_MS); + + assertThat(lux.get()).isEqualTo(-1); + verify(mSensorManager).unregisterListener(any(SensorEventListener.class)); + verifyNoMoreInteractions(mSensorManager); + } + @Test public void testNextLuxWhenAlreadyEnabledAndNotAvailable() { testNextLuxWhenAlreadyEnabled(false /* dataIsAvailable */); -- cgit v1.2.3-59-g8ed1b