Merge "Refactor UdfpsView into FrameLayout containing 2 views" into sc-dev

This commit is contained in:
Kevin Chyn
2021-02-03 03:41:46 +00:00
committed by Android (Google) Code Review
9 changed files with 397 additions and 157 deletions

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<com.android.systemui.biometrics.UdfpsAnimationView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/udfps_animation_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<com.android.systemui.biometrics.UdfpsSurfaceView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/udfps_surface_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.biometrics;
import android.annotation.NonNull;
import android.view.Surface;
/**
* Interface for controlling the high-brightness mode (HBM). UdfpsView can use this callback to
* enable the HBM while showing the fingerprint illumination, and to disable the HBM after the
* illumination is no longer necessary.
*/
public interface HbmCallback {
/**
* UdfpsView will call this to enable the HBM before drawing the illumination dot.
*
* @param surface A valid surface for which the HBM should be enabled.
*/
void enableHbm(@NonNull Surface surface);
/**
* UdfpsView will call this to disable the HBM when the illumination is not longer needed.
*
* @param surface A valid surface for which the HBM should be disabled.
*/
void disableHbm(@NonNull Surface surface);
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.biometrics;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.statusbar.phone.ScrimController;
/**
* Class that coordinates non-HBM animations (such as enroll, keyguard, BiometricPrompt,
* FingerprintManager).
*/
public class UdfpsAnimationView extends View implements DozeReceiver,
ScrimController.ScrimChangedListener {
private static final String TAG = "UdfpsAnimationView";
@NonNull private UdfpsView mParent;
@Nullable private UdfpsAnimation mUdfpsAnimation;
@NonNull private RectF mSensorRect;
private int mNotificationPanelAlpha;
public UdfpsAnimationView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mSensorRect = new RectF();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mUdfpsAnimation != null) {
final int alpha = mParent.shouldPauseAuth() ? 255 - mNotificationPanelAlpha : 255;
mUdfpsAnimation.setAlpha(alpha);
mUdfpsAnimation.draw(canvas);
}
}
void setParent(@NonNull UdfpsView parent) {
mParent = parent;
}
void setAnimation(@Nullable UdfpsAnimation animation) {
mUdfpsAnimation = animation;
}
void onSensorRectUpdated(@NonNull RectF sensorRect) {
mSensorRect = sensorRect;
if (mUdfpsAnimation != null) {
mUdfpsAnimation.onSensorRectUpdated(mSensorRect);
}
}
void updateColor() {
if (mUdfpsAnimation != null) {
mUdfpsAnimation.updateColor();
}
}
@Override
public void dozeTimeTick() {
if (mUdfpsAnimation instanceof DozeReceiver) {
((DozeReceiver) mUdfpsAnimation).dozeTimeTick();
}
}
@Override
public void onAlphaChanged(float alpha) {
mNotificationPanelAlpha = (int) (alpha * 255);
postInvalidate();
}
void onEnrollmentProgress(int remaining) {
if (mUdfpsAnimation instanceof UdfpsAnimationEnroll) {
((UdfpsAnimationEnroll) mUdfpsAnimation).onEnrollmentProgress(remaining);
}
}
void onEnrollmentHelp() {
if (mUdfpsAnimation instanceof UdfpsAnimationEnroll) {
((UdfpsAnimationEnroll) mUdfpsAnimation).onEnrollmentHelp();
}
}
}

View File

@@ -62,7 +62,7 @@ import javax.inject.Inject;
*/
@SuppressWarnings("deprecation")
@SysUISingleton
public class UdfpsController implements UdfpsView.HbmCallback, DozeReceiver {
public class UdfpsController implements DozeReceiver, HbmCallback {
private static final String TAG = "UdfpsController";
private static final long AOD_INTERRUPT_TIMEOUT_MILLIS = 1000;
@@ -374,9 +374,8 @@ public class UdfpsController implements UdfpsView.HbmCallback, DozeReceiver {
// This method can be called from the UI thread.
private void onFingerDown(int x, int y, float minor, float major) {
mView.setOnIlluminatedRunnable(
() -> mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major));
mView.startIllumination();
mView.startIllumination(() ->
mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major));
}
// This method can be called from the UI thread.
@@ -386,13 +385,13 @@ public class UdfpsController implements UdfpsView.HbmCallback, DozeReceiver {
}
@Override
public void enableHbm(Surface surface) {
public void enableHbm(@NonNull Surface surface) {
// Do nothing. This method can be implemented for devices that require the high-brightness
// mode for fingerprint illumination.
}
@Override
public void disableHbm(Surface surface) {
public void disableHbm(@NonNull Surface surface) {
// Do nothing. This method can be implemented for devices that require the high-brightness
// mode for fingerprint illumination.
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.biometrics;
import android.annotation.Nullable;
/**
* Interface that should be implemented by UI's that need to coordinate user touches,
* views/animations, and modules that start/stop display illumination.
*/
interface UdfpsIlluminator {
/**
* @param callback Invoked when HBM should be enabled or disabled.
*/
void setHbmCallback(@Nullable HbmCallback callback);
/**
* Invoked when illumination should start.
* @param onIlluminatedRunnable Invoked when the display has been illuminated.
*/
void startIllumination(@Nullable Runnable onIlluminatedRunnable);
/**
* Invoked when illumination should end.
*/
void stopIllumination();
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.biometrics;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* Under-display fingerprint sensor Surface View. The surface should be used for HBM-specific things
* only. All other animations should be done on the other view.
*/
public class UdfpsSurfaceView extends SurfaceView implements UdfpsIlluminator {
private static final String TAG = "UdfpsSurfaceView";
/**
* This is used instead of {@link android.graphics.drawable.Drawable}, because the latter has
* several abstract methods that are not used here but require implementation.
*/
private interface SimpleDrawable {
void draw(Canvas canvas);
}
@NonNull private final SurfaceHolder mHolder;
@NonNull private final Paint mSensorPaint;
@NonNull private final SimpleDrawable mIlluminationDotDrawable;
@NonNull private RectF mSensorRect;
@Nullable private HbmCallback mHbmCallback;
public UdfpsSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
mHolder = getHolder();
mHolder.setFormat(PixelFormat.RGBA_8888);
mSensorRect = new RectF();
mSensorPaint = new Paint(0 /* flags */);
mSensorPaint.setAntiAlias(true);
mSensorPaint.setARGB(255, 255, 255, 255);
mSensorPaint.setStyle(Paint.Style.FILL);
mIlluminationDotDrawable = canvas -> canvas.drawOval(mSensorRect, mSensorPaint);
}
@Override
public void setHbmCallback(@Nullable HbmCallback callback) {
mHbmCallback = callback;
}
@Override
public void startIllumination(@Nullable Runnable onIlluminatedRunnable) {
if (mHbmCallback != null && mHolder.getSurface().isValid()) {
mHbmCallback.enableHbm(mHolder.getSurface());
}
drawImmediately(mIlluminationDotDrawable);
if (onIlluminatedRunnable != null) {
// No framework API can reliably tell when a frame reaches the panel. A timeout is the
// safest solution. The frame should be displayed within 3 refresh cycles, which on a
// 60 Hz panel equates to 50 milliseconds.
postDelayed(onIlluminatedRunnable, 50 /* delayMillis */);
}
}
@Override
public void stopIllumination() {
if (mHbmCallback != null && mHolder.getSurface().isValid()) {
mHbmCallback.disableHbm(mHolder.getSurface());
}
invalidate();
}
void onSensorRectUpdated(@NonNull RectF sensorRect) {
mSensorRect = sensorRect;
}
/**
* Immediately draws the provided drawable on this SurfaceView's surface.
*/
private void drawImmediately(@NonNull SimpleDrawable drawable) {
Canvas canvas = null;
try {
canvas = mHolder.lockCanvas();
drawable.draw(canvas);
} finally {
// Make sure the surface is never left in a bad state.
if (canvas != null) {
mHolder.unlockCanvasAndPost(canvas);
}
}
}
}

View File

@@ -27,16 +27,14 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.RectF;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import com.android.systemui.R;
import com.android.systemui.doze.DozeReceiver;
@@ -44,56 +42,20 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.ScrimController;
/**
* A full screen view with a configurable illumination dot and scrim.
* A view containing 1) A SurfaceView for HBM, and 2) A normal drawable view for all other
* animations.
*/
public class UdfpsView extends SurfaceView implements DozeReceiver,
public class UdfpsView extends FrameLayout implements DozeReceiver, UdfpsIlluminator,
StatusBarStateController.StateListener, ScrimController.ScrimChangedListener {
private static final String TAG = "UdfpsView";
/**
* Interface for controlling the high-brightness mode (HBM). UdfpsView can use this callback to
* enable the HBM while showing the fingerprint illumination, and to disable the HBM after the
* illumination is no longer necessary.
*/
interface HbmCallback {
/**
* UdfpsView will call this to enable the HBM before drawing the illumination dot.
*
* @param surface A valid surface for which the HBM should be enabled.
*/
void enableHbm(@NonNull Surface surface);
/**
* UdfpsView will call this to disable the HBM when the illumination is not longer needed.
*
* @param surface A valid surface for which the HBM should be disabled.
*/
void disableHbm(@NonNull Surface surface);
}
/**
* This is used instead of {@link android.graphics.drawable.Drawable}, because the latter has
* several abstract methods that are not used here but require implementation.
*/
private interface SimpleDrawable {
void draw(Canvas canvas);
}
// Radius in pixels.
private static final float SENSOR_SHADOW_RADIUS = 2.0f;
private static final int DEBUG_TEXT_SIZE_PX = 32;
@NonNull private final SurfaceHolder mHolder;
@NonNull private final UdfpsSurfaceView mHbmSurfaceView;
@NonNull private final UdfpsAnimationView mAnimationView;
@NonNull private final RectF mSensorRect;
@NonNull private final Paint mSensorPaint;
@NonNull private final Paint mDebugTextPaint;
@NonNull private final SimpleDrawable mIlluminationDotDrawable;
@NonNull private final SimpleDrawable mClearSurfaceDrawable;
@Nullable private UdfpsAnimation mUdfpsAnimation;
@Nullable private HbmCallback mHbmCallback;
@Nullable private Runnable mOnIlluminatedRunnable;
// Used to obtain the sensor location.
@NonNull private FingerprintSensorPropertiesInternal mSensorProps;
@@ -103,7 +65,6 @@ public class UdfpsView extends SurfaceView implements DozeReceiver,
private boolean mIlluminationRequested;
private int mStatusBarState;
private boolean mNotificationShadeExpanded;
private int mNotificationPanelAlpha;
public UdfpsView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -121,27 +82,27 @@ public class UdfpsView extends SurfaceView implements DozeReceiver,
a.recycle();
}
mHolder = getHolder();
mHolder.setFormat(PixelFormat.RGBA_8888);
// Inflate UdfpsSurfaceView
final LayoutInflater inflater = LayoutInflater.from(context);
mHbmSurfaceView = (UdfpsSurfaceView) inflater.inflate(R.layout.udfps_surface_view,
null, false);
addView(mHbmSurfaceView);
mHbmSurfaceView.setVisibility(View.INVISIBLE);
// Inflate UdfpsAnimationView
mAnimationView = (UdfpsAnimationView) inflater.inflate(R.layout.udfps_animation_view,
null, false);
mAnimationView.setParent(this);
addView(mAnimationView);
mSensorRect = new RectF();
mSensorPaint = new Paint(0 /* flags */);
mSensorPaint.setAntiAlias(true);
mSensorPaint.setARGB(255, 255, 255, 255);
mSensorPaint.setStyle(Paint.Style.FILL);
mDebugTextPaint = new Paint();
mDebugTextPaint.setAntiAlias(true);
mDebugTextPaint.setColor(Color.BLUE);
mDebugTextPaint.setTextSize(DEBUG_TEXT_SIZE_PX);
mIlluminationDotDrawable = canvas -> canvas.drawOval(mSensorRect, mSensorPaint);
mClearSurfaceDrawable = canvas -> canvas.drawColor(0, PorterDuff.Mode.CLEAR);
mIlluminationRequested = false;
// SurfaceView sets this to true by default. We must set it to false to allow
// onDraw to be called.
setWillNotDraw(false);
}
void setSensorProperties(@NonNull FingerprintSensorPropertiesInternal properties) {
@@ -149,29 +110,17 @@ public class UdfpsView extends SurfaceView implements DozeReceiver,
}
void setUdfpsAnimation(@Nullable UdfpsAnimation animation) {
mUdfpsAnimation = animation;
mAnimationView.setAnimation(animation);
}
/**
* Sets a callback that can be used to enable and disable the high-brightness mode (HBM).
*/
void setHbmCallback(@Nullable HbmCallback callback) {
mHbmCallback = callback;
}
/**
* Sets a runnable that will be run when the first illumination frame reaches the panel.
* The runnable is reset to null after it is executed once.
*/
void setOnIlluminatedRunnable(Runnable runnable) {
mOnIlluminatedRunnable = runnable;
@Override
public void setHbmCallback(@Nullable HbmCallback callback) {
mHbmSurfaceView.setHbmCallback(callback);
}
@Override
public void dozeTimeTick() {
if (mUdfpsAnimation instanceof DozeReceiver) {
((DozeReceiver) mUdfpsAnimation).dozeTimeTick();
}
mAnimationView.dozeTimeTick();
}
@Override
@@ -186,17 +135,15 @@ public class UdfpsView extends SurfaceView implements DozeReceiver,
@Override
public void onAlphaChanged(float alpha) {
mNotificationPanelAlpha = (int) (alpha * 255);
postInvalidate();
mAnimationView.onAlphaChanged(alpha);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mSensorRect.set(0, 0, 2 * mSensorProps.sensorRadius, 2 * mSensorProps.sensorRadius);
if (mUdfpsAnimation != null) {
mUdfpsAnimation.onSensorRectUpdated(new RectF(mSensorRect));
}
mHbmSurfaceView.onSensorRectUpdated(new RectF(mSensorRect));
mAnimationView.onSensorRectUpdated(new RectF(mSensorRect));
}
@Override
@@ -205,13 +152,7 @@ public class UdfpsView extends SurfaceView implements DozeReceiver,
Log.v(TAG, "onAttachedToWindow");
// Retrieve the colors each time, since it depends on day/night mode
updateColor();
}
private void updateColor() {
if (mUdfpsAnimation != null) {
mUdfpsAnimation.updateColor();
}
mAnimationView.updateColor();
}
@Override
@@ -220,25 +161,6 @@ public class UdfpsView extends SurfaceView implements DozeReceiver,
Log.v(TAG, "onDetachedFromWindow");
}
/**
* Immediately draws the provided drawable on this SurfaceView's surface.
*/
private void drawImmediately(@NonNull SimpleDrawable drawable) {
Canvas canvas = null;
try {
canvas = mHolder.lockCanvas();
drawable.draw(canvas);
} finally {
// Make sure the surface is never left in a bad state.
if (canvas != null) {
mHolder.unlockCanvasAndPost(canvas);
}
}
}
/**
* This onDraw will not execute if setWillNotDraw(true) is called.
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
@@ -246,11 +168,6 @@ public class UdfpsView extends SurfaceView implements DozeReceiver,
if (!TextUtils.isEmpty(mDebugMessage)) {
canvas.drawText(mDebugMessage, 0, 160, mDebugTextPaint);
}
if (mUdfpsAnimation != null) {
final int alpha = shouldPauseAuth() ? 255 - mNotificationPanelAlpha : 255;
mUdfpsAnimation.setAlpha(alpha);
mUdfpsAnimation.draw(canvas);
}
}
}
@@ -283,7 +200,7 @@ public class UdfpsView extends SurfaceView implements DozeReceiver,
* authentication which would cause the UDFPS icons to abruptly disappear, do it here by not
* sending onFingerDown and smoothly animating away.
*/
private boolean shouldPauseAuth() {
boolean shouldPauseAuth() {
return (mNotificationShadeExpanded && mStatusBarState != KEYGUARD)
|| mStatusBarState == SHADE_LOCKED
|| mStatusBarState == FULLSCREEN_USER_SWITCHER;
@@ -293,49 +210,30 @@ public class UdfpsView extends SurfaceView implements DozeReceiver,
return mIlluminationRequested;
}
void startIllumination() {
/**
* @param onIlluminatedRunnable Runs when the first illumination frame reaches the panel.
*/
@Override
public void startIllumination(@Nullable Runnable onIlluminatedRunnable) {
mIlluminationRequested = true;
// Disable onDraw to prevent overriding the illumination dot with the regular UI.
setWillNotDraw(true);
if (mHbmCallback != null && mHolder.getSurface().isValid()) {
mHbmCallback.enableHbm(mHolder.getSurface());
}
drawImmediately(mIlluminationDotDrawable);
if (mOnIlluminatedRunnable != null) {
// No framework API can reliably tell when a frame reaches the panel. A timeout is the
// safest solution. The frame should be displayed within 3 refresh cycles, which on a
// 60 Hz panel equates to 50 milliseconds.
postDelayed(mOnIlluminatedRunnable, 50 /* delayMillis */);
mOnIlluminatedRunnable = null;
}
mAnimationView.setVisibility(View.INVISIBLE);
mHbmSurfaceView.setVisibility(View.VISIBLE);
mHbmSurfaceView.startIllumination(onIlluminatedRunnable);
}
void stopIllumination() {
@Override
public void stopIllumination() {
mIlluminationRequested = false;
if (mHbmCallback != null && mHolder.getSurface().isValid()) {
mHbmCallback.disableHbm(mHolder.getSurface());
}
// It may be necessary to clear the surface for the HBM changes to apply.
drawImmediately(mClearSurfaceDrawable);
// Enable onDraw to allow the regular UI to be drawn.
setWillNotDraw(false);
invalidate();
mAnimationView.setVisibility(View.VISIBLE);
mHbmSurfaceView.setVisibility(View.INVISIBLE);
mHbmSurfaceView.stopIllumination();
}
void onEnrollmentProgress(int remaining) {
if (mUdfpsAnimation instanceof UdfpsAnimationEnroll) {
((UdfpsAnimationEnroll) mUdfpsAnimation).onEnrollmentProgress(remaining);
}
mAnimationView.onEnrollmentProgress(remaining);
}
void onEnrollmentHelp() {
if (mUdfpsAnimation instanceof UdfpsAnimationEnroll) {
((UdfpsAnimationEnroll) mUdfpsAnimation).onEnrollmentHelp();
}
mAnimationView.onEnrollmentHelp();
}
}

View File

@@ -188,9 +188,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event);
event.recycle();
// THEN illumination begins
verify(mUdfpsView).startIllumination();
// AND onIlluminatedRunnable that notifies FingerprintManager is set
verify(mUdfpsView).setOnIlluminatedRunnable(mOnIlluminatedRunnableCaptor.capture());
verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture());
mOnIlluminatedRunnableCaptor.getValue().run();
verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mSensorProps.sensorId), eq(0),
eq(0), eq(0f), eq(0f));
@@ -205,9 +204,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
// WHEN fingerprint is requested because of AOD interrupt
mUdfpsController.onAodInterrupt(0, 0, 2f, 3f);
// THEN illumination begins
verify(mUdfpsView).startIllumination();
// AND onIlluminatedRunnable that notifies FingerprintManager is set
verify(mUdfpsView).setOnIlluminatedRunnable(mOnIlluminatedRunnableCaptor.capture());
verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture());
mOnIlluminatedRunnableCaptor.getValue().run();
verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mSensorProps.sensorId), eq(0),
eq(0), eq(3f) /* minor */, eq(2f) /* major */);