Merge "Added success lotties to BP for fp" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
62b30d3e23
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -92,7 +92,7 @@ open class AuthBiometricFingerprintIconController(
|
||||
STATE_ERROR -> true
|
||||
STATE_AUTHENTICATING_ANIMATING_IN,
|
||||
STATE_AUTHENTICATING -> oldState == STATE_ERROR || oldState == STATE_HELP
|
||||
STATE_AUTHENTICATED -> false
|
||||
STATE_AUTHENTICATED -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
@@ -114,7 +114,13 @@ open class AuthBiometricFingerprintIconController(
|
||||
R.raw.fingerprint_dialogue_fingerprint_to_error_lottie
|
||||
}
|
||||
}
|
||||
STATE_AUTHENTICATED -> R.raw.fingerprint_dialogue_fingerprint_to_error_lottie
|
||||
STATE_AUTHENTICATED -> {
|
||||
if (oldState == STATE_ERROR || oldState == STATE_HELP) {
|
||||
R.raw.fingerprint_dialogue_error_to_success_lottie
|
||||
} else {
|
||||
R.raw.fingerprint_dialogue_fingerprint_to_success_lottie
|
||||
}
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
return if (id != null) return id else null
|
||||
|
||||
@@ -75,7 +75,7 @@ open class AuthBiometricFingerprintView(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getDelayAfterAuthenticatedDurationMs() = 0
|
||||
override fun getDelayAfterAuthenticatedDurationMs() = 500
|
||||
|
||||
override fun getStateForAfterError() = STATE_AUTHENTICATING
|
||||
|
||||
|
||||
@@ -468,6 +468,7 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
break;
|
||||
|
||||
case STATE_AUTHENTICATED:
|
||||
removePendingAnimations();
|
||||
if (mSize != AuthDialog.SIZE_SMALL) {
|
||||
mConfirmButton.setVisibility(View.GONE);
|
||||
mNegativeButton.setVisibility(View.GONE);
|
||||
|
||||
@@ -41,11 +41,13 @@ import org.mockito.junit.MockitoJUnit
|
||||
@SmallTest
|
||||
class AuthBiometricFingerprintAndFaceViewTest : SysuiTestCase() {
|
||||
|
||||
@JvmField @Rule
|
||||
@JvmField
|
||||
@Rule
|
||||
var mockitoRule = MockitoJUnit.rule()
|
||||
|
||||
@Mock
|
||||
private lateinit var callback: AuthBiometricView.Callback
|
||||
|
||||
@Mock
|
||||
private lateinit var panelController: AuthPanelController
|
||||
|
||||
@@ -67,6 +69,7 @@ class AuthBiometricFingerprintAndFaceViewTest : SysuiTestCase() {
|
||||
fun fingerprintSuccessDoesNotRequireExplicitConfirmation() {
|
||||
biometricView.onDialogAnimatedIn()
|
||||
biometricView.onAuthenticationSucceeded(TYPE_FINGERPRINT)
|
||||
TestableLooper.get(this).moveTimeForward(1000)
|
||||
waitForIdleSync()
|
||||
|
||||
assertThat(biometricView.isAuthenticated).isTrue()
|
||||
@@ -86,6 +89,7 @@ class AuthBiometricFingerprintAndFaceViewTest : SysuiTestCase() {
|
||||
|
||||
// icon acts as confirm button
|
||||
biometricView.mIconView.performClick()
|
||||
TestableLooper.get(this).moveTimeForward(1000)
|
||||
waitForIdleSync()
|
||||
|
||||
assertThat(biometricView.isAuthenticated).isTrue()
|
||||
@@ -102,6 +106,7 @@ class AuthBiometricFingerprintAndFaceViewTest : SysuiTestCase() {
|
||||
verify(callback, never()).onAction(AuthBiometricView.Callback.ACTION_ERROR)
|
||||
|
||||
biometricView.onError(TYPE_FINGERPRINT, "that's a nope")
|
||||
TestableLooper.get(this).moveTimeForward(1000)
|
||||
waitForIdleSync()
|
||||
|
||||
verify(callback).onAction(AuthBiometricView.Callback.ACTION_ERROR)
|
||||
|
||||
@@ -42,20 +42,23 @@ import org.mockito.junit.MockitoJUnit
|
||||
@SmallTest
|
||||
class AuthBiometricFingerprintViewTest : SysuiTestCase() {
|
||||
|
||||
@JvmField @Rule
|
||||
@JvmField
|
||||
@Rule
|
||||
val mockitoRule = MockitoJUnit.rule()
|
||||
|
||||
@Mock
|
||||
private lateinit var callback: AuthBiometricView.Callback
|
||||
|
||||
@Mock
|
||||
private lateinit var panelController: AuthPanelController
|
||||
|
||||
private lateinit var biometricView: AuthBiometricView
|
||||
|
||||
private fun createView(allowDeviceCredential: Boolean = false): AuthBiometricFingerprintView {
|
||||
val view = R.layout.auth_biometric_fingerprint_view.asTestAuthBiometricView(
|
||||
val view: AuthBiometricFingerprintView =
|
||||
R.layout.auth_biometric_fingerprint_view.asTestAuthBiometricView(
|
||||
mContext, callback, panelController, allowDeviceCredential = allowDeviceCredential
|
||||
) as AuthBiometricFingerprintView
|
||||
)
|
||||
waitForIdleSync()
|
||||
return view
|
||||
}
|
||||
@@ -73,6 +76,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testOnAuthenticationSucceeded_noConfirmationRequired_sendsActionAuthenticated() {
|
||||
biometricView.onAuthenticationSucceeded(BiometricAuthenticator.TYPE_FINGERPRINT)
|
||||
TestableLooper.get(this).moveTimeForward(1000)
|
||||
waitForIdleSync()
|
||||
|
||||
assertThat(biometricView.isAuthenticated).isTrue()
|
||||
@@ -83,6 +87,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
|
||||
fun testOnAuthenticationSucceeded_confirmationRequired_updatesDialogContents() {
|
||||
biometricView.setRequireConfirmation(true)
|
||||
biometricView.onAuthenticationSucceeded(BiometricAuthenticator.TYPE_FINGERPRINT)
|
||||
TestableLooper.get(this).moveTimeForward(1000)
|
||||
waitForIdleSync()
|
||||
|
||||
// TODO: this should be tested in the subclasses
|
||||
@@ -104,6 +109,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testPositiveButton_sendsActionAuthenticated() {
|
||||
biometricView.mConfirmButton.performClick()
|
||||
TestableLooper.get(this).moveTimeForward(1000)
|
||||
waitForIdleSync()
|
||||
|
||||
verify(callback).onAction(AuthBiometricView.Callback.ACTION_AUTHENTICATED)
|
||||
@@ -114,6 +120,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
|
||||
fun testNegativeButton_beforeAuthentication_sendsActionButtonNegative() {
|
||||
biometricView.onDialogAnimatedIn()
|
||||
biometricView.mNegativeButton.performClick()
|
||||
TestableLooper.get(this).moveTimeForward(1000)
|
||||
waitForIdleSync()
|
||||
|
||||
verify(callback).onAction(AuthBiometricView.Callback.ACTION_BUTTON_NEGATIVE)
|
||||
@@ -126,6 +133,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
|
||||
|
||||
assertThat(biometricView.mNegativeButton.visibility).isEqualTo(View.GONE)
|
||||
biometricView.mCancelButton.performClick()
|
||||
TestableLooper.get(this).moveTimeForward(1000)
|
||||
waitForIdleSync()
|
||||
|
||||
verify(callback).onAction(AuthBiometricView.Callback.ACTION_USER_CANCELED)
|
||||
@@ -134,6 +142,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testTryAgainButton_sendsActionTryAgain() {
|
||||
biometricView.mTryAgainButton.performClick()
|
||||
TestableLooper.get(this).moveTimeForward(1000)
|
||||
waitForIdleSync()
|
||||
|
||||
verify(callback).onAction(AuthBiometricView.Callback.ACTION_BUTTON_TRY_AGAIN)
|
||||
@@ -144,6 +153,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testOnErrorSendsActionError() {
|
||||
biometricView.onError(BiometricAuthenticator.TYPE_FACE, "testError")
|
||||
TestableLooper.get(this).moveTimeForward(1000)
|
||||
waitForIdleSync()
|
||||
|
||||
verify(callback).onAction(eq(AuthBiometricView.Callback.ACTION_ERROR))
|
||||
@@ -156,6 +166,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
|
||||
|
||||
val message = "another error"
|
||||
biometricView.onError(BiometricAuthenticator.TYPE_FACE, message)
|
||||
TestableLooper.get(this).moveTimeForward(1000)
|
||||
waitForIdleSync()
|
||||
|
||||
assertThat(biometricView.isAuthenticating).isFalse()
|
||||
@@ -178,6 +189,7 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
|
||||
val view = View(mContext)
|
||||
biometricView.setBackgroundView(view)
|
||||
biometricView.onAuthenticationSucceeded(BiometricAuthenticator.TYPE_FINGERPRINT)
|
||||
waitForIdleSync()
|
||||
view.performClick()
|
||||
|
||||
verify(callback, never())
|
||||
@@ -225,14 +237,14 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
|
||||
biometricView.onSaveState(state)
|
||||
assertThat(biometricView.mTryAgainButton.visibility).isEqualTo(View.GONE)
|
||||
assertThat(state.getInt(AuthDialog.KEY_BIOMETRIC_TRY_AGAIN_VISIBILITY))
|
||||
.isEqualTo(View.GONE)
|
||||
.isEqualTo(View.GONE)
|
||||
assertThat(state.getInt(AuthDialog.KEY_BIOMETRIC_STATE))
|
||||
.isEqualTo(AuthBiometricView.STATE_ERROR)
|
||||
.isEqualTo(AuthBiometricView.STATE_ERROR)
|
||||
assertThat(biometricView.mIndicatorView.visibility).isEqualTo(View.VISIBLE)
|
||||
assertThat(state.getBoolean(AuthDialog.KEY_BIOMETRIC_INDICATOR_ERROR_SHOWING)).isTrue()
|
||||
assertThat(biometricView.mIndicatorView.text).isEqualTo(failureMessage)
|
||||
assertThat(state.getString(AuthDialog.KEY_BIOMETRIC_INDICATOR_STRING))
|
||||
.isEqualTo(failureMessage)
|
||||
.isEqualTo(failureMessage)
|
||||
|
||||
// TODO: Test dialog size. Should move requireConfirmation to buildBiometricPromptBundle
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -45,6 +46,9 @@ public class TestableLooper {
|
||||
* catch crashes.
|
||||
*/
|
||||
public static final boolean HOLD_MAIN_THREAD = false;
|
||||
private static final Field MESSAGE_QUEUE_MESSAGES_FIELD;
|
||||
private static final Field MESSAGE_NEXT_FIELD;
|
||||
private static final Field MESSAGE_WHEN_FIELD;
|
||||
|
||||
private Looper mLooper;
|
||||
private MessageQueue mQueue;
|
||||
@@ -54,6 +58,19 @@ public class TestableLooper {
|
||||
private Runnable mEmptyMessage;
|
||||
private TestLooperManager mQueueWrapper;
|
||||
|
||||
static {
|
||||
try {
|
||||
MESSAGE_QUEUE_MESSAGES_FIELD = MessageQueue.class.getDeclaredField("mMessages");
|
||||
MESSAGE_QUEUE_MESSAGES_FIELD.setAccessible(true);
|
||||
MESSAGE_NEXT_FIELD = Message.class.getDeclaredField("next");
|
||||
MESSAGE_NEXT_FIELD.setAccessible(true);
|
||||
MESSAGE_WHEN_FIELD = Message.class.getDeclaredField("when");
|
||||
MESSAGE_WHEN_FIELD.setAccessible(true);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new RuntimeException("Failed to initialize TestableLooper", e);
|
||||
}
|
||||
}
|
||||
|
||||
public TestableLooper(Looper l) throws Exception {
|
||||
this(acquireLooperManager(l), l);
|
||||
}
|
||||
@@ -119,6 +136,33 @@ public class TestableLooper {
|
||||
while (processQueuedMessages() != 0) ;
|
||||
}
|
||||
|
||||
public void moveTimeForward(long milliSeconds) {
|
||||
try {
|
||||
Message msg = getMessageLinkedList();
|
||||
while (msg != null) {
|
||||
long updatedWhen = msg.getWhen() - milliSeconds;
|
||||
if (updatedWhen < 0) {
|
||||
updatedWhen = 0;
|
||||
}
|
||||
MESSAGE_WHEN_FIELD.set(msg, updatedWhen);
|
||||
msg = (Message) MESSAGE_NEXT_FIELD.get(msg);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException("Access failed in TestableLooper: set - Message.when", e);
|
||||
}
|
||||
}
|
||||
|
||||
private Message getMessageLinkedList() {
|
||||
try {
|
||||
MessageQueue queue = mLooper.getQueue();
|
||||
return (Message) MESSAGE_QUEUE_MESSAGES_FIELD.get(queue);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(
|
||||
"Access failed in TestableLooper: get - MessageQueue.mMessages",
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
private int processQueuedMessages() {
|
||||
int count = 0;
|
||||
mEmptyMessage = () -> { };
|
||||
|
||||
@@ -19,15 +19,19 @@ import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@@ -162,7 +166,7 @@ public class TestableLooperTest {
|
||||
|
||||
@Test
|
||||
public void testCorrectLooperExecution() throws Exception {
|
||||
boolean[] hasRun = new boolean[] { false };
|
||||
boolean[] hasRun = new boolean[]{false};
|
||||
Runnable r = () -> {
|
||||
assertEquals("Should run on main looper", Looper.getMainLooper(), Looper.myLooper());
|
||||
hasRun[0] = true;
|
||||
@@ -177,4 +181,63 @@ public class TestableLooperTest {
|
||||
testableLooper.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelayedDispatchNoTimeMove() {
|
||||
Handler handler = spy(new Handler(mTestableLooper.getLooper()));
|
||||
InOrder inOrder = inOrder(handler);
|
||||
|
||||
final Message messageA = handler.obtainMessage(1);
|
||||
final Message messageB = handler.obtainMessage(2);
|
||||
|
||||
handler.sendMessageDelayed(messageA, 0);
|
||||
handler.sendMessageDelayed(messageB, 0);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
inOrder.verify(handler).dispatchMessage(messageA);
|
||||
inOrder.verify(handler).dispatchMessage(messageB);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelayedMessageDoesntSend() {
|
||||
Handler handler = spy(new Handler(mTestableLooper.getLooper()));
|
||||
InOrder inOrder = inOrder(handler);
|
||||
|
||||
final Message messageA = handler.obtainMessage(1);
|
||||
final Message messageB = handler.obtainMessage(2);
|
||||
final Message messageC = handler.obtainMessage(3);
|
||||
|
||||
handler.sendMessageDelayed(messageA, 0);
|
||||
handler.sendMessageDelayed(messageB, 0);
|
||||
handler.sendMessageDelayed(messageC, 500);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
inOrder.verify(handler).dispatchMessage(messageA);
|
||||
inOrder.verify(handler).dispatchMessage(messageB);
|
||||
verify(handler, never()).dispatchMessage(messageC);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageSendsAfterDelay() {
|
||||
Handler handler = spy(new Handler(mTestableLooper.getLooper()));
|
||||
InOrder inOrder = inOrder(handler);
|
||||
|
||||
final Message messageA = handler.obtainMessage(1);
|
||||
final Message messageB = handler.obtainMessage(2);
|
||||
final Message messageC = handler.obtainMessage(3);
|
||||
|
||||
handler.sendMessageDelayed(messageA, 0);
|
||||
handler.sendMessageDelayed(messageB, 0);
|
||||
handler.sendMessageDelayed(messageC, 500);
|
||||
|
||||
mTestableLooper.moveTimeForward(500);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
inOrder.verify(handler).dispatchMessage(messageA);
|
||||
inOrder.verify(handler).dispatchMessage(messageB);
|
||||
inOrder.verify(handler).dispatchMessage(messageC);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user