Merge "Update lock icon location if auth setup is delayed" into sc-qpr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
001ec6038a
@@ -27,6 +27,7 @@ import android.widget.FrameLayout;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
import com.android.settingslib.Utils;
|
import com.android.settingslib.Utils;
|
||||||
import com.android.systemui.Dumpable;
|
import com.android.systemui.Dumpable;
|
||||||
@@ -79,7 +80,11 @@ public class LockIconView extends FrameLayout implements Dumpable {
|
|||||||
mLockIcon.setImageDrawable(drawable);
|
mLockIcon.setImageDrawable(drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCenterLocation(@NonNull PointF center, int radius) {
|
/**
|
||||||
|
* Set the location of the lock icon.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public void setCenterLocation(@NonNull PointF center, int radius) {
|
||||||
mLockIconCenter = center;
|
mLockIconCenter = center;
|
||||||
mRadius = radius;
|
mRadius = radius;
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ import javax.inject.Inject;
|
|||||||
/**
|
/**
|
||||||
* Controls when to show the LockIcon affordance (lock/unlocked icon or circle) on lock screen.
|
* Controls when to show the LockIcon affordance (lock/unlocked icon or circle) on lock screen.
|
||||||
*
|
*
|
||||||
* This view will only be shown if the user has UDFPS or FaceAuth enrolled
|
* For devices with UDFPS, the lock icon will show at the sensor location. Else, the lock
|
||||||
|
* icon will show a set distance from the bottom of the device.
|
||||||
*/
|
*/
|
||||||
@StatusBarComponent.StatusBarScope
|
@StatusBarComponent.StatusBarScope
|
||||||
public class LockIconViewController extends ViewController<LockIconView> implements Dumpable {
|
public class LockIconViewController extends ViewController<LockIconView> implements Dumpable {
|
||||||
@@ -172,15 +173,14 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onInit() {
|
protected void onInit() {
|
||||||
|
mAuthController.addCallback(mAuthControllerCallback);
|
||||||
|
mUdfpsSupported = mAuthController.getUdfpsSensorLocation() != null;
|
||||||
|
|
||||||
mView.setAccessibilityDelegate(mAccessibilityDelegate);
|
mView.setAccessibilityDelegate(mAccessibilityDelegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onViewAttached() {
|
protected void onViewAttached() {
|
||||||
// we check this here instead of onInit since the FingerprintManager + FaceManager may not
|
|
||||||
// have started up yet onInit
|
|
||||||
mUdfpsSupported = mAuthController.getUdfpsSensorLocation() != null;
|
|
||||||
|
|
||||||
updateConfiguration();
|
updateConfiguration();
|
||||||
updateKeyguardShowing();
|
updateKeyguardShowing();
|
||||||
mUserUnlockedWithBiometric = false;
|
mUserUnlockedWithBiometric = false;
|
||||||
@@ -584,4 +584,12 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
|
|||||||
public void setAlpha(float alpha) {
|
public void setAlpha(float alpha) {
|
||||||
mView.setAlpha(alpha);
|
mView.setAlpha(alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onAllAuthenticatorsRegistered() {
|
||||||
|
mUdfpsSupported = mAuthController.getUdfpsSensorLocation() != null;
|
||||||
|
updateConfiguration();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -786,7 +786,11 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
|||||||
.build(sensorIds, credentialAllowed, mFpProps, mFaceProps);
|
.build(sensorIds, credentialAllowed, mFpProps, mFaceProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Callback {
|
/**
|
||||||
|
* AuthController callback used to receive signal for when biometric authenticators are
|
||||||
|
* registered.
|
||||||
|
*/
|
||||||
|
public interface Callback {
|
||||||
/**
|
/**
|
||||||
* Called when authenticators are registered. If authenticators are already
|
* Called when authenticators are registered. If authenticators are already
|
||||||
* registered before this call, this callback will never be triggered.
|
* registered before this call, this callback will never be triggered.
|
||||||
|
|||||||
@@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* 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.keyguard;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.eq;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.PointF;
|
||||||
|
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||||
|
import android.os.Vibrator;
|
||||||
|
import android.testing.AndroidTestingRunner;
|
||||||
|
import android.testing.TestableLooper;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.accessibility.AccessibilityManager;
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||||
|
import com.android.keyguard.KeyguardViewController;
|
||||||
|
import com.android.keyguard.LockIconView;
|
||||||
|
import com.android.keyguard.LockIconViewController;
|
||||||
|
import com.android.systemui.SysuiTestCase;
|
||||||
|
import com.android.systemui.biometrics.AuthController;
|
||||||
|
import com.android.systemui.biometrics.AuthRippleController;
|
||||||
|
import com.android.systemui.dump.DumpManager;
|
||||||
|
import com.android.systemui.plugins.FalsingManager;
|
||||||
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
|
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||||
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
|
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Captor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidTestingRunner.class)
|
||||||
|
@TestableLooper.RunWithLooper
|
||||||
|
public class LockIconViewControllerTest extends SysuiTestCase {
|
||||||
|
private @Mock LockIconView mLockIconView;
|
||||||
|
private @Mock Context mContext;
|
||||||
|
private @Mock Resources mResources;
|
||||||
|
private @Mock DisplayMetrics mDisplayMetrics;
|
||||||
|
private @Mock StatusBarStateController mStatusBarStateController;
|
||||||
|
private @Mock KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||||
|
private @Mock KeyguardViewController mKeyguardViewController;
|
||||||
|
private @Mock KeyguardStateController mKeyguardStateController;
|
||||||
|
private @Mock FalsingManager mFalsingManager;
|
||||||
|
private @Mock AuthController mAuthController;
|
||||||
|
private @Mock DumpManager mDumpManager;
|
||||||
|
private @Mock AccessibilityManager mAccessibilityManager;
|
||||||
|
private @Mock ConfigurationController mConfigurationController;
|
||||||
|
private @Mock DelayableExecutor mDelayableExecutor;
|
||||||
|
private @Mock Vibrator mVibrator;
|
||||||
|
private @Mock AuthRippleController mAuthRippleController;
|
||||||
|
|
||||||
|
private LockIconViewController mLockIconViewController;
|
||||||
|
|
||||||
|
// Capture listeners so that they can be used to send events
|
||||||
|
@Captor private ArgumentCaptor<View.OnAttachStateChangeListener> mAttachCaptor =
|
||||||
|
ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
|
||||||
|
private View.OnAttachStateChangeListener mAttachListener;
|
||||||
|
|
||||||
|
@Captor private ArgumentCaptor<AuthController.Callback> mAuthControllerCallbackCaptor;
|
||||||
|
private AuthController.Callback mAuthControllerCallback;
|
||||||
|
|
||||||
|
@Captor private ArgumentCaptor<PointF> mPointCaptor;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
|
when(mLockIconView.getResources()).thenReturn(mResources);
|
||||||
|
when(mLockIconView.getContext()).thenReturn(mContext);
|
||||||
|
when(mContext.getResources()).thenReturn(mResources);
|
||||||
|
when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
|
||||||
|
|
||||||
|
mLockIconViewController = new LockIconViewController(
|
||||||
|
mLockIconView,
|
||||||
|
mStatusBarStateController,
|
||||||
|
mKeyguardUpdateMonitor,
|
||||||
|
mKeyguardViewController,
|
||||||
|
mKeyguardStateController,
|
||||||
|
mFalsingManager,
|
||||||
|
mAuthController,
|
||||||
|
mDumpManager,
|
||||||
|
mAccessibilityManager,
|
||||||
|
mConfigurationController,
|
||||||
|
mDelayableExecutor,
|
||||||
|
mVibrator,
|
||||||
|
mAuthRippleController
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateFingerprintLocationOnInit() {
|
||||||
|
// GIVEN fp sensor location is available pre-init
|
||||||
|
final PointF udfpsLocation = new PointF(50, 75);
|
||||||
|
final int radius = 33;
|
||||||
|
final FingerprintSensorPropertiesInternal fpProps =
|
||||||
|
new FingerprintSensorPropertiesInternal(
|
||||||
|
/* sensorId */ 0,
|
||||||
|
/* strength */ 0,
|
||||||
|
/* max enrollments per user */ 5,
|
||||||
|
/* component info */ new ArrayList<>(),
|
||||||
|
/* sensorType */ 3,
|
||||||
|
/* resetLockoutRequiresHwToken */ false,
|
||||||
|
(int) udfpsLocation.x, (int) udfpsLocation.y, radius);
|
||||||
|
when(mAuthController.getUdfpsSensorLocation()).thenReturn(udfpsLocation);
|
||||||
|
when(mAuthController.getUdfpsProps()).thenReturn(List.of(fpProps));
|
||||||
|
|
||||||
|
// WHEN lock icon view controller is initialized and attached
|
||||||
|
mLockIconViewController.init();
|
||||||
|
captureAttachListener();
|
||||||
|
mAttachListener.onViewAttachedToWindow(null);
|
||||||
|
|
||||||
|
// THEN lock icon view location is updated with the same coordinates as fpProps
|
||||||
|
verify(mLockIconView).setCenterLocation(mPointCaptor.capture(), eq(radius));
|
||||||
|
assertEquals(udfpsLocation, mPointCaptor.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateFingerprintLocationOnAuthenticatorsRegistered() {
|
||||||
|
// GIVEN fp sensor location is not available pre-init
|
||||||
|
when(mAuthController.getFingerprintSensorLocation()).thenReturn(null);
|
||||||
|
when(mAuthController.getUdfpsProps()).thenReturn(null);
|
||||||
|
mLockIconViewController.init();
|
||||||
|
|
||||||
|
// GIVEN fp sensor location is available post-init
|
||||||
|
captureAuthControllerCallback();
|
||||||
|
final PointF udfpsLocation = new PointF(50, 75);
|
||||||
|
final int radius = 33;
|
||||||
|
final FingerprintSensorPropertiesInternal fpProps =
|
||||||
|
new FingerprintSensorPropertiesInternal(
|
||||||
|
/* sensorId */ 0,
|
||||||
|
/* strength */ 0,
|
||||||
|
/* max enrollments per user */ 5,
|
||||||
|
/* component info */ new ArrayList<>(),
|
||||||
|
/* sensorType */ 3,
|
||||||
|
/* resetLockoutRequiresHwToken */ false,
|
||||||
|
(int) udfpsLocation.x, (int) udfpsLocation.y, radius);
|
||||||
|
when(mAuthController.getUdfpsSensorLocation()).thenReturn(udfpsLocation);
|
||||||
|
when(mAuthController.getUdfpsProps()).thenReturn(List.of(fpProps));
|
||||||
|
|
||||||
|
// WHEN all authenticators are registered
|
||||||
|
mAuthControllerCallback.onAllAuthenticatorsRegistered();
|
||||||
|
|
||||||
|
// THEN lock icon view location is updated with the same coordinates as fpProps
|
||||||
|
verify(mLockIconView).setCenterLocation(mPointCaptor.capture(), eq(radius));
|
||||||
|
assertEquals(udfpsLocation, mPointCaptor.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void captureAuthControllerCallback() {
|
||||||
|
verify(mAuthController).addCallback(mAuthControllerCallbackCaptor.capture());
|
||||||
|
mAuthControllerCallback = mAuthControllerCallbackCaptor.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void captureAttachListener() {
|
||||||
|
verify(mLockIconView).addOnAttachStateChangeListener(mAttachCaptor.capture());
|
||||||
|
mAttachListener = mAttachCaptor.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user