Respect halControlsIllumination provided by the HAL

Bug: 224573604
Test: atest SystemUITests:com.android.systemui.biometrics
Change-Id: I665b8c6a131ff3fd66701fea7ca6368e33b39c13
Merged-In: I665b8c6a131ff3fd66701fea7ca6368e33b39c13
This commit is contained in:
Ilya Matyukhin
2022-04-20 22:02:12 +00:00
parent 5ecc0793a1
commit 59d49a4238
15 changed files with 56 additions and 22 deletions

View File

@@ -39,6 +39,7 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna
* See {@link FingerprintSensorProperties.SensorType}. * See {@link FingerprintSensorProperties.SensorType}.
*/ */
public final @FingerprintSensorProperties.SensorType int sensorType; public final @FingerprintSensorProperties.SensorType int sensorType;
public final boolean halControlsIllumination;
private final List<SensorLocationInternal> mSensorLocations; private final List<SensorLocationInternal> mSensorLocations;
@@ -46,6 +47,7 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna
@SensorProperties.Strength int strength, int maxEnrollmentsPerUser, @SensorProperties.Strength int strength, int maxEnrollmentsPerUser,
@NonNull List<ComponentInfoInternal> componentInfo, @NonNull List<ComponentInfoInternal> componentInfo,
@FingerprintSensorProperties.SensorType int sensorType, @FingerprintSensorProperties.SensorType int sensorType,
boolean halControlsIllumination,
boolean resetLockoutRequiresHardwareAuthToken, boolean resetLockoutRequiresHardwareAuthToken,
@NonNull List<SensorLocationInternal> sensorLocations) { @NonNull List<SensorLocationInternal> sensorLocations) {
// IBiometricsFingerprint@2.1 handles lockout in the framework, so the challenge is not // IBiometricsFingerprint@2.1 handles lockout in the framework, so the challenge is not
@@ -55,6 +57,7 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna
super(sensorId, strength, maxEnrollmentsPerUser, componentInfo, super(sensorId, strength, maxEnrollmentsPerUser, componentInfo,
resetLockoutRequiresHardwareAuthToken, false /* resetLockoutRequiresChallenge */); resetLockoutRequiresHardwareAuthToken, false /* resetLockoutRequiresChallenge */);
this.sensorType = sensorType; this.sensorType = sensorType;
this.halControlsIllumination = halControlsIllumination;
this.mSensorLocations = List.copyOf(sensorLocations); this.mSensorLocations = List.copyOf(sensorLocations);
} }
@@ -68,14 +71,15 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna
boolean resetLockoutRequiresHardwareAuthToken) { boolean resetLockoutRequiresHardwareAuthToken) {
// TODO(b/179175438): Value should be provided from the HAL // TODO(b/179175438): Value should be provided from the HAL
this(sensorId, strength, maxEnrollmentsPerUser, componentInfo, sensorType, this(sensorId, strength, maxEnrollmentsPerUser, componentInfo, sensorType,
resetLockoutRequiresHardwareAuthToken, List.of(new SensorLocationInternal( false /* halControlsIllumination */, resetLockoutRequiresHardwareAuthToken,
"" /* displayId */, 540 /* sensorLocationX */, 1636 /* sensorLocationY */, List.of(new SensorLocationInternal("" /* displayId */, 540 /* sensorLocationX */,
130 /* sensorRadius */))); 1636 /* sensorLocationY */, 130 /* sensorRadius */)));
} }
protected FingerprintSensorPropertiesInternal(Parcel in) { protected FingerprintSensorPropertiesInternal(Parcel in) {
super(in); super(in);
sensorType = in.readInt(); sensorType = in.readInt();
halControlsIllumination = in.readBoolean();
mSensorLocations = in.createTypedArrayList(SensorLocationInternal.CREATOR); mSensorLocations = in.createTypedArrayList(SensorLocationInternal.CREATOR);
} }
@@ -101,6 +105,7 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags); super.writeToParcel(dest, flags);
dest.writeInt(sensorType); dest.writeInt(sensorType);
dest.writeBoolean(halControlsIllumination);
dest.writeTypedList(mSensorLocations); dest.writeTypedList(mSensorLocations);
} }

