Merge "Add a final lux method to ALSProbe." into tm-qpr-dev am: 9541293118
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20190474 Change-Id: I81c3e58d2ea8df676a4f33bd2a8680f7a942de9f Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -30,7 +30,10 @@ import android.util.Slog;
|
|||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.server.biometrics.sensors.BaseClientMonitor;
|
import com.android.server.biometrics.sensors.BaseClientMonitor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/** Probe for ambient light. */
|
/** Probe for ambient light. */
|
||||||
final class ALSProbe implements Probe {
|
final class ALSProbe implements Probe {
|
||||||
@@ -47,12 +50,18 @@ final class ALSProbe implements Probe {
|
|||||||
|
|
||||||
private boolean mEnabled = false;
|
private boolean mEnabled = false;
|
||||||
private boolean mDestroyed = false;
|
private boolean mDestroyed = false;
|
||||||
|
private boolean mDestroyRequested = false;
|
||||||
|
private boolean mDisableRequested = false;
|
||||||
|
private volatile NextConsumer mNextConsumer = null;
|
||||||
private volatile float mLastAmbientLux = -1;
|
private volatile float mLastAmbientLux = -1;
|
||||||
|
|
||||||
private final SensorEventListener mLightSensorListener = new SensorEventListener() {
|
private final SensorEventListener mLightSensorListener = new SensorEventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSensorChanged(SensorEvent event) {
|
public void onSensorChanged(SensorEvent event) {
|
||||||
mLastAmbientLux = event.values[0];
|
mLastAmbientLux = event.values[0];
|
||||||
|
if (mNextConsumer != null) {
|
||||||
|
completeNextConsumer(mLastAmbientLux);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -102,29 +111,84 @@ final class ALSProbe implements Probe {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void enable() {
|
public synchronized void enable() {
|
||||||
if (!mDestroyed) {
|
if (!mDestroyed && !mDestroyRequested) {
|
||||||
|
mDisableRequested = false;
|
||||||
enableLightSensorLoggingLocked();
|
enableLightSensorLoggingLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void disable() {
|
public synchronized void disable() {
|
||||||
if (!mDestroyed) {
|
mDisableRequested = true;
|
||||||
|
|
||||||
|
// if a final consumer is set it will call destroy/disable on the next value if requested
|
||||||
|
if (!mDestroyed && mNextConsumer == null) {
|
||||||
disableLightSensorLoggingLocked();
|
disableLightSensorLoggingLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void destroy() {
|
public synchronized void destroy() {
|
||||||
disable();
|
mDestroyRequested = true;
|
||||||
mDestroyed = true;
|
|
||||||
|
// if a final consumer is set it will call destroy/disable on the next value if requested
|
||||||
|
if (!mDestroyed && mNextConsumer == null) {
|
||||||
|
disable();
|
||||||
|
mDestroyed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The most recent lux reading. */
|
/** The most recent lux reading. */
|
||||||
public float getCurrentLux() {
|
public float getMostRecentLux() {
|
||||||
return mLastAmbientLux;
|
return mLastAmbientLux;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a listener for the next available ALS reading, which will be reported to the given
|
||||||
|
* consumer even if this probe is {@link #disable()}'ed or {@link #destroy()}'ed before a value
|
||||||
|
* is available.
|
||||||
|
*
|
||||||
|
* This method is intended to be used for event logs that occur when the screen may be
|
||||||
|
* off and sampling may have been {@link #disable()}'ed. In these cases, this method will turn
|
||||||
|
* on the sensor (if needed), fetch & report the first value, and then destroy or disable this
|
||||||
|
* probe (if needed).
|
||||||
|
*
|
||||||
|
* @param consumer consumer to notify when the data is available
|
||||||
|
* @param handler handler for notifying the consumer, or null
|
||||||
|
*/
|
||||||
|
public synchronized void awaitNextLux(@NonNull Consumer<Float> consumer,
|
||||||
|
@Nullable Handler handler) {
|
||||||
|
final NextConsumer nextConsumer = new NextConsumer(consumer, handler);
|
||||||
|
final float current = mLastAmbientLux;
|
||||||
|
if (current > 0) {
|
||||||
|
nextConsumer.consume(current);
|
||||||
|
} else if (mDestroyed) {
|
||||||
|
nextConsumer.consume(-1f);
|
||||||
|
} else if (mNextConsumer != null) {
|
||||||
|
mNextConsumer.add(nextConsumer);
|
||||||
|
} else {
|
||||||
|
mNextConsumer = nextConsumer;
|
||||||
|
enableLightSensorLoggingLocked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
private void enableLightSensorLoggingLocked() {
|
||||||
if (!mEnabled) {
|
if (!mEnabled) {
|
||||||
mEnabled = true;
|
mEnabled = true;
|
||||||
@@ -160,4 +224,30 @@ final class ALSProbe implements Probe {
|
|||||||
+ mLightSensorListener.hashCode());
|
+ mLightSensorListener.hashCode());
|
||||||
disable();
|
disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class NextConsumer {
|
||||||
|
@NonNull private final Consumer<Float> mConsumer;
|
||||||
|
@Nullable private final Handler mHandler;
|
||||||
|
@NonNull private final List<NextConsumer> mOthers = new ArrayList<>();
|
||||||
|
|
||||||
|
private NextConsumer(@NonNull Consumer<Float> consumer, @Nullable Handler handler) {
|
||||||
|
mConsumer = consumer;
|
||||||
|
mHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void consume(float value) {
|
||||||
|
if (mHandler != null) {
|
||||||
|
mHandler.post(() -> mConsumer.accept(value));
|
||||||
|
} else {
|
||||||
|
mConsumer.accept(value);
|
||||||
|
}
|
||||||
|
for (NextConsumer c : mOthers) {
|
||||||
|
c.consume(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(NextConsumer consumer) {
|
||||||
|
mOthers.add(consumer);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,8 +62,7 @@ public class BiometricFrameworkStatsLogger {
|
|||||||
/** {@see FrameworkStatsLog.BIOMETRIC_AUTHENTICATED}. */
|
/** {@see FrameworkStatsLog.BIOMETRIC_AUTHENTICATED}. */
|
||||||
public void authenticate(OperationContext operationContext,
|
public void authenticate(OperationContext operationContext,
|
||||||
int statsModality, int statsAction, int statsClient, boolean isDebug, long latency,
|
int statsModality, int statsAction, int statsClient, boolean isDebug, long latency,
|
||||||
int authState, boolean requireConfirmation,
|
int authState, boolean requireConfirmation, int targetUserId, float ambientLightLux) {
|
||||||
int targetUserId, float ambientLightLux) {
|
|
||||||
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED,
|
FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED,
|
||||||
statsModality,
|
statsModality,
|
||||||
targetUserId,
|
targetUserId,
|
||||||
@@ -80,6 +79,16 @@ public class BiometricFrameworkStatsLogger {
|
|||||||
operationContext.isAod);
|
operationContext.isAod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** {@see FrameworkStatsLog.BIOMETRIC_AUTHENTICATED}. */
|
||||||
|
public void authenticate(OperationContext operationContext,
|
||||||
|
int statsModality, int statsAction, int statsClient, boolean isDebug, long latency,
|
||||||
|
int authState, boolean requireConfirmation, int targetUserId, ALSProbe alsProbe) {
|
||||||
|
alsProbe.awaitNextLux((ambientLightLux) -> {
|
||||||
|
authenticate(operationContext, statsModality, statsAction, statsClient, isDebug,
|
||||||
|
latency, authState, requireConfirmation, targetUserId, ambientLightLux);
|
||||||
|
}, null /* handler */);
|
||||||
|
}
|
||||||
|
|
||||||
/** {@see FrameworkStatsLog.BIOMETRIC_ENROLLED}. */
|
/** {@see FrameworkStatsLog.BIOMETRIC_ENROLLED}. */
|
||||||
public void enroll(int statsModality, int statsAction, int statsClient,
|
public void enroll(int statsModality, int statsAction, int statsClient,
|
||||||
int targetUserId, long latency, boolean enrollSuccessful, float ambientLightLux) {
|
int targetUserId, long latency, boolean enrollSuccessful, float ambientLightLux) {
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ public class BiometricLogger {
|
|||||||
+ ", RequireConfirmation: " + requireConfirmation
|
+ ", RequireConfirmation: " + requireConfirmation
|
||||||
+ ", State: " + authState
|
+ ", State: " + authState
|
||||||
+ ", Latency: " + latency
|
+ ", Latency: " + latency
|
||||||
+ ", Lux: " + mALSProbe.getCurrentLux());
|
+ ", Lux: " + mALSProbe.getMostRecentLux());
|
||||||
} else {
|
} else {
|
||||||
Slog.v(TAG, "Authentication latency: " + latency);
|
Slog.v(TAG, "Authentication latency: " + latency);
|
||||||
}
|
}
|
||||||
@@ -231,7 +231,7 @@ public class BiometricLogger {
|
|||||||
|
|
||||||
mSink.authenticate(operationContext, mStatsModality, mStatsAction, mStatsClient,
|
mSink.authenticate(operationContext, mStatsModality, mStatsAction, mStatsClient,
|
||||||
Utils.isDebugEnabled(context, targetUserId),
|
Utils.isDebugEnabled(context, targetUserId),
|
||||||
latency, authState, requireConfirmation, targetUserId, mALSProbe.getCurrentLux());
|
latency, authState, requireConfirmation, targetUserId, mALSProbe);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Log enrollment outcome. */
|
/** Log enrollment outcome. */
|
||||||
@@ -245,7 +245,7 @@ public class BiometricLogger {
|
|||||||
+ ", User: " + targetUserId
|
+ ", User: " + targetUserId
|
||||||
+ ", Client: " + mStatsClient
|
+ ", Client: " + mStatsClient
|
||||||
+ ", Latency: " + latency
|
+ ", Latency: " + latency
|
||||||
+ ", Lux: " + mALSProbe.getCurrentLux()
|
+ ", Lux: " + mALSProbe.getMostRecentLux()
|
||||||
+ ", Success: " + enrollSuccessful);
|
+ ", Success: " + enrollSuccessful);
|
||||||
} else {
|
} else {
|
||||||
Slog.v(TAG, "Enroll latency: " + latency);
|
Slog.v(TAG, "Enroll latency: " + latency);
|
||||||
@@ -256,7 +256,7 @@ public class BiometricLogger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mSink.enroll(mStatsModality, mStatsAction, mStatsClient,
|
mSink.enroll(mStatsModality, mStatsAction, mStatsClient,
|
||||||
targetUserId, latency, enrollSuccessful, mALSProbe.getCurrentLux());
|
targetUserId, latency, enrollSuccessful, mALSProbe.getMostRecentLux());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Report unexpected enrollment reported by the HAL. */
|
/** Report unexpected enrollment reported by the HAL. */
|
||||||
|
|||||||
@@ -333,6 +333,9 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
|
|||||||
mALSProbeCallback.getProbe().disable();
|
mALSProbeCallback.getProbe().disable();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (getBiometricContext().isAwake()) {
|
||||||
|
mALSProbeCallback.getProbe().enable();
|
||||||
|
}
|
||||||
|
|
||||||
if (session.hasContextMethods()) {
|
if (session.hasContextMethods()) {
|
||||||
return session.getSession().authenticateWithContext(mOperationId, opContext);
|
return session.getSession().authenticateWithContext(mOperationId, opContext);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.anyInt;
|
|||||||
import static org.mockito.Mockito.eq;
|
import static org.mockito.Mockito.eq;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.reset;
|
import static org.mockito.Mockito.reset;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -50,6 +51,9 @@ import org.mockito.Mock;
|
|||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.mockito.junit.MockitoRule;
|
import org.mockito.junit.MockitoRule;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
@Presubmit
|
@Presubmit
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner.class)
|
@RunWith(AndroidTestingRunner.class)
|
||||||
@@ -93,7 +97,7 @@ public class ALSProbeTest {
|
|||||||
mSensorEventListenerCaptor.getValue().onSensorChanged(
|
mSensorEventListenerCaptor.getValue().onSensorChanged(
|
||||||
new SensorEvent(mLightSensor, 1, 2, new float[]{value}));
|
new SensorEvent(mLightSensor, 1, 2, new float[]{value}));
|
||||||
|
|
||||||
assertThat(mProbe.getCurrentLux()).isEqualTo(value);
|
assertThat(mProbe.getMostRecentLux()).isEqualTo(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -121,13 +125,17 @@ public class ALSProbeTest {
|
|||||||
mProbe.destroy();
|
mProbe.destroy();
|
||||||
mProbe.enable();
|
mProbe.enable();
|
||||||
|
|
||||||
|
AtomicInteger lux = new AtomicInteger(10);
|
||||||
|
mProbe.awaitNextLux((v) -> lux.set(Math.round(v)), null /* handler */);
|
||||||
|
|
||||||
verify(mSensorManager, never()).registerListener(any(), any(), anyInt());
|
verify(mSensorManager, never()).registerListener(any(), any(), anyInt());
|
||||||
verifyNoMoreInteractions(mSensorManager);
|
verifyNoMoreInteractions(mSensorManager);
|
||||||
|
assertThat(lux.get()).isLessThan(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDisabledReportsNegativeValue() {
|
public void testDisabledReportsNegativeValue() {
|
||||||
assertThat(mProbe.getCurrentLux()).isLessThan(0f);
|
assertThat(mProbe.getMostRecentLux()).isLessThan(0f);
|
||||||
|
|
||||||
mProbe.enable();
|
mProbe.enable();
|
||||||
verify(mSensorManager).registerListener(
|
verify(mSensorManager).registerListener(
|
||||||
@@ -136,7 +144,7 @@ public class ALSProbeTest {
|
|||||||
new SensorEvent(mLightSensor, 1, 1, new float[]{4.0f}));
|
new SensorEvent(mLightSensor, 1, 1, new float[]{4.0f}));
|
||||||
mProbe.disable();
|
mProbe.disable();
|
||||||
|
|
||||||
assertThat(mProbe.getCurrentLux()).isLessThan(0f);
|
assertThat(mProbe.getMostRecentLux()).isLessThan(0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -150,7 +158,7 @@ public class ALSProbeTest {
|
|||||||
|
|
||||||
verify(mSensorManager).unregisterListener(eq(mSensorEventListenerCaptor.getValue()));
|
verify(mSensorManager).unregisterListener(eq(mSensorEventListenerCaptor.getValue()));
|
||||||
verifyNoMoreInteractions(mSensorManager);
|
verifyNoMoreInteractions(mSensorManager);
|
||||||
assertThat(mProbe.getCurrentLux()).isLessThan(0f);
|
assertThat(mProbe.getMostRecentLux()).isLessThan(0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -166,7 +174,148 @@ public class ALSProbeTest {
|
|||||||
|
|
||||||
verify(mSensorManager).unregisterListener(any(SensorEventListener.class));
|
verify(mSensorManager).unregisterListener(any(SensorEventListener.class));
|
||||||
verifyNoMoreInteractions(mSensorManager);
|
verifyNoMoreInteractions(mSensorManager);
|
||||||
assertThat(mProbe.getCurrentLux()).isLessThan(0f);
|
assertThat(mProbe.getMostRecentLux()).isLessThan(0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNextLuxWhenAlreadyEnabledAndNotAvailable() {
|
||||||
|
testNextLuxWhenAlreadyEnabled(false /* dataIsAvailable */);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNextLuxWhenAlreadyEnabledAndAvailable() {
|
||||||
|
testNextLuxWhenAlreadyEnabled(true /* dataIsAvailable */);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testNextLuxWhenAlreadyEnabled(boolean dataIsAvailable) {
|
||||||
|
final List<Integer> values = List.of(1, 2, 3, 4, 6);
|
||||||
|
mProbe.enable();
|
||||||
|
|
||||||
|
verify(mSensorManager).registerListener(
|
||||||
|
mSensorEventListenerCaptor.capture(), any(), anyInt());
|
||||||
|
|
||||||
|
if (dataIsAvailable) {
|
||||||
|
for (int v : values) {
|
||||||
|
mSensorEventListenerCaptor.getValue().onSensorChanged(
|
||||||
|
new SensorEvent(mLightSensor, 1, 1, new float[]{v}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AtomicInteger lux = new AtomicInteger(-1);
|
||||||
|
mProbe.awaitNextLux((v) -> lux.set(Math.round(v)), null /* handler */);
|
||||||
|
if (!dataIsAvailable) {
|
||||||
|
for (int v : values) {
|
||||||
|
mSensorEventListenerCaptor.getValue().onSensorChanged(
|
||||||
|
new SensorEvent(mLightSensor, 1, 1, new float[]{v}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mSensorEventListenerCaptor.getValue().onSensorChanged(
|
||||||
|
new SensorEvent(mLightSensor, 1, 1, new float[]{200f}));
|
||||||
|
|
||||||
|
// should remain enabled
|
||||||
|
assertThat(lux.get()).isEqualTo(values.get(dataIsAvailable ? values.size() - 1 : 0));
|
||||||
|
verify(mSensorManager, never()).unregisterListener(any(SensorEventListener.class));
|
||||||
|
verifyNoMoreInteractions(mSensorManager);
|
||||||
|
|
||||||
|
final int anotherValue = 12;
|
||||||
|
mSensorEventListenerCaptor.getValue().onSensorChanged(
|
||||||
|
new SensorEvent(mLightSensor, 1, 1, new float[]{12}));
|
||||||
|
assertThat(mProbe.getMostRecentLux()).isEqualTo(anotherValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNextLuxWhenNotEnabled() {
|
||||||
|
testNextLuxWhenNotEnabled(false /* enableWhileWaiting */);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNextLuxWhenNotEnabledButEnabledLater() {
|
||||||
|
testNextLuxWhenNotEnabled(true /* enableWhileWaiting */);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testNextLuxWhenNotEnabled(boolean enableWhileWaiting) {
|
||||||
|
final List<Integer> values = List.of(1, 2, 3, 4, 6);
|
||||||
|
mProbe.disable();
|
||||||
|
|
||||||
|
AtomicInteger lux = new AtomicInteger(-1);
|
||||||
|
mProbe.awaitNextLux((v) -> lux.set(Math.round(v)), null /* handler */);
|
||||||
|
|
||||||
|
if (enableWhileWaiting) {
|
||||||
|
mProbe.enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
verify(mSensorManager).registerListener(
|
||||||
|
mSensorEventListenerCaptor.capture(), any(), anyInt());
|
||||||
|
for (int v : values) {
|
||||||
|
mSensorEventListenerCaptor.getValue().onSensorChanged(
|
||||||
|
new SensorEvent(mLightSensor, 1, 1, new float[]{v}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// should restore the disabled state
|
||||||
|
assertThat(lux.get()).isEqualTo(values.get(0));
|
||||||
|
verify(mSensorManager, enableWhileWaiting ? never() : times(1)).unregisterListener(
|
||||||
|
any(SensorEventListener.class));
|
||||||
|
verifyNoMoreInteractions(mSensorManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNextLuxIsNotCanceledByDisableOrDestroy() {
|
||||||
|
final int value = 7;
|
||||||
|
AtomicInteger lux = new AtomicInteger(-1);
|
||||||
|
mProbe.awaitNextLux((v) -> lux.set(Math.round(v)), null /* handler */);
|
||||||
|
|
||||||
|
verify(mSensorManager).registerListener(
|
||||||
|
mSensorEventListenerCaptor.capture(), any(), anyInt());
|
||||||
|
|
||||||
|
mProbe.destroy();
|
||||||
|
mProbe.disable();
|
||||||
|
|
||||||
|
assertThat(lux.get()).isEqualTo(-1);
|
||||||
|
|
||||||
|
mSensorEventListenerCaptor.getValue().onSensorChanged(
|
||||||
|
new SensorEvent(mLightSensor, 1, 1, new float[]{value}));
|
||||||
|
|
||||||
|
assertThat(lux.get()).isEqualTo(value);
|
||||||
|
|
||||||
|
mSensorEventListenerCaptor.getValue().onSensorChanged(
|
||||||
|
new SensorEvent(mLightSensor, 1, 1, new float[]{value + 1}));
|
||||||
|
|
||||||
|
// should remain destroyed
|
||||||
|
mProbe.enable();
|
||||||
|
|
||||||
|
assertThat(lux.get()).isEqualTo(value);
|
||||||
|
verify(mSensorManager).unregisterListener(any(SensorEventListener.class));
|
||||||
|
verifyNoMoreInteractions(mSensorManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultipleNextConsumers() {
|
||||||
|
final int value = 7;
|
||||||
|
AtomicInteger lux = new AtomicInteger(-1);
|
||||||
|
AtomicInteger lux2 = new AtomicInteger(-1);
|
||||||
|
mProbe.awaitNextLux((v) -> lux.set(Math.round(v)), null /* handler */);
|
||||||
|
mProbe.awaitNextLux((v) -> lux2.set(Math.round(v)), null /* handler */);
|
||||||
|
|
||||||
|
verify(mSensorManager).registerListener(
|
||||||
|
mSensorEventListenerCaptor.capture(), any(), anyInt());
|
||||||
|
mSensorEventListenerCaptor.getValue().onSensorChanged(
|
||||||
|
new SensorEvent(mLightSensor, 1, 1, new float[]{value}));
|
||||||
|
|
||||||
|
assertThat(lux.get()).isEqualTo(value);
|
||||||
|
assertThat(lux2.get()).isEqualTo(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoNextLuxWhenDestroyed() {
|
||||||
|
mProbe.destroy();
|
||||||
|
|
||||||
|
AtomicInteger lux = new AtomicInteger(-20);
|
||||||
|
mProbe.awaitNextLux((v) -> lux.set(Math.round(v)), null /* handler */);
|
||||||
|
|
||||||
|
assertThat(lux.get()).isEqualTo(-1);
|
||||||
|
verify(mSensorManager, never()).registerListener(
|
||||||
|
mSensorEventListenerCaptor.capture(), any(), anyInt());
|
||||||
|
verifyNoMoreInteractions(mSensorManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void moveTimeBy(long millis) {
|
private void moveTimeBy(long millis) {
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ public class BiometricLoggerTest {
|
|||||||
verify(mSink).authenticate(eq(mOpContext),
|
verify(mSink).authenticate(eq(mOpContext),
|
||||||
eq(DEFAULT_MODALITY), eq(DEFAULT_ACTION), eq(DEFAULT_CLIENT), anyBoolean(),
|
eq(DEFAULT_MODALITY), eq(DEFAULT_ACTION), eq(DEFAULT_CLIENT), anyBoolean(),
|
||||||
anyLong(), anyInt(), eq(requireConfirmation),
|
anyLong(), anyInt(), eq(requireConfirmation),
|
||||||
eq(targetUserId), anyFloat());
|
eq(targetUserId), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.inOrder;
|
|||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.reset;
|
import static org.mockito.Mockito.reset;
|
||||||
import static org.mockito.Mockito.same;
|
import static org.mockito.Mockito.same;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@@ -215,7 +216,7 @@ public class FingerprintAuthenticationClientTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void luxProbeWhenAwake() throws RemoteException {
|
public void luxProbeWhenAwake() throws RemoteException {
|
||||||
when(mBiometricContext.isAwake()).thenReturn(false, true, false);
|
when(mBiometricContext.isAwake()).thenReturn(false);
|
||||||
when(mBiometricContext.isAod()).thenReturn(false);
|
when(mBiometricContext.isAod()).thenReturn(false);
|
||||||
final FingerprintAuthenticationClient client = createClient();
|
final FingerprintAuthenticationClient client = createClient();
|
||||||
client.start(mCallback);
|
client.start(mCallback);
|
||||||
@@ -228,14 +229,37 @@ public class FingerprintAuthenticationClientTest {
|
|||||||
verify(mLuxProbe, never()).enable();
|
verify(mLuxProbe, never()).enable();
|
||||||
|
|
||||||
reset(mLuxProbe);
|
reset(mLuxProbe);
|
||||||
|
when(mBiometricContext.isAwake()).thenReturn(true);
|
||||||
|
|
||||||
mContextInjector.getValue().accept(opContext);
|
mContextInjector.getValue().accept(opContext);
|
||||||
verify(mLuxProbe).enable();
|
verify(mLuxProbe).enable();
|
||||||
verify(mLuxProbe, never()).disable();
|
verify(mLuxProbe, never()).disable();
|
||||||
|
|
||||||
|
when(mBiometricContext.isAwake()).thenReturn(false);
|
||||||
|
|
||||||
mContextInjector.getValue().accept(opContext);
|
mContextInjector.getValue().accept(opContext);
|
||||||
verify(mLuxProbe).disable();
|
verify(mLuxProbe).disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void luxProbeEnabledOnStartWhenWake() throws RemoteException {
|
||||||
|
luxProbeEnabledOnStart(true /* isAwake */);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void luxProbeNotEnabledOnStartWhenNotWake() throws RemoteException {
|
||||||
|
luxProbeEnabledOnStart(false /* isAwake */);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void luxProbeEnabledOnStart(boolean isAwake) throws RemoteException {
|
||||||
|
when(mBiometricContext.isAwake()).thenReturn(isAwake);
|
||||||
|
when(mBiometricContext.isAod()).thenReturn(false);
|
||||||
|
final FingerprintAuthenticationClient client = createClient();
|
||||||
|
client.start(mCallback);
|
||||||
|
|
||||||
|
verify(mLuxProbe, isAwake ? times(1) : never()).enable();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void luxProbeDisabledOnAod() throws RemoteException {
|
public void luxProbeDisabledOnAod() throws RemoteException {
|
||||||
when(mBiometricContext.isAwake()).thenReturn(false);
|
when(mBiometricContext.isAwake()).thenReturn(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user