Merge "Add unit tests for LockSettingsStrongAuth" into rvc-dev am: 01f08dcef1
Change-Id: Iaeeeb321be73d16d4cf9854e98efd4330bad8ea7
This commit is contained in:
@@ -26,6 +26,7 @@ import android.app.admin.DevicePolicyManager;
|
|||||||
import android.app.trust.IStrongAuthTracker;
|
import android.app.trust.IStrongAuthTracker;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.RemoteCallbackList;
|
import android.os.RemoteCallbackList;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
@@ -36,6 +37,7 @@ import android.util.Slog;
|
|||||||
import android.util.SparseBooleanArray;
|
import android.util.SparseBooleanArray;
|
||||||
import android.util.SparseIntArray;
|
import android.util.SparseIntArray;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.util.IndentingPrintWriter;
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
|
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
|
||||||
|
|
||||||
@@ -57,11 +59,14 @@ public class LockSettingsStrongAuth {
|
|||||||
private static final int MSG_STRONG_BIOMETRIC_UNLOCK = 8;
|
private static final int MSG_STRONG_BIOMETRIC_UNLOCK = 8;
|
||||||
private static final int MSG_SCHEDULE_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT = 9;
|
private static final int MSG_SCHEDULE_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT = 9;
|
||||||
|
|
||||||
private static final String STRONG_AUTH_TIMEOUT_ALARM_TAG =
|
@VisibleForTesting
|
||||||
|
protected static final String STRONG_AUTH_TIMEOUT_ALARM_TAG =
|
||||||
"LockSettingsStrongAuth.timeoutForUser";
|
"LockSettingsStrongAuth.timeoutForUser";
|
||||||
private static final String NON_STRONG_BIOMETRIC_TIMEOUT_ALARM_TAG =
|
@VisibleForTesting
|
||||||
|
protected static final String NON_STRONG_BIOMETRIC_TIMEOUT_ALARM_TAG =
|
||||||
"LockSettingsPrimaryAuth.nonStrongBiometricTimeoutForUser";
|
"LockSettingsPrimaryAuth.nonStrongBiometricTimeoutForUser";
|
||||||
private static final String NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_ALARM_TAG =
|
@VisibleForTesting
|
||||||
|
protected static final String NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_ALARM_TAG =
|
||||||
"LockSettingsPrimaryAuth.nonStrongBiometricIdleTimeoutForUser";
|
"LockSettingsPrimaryAuth.nonStrongBiometricIdleTimeoutForUser";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,28 +78,71 @@ public class LockSettingsStrongAuth {
|
|||||||
4 * 60 * 60 * 1000; // 4h
|
4 * 60 * 60 * 1000; // 4h
|
||||||
|
|
||||||
private final RemoteCallbackList<IStrongAuthTracker> mTrackers = new RemoteCallbackList<>();
|
private final RemoteCallbackList<IStrongAuthTracker> mTrackers = new RemoteCallbackList<>();
|
||||||
private final SparseIntArray mStrongAuthForUser = new SparseIntArray();
|
@VisibleForTesting
|
||||||
private final SparseBooleanArray mIsNonStrongBiometricAllowedForUser = new SparseBooleanArray();
|
protected final SparseIntArray mStrongAuthForUser = new SparseIntArray();
|
||||||
private final ArrayMap<Integer, StrongAuthTimeoutAlarmListener>
|
@VisibleForTesting
|
||||||
|
protected final SparseBooleanArray mIsNonStrongBiometricAllowedForUser =
|
||||||
|
new SparseBooleanArray();
|
||||||
|
@VisibleForTesting
|
||||||
|
protected final ArrayMap<Integer, StrongAuthTimeoutAlarmListener>
|
||||||
mStrongAuthTimeoutAlarmListenerForUser = new ArrayMap<>();
|
mStrongAuthTimeoutAlarmListenerForUser = new ArrayMap<>();
|
||||||
// Track non-strong biometric timeout
|
// Track non-strong biometric timeout
|
||||||
private final ArrayMap<Integer, NonStrongBiometricTimeoutAlarmListener>
|
@VisibleForTesting
|
||||||
|
protected final ArrayMap<Integer, NonStrongBiometricTimeoutAlarmListener>
|
||||||
mNonStrongBiometricTimeoutAlarmListener = new ArrayMap<>();
|
mNonStrongBiometricTimeoutAlarmListener = new ArrayMap<>();
|
||||||
// Track non-strong biometric idle timeout
|
// Track non-strong biometric idle timeout
|
||||||
private final ArrayMap<Integer, NonStrongBiometricIdleTimeoutAlarmListener>
|
@VisibleForTesting
|
||||||
|
protected final ArrayMap<Integer, NonStrongBiometricIdleTimeoutAlarmListener>
|
||||||
mNonStrongBiometricIdleTimeoutAlarmListener = new ArrayMap<>();
|
mNonStrongBiometricIdleTimeoutAlarmListener = new ArrayMap<>();
|
||||||
|
|
||||||
private final int mDefaultStrongAuthFlags;
|
private final int mDefaultStrongAuthFlags;
|
||||||
private final boolean mDefaultIsNonStrongBiometricAllowed = true;
|
private final boolean mDefaultIsNonStrongBiometricAllowed = true;
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
private final Injector mInjector;
|
||||||
private AlarmManager mAlarmManager;
|
private final AlarmManager mAlarmManager;
|
||||||
|
|
||||||
public LockSettingsStrongAuth(Context context) {
|
public LockSettingsStrongAuth(Context context) {
|
||||||
|
this(context, new Injector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
protected LockSettingsStrongAuth(Context context, Injector injector) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mDefaultStrongAuthFlags = StrongAuthTracker.getDefaultFlags(context);
|
mInjector = injector;
|
||||||
mAlarmManager = context.getSystemService(AlarmManager.class);
|
mDefaultStrongAuthFlags = mInjector.getDefaultStrongAuthFlags(context);
|
||||||
|
mAlarmManager = mInjector.getAlarmManager(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for injecting dependencies into LockSettingsStrongAuth.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public static class Injector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to mock AlarmManager for testing.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public AlarmManager getAlarmManager(Context context) {
|
||||||
|
return context.getSystemService(AlarmManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to get different default StrongAuthFlags for testing.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public int getDefaultStrongAuthFlags(Context context) {
|
||||||
|
return StrongAuthTracker.getDefaultFlags(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to get different triggerAtMillis values when setting alarms for testing.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public long getNextAlarmTimeMs(long timeout) {
|
||||||
|
return SystemClock.elapsedRealtime() + timeout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleAddStrongAuthTracker(IStrongAuthTracker tracker) {
|
private void handleAddStrongAuthTracker(IStrongAuthTracker tracker) {
|
||||||
@@ -186,7 +234,8 @@ public class LockSettingsStrongAuth {
|
|||||||
private void handleScheduleStrongAuthTimeout(int userId) {
|
private void handleScheduleStrongAuthTimeout(int userId) {
|
||||||
final DevicePolicyManager dpm =
|
final DevicePolicyManager dpm =
|
||||||
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
|
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||||
long when = SystemClock.elapsedRealtime() + dpm.getRequiredStrongAuthTimeout(null, userId);
|
long nextAlarmTime =
|
||||||
|
mInjector.getNextAlarmTimeMs(dpm.getRequiredStrongAuthTimeout(null, userId));
|
||||||
// cancel current alarm listener for the user (if there was one)
|
// cancel current alarm listener for the user (if there was one)
|
||||||
StrongAuthTimeoutAlarmListener alarm = mStrongAuthTimeoutAlarmListenerForUser.get(userId);
|
StrongAuthTimeoutAlarmListener alarm = mStrongAuthTimeoutAlarmListenerForUser.get(userId);
|
||||||
if (alarm != null) {
|
if (alarm != null) {
|
||||||
@@ -196,8 +245,8 @@ public class LockSettingsStrongAuth {
|
|||||||
mStrongAuthTimeoutAlarmListenerForUser.put(userId, alarm);
|
mStrongAuthTimeoutAlarmListenerForUser.put(userId, alarm);
|
||||||
}
|
}
|
||||||
// schedule a new alarm listener for the user
|
// schedule a new alarm listener for the user
|
||||||
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when, STRONG_AUTH_TIMEOUT_ALARM_TAG,
|
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextAlarmTime,
|
||||||
alarm, mHandler);
|
STRONG_AUTH_TIMEOUT_ALARM_TAG, alarm, mHandler);
|
||||||
|
|
||||||
// cancel current non-strong biometric alarm listener for the user (if there was one)
|
// cancel current non-strong biometric alarm listener for the user (if there was one)
|
||||||
cancelNonStrongBiometricAlarmListener(userId);
|
cancelNonStrongBiometricAlarmListener(userId);
|
||||||
@@ -209,7 +258,7 @@ public class LockSettingsStrongAuth {
|
|||||||
|
|
||||||
private void handleScheduleNonStrongBiometricTimeout(int userId) {
|
private void handleScheduleNonStrongBiometricTimeout(int userId) {
|
||||||
if (DEBUG) Slog.d(TAG, "handleScheduleNonStrongBiometricTimeout for userId=" + userId);
|
if (DEBUG) Slog.d(TAG, "handleScheduleNonStrongBiometricTimeout for userId=" + userId);
|
||||||
long when = SystemClock.elapsedRealtime() + DEFAULT_NON_STRONG_BIOMETRIC_TIMEOUT_MS;
|
long nextAlarmTime = mInjector.getNextAlarmTimeMs(DEFAULT_NON_STRONG_BIOMETRIC_TIMEOUT_MS);
|
||||||
NonStrongBiometricTimeoutAlarmListener alarm = mNonStrongBiometricTimeoutAlarmListener
|
NonStrongBiometricTimeoutAlarmListener alarm = mNonStrongBiometricTimeoutAlarmListener
|
||||||
.get(userId);
|
.get(userId);
|
||||||
if (alarm != null) {
|
if (alarm != null) {
|
||||||
@@ -226,7 +275,7 @@ public class LockSettingsStrongAuth {
|
|||||||
alarm = new NonStrongBiometricTimeoutAlarmListener(userId);
|
alarm = new NonStrongBiometricTimeoutAlarmListener(userId);
|
||||||
mNonStrongBiometricTimeoutAlarmListener.put(userId, alarm);
|
mNonStrongBiometricTimeoutAlarmListener.put(userId, alarm);
|
||||||
// schedule a new alarm listener for the user
|
// schedule a new alarm listener for the user
|
||||||
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when,
|
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextAlarmTime,
|
||||||
NON_STRONG_BIOMETRIC_TIMEOUT_ALARM_TAG, alarm, mHandler);
|
NON_STRONG_BIOMETRIC_TIMEOUT_ALARM_TAG, alarm, mHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +317,8 @@ public class LockSettingsStrongAuth {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setIsNonStrongBiometricAllowed(boolean allowed, int userId) {
|
@VisibleForTesting
|
||||||
|
protected void setIsNonStrongBiometricAllowed(boolean allowed, int userId) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "setIsNonStrongBiometricAllowed for allowed=" + allowed
|
Slog.d(TAG, "setIsNonStrongBiometricAllowed for allowed=" + allowed
|
||||||
+ ", userId=" + userId);
|
+ ", userId=" + userId);
|
||||||
@@ -302,7 +352,8 @@ public class LockSettingsStrongAuth {
|
|||||||
|
|
||||||
private void handleScheduleNonStrongBiometricIdleTimeout(int userId) {
|
private void handleScheduleNonStrongBiometricIdleTimeout(int userId) {
|
||||||
if (DEBUG) Slog.d(TAG, "handleScheduleNonStrongBiometricIdleTimeout for userId=" + userId);
|
if (DEBUG) Slog.d(TAG, "handleScheduleNonStrongBiometricIdleTimeout for userId=" + userId);
|
||||||
long when = SystemClock.elapsedRealtime() + DEFAULT_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_MS;
|
long nextAlarmTime =
|
||||||
|
mInjector.getNextAlarmTimeMs(DEFAULT_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_MS);
|
||||||
// cancel current alarm listener for the user (if there was one)
|
// cancel current alarm listener for the user (if there was one)
|
||||||
NonStrongBiometricIdleTimeoutAlarmListener alarm =
|
NonStrongBiometricIdleTimeoutAlarmListener alarm =
|
||||||
mNonStrongBiometricIdleTimeoutAlarmListener.get(userId);
|
mNonStrongBiometricIdleTimeoutAlarmListener.get(userId);
|
||||||
@@ -315,7 +366,7 @@ public class LockSettingsStrongAuth {
|
|||||||
}
|
}
|
||||||
// schedule a new alarm listener for the user
|
// schedule a new alarm listener for the user
|
||||||
if (DEBUG) Slog.d(TAG, "Schedule a new alarm for non-strong biometric idle timeout");
|
if (DEBUG) Slog.d(TAG, "Schedule a new alarm for non-strong biometric idle timeout");
|
||||||
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when,
|
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextAlarmTime,
|
||||||
NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_ALARM_TAG, alarm, mHandler);
|
NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_ALARM_TAG, alarm, mHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,7 +486,8 @@ public class LockSettingsStrongAuth {
|
|||||||
/**
|
/**
|
||||||
* Alarm of fallback timeout for primary auth
|
* Alarm of fallback timeout for primary auth
|
||||||
*/
|
*/
|
||||||
private class StrongAuthTimeoutAlarmListener implements OnAlarmListener {
|
@VisibleForTesting
|
||||||
|
protected class StrongAuthTimeoutAlarmListener implements OnAlarmListener {
|
||||||
|
|
||||||
private final int mUserId;
|
private final int mUserId;
|
||||||
|
|
||||||
@@ -452,7 +504,8 @@ public class LockSettingsStrongAuth {
|
|||||||
/**
|
/**
|
||||||
* Alarm of fallback timeout for non-strong biometric (i.e. weak or convenience)
|
* Alarm of fallback timeout for non-strong biometric (i.e. weak or convenience)
|
||||||
*/
|
*/
|
||||||
private class NonStrongBiometricTimeoutAlarmListener implements OnAlarmListener {
|
@VisibleForTesting
|
||||||
|
protected class NonStrongBiometricTimeoutAlarmListener implements OnAlarmListener {
|
||||||
|
|
||||||
private final int mUserId;
|
private final int mUserId;
|
||||||
|
|
||||||
@@ -469,7 +522,8 @@ public class LockSettingsStrongAuth {
|
|||||||
/**
|
/**
|
||||||
* Alarm of idle timeout for non-strong biometric (i.e. weak or convenience biometric)
|
* Alarm of idle timeout for non-strong biometric (i.e. weak or convenience biometric)
|
||||||
*/
|
*/
|
||||||
private class NonStrongBiometricIdleTimeoutAlarmListener implements OnAlarmListener {
|
@VisibleForTesting
|
||||||
|
protected class NonStrongBiometricIdleTimeoutAlarmListener implements OnAlarmListener {
|
||||||
|
|
||||||
private final int mUserId;
|
private final int mUserId;
|
||||||
|
|
||||||
@@ -484,7 +538,8 @@ public class LockSettingsStrongAuth {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Handler mHandler = new Handler() {
|
@VisibleForTesting
|
||||||
|
protected final Handler mHandler = new Handler(Looper.getMainLooper()) {
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
|
|||||||
@@ -0,0 +1,252 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.server.locksettings;
|
||||||
|
|
||||||
|
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
|
||||||
|
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
|
||||||
|
import static com.android.server.locksettings.LockSettingsStrongAuth.DEFAULT_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_MS;
|
||||||
|
import static com.android.server.locksettings.LockSettingsStrongAuth.DEFAULT_NON_STRONG_BIOMETRIC_TIMEOUT_MS;
|
||||||
|
import static com.android.server.locksettings.LockSettingsStrongAuth.NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_ALARM_TAG;
|
||||||
|
import static com.android.server.locksettings.LockSettingsStrongAuth.NON_STRONG_BIOMETRIC_TIMEOUT_ALARM_TAG;
|
||||||
|
import static com.android.server.locksettings.LockSettingsStrongAuth.STRONG_AUTH_TIMEOUT_ALARM_TAG;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertFalse;
|
||||||
|
import static junit.framework.Assert.assertNotNull;
|
||||||
|
import static junit.framework.Assert.assertNull;
|
||||||
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.app.AlarmManager;
|
||||||
|
import android.app.admin.DevicePolicyManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.test.InstrumentationRegistry;
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import com.android.server.locksettings.LockSettingsStrongAuth.NonStrongBiometricIdleTimeoutAlarmListener;
|
||||||
|
import com.android.server.locksettings.LockSettingsStrongAuth.NonStrongBiometricTimeoutAlarmListener;
|
||||||
|
import com.android.server.locksettings.LockSettingsStrongAuth.StrongAuthTimeoutAlarmListener;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
public class LockSettingsStrongAuthTest {
|
||||||
|
|
||||||
|
private static final String TAG = LockSettingsStrongAuthTest.class.getSimpleName();
|
||||||
|
|
||||||
|
private static final int PRIMARY_USER_ID = 0;
|
||||||
|
|
||||||
|
private LockSettingsStrongAuth mStrongAuth;
|
||||||
|
private final int mDefaultStrongAuthFlags = STRONG_AUTH_NOT_REQUIRED;
|
||||||
|
private final boolean mDefaultIsNonStrongBiometricAllowed = true;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Context mContext;
|
||||||
|
@Mock
|
||||||
|
private LockSettingsStrongAuth.Injector mInjector;
|
||||||
|
@Mock
|
||||||
|
private AlarmManager mAlarmManager;
|
||||||
|
@Mock
|
||||||
|
private DevicePolicyManager mDPM;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
|
when(mInjector.getAlarmManager(mContext)).thenReturn(mAlarmManager);
|
||||||
|
when(mInjector.getDefaultStrongAuthFlags(mContext)).thenReturn(mDefaultStrongAuthFlags);
|
||||||
|
when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(mDPM);
|
||||||
|
|
||||||
|
mStrongAuth = new LockSettingsStrongAuth(mContext, mInjector);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testScheduleNonStrongBiometricIdleTimeout() {
|
||||||
|
final long nextAlarmTime = 1000;
|
||||||
|
when(mInjector.getNextAlarmTimeMs(DEFAULT_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_MS))
|
||||||
|
.thenReturn(nextAlarmTime);
|
||||||
|
mStrongAuth.scheduleNonStrongBiometricIdleTimeout(PRIMARY_USER_ID);
|
||||||
|
|
||||||
|
waitForIdle();
|
||||||
|
NonStrongBiometricIdleTimeoutAlarmListener alarm = mStrongAuth
|
||||||
|
.mNonStrongBiometricIdleTimeoutAlarmListener.get(PRIMARY_USER_ID);
|
||||||
|
// verify that a new alarm for idle timeout is added for the user
|
||||||
|
assertNotNull(alarm);
|
||||||
|
// verify that the alarm is scheduled
|
||||||
|
verifyAlarm(nextAlarmTime, NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_ALARM_TAG, alarm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetIsNonStrongBiometricAllowed_disallowed() {
|
||||||
|
mStrongAuth.setIsNonStrongBiometricAllowed(false /* allowed */, PRIMARY_USER_ID);
|
||||||
|
|
||||||
|
waitForIdle();
|
||||||
|
// verify that unlocking with non-strong biometrics is not allowed
|
||||||
|
assertFalse(mStrongAuth.mIsNonStrongBiometricAllowedForUser
|
||||||
|
.get(PRIMARY_USER_ID, mDefaultIsNonStrongBiometricAllowed));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReportSuccessfulBiometricUnlock_nonStrongBiometric_fallbackTimeout() {
|
||||||
|
final long nextAlarmTime = 1000;
|
||||||
|
when(mInjector.getNextAlarmTimeMs(DEFAULT_NON_STRONG_BIOMETRIC_TIMEOUT_MS))
|
||||||
|
.thenReturn(nextAlarmTime);
|
||||||
|
mStrongAuth.reportSuccessfulBiometricUnlock(false /* isStrongBiometric */, PRIMARY_USER_ID);
|
||||||
|
|
||||||
|
waitForIdle();
|
||||||
|
NonStrongBiometricTimeoutAlarmListener alarm =
|
||||||
|
mStrongAuth.mNonStrongBiometricTimeoutAlarmListener.get(PRIMARY_USER_ID);
|
||||||
|
// verify that a new alarm for fallback timeout is added for the user
|
||||||
|
assertNotNull(alarm);
|
||||||
|
// verify that the alarm is scheduled
|
||||||
|
verifyAlarm(nextAlarmTime, NON_STRONG_BIOMETRIC_TIMEOUT_ALARM_TAG, alarm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequireStrongAuth_nonStrongBiometric_fallbackTimeout() {
|
||||||
|
mStrongAuth.requireStrongAuth(
|
||||||
|
STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT /* strongAuthReason */,
|
||||||
|
PRIMARY_USER_ID);
|
||||||
|
|
||||||
|
waitForIdle();
|
||||||
|
// verify that the StrongAuthFlags for the user contains the expected flag
|
||||||
|
final int expectedFlag = STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
|
||||||
|
verifyStrongAuthFlags(expectedFlag, PRIMARY_USER_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReportSuccessfulBiometricUnlock_nonStrongBiometric_cancelIdleTimeout() {
|
||||||
|
// lock device and schedule an alarm for non-strong biometric idle timeout
|
||||||
|
mStrongAuth.scheduleNonStrongBiometricIdleTimeout(PRIMARY_USER_ID);
|
||||||
|
// unlock with non-strong biometric
|
||||||
|
mStrongAuth.reportSuccessfulBiometricUnlock(false /* isStrongBiometric */, PRIMARY_USER_ID);
|
||||||
|
|
||||||
|
waitForIdle();
|
||||||
|
|
||||||
|
// verify that the current alarm for idle timeout is cancelled after a successful unlock
|
||||||
|
verify(mAlarmManager).cancel(any(NonStrongBiometricIdleTimeoutAlarmListener.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReportSuccessfulBiometricUnlock_strongBio_cancelAlarmsAndAllowNonStrongBio() {
|
||||||
|
setupAlarms(PRIMARY_USER_ID);
|
||||||
|
mStrongAuth.reportSuccessfulBiometricUnlock(true /* isStrongBiometric */, PRIMARY_USER_ID);
|
||||||
|
|
||||||
|
waitForIdle();
|
||||||
|
// verify that unlocking with strong biometric cancels alarms for fallback and idle timeout
|
||||||
|
// and re-allow unlocking with non-strong biometric
|
||||||
|
verifyAlarmsCancelledAndNonStrongBiometricAllowed(PRIMARY_USER_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReportSuccessfulStrongAuthUnlock_schedulePrimaryAuthTimeout() {
|
||||||
|
final long nextAlarmTime = 1000;
|
||||||
|
when(mInjector.getNextAlarmTimeMs(mDPM.getRequiredStrongAuthTimeout(null, PRIMARY_USER_ID)))
|
||||||
|
.thenReturn(nextAlarmTime);
|
||||||
|
mStrongAuth.reportSuccessfulStrongAuthUnlock(PRIMARY_USER_ID);
|
||||||
|
|
||||||
|
waitForIdle();
|
||||||
|
StrongAuthTimeoutAlarmListener alarm =
|
||||||
|
mStrongAuth.mStrongAuthTimeoutAlarmListenerForUser.get(PRIMARY_USER_ID);
|
||||||
|
// verify that a new alarm for primary auth timeout is added for the user
|
||||||
|
assertNotNull(alarm);
|
||||||
|
// verify that the alarm is scheduled
|
||||||
|
verifyAlarm(nextAlarmTime, STRONG_AUTH_TIMEOUT_ALARM_TAG, alarm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReportSuccessfulStrongAuthUnlock_cancelAlarmsAndAllowNonStrongBio() {
|
||||||
|
setupAlarms(PRIMARY_USER_ID);
|
||||||
|
mStrongAuth.reportSuccessfulStrongAuthUnlock(PRIMARY_USER_ID);
|
||||||
|
|
||||||
|
waitForIdle();
|
||||||
|
// verify that unlocking with primary auth (PIN/pattern/password) cancels alarms
|
||||||
|
// for fallback and idle timeout and re-allow unlocking with non-strong biometric
|
||||||
|
verifyAlarmsCancelledAndNonStrongBiometricAllowed(PRIMARY_USER_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFallbackTimeout_convenienceBiometric_weakBiometric() {
|
||||||
|
// assume that unlock with convenience biometric
|
||||||
|
mStrongAuth.reportSuccessfulBiometricUnlock(false /* isStrongBiometric */, PRIMARY_USER_ID);
|
||||||
|
// assume that unlock again with weak biometric
|
||||||
|
mStrongAuth.reportSuccessfulBiometricUnlock(false /* isStrongBiometric */, PRIMARY_USER_ID);
|
||||||
|
|
||||||
|
waitForIdle();
|
||||||
|
// verify that the fallback alarm scheduled when unlocking with convenience biometric is
|
||||||
|
// not affected when unlocking again with weak biometric
|
||||||
|
verify(mAlarmManager, never()).cancel(any(NonStrongBiometricTimeoutAlarmListener.class));
|
||||||
|
assertNotNull(mStrongAuth.mNonStrongBiometricTimeoutAlarmListener.get(PRIMARY_USER_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyAlarm(long when, String tag, AlarmManager.OnAlarmListener alarm) {
|
||||||
|
verify(mAlarmManager).set(
|
||||||
|
eq(AlarmManager.ELAPSED_REALTIME),
|
||||||
|
eq(when),
|
||||||
|
eq(tag),
|
||||||
|
eq(alarm),
|
||||||
|
eq(mStrongAuth.mHandler));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyStrongAuthFlags(int reason, int userId) {
|
||||||
|
final int flags = mStrongAuth.mStrongAuthForUser.get(userId, mDefaultStrongAuthFlags);
|
||||||
|
Log.d(TAG, "verifyStrongAuthFlags:"
|
||||||
|
+ " reason=" + Integer.toHexString(reason)
|
||||||
|
+ " userId=" + userId
|
||||||
|
+ " flags=" + Integer.toHexString(flags));
|
||||||
|
assertTrue(containsFlag(flags, reason));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupAlarms(int userId) {
|
||||||
|
// schedule (a) an alarm for non-strong biometric fallback timeout and (b) an alarm for
|
||||||
|
// non-strong biometric idle timeout, so later we can verify that unlocking with
|
||||||
|
// strong biometric or primary auth will cancel those alarms
|
||||||
|
mStrongAuth.reportSuccessfulBiometricUnlock(false /* isStrongBiometric */, PRIMARY_USER_ID);
|
||||||
|
mStrongAuth.scheduleNonStrongBiometricIdleTimeout(PRIMARY_USER_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyAlarmsCancelledAndNonStrongBiometricAllowed(int userId) {
|
||||||
|
// verify that the current alarm for non-strong biometric fallback timeout is cancelled and
|
||||||
|
// removed
|
||||||
|
verify(mAlarmManager).cancel(any(NonStrongBiometricTimeoutAlarmListener.class));
|
||||||
|
assertNull(mStrongAuth.mNonStrongBiometricTimeoutAlarmListener.get(userId));
|
||||||
|
|
||||||
|
// verify that the current alarm for non-strong biometric idle timeout is cancelled
|
||||||
|
verify(mAlarmManager).cancel(any(NonStrongBiometricIdleTimeoutAlarmListener.class));
|
||||||
|
|
||||||
|
// verify that unlocking with non-strong biometrics is allowed
|
||||||
|
assertTrue(mStrongAuth.mIsNonStrongBiometricAllowedForUser
|
||||||
|
.get(userId, mDefaultIsNonStrongBiometricAllowed));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean containsFlag(int haystack, int needle) {
|
||||||
|
return (haystack & needle) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void waitForIdle() {
|
||||||
|
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user