View File

@@ -278,6 +278,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
} }
}); });
mUdfpsController.setAuthControllerUpdateUdfpsLocation(this::updateUdfpsLocation); mUdfpsController.setAuthControllerUpdateUdfpsLocation(this::updateUdfpsLocation);
mUdfpsController.setHalControlsIllumination(mUdfpsProps.get(0).halControlsIllumination);
mUdfpsBounds = mUdfpsProps.get(0).getLocation().getRect(); mUdfpsBounds = mUdfpsProps.get(0).getLocation().getRect();
updateUdfpsLocation(); updateUdfpsLocation();
} }

View File

@@ -131,6 +131,7 @@ public class UdfpsController implements DozeReceiver {
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple // Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
// sensors, this, in addition to a lot of the code here, will be updated. // sensors, this, in addition to a lot of the code here, will be updated.
@VisibleForTesting int mSensorId; @VisibleForTesting int mSensorId;
private boolean mHalControlsIllumination;
@VisibleForTesting @NonNull UdfpsOverlayParams mOverlayParams = new UdfpsOverlayParams(); @VisibleForTesting @NonNull UdfpsOverlayParams mOverlayParams = new UdfpsOverlayParams();
// TODO(b/229290039): UDFPS controller should manage its dimensions on its own. Remove this. // TODO(b/229290039): UDFPS controller should manage its dimensions on its own. Remove this.
@Nullable private Runnable mAuthControllerUpdateUdfpsLocation; @Nullable private Runnable mAuthControllerUpdateUdfpsLocation;
@@ -201,9 +202,10 @@ public class UdfpsController implements DozeReceiver {
mKeyguardUpdateMonitor, mDialogManager, mDumpManager, mKeyguardUpdateMonitor, mDialogManager, mDumpManager,
mLockscreenShadeTransitionController, mConfigurationController, mLockscreenShadeTransitionController, mConfigurationController,
mSystemClock, mKeyguardStateController, mSystemClock, mKeyguardStateController,
mUnlockedScreenOffAnimationController, mHbmProvider, requestId, reason, mUnlockedScreenOffAnimationController, mHalControlsIllumination,
callback, (view, event, fromUdfpsView) -> onTouch(requestId, event, mHbmProvider, requestId, reason, callback,
fromUdfpsView), mActivityLaunchAnimator))); (view, event, fromUdfpsView) -> onTouch(requestId, event,
fromUdfpsView), mActivityLaunchAnimator)));
} }
@Override @Override
@@ -310,6 +312,11 @@ public class UdfpsController implements DozeReceiver {
mAuthControllerUpdateUdfpsLocation = r; mAuthControllerUpdateUdfpsLocation = r;
} }
// TODO(b/229290039): UDFPS controller should manage its properties on its own. Remove this.
public void setHalControlsIllumination(boolean value) {
mHalControlsIllumination = value;
}
/** /**
* Calculate the pointer speed given a velocity tracker and the pointer id. * Calculate the pointer speed given a velocity tracker and the pointer id.
* This assumes that the velocity tracker has already been passed all relevant motion events. * This assumes that the velocity tracker has already been passed all relevant motion events.

View File

@@ -77,6 +77,7 @@ class UdfpsControllerOverlay(
private val systemClock: SystemClock, private val systemClock: SystemClock,
private val keyguardStateController: KeyguardStateController, private val keyguardStateController: KeyguardStateController,
private val unlockedScreenOffAnimationController: UnlockedScreenOffAnimationController, private val unlockedScreenOffAnimationController: UnlockedScreenOffAnimationController,
private val halControlsIllumination: Boolean,
private var hbmProvider: UdfpsHbmProvider, private var hbmProvider: UdfpsHbmProvider,
val requestId: Long, val requestId: Long,
@ShowReason val requestReason: Int, @ShowReason val requestReason: Int,
@@ -137,6 +138,7 @@ class UdfpsControllerOverlay(
R.layout.udfps_view, null, false R.layout.udfps_view, null, false
) as UdfpsView).apply { ) as UdfpsView).apply {
overlayParams = params overlayParams = params
halControlsIllumination = this@UdfpsControllerOverlay.halControlsIllumination
setHbmProvider(hbmProvider) setHbmProvider(hbmProvider)
val animation = inflateUdfpsAnimation(this, controller) val animation = inflateUdfpsAnimation(this, controller)
if (animation != null) { if (animation != null) {

View File

@@ -34,8 +34,11 @@ public interface UdfpsHbmProvider {
* invoked from the UI thread. * invoked from the UI thread.
* *
* @param onHbmEnabled A runnable that will be executed once HBM is enabled. * @param onHbmEnabled A runnable that will be executed once HBM is enabled.
*
* TODO(b/231335067): enableHbm with halControlsIllumination=true shouldn't make sense.
* This only makes sense now because vendor code may rely on the side effects of enableHbm.
*/ */
void enableHbm(@Nullable Runnable onHbmEnabled); void enableHbm(boolean halControlsIllumination, @Nullable Runnable onHbmEnabled);
/** /**
* UdfpsView will call this to disable HBM when illumination is no longer needed. * UdfpsView will call this to disable HBM when illumination is no longer needed.
@@ -46,8 +49,6 @@ public interface UdfpsHbmProvider {
* The call must be made from the UI thread. The callback, if provided, will also be invoked * The call must be made from the UI thread. The callback, if provided, will also be invoked
* from the UI thread. * from the UI thread.
* *
*
*
* @param onHbmDisabled A runnable that will be executed once HBM is disabled. * @param onHbmDisabled A runnable that will be executed once HBM is disabled.
*/ */
void disableHbm(@Nullable Runnable onHbmDisabled); void disableHbm(@Nullable Runnable onHbmDisabled);

View File

@@ -63,9 +63,12 @@ class UdfpsView(
/** View controller (can be different for enrollment, BiometricPrompt, Keyguard, etc.). */ /** View controller (can be different for enrollment, BiometricPrompt, Keyguard, etc.). */
var animationViewController: UdfpsAnimationViewController<*>? = null var animationViewController: UdfpsAnimationViewController<*>? = null
/** Parameters that affect the position and size of the overlay. Visible for testing. */ /** Parameters that affect the position and size of the overlay. */
var overlayParams = UdfpsOverlayParams() var overlayParams = UdfpsOverlayParams()
/** Whether the HAL is responsible for enabling and disabling of LHBM. */
var halControlsIllumination: Boolean = true
/** Debug message. */ /** Debug message. */
var debugMessage: String? = null var debugMessage: String? = null
set(value) { set(value) {
@@ -154,11 +157,17 @@ class UdfpsView(
} }
private fun doIlluminate(onIlluminatedRunnable: Runnable?) { private fun doIlluminate(onIlluminatedRunnable: Runnable?) {
hbmProvider?.enableHbm() { // TODO(b/231335067): enableHbm with halControlsIllumination=true shouldn't make sense.
// This only makes sense now because vendor code may rely on the side effects of enableHbm.
hbmProvider?.enableHbm(halControlsIllumination) {
if (onIlluminatedRunnable != null) { if (onIlluminatedRunnable != null) {
// No framework API can reliably tell when a frame reaches the panel. A timeout if (halControlsIllumination) {
// is the safest solution. onIlluminatedRunnable.run()
postDelayed(onIlluminatedRunnable, onIlluminatedDelayMs) } else {
// No framework API can reliably tell when a frame reaches the panel. A timeout
// is the safest solution.
postDelayed(onIlluminatedRunnable, onIlluminatedDelayMs)
}
} else { } else {
Log.w(TAG, "doIlluminate | onIlluminatedRunnable is null") Log.w(TAG, "doIlluminate | onIlluminatedRunnable is null")
} }

View File

@@ -29,6 +29,7 @@ fun SensorLocationInternal.asFingerprintSensorProperties(
@FingerprintSensorProperties.SensorType sensorType: Int = @FingerprintSensorProperties.SensorType sensorType: Int =
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
maxEnrollmentsPerUser: Int = 1, maxEnrollmentsPerUser: Int = 1,
halControlsIllumination: Boolean = true,
info: List<ComponentInfoInternal> = listOf(ComponentInfoInternal("a", "b", "c", "d", "e")), info: List<ComponentInfoInternal> = listOf(ComponentInfoInternal("a", "b", "c", "d", "e")),
resetLockoutRequiresHardwareAuthToken: Boolean = false resetLockoutRequiresHardwareAuthToken: Boolean = false
) = FingerprintSensorPropertiesInternal( ) = FingerprintSensorPropertiesInternal(
@@ -37,6 +38,7 @@ fun SensorLocationInternal.asFingerprintSensorProperties(
maxEnrollmentsPerUser, maxEnrollmentsPerUser,
info, info,
sensorType, sensorType,
halControlsIllumination,
resetLockoutRequiresHardwareAuthToken, resetLockoutRequiresHardwareAuthToken,
listOf(this) listOf(this)
) )

View File

@@ -185,6 +185,7 @@ class SidefpsControllerTest : SysuiTestCase() {
5 /* maxEnrollmentsPerUser */, 5 /* maxEnrollmentsPerUser */,
listOf() /* componentInfo */, listOf() /* componentInfo */,
FingerprintSensorProperties.TYPE_POWER_BUTTON, FingerprintSensorProperties.TYPE_POWER_BUTTON,
true /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */, true /* resetLockoutRequiresHardwareAuthToken */,
locations locations
) )

View File

@@ -65,6 +65,7 @@ import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever import org.mockito.Mockito.`when` as whenever
private const val HAL_CONTROLS_ILLUMINATION = true
private const val REQUEST_ID = 2L private const val REQUEST_ID = 2L
// Dimensions for the current display resolution. // Dimensions for the current display resolution.
@@ -129,8 +130,8 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
statusBarStateController, panelExpansionStateManager, statusBarKeyguardViewManager, statusBarStateController, panelExpansionStateManager, statusBarKeyguardViewManager,
keyguardUpdateMonitor, dialogManager, dumpManager, transitionController, keyguardUpdateMonitor, dialogManager, dumpManager, transitionController,
configurationController, systemClock, keyguardStateController, configurationController, systemClock, keyguardStateController,
unlockedScreenOffAnimationController, hbmProvider, REQUEST_ID, reason, unlockedScreenOffAnimationController, HAL_CONTROLS_ILLUMINATION, hbmProvider,
controllerCallback, onTouch, activityLaunchAnimator) REQUEST_ID, reason, controllerCallback, onTouch, activityLaunchAnimator)
block() block()
} }

View File

@@ -62,6 +62,7 @@ public class UdfpsDialogMeasureAdapterTest extends SysuiTestCase {
0 /* sensorId */, SensorProperties.STRENGTH_STRONG, 5 /* maxEnrollmentsPerUser */, 0 /* sensorId */, SensorProperties.STRENGTH_STRONG, 5 /* maxEnrollmentsPerUser */,
componentInfo, componentInfo,
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
true /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */, true /* resetLockoutRequiresHardwareAuthToken */,
List.of(new SensorLocationInternal("" /* displayId */, List.of(new SensorLocationInternal("" /* displayId */,
sensorLocationX, sensorLocationY, sensorRadius))); sensorLocationX, sensorLocationY, sensorRadius)));
@@ -127,6 +128,7 @@ public class UdfpsDialogMeasureAdapterTest extends SysuiTestCase {
0 /* sensorId */, SensorProperties.STRENGTH_STRONG, 5 /* maxEnrollmentsPerUser */, 0 /* sensorId */, SensorProperties.STRENGTH_STRONG, 5 /* maxEnrollmentsPerUser */,
componentInfo, componentInfo,
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
true /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */, true /* resetLockoutRequiresHardwareAuthToken */,
List.of(new SensorLocationInternal("" /* displayId */, List.of(new SensorLocationInternal("" /* displayId */,
sensorLocationX, sensorLocationY, sensorRadius))); sensorLocationX, sensorLocationY, sensorRadius)));

View File

@@ -36,6 +36,7 @@ import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.never import org.mockito.Mockito.never
import org.mockito.Mockito.nullable import org.mockito.Mockito.nullable
@@ -43,7 +44,6 @@ import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever import org.mockito.Mockito.`when` as whenever
private const val DISPLAY_ID = "" // default display id
private const val SENSOR_X = 50 private const val SENSOR_X = 50
private const val SENSOR_Y = 250 private const val SENSOR_Y = 250
private const val SENSOR_RADIUS = 10 private const val SENSOR_RADIUS = 10
@@ -146,7 +146,7 @@ class UdfpsViewTest : SysuiTestCase() {
view.startIllumination(onDone) view.startIllumination(onDone)
val illuminator = withArgCaptor<Runnable> { val illuminator = withArgCaptor<Runnable> {
verify(hbmProvider).enableHbm(capture()) verify(hbmProvider).enableHbm(anyBoolean(), capture())
} }
assertThat(view.isIlluminationRequested).isTrue() assertThat(view.isIlluminationRequested).isTrue()

View File

@@ -413,6 +413,7 @@ public class LockIconViewControllerTest extends SysuiTestCase {
/* max enrollments per user */ 5, /* max enrollments per user */ 5,
/* component info */ new ArrayList<>(), /* component info */ new ArrayList<>(),
/* sensorType */ 3, /* sensorType */ 3,
/* halControlsIllumination */ true,
/* resetLockoutRequiresHwToken */ false, /* resetLockoutRequiresHwToken */ false,
List.of(new SensorLocationInternal("" /* displayId */, List.of(new SensorLocationInternal("" /* displayId */,
(int) udfpsLocation.x, (int) udfpsLocation.y, radius))); (int) udfpsLocation.x, (int) udfpsLocation.y, radius)));

View File

@@ -805,9 +805,10 @@ public class AuthService extends SystemService {
if (isUdfps && udfpsProps.length == 3) { if (isUdfps && udfpsProps.length == 3) {
return new FingerprintSensorPropertiesInternal(sensorId, return new FingerprintSensorPropertiesInternal(sensorId,
Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser, Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser,
componentInfo, sensorType, resetLockoutRequiresHardwareAuthToken, componentInfo, sensorType, true /* halControlsIllumination */,
List.of(new SensorLocationInternal("" /* display */, resetLockoutRequiresHardwareAuthToken,
udfpsProps[0], udfpsProps[1], udfpsProps[2]))); List.of(new SensorLocationInternal("" /* display */, udfpsProps[0],
udfpsProps[1], udfpsProps[2])));
} else { } else {
return new FingerprintSensorPropertiesInternal(sensorId, return new FingerprintSensorPropertiesInternal(sensorId,
Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser, Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser,

View File

@@ -176,6 +176,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
prop.commonProps.maxEnrollmentsPerUser, prop.commonProps.maxEnrollmentsPerUser,
componentInfo, componentInfo,
prop.sensorType, prop.sensorType,
prop.halControlsIllumination,
true /* resetLockoutRequiresHardwareAuthToken */, true /* resetLockoutRequiresHardwareAuthToken */,
!workaroundLocations.isEmpty() ? workaroundLocations : !workaroundLocations.isEmpty() ? workaroundLocations :
Arrays.stream(prop.sensorLocations).map(location -> Arrays.stream(prop.sensorLocations).map(location ->

View File

@@ -400,7 +400,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
.getInteger(R.integer.config_fingerprintMaxTemplatesPerUser); .getInteger(R.integer.config_fingerprintMaxTemplatesPerUser);
mSensorProperties = new FingerprintSensorPropertiesInternal(sensorProps.sensorId, mSensorProperties = new FingerprintSensorPropertiesInternal(sensorProps.sensorId,
sensorProps.sensorStrength, maxTemplatesAllowed, sensorProps.componentInfo, sensorProps.sensorStrength, maxTemplatesAllowed, sensorProps.componentInfo,
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, false /* halControlsIllumination */,
resetLockoutRequiresHardwareAuthToken, sensorProps.getAllLocations()); resetLockoutRequiresHardwareAuthToken, sensorProps.getAllLocations());
mMockHalResultController = controller; mMockHalResultController = controller;
mUserHasTrust = new SparseBooleanArray(); mUserHasTrust = new SparseBooleanArray();