Loading core/java/android/hardware/biometrics/IBiometricContextListener.aidl +4 −1 Original line number Diff line number Diff line Loading @@ -23,5 +23,8 @@ package android.hardware.biometrics; * @hide */ oneway interface IBiometricContextListener { void onDozeChanged(boolean isDozing); // Called when doze or awake (screen on) status changes. // These may be called while the device is still transitioning to the new state // (i.e. about to become awake or enter doze) void onDozeChanged(boolean isDozing, boolean isAwake); } packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +23 −5 Original line number Diff line number Diff line Loading @@ -19,6 +19,9 @@ package com.android.systemui.biometrics; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; Loading Loading @@ -655,7 +658,6 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba @Background DelayableExecutor bgExecutor) { super(context); mExecution = execution; mWakefulnessLifecycle = wakefulnessLifecycle; mUserManager = userManager; mLockPatternUtils = lockPatternUtils; mHandler = handler; Loading @@ -681,11 +683,24 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba return Unit.INSTANCE; }); mWakefulnessLifecycle = wakefulnessLifecycle; mWakefulnessLifecycle.addObserver(new WakefulnessLifecycle.Observer() { @Override public void onFinishedWakingUp() { notifyDozeChanged(mStatusBarStateController.isDozing(), WAKEFULNESS_AWAKE); } @Override public void onStartedGoingToSleep() { notifyDozeChanged(mStatusBarStateController.isDozing(), WAKEFULNESS_GOING_TO_SLEEP); } }); mStatusBarStateController = statusBarStateController; mStatusBarStateController.addCallback(new StatusBarStateController.StateListener() { @Override public void onDozingChanged(boolean isDozing) { notifyDozeChanged(isDozing); notifyDozeChanged(isDozing, wakefulnessLifecycle.getWakefulness()); } }); Loading Loading @@ -763,13 +778,16 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba @Override public void setBiometicContextListener(IBiometricContextListener listener) { mBiometricContextListener = listener; notifyDozeChanged(mStatusBarStateController.isDozing()); notifyDozeChanged(mStatusBarStateController.isDozing(), mWakefulnessLifecycle.getWakefulness()); } private void notifyDozeChanged(boolean isDozing) { private void notifyDozeChanged(boolean isDozing, @WakefulnessLifecycle.Wakefulness int wakefullness) { if (mBiometricContextListener != null) { try { mBiometricContextListener.onDozeChanged(isDozing); final boolean isAwake = wakefullness == WAKEFULNESS_AWAKE; mBiometricContextListener.onDozeChanged(isDozing, isAwake); } catch (RemoteException e) { Log.w(TAG, "failed to notify initial doze state"); } Loading packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +35 −8 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRIN import static android.hardware.biometrics.BiometricManager.Authenticators; import static android.hardware.biometrics.BiometricManager.BIOMETRIC_MULTI_SENSOR_FINGERPRINT_AND_FACE; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertEquals; Loading Loading @@ -156,11 +158,13 @@ public class AuthControllerTest extends SysuiTestCase { @Mock private InteractionJankMonitor mInteractionJankMonitor; @Captor ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor; private ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor; @Captor private ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor; @Captor ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor; private ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor; @Captor ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor; private ArgumentCaptor<WakefulnessLifecycle.Observer> mWakefullnessObserverCaptor; private TestableContext mContextSpy; private Execution mExecution; Loading Loading @@ -224,7 +228,9 @@ public class AuthControllerTest extends SysuiTestCase { mAuthenticatorsRegisteredCaptor.capture()); when(mStatusBarStateController.isDozing()).thenReturn(false); when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE); verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture()); verify(mWakefulnessLifecycle).addObserver(mWakefullnessObserverCaptor.capture()); mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(props); Loading Loading @@ -721,16 +727,37 @@ public class AuthControllerTest extends SysuiTestCase { } @Test public void testForwardsDozeEvent() throws RemoteException { public void testForwardsDozeEvents() throws RemoteException { when(mStatusBarStateController.isDozing()).thenReturn(true); when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE); mAuthController.setBiometicContextListener(mContextListener); mStatusBarStateListenerCaptor.getValue().onDozingChanged(false); mStatusBarStateListenerCaptor.getValue().onDozingChanged(true); mStatusBarStateListenerCaptor.getValue().onDozingChanged(false); InOrder order = inOrder(mContextListener); order.verify(mContextListener, times(2)).onDozeChanged(eq(true), eq(true)); order.verify(mContextListener).onDozeChanged(eq(false), eq(true)); order.verifyNoMoreInteractions(); } @Test public void testForwardsWakeEvents() throws RemoteException { when(mStatusBarStateController.isDozing()).thenReturn(false); when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE); mAuthController.setBiometicContextListener(mContextListener); mWakefullnessObserverCaptor.getValue().onStartedGoingToSleep(); mWakefullnessObserverCaptor.getValue().onFinishedGoingToSleep(); mWakefullnessObserverCaptor.getValue().onStartedWakingUp(); mWakefullnessObserverCaptor.getValue().onFinishedWakingUp(); mWakefullnessObserverCaptor.getValue().onPostFinishedWakingUp(); InOrder order = inOrder(mContextListener); // invoked twice since the initial state is false order.verify(mContextListener, times(2)).onDozeChanged(eq(false)); order.verify(mContextListener).onDozeChanged(eq(true)); order.verify(mContextListener).onDozeChanged(eq(false), eq(true)); order.verify(mContextListener).onDozeChanged(eq(false), eq(false)); order.verify(mContextListener).onDozeChanged(eq(false), eq(true)); order.verifyNoMoreInteractions(); } @Test Loading services/core/java/com/android/server/biometrics/log/BiometricContext.java +3 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,9 @@ public interface BiometricContext { /** If the display is in AOD. */ boolean isAod(); /** If the device is awake or is becoming awake. */ boolean isAwake(); /** * Subscribe to context changes. * Loading services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java +21 −6 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ import java.util.function.Consumer; /** * A default provider for {@link BiometricContext}. */ class BiometricContextProvider implements BiometricContext { final class BiometricContextProvider implements BiometricContext { private static final String TAG = "BiometricContextProvider"; Loading Loading @@ -76,7 +76,8 @@ class BiometricContextProvider implements BiometricContext { private final Map<Integer, InstanceId> mSession = new ConcurrentHashMap<>(); private final AmbientDisplayConfiguration mAmbientDisplayConfiguration; private boolean mIsDozing = false; private boolean mIsAod = false; private boolean mIsAwake = false; @VisibleForTesting BiometricContextProvider(@NonNull AmbientDisplayConfiguration ambientDisplayConfiguration, Loading @@ -85,10 +86,15 @@ class BiometricContextProvider implements BiometricContext { try { service.setBiometicContextListener(new IBiometricContextListener.Stub() { @Override public void onDozeChanged(boolean isDozing) { mIsDozing = isDozing; public void onDozeChanged(boolean isDozing, boolean isAwake) { isDozing = isDozing && isAodEnabled(); final boolean changed = (mIsAod != isDozing) || (mIsAwake != isAwake); if (changed) { mIsAod = isDozing; mIsAwake = isAwake; notifyChanged(); } } private void notifyChanged() { if (handler != null) { Loading @@ -97,6 +103,10 @@ class BiometricContextProvider implements BiometricContext { notifySubscribers(); } } private boolean isAodEnabled() { return mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT); } }); service.registerSessionListener(SESSION_TYPES, new ISessionListener.Stub() { @Override Loading Loading @@ -161,7 +171,12 @@ class BiometricContextProvider implements BiometricContext { @Override public boolean isAod() { return mIsDozing && mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT); return mIsAod; } @Override public boolean isAwake() { return mIsAwake; } @Override Loading Loading
core/java/android/hardware/biometrics/IBiometricContextListener.aidl +4 −1 Original line number Diff line number Diff line Loading @@ -23,5 +23,8 @@ package android.hardware.biometrics; * @hide */ oneway interface IBiometricContextListener { void onDozeChanged(boolean isDozing); // Called when doze or awake (screen on) status changes. // These may be called while the device is still transitioning to the new state // (i.e. about to become awake or enter doze) void onDozeChanged(boolean isDozing, boolean isAwake); }
packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +23 −5 Original line number Diff line number Diff line Loading @@ -19,6 +19,9 @@ package com.android.systemui.biometrics; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; Loading Loading @@ -655,7 +658,6 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba @Background DelayableExecutor bgExecutor) { super(context); mExecution = execution; mWakefulnessLifecycle = wakefulnessLifecycle; mUserManager = userManager; mLockPatternUtils = lockPatternUtils; mHandler = handler; Loading @@ -681,11 +683,24 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba return Unit.INSTANCE; }); mWakefulnessLifecycle = wakefulnessLifecycle; mWakefulnessLifecycle.addObserver(new WakefulnessLifecycle.Observer() { @Override public void onFinishedWakingUp() { notifyDozeChanged(mStatusBarStateController.isDozing(), WAKEFULNESS_AWAKE); } @Override public void onStartedGoingToSleep() { notifyDozeChanged(mStatusBarStateController.isDozing(), WAKEFULNESS_GOING_TO_SLEEP); } }); mStatusBarStateController = statusBarStateController; mStatusBarStateController.addCallback(new StatusBarStateController.StateListener() { @Override public void onDozingChanged(boolean isDozing) { notifyDozeChanged(isDozing); notifyDozeChanged(isDozing, wakefulnessLifecycle.getWakefulness()); } }); Loading Loading @@ -763,13 +778,16 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba @Override public void setBiometicContextListener(IBiometricContextListener listener) { mBiometricContextListener = listener; notifyDozeChanged(mStatusBarStateController.isDozing()); notifyDozeChanged(mStatusBarStateController.isDozing(), mWakefulnessLifecycle.getWakefulness()); } private void notifyDozeChanged(boolean isDozing) { private void notifyDozeChanged(boolean isDozing, @WakefulnessLifecycle.Wakefulness int wakefullness) { if (mBiometricContextListener != null) { try { mBiometricContextListener.onDozeChanged(isDozing); final boolean isAwake = wakefullness == WAKEFULNESS_AWAKE; mBiometricContextListener.onDozeChanged(isDozing, isAwake); } catch (RemoteException e) { Log.w(TAG, "failed to notify initial doze state"); } Loading
packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +35 −8 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRIN import static android.hardware.biometrics.BiometricManager.Authenticators; import static android.hardware.biometrics.BiometricManager.BIOMETRIC_MULTI_SENSOR_FINGERPRINT_AND_FACE; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertEquals; Loading Loading @@ -156,11 +158,13 @@ public class AuthControllerTest extends SysuiTestCase { @Mock private InteractionJankMonitor mInteractionJankMonitor; @Captor ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor; private ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor; @Captor private ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor; @Captor ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor; private ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor; @Captor ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor; private ArgumentCaptor<WakefulnessLifecycle.Observer> mWakefullnessObserverCaptor; private TestableContext mContextSpy; private Execution mExecution; Loading Loading @@ -224,7 +228,9 @@ public class AuthControllerTest extends SysuiTestCase { mAuthenticatorsRegisteredCaptor.capture()); when(mStatusBarStateController.isDozing()).thenReturn(false); when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE); verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture()); verify(mWakefulnessLifecycle).addObserver(mWakefullnessObserverCaptor.capture()); mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(props); Loading Loading @@ -721,16 +727,37 @@ public class AuthControllerTest extends SysuiTestCase { } @Test public void testForwardsDozeEvent() throws RemoteException { public void testForwardsDozeEvents() throws RemoteException { when(mStatusBarStateController.isDozing()).thenReturn(true); when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE); mAuthController.setBiometicContextListener(mContextListener); mStatusBarStateListenerCaptor.getValue().onDozingChanged(false); mStatusBarStateListenerCaptor.getValue().onDozingChanged(true); mStatusBarStateListenerCaptor.getValue().onDozingChanged(false); InOrder order = inOrder(mContextListener); order.verify(mContextListener, times(2)).onDozeChanged(eq(true), eq(true)); order.verify(mContextListener).onDozeChanged(eq(false), eq(true)); order.verifyNoMoreInteractions(); } @Test public void testForwardsWakeEvents() throws RemoteException { when(mStatusBarStateController.isDozing()).thenReturn(false); when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE); mAuthController.setBiometicContextListener(mContextListener); mWakefullnessObserverCaptor.getValue().onStartedGoingToSleep(); mWakefullnessObserverCaptor.getValue().onFinishedGoingToSleep(); mWakefullnessObserverCaptor.getValue().onStartedWakingUp(); mWakefullnessObserverCaptor.getValue().onFinishedWakingUp(); mWakefullnessObserverCaptor.getValue().onPostFinishedWakingUp(); InOrder order = inOrder(mContextListener); // invoked twice since the initial state is false order.verify(mContextListener, times(2)).onDozeChanged(eq(false)); order.verify(mContextListener).onDozeChanged(eq(true)); order.verify(mContextListener).onDozeChanged(eq(false), eq(true)); order.verify(mContextListener).onDozeChanged(eq(false), eq(false)); order.verify(mContextListener).onDozeChanged(eq(false), eq(true)); order.verifyNoMoreInteractions(); } @Test Loading
services/core/java/com/android/server/biometrics/log/BiometricContext.java +3 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,9 @@ public interface BiometricContext { /** If the display is in AOD. */ boolean isAod(); /** If the device is awake or is becoming awake. */ boolean isAwake(); /** * Subscribe to context changes. * Loading
services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java +21 −6 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ import java.util.function.Consumer; /** * A default provider for {@link BiometricContext}. */ class BiometricContextProvider implements BiometricContext { final class BiometricContextProvider implements BiometricContext { private static final String TAG = "BiometricContextProvider"; Loading Loading @@ -76,7 +76,8 @@ class BiometricContextProvider implements BiometricContext { private final Map<Integer, InstanceId> mSession = new ConcurrentHashMap<>(); private final AmbientDisplayConfiguration mAmbientDisplayConfiguration; private boolean mIsDozing = false; private boolean mIsAod = false; private boolean mIsAwake = false; @VisibleForTesting BiometricContextProvider(@NonNull AmbientDisplayConfiguration ambientDisplayConfiguration, Loading @@ -85,10 +86,15 @@ class BiometricContextProvider implements BiometricContext { try { service.setBiometicContextListener(new IBiometricContextListener.Stub() { @Override public void onDozeChanged(boolean isDozing) { mIsDozing = isDozing; public void onDozeChanged(boolean isDozing, boolean isAwake) { isDozing = isDozing && isAodEnabled(); final boolean changed = (mIsAod != isDozing) || (mIsAwake != isAwake); if (changed) { mIsAod = isDozing; mIsAwake = isAwake; notifyChanged(); } } private void notifyChanged() { if (handler != null) { Loading @@ -97,6 +103,10 @@ class BiometricContextProvider implements BiometricContext { notifySubscribers(); } } private boolean isAodEnabled() { return mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT); } }); service.registerSessionListener(SESSION_TYPES, new ISessionListener.Stub() { @Override Loading Loading @@ -161,7 +171,12 @@ class BiometricContextProvider implements BiometricContext { @Override public boolean isAod() { return mIsDozing && mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT); return mIsAod; } @Override public boolean isAwake() { return mIsAwake; } @Override Loading