Merge "Support remote device credentials validation in UI."
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
package com.android.settings.password;
|
||||
|
||||
import static com.android.settings.password.TestUtils.COMPONENT_NAME;
|
||||
import static com.android.settings.password.TestUtils.VALID_REMAINING_ATTEMPTS;
|
||||
import static com.android.settings.password.TestUtils.createStartLockscreenValidationRequest;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -10,6 +14,8 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.KeyguardManager;
|
||||
import android.app.StartLockscreenValidationRequest;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
@@ -160,6 +166,93 @@ public class ChooseLockSettingsHelperTest {
|
||||
startedIntent.getComponent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchConfirmPassword_remoteValidation_passwordLockType() throws Exception {
|
||||
Activity activity = Robolectric.setupActivity(Activity.class);
|
||||
ShadowActivity shadowActivity = Shadows.shadowOf(activity);
|
||||
StartLockscreenValidationRequest request = createStartLockscreenValidationRequest(
|
||||
KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS);
|
||||
|
||||
ChooseLockSettingsHelper chooseLockSettingsHelper = getChooseLockSettingsHelper(
|
||||
new ChooseLockSettingsHelper.Builder(activity)
|
||||
.setRemoteLockscreenValidation(true)
|
||||
.setStartLockscreenValidationRequest(request)
|
||||
.setRemoteLockscreenValidationServiceComponent(COMPONENT_NAME));
|
||||
chooseLockSettingsHelper.launch();
|
||||
|
||||
Intent startedIntent = shadowActivity.getNextStartedActivity();
|
||||
assertEquals(new ComponentName("com.android.settings",
|
||||
ConfirmLockPassword.class.getName()), startedIntent.getComponent());
|
||||
assertThat(startedIntent.getBooleanExtra(
|
||||
ConfirmDeviceCredentialBaseFragment.IS_REMOTE_LOCKSCREEN_VALIDATION, false)
|
||||
).isTrue();
|
||||
assertThat(startedIntent.getParcelableExtra(
|
||||
KeyguardManager.EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST,
|
||||
StartLockscreenValidationRequest.class)
|
||||
).isEqualTo(request);
|
||||
assertThat(startedIntent.getParcelableExtra(
|
||||
Intent.EXTRA_COMPONENT_NAME, ComponentName.class)
|
||||
).isEqualTo(COMPONENT_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchConfirmPassword_remoteValidation_pinLockType() throws Exception {
|
||||
Activity activity = Robolectric.setupActivity(Activity.class);
|
||||
ShadowActivity shadowActivity = Shadows.shadowOf(activity);
|
||||
StartLockscreenValidationRequest request = createStartLockscreenValidationRequest(
|
||||
KeyguardManager.PIN, VALID_REMAINING_ATTEMPTS);
|
||||
|
||||
ChooseLockSettingsHelper chooseLockSettingsHelper = getChooseLockSettingsHelper(
|
||||
new ChooseLockSettingsHelper.Builder(activity)
|
||||
.setRemoteLockscreenValidation(true)
|
||||
.setStartLockscreenValidationRequest(request)
|
||||
.setRemoteLockscreenValidationServiceComponent(COMPONENT_NAME));
|
||||
chooseLockSettingsHelper.launch();
|
||||
|
||||
Intent startedIntent = shadowActivity.getNextStartedActivity();
|
||||
assertEquals(new ComponentName("com.android.settings",
|
||||
ConfirmLockPassword.class.getName()), startedIntent.getComponent());
|
||||
assertThat(startedIntent.getBooleanExtra(
|
||||
ConfirmDeviceCredentialBaseFragment.IS_REMOTE_LOCKSCREEN_VALIDATION, false)
|
||||
).isTrue();
|
||||
assertThat(startedIntent.getParcelableExtra(
|
||||
KeyguardManager.EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST,
|
||||
StartLockscreenValidationRequest.class)
|
||||
).isEqualTo(request);
|
||||
assertThat(startedIntent.getParcelableExtra(
|
||||
Intent.EXTRA_COMPONENT_NAME, ComponentName.class)
|
||||
).isEqualTo(COMPONENT_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchConfirmPattern_remoteValidation_patternLockType() throws Exception {
|
||||
Activity activity = Robolectric.setupActivity(Activity.class);
|
||||
ShadowActivity shadowActivity = Shadows.shadowOf(activity);
|
||||
StartLockscreenValidationRequest request = createStartLockscreenValidationRequest(
|
||||
KeyguardManager.PATTERN, VALID_REMAINING_ATTEMPTS);
|
||||
|
||||
ChooseLockSettingsHelper chooseLockSettingsHelper = getChooseLockSettingsHelper(
|
||||
new ChooseLockSettingsHelper.Builder(activity)
|
||||
.setRemoteLockscreenValidation(true)
|
||||
.setStartLockscreenValidationRequest(request)
|
||||
.setRemoteLockscreenValidationServiceComponent(COMPONENT_NAME));
|
||||
chooseLockSettingsHelper.launch();
|
||||
|
||||
Intent startedIntent = shadowActivity.getNextStartedActivity();
|
||||
assertEquals(new ComponentName("com.android.settings",
|
||||
ConfirmLockPattern.class.getName()), startedIntent.getComponent());
|
||||
assertThat(startedIntent.getBooleanExtra(
|
||||
ConfirmDeviceCredentialBaseFragment.IS_REMOTE_LOCKSCREEN_VALIDATION, false)
|
||||
).isTrue();
|
||||
assertThat(startedIntent.getParcelableExtra(
|
||||
KeyguardManager.EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST,
|
||||
StartLockscreenValidationRequest.class)
|
||||
).isEqualTo(request);
|
||||
assertThat(startedIntent.getParcelableExtra(
|
||||
Intent.EXTRA_COMPONENT_NAME, ComponentName.class)
|
||||
).isEqualTo(COMPONENT_NAME);
|
||||
}
|
||||
|
||||
private ChooseLockSettingsHelper getChooseLockSettingsHelper(
|
||||
ChooseLockSettingsHelper.Builder builder) {
|
||||
LockPatternUtils mockLockPatternUtils = mock(LockPatternUtils.class);
|
||||
|
@@ -16,25 +16,162 @@
|
||||
|
||||
package com.android.settings.password;
|
||||
|
||||
import static com.android.settings.password.TestUtils.NO_MORE_REMAINING_ATTEMPTS;
|
||||
import static com.android.settings.password.TestUtils.PACKAGE_NAME;
|
||||
import static com.android.settings.password.TestUtils.SERVICE_NAME;
|
||||
import static com.android.settings.password.TestUtils.VALID_REMAINING_ATTEMPTS;
|
||||
import static com.android.settings.password.TestUtils.buildConfirmDeviceCredentialBaseActivity;
|
||||
import static com.android.settings.password.TestUtils.createPackageInfoWithService;
|
||||
import static com.android.settings.password.TestUtils.createRemoteLockscreenValidationIntent;
|
||||
import static com.android.settings.password.TestUtils.createStartLockscreenValidationRequest;
|
||||
import static com.android.settings.password.TestUtils.getConfirmDeviceCredentialBaseFragment;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.KeyguardManager;
|
||||
import android.app.admin.ManagedSubscriptionsPolicy;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.FeatureFlagUtils;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.password.ConfirmDeviceCredentialBaseFragment.LastTryDialog;
|
||||
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
|
||||
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowApplicationPackageManager;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
ShadowLockPatternUtils.class,
|
||||
ShadowUtils.class,
|
||||
ShadowDevicePolicyManager.class,
|
||||
ShadowUserManager.class,
|
||||
ShadowApplicationPackageManager.class
|
||||
})
|
||||
public class ConfirmCredentialTest {
|
||||
|
||||
private Context mContext = RuntimeEnvironment.application;
|
||||
private Context mContext;
|
||||
private ShadowApplicationPackageManager mShadowApplicationPackageManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
|
||||
mShadowApplicationPackageManager =
|
||||
(ShadowApplicationPackageManager) Shadows.shadowOf(mContext.getPackageManager());
|
||||
mShadowApplicationPackageManager.addPackageNoDefaults(
|
||||
TestUtils.createPackageInfoWithService(
|
||||
PACKAGE_NAME, SERVICE_NAME,
|
||||
Manifest.permission.BIND_REMOTE_LOCKSCREEN_VALIDATION_SERVICE));
|
||||
|
||||
final ShadowDevicePolicyManager shadowDpm = ShadowDevicePolicyManager.getShadow();
|
||||
shadowDpm.setManagedSubscriptionsPolicy(
|
||||
new ManagedSubscriptionsPolicy(
|
||||
ManagedSubscriptionsPolicy.TYPE_ALL_PERSONAL_SUBSCRIPTIONS));
|
||||
|
||||
FeatureFlagUtils.setEnabled(mContext,
|
||||
FeatureFlagUtils.SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_successfullyStart() {
|
||||
ConfirmDeviceCredentialBaseActivity activity =
|
||||
buildConfirmDeviceCredentialBaseActivity(ConfirmLockPassword.class, new Intent());
|
||||
ConfirmDeviceCredentialBaseFragment fragment =
|
||||
getConfirmDeviceCredentialBaseFragment(activity);
|
||||
|
||||
assertThat(activity.isFinishing()).isFalse();
|
||||
assertThat(fragment.mRemoteValidation).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_remoteValidation_successfullyStart() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity = buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPassword.class, createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS));
|
||||
ConfirmDeviceCredentialBaseFragment fragment =
|
||||
getConfirmDeviceCredentialBaseFragment(activity);
|
||||
|
||||
assertThat(activity.isFinishing()).isFalse();
|
||||
assertThat(fragment.mRemoteValidation).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_remoteValidation_flagDisabled_finishActivity() throws Exception {
|
||||
FeatureFlagUtils.setEnabled(mContext,
|
||||
FeatureFlagUtils.SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, false);
|
||||
|
||||
ConfirmDeviceCredentialBaseActivity activity = buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPassword.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS));
|
||||
|
||||
assertThat(activity.isFinishing()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_remoteValidation_invalidServiceComponentName_finishActivity()
|
||||
throws Exception {
|
||||
Intent intentWithInvalidComponentName = new Intent()
|
||||
.putExtra(ConfirmDeviceCredentialBaseFragment.IS_REMOTE_LOCKSCREEN_VALIDATION, true)
|
||||
.putExtra(KeyguardManager.EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST,
|
||||
createStartLockscreenValidationRequest(
|
||||
KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS))
|
||||
.putExtra(Intent.EXTRA_COMPONENT_NAME, new ComponentName("pkg", "cls"));
|
||||
|
||||
ConfirmDeviceCredentialBaseActivity activity = buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPassword.class, intentWithInvalidComponentName);
|
||||
|
||||
assertThat(activity.isFinishing()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_remoteValidation_serviceDoesNotRequestCorrectPermission_finishActivity()
|
||||
throws Exception {
|
||||
// Remove package with valid ServiceInfo
|
||||
mShadowApplicationPackageManager.removePackage(PACKAGE_NAME);
|
||||
// Add a service that does not request the BIND_REMOTE_LOCKSCREEN_SERVICE permission
|
||||
mShadowApplicationPackageManager.addPackageNoDefaults(
|
||||
createPackageInfoWithService(
|
||||
PACKAGE_NAME,
|
||||
SERVICE_NAME,
|
||||
Manifest.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE));
|
||||
|
||||
ConfirmDeviceCredentialBaseActivity activity = buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPassword.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS));
|
||||
|
||||
assertThat(activity.isFinishing()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_remoteValidation_noMoreAttempts_finishActivity() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity = buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPassword.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PASSWORD, NO_MORE_REMAINING_ATTEMPTS));
|
||||
|
||||
assertThat(activity.isFinishing()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLastTryDialogShownExactlyOnce() {
|
||||
|
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.settings.password;
|
||||
|
||||
import static com.android.settings.password.ConfirmLockPassword.ConfirmLockPasswordFragment;
|
||||
import static com.android.settings.password.TestUtils.GUESS_INVALID_RESULT;
|
||||
import static com.android.settings.password.TestUtils.GUESS_VALID_RESULT;
|
||||
import static com.android.settings.password.TestUtils.LOCKOUT_RESULT;
|
||||
import static com.android.settings.password.TestUtils.NO_REMAINING_ATTEMPTS_RESULT;
|
||||
import static com.android.settings.password.TestUtils.PACKAGE_NAME;
|
||||
import static com.android.settings.password.TestUtils.SERVICE_NAME;
|
||||
import static com.android.settings.password.TestUtils.TIMEOUT_MS;
|
||||
import static com.android.settings.password.TestUtils.VALID_REMAINING_ATTEMPTS;
|
||||
import static com.android.settings.password.TestUtils.buildConfirmDeviceCredentialBaseActivity;
|
||||
import static com.android.settings.password.TestUtils.createRemoteLockscreenValidationIntent;
|
||||
import static com.android.settings.password.TestUtils.getConfirmDeviceCredentialBaseFragment;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.KeyguardManager;
|
||||
import android.app.admin.ManagedSubscriptionsPolicy;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.UserHandle;
|
||||
import android.service.remotelockscreenvalidation.IRemoteLockscreenValidationCallback;
|
||||
import android.service.remotelockscreenvalidation.RemoteLockscreenValidationClient;
|
||||
import android.text.InputType;
|
||||
import android.util.FeatureFlagUtils;
|
||||
import android.widget.ImeAwareEditText;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
|
||||
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||
|
||||
import org.junit.After;
|
||||
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 org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowApplicationPackageManager;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
ShadowLockPatternUtils.class,
|
||||
ShadowUtils.class,
|
||||
ShadowDevicePolicyManager.class,
|
||||
ShadowUserManager.class,
|
||||
ShadowApplicationPackageManager.class
|
||||
})
|
||||
public class ConfirmLockPasswordTest {
|
||||
|
||||
@Mock
|
||||
CredentialCheckResultTracker mCredentialCheckResultTracker;
|
||||
@Mock
|
||||
RemoteLockscreenValidationClient mRemoteLockscreenValidationClient;
|
||||
@Captor
|
||||
ArgumentCaptor<IRemoteLockscreenValidationCallback> mCallbackCaptor;
|
||||
|
||||
private Context mContext;
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mLockPatternUtils = new LockPatternUtils(mContext);
|
||||
|
||||
ShadowApplicationPackageManager shadowApplicationPackageManager =
|
||||
(ShadowApplicationPackageManager) Shadows.shadowOf(mContext.getPackageManager());
|
||||
shadowApplicationPackageManager.addPackageNoDefaults(
|
||||
TestUtils.createPackageInfoWithService(
|
||||
PACKAGE_NAME,
|
||||
SERVICE_NAME,
|
||||
Manifest.permission.BIND_REMOTE_LOCKSCREEN_VALIDATION_SERVICE));
|
||||
|
||||
final ShadowDevicePolicyManager shadowDpm = ShadowDevicePolicyManager.getShadow();
|
||||
shadowDpm.setManagedSubscriptionsPolicy(
|
||||
new ManagedSubscriptionsPolicy(
|
||||
ManagedSubscriptionsPolicy.TYPE_ALL_PERSONAL_SUBSCRIPTIONS));
|
||||
|
||||
// Set false by default so we can check if lock was set when remote validation succeeds.
|
||||
ShadowLockPatternUtils.setIsSecure(UserHandle.myUserId(), false);
|
||||
|
||||
FeatureFlagUtils.setEnabled(mContext,
|
||||
FeatureFlagUtils.SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, true);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowLockPatternUtils.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_remoteValidation_password_successfullyStart() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity =
|
||||
buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPassword.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS));
|
||||
ConfirmLockPasswordFragment fragment =
|
||||
(ConfirmLockPasswordFragment) getConfirmDeviceCredentialBaseFragment(activity);
|
||||
|
||||
assertThat(activity.isFinishing()).isFalse();
|
||||
assertThat(fragment.mRemoteValidation).isTrue();
|
||||
ImeAwareEditText editText = (ImeAwareEditText) activity.findViewById(R.id.password_entry);
|
||||
assertThat(editText.getInputType()).isEqualTo(
|
||||
InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_remoteValidation_pin_successfullyStart() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity =
|
||||
buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPassword.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PIN, VALID_REMAINING_ATTEMPTS));
|
||||
ConfirmLockPasswordFragment fragment =
|
||||
(ConfirmLockPasswordFragment) getConfirmDeviceCredentialBaseFragment(activity);
|
||||
|
||||
assertThat(activity.isFinishing()).isFalse();
|
||||
assertThat(fragment.mRemoteValidation).isTrue();
|
||||
ImeAwareEditText editText = (ImeAwareEditText) activity.findViewById(R.id.password_entry);
|
||||
assertThat(editText.getInputType()).isEqualTo(
|
||||
InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleNext_normalFlow_doesNotAttemptRemoteLockscreenValidation() {
|
||||
ConfirmLockPassword activity = Robolectric.buildActivity(
|
||||
ConfirmLockPassword.class, new Intent()).setup().get();
|
||||
ConfirmLockPasswordFragment fragment =
|
||||
(ConfirmLockPasswordFragment) getConfirmDeviceCredentialBaseFragment(activity);
|
||||
ImeAwareEditText passwordEntry = activity.findViewById(R.id.password_entry);
|
||||
fragment.mRemoteLockscreenValidationClient = mRemoteLockscreenValidationClient;
|
||||
|
||||
triggerHandleNext(fragment, passwordEntry);
|
||||
|
||||
verifyNoInteractions(mRemoteLockscreenValidationClient);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleNext_remoteValidation_correctGuess_checkboxChecked() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity =
|
||||
buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPassword.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS));
|
||||
ConfirmLockPasswordFragment fragment =
|
||||
(ConfirmLockPasswordFragment) getConfirmDeviceCredentialBaseFragment(activity);
|
||||
ReflectionHelpers.setField(fragment,
|
||||
"mCredentialCheckResultTracker", mCredentialCheckResultTracker);
|
||||
ImeAwareEditText passwordEntry = activity.findViewById(R.id.password_entry);
|
||||
fragment.mRemoteLockscreenValidationClient = mRemoteLockscreenValidationClient;
|
||||
|
||||
triggerHandleNext(fragment, passwordEntry);
|
||||
verify(mRemoteLockscreenValidationClient)
|
||||
.validateLockscreenGuess(any(), mCallbackCaptor.capture());
|
||||
mCallbackCaptor.getValue().onSuccess(GUESS_VALID_RESULT);
|
||||
|
||||
verify(mCredentialCheckResultTracker).setResult(
|
||||
eq(true), any(), eq(0), eq(fragment.mEffectiveUserId));
|
||||
assertThat(mLockPatternUtils.isSecure(fragment.mEffectiveUserId)).isTrue();
|
||||
assertThat(fragment.mDeviceCredentialGuess).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleNext_remoteValidation_correctGuess_checkboxUnchecked() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity =
|
||||
buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPassword.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS));
|
||||
ConfirmLockPasswordFragment fragment =
|
||||
(ConfirmLockPasswordFragment) getConfirmDeviceCredentialBaseFragment(activity);
|
||||
ReflectionHelpers.setField(fragment,
|
||||
"mCredentialCheckResultTracker", mCredentialCheckResultTracker);
|
||||
fragment.mCheckBox.setChecked(false);
|
||||
ImeAwareEditText passwordEntry = activity.findViewById(R.id.password_entry);
|
||||
fragment.mRemoteLockscreenValidationClient = mRemoteLockscreenValidationClient;
|
||||
|
||||
triggerHandleNext(fragment, passwordEntry);
|
||||
verify(mRemoteLockscreenValidationClient)
|
||||
.validateLockscreenGuess(any(), mCallbackCaptor.capture());
|
||||
mCallbackCaptor.getValue().onSuccess(GUESS_VALID_RESULT);
|
||||
|
||||
verify(mCredentialCheckResultTracker).setResult(
|
||||
eq(true), any(), eq(0), eq(fragment.mEffectiveUserId));
|
||||
assertThat(mLockPatternUtils.isSecure(fragment.mEffectiveUserId)).isFalse();
|
||||
assertThat(fragment.mDeviceCredentialGuess).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleNext_remoteValidation_guessInvalid() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity =
|
||||
buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPassword.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS));
|
||||
ConfirmLockPasswordFragment fragment =
|
||||
(ConfirmLockPasswordFragment) getConfirmDeviceCredentialBaseFragment(activity);
|
||||
ReflectionHelpers.setField(fragment,
|
||||
"mCredentialCheckResultTracker", mCredentialCheckResultTracker);
|
||||
ImeAwareEditText passwordEntry = activity.findViewById(R.id.password_entry);
|
||||
fragment.mRemoteLockscreenValidationClient = mRemoteLockscreenValidationClient;
|
||||
|
||||
triggerHandleNext(fragment, passwordEntry);
|
||||
verify(mRemoteLockscreenValidationClient)
|
||||
.validateLockscreenGuess(any(), mCallbackCaptor.capture());
|
||||
mCallbackCaptor.getValue().onSuccess(GUESS_INVALID_RESULT);
|
||||
|
||||
verify(mCredentialCheckResultTracker).setResult(
|
||||
eq(false), any(), eq(0), eq(fragment.mEffectiveUserId));
|
||||
assertThat(mLockPatternUtils.isSecure(fragment.mEffectiveUserId)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleNext_remoteValidation_lockout() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity =
|
||||
buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPassword.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS));
|
||||
ConfirmLockPasswordFragment fragment =
|
||||
(ConfirmLockPasswordFragment) getConfirmDeviceCredentialBaseFragment(activity);
|
||||
ReflectionHelpers.setField(fragment,
|
||||
"mCredentialCheckResultTracker", mCredentialCheckResultTracker);
|
||||
ImeAwareEditText passwordEntry = activity.findViewById(R.id.password_entry);
|
||||
fragment.mRemoteLockscreenValidationClient = mRemoteLockscreenValidationClient;
|
||||
|
||||
triggerHandleNext(fragment, passwordEntry);
|
||||
verify(mRemoteLockscreenValidationClient)
|
||||
.validateLockscreenGuess(any(), mCallbackCaptor.capture());
|
||||
mCallbackCaptor.getValue().onSuccess(LOCKOUT_RESULT);
|
||||
|
||||
verify(mCredentialCheckResultTracker).setResult(
|
||||
eq(false), any(), eq(TIMEOUT_MS), eq(fragment.mEffectiveUserId));
|
||||
assertThat(mLockPatternUtils.isSecure(fragment.mEffectiveUserId)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleNext_remoteValidation_noRemainingAttempts_finishActivity() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity =
|
||||
buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPassword.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS));
|
||||
ConfirmLockPasswordFragment fragment =
|
||||
(ConfirmLockPasswordFragment) getConfirmDeviceCredentialBaseFragment(activity);
|
||||
ReflectionHelpers.setField(fragment,
|
||||
"mCredentialCheckResultTracker", mCredentialCheckResultTracker);
|
||||
ImeAwareEditText passwordEntry = activity.findViewById(R.id.password_entry);
|
||||
fragment.mRemoteLockscreenValidationClient = mRemoteLockscreenValidationClient;
|
||||
|
||||
triggerHandleNext(fragment, passwordEntry);
|
||||
verify(mRemoteLockscreenValidationClient)
|
||||
.validateLockscreenGuess(any(), mCallbackCaptor.capture());
|
||||
mCallbackCaptor.getValue().onSuccess(NO_REMAINING_ATTEMPTS_RESULT);
|
||||
|
||||
assertThat(activity.isFinishing()).isTrue();
|
||||
verify(mCredentialCheckResultTracker, never())
|
||||
.setResult(anyBoolean(), any(), anyInt(), anyInt());
|
||||
assertThat(mLockPatternUtils.isSecure(fragment.mEffectiveUserId)).isFalse();
|
||||
}
|
||||
|
||||
private void triggerHandleNext(
|
||||
ConfirmLockPasswordFragment fragment, ImeAwareEditText passwordEntry) {
|
||||
passwordEntry.setText("Password");
|
||||
ReflectionHelpers.callInstanceMethod(fragment, "handleNext");
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.settings.password;
|
||||
|
||||
import static com.android.settings.password.TestUtils.GUESS_INVALID_RESULT;
|
||||
import static com.android.settings.password.TestUtils.GUESS_VALID_RESULT;
|
||||
import static com.android.settings.password.TestUtils.LOCKOUT_RESULT;
|
||||
import static com.android.settings.password.TestUtils.NO_REMAINING_ATTEMPTS_RESULT;
|
||||
import static com.android.settings.password.TestUtils.PACKAGE_NAME;
|
||||
import static com.android.settings.password.TestUtils.SERVICE_NAME;
|
||||
import static com.android.settings.password.TestUtils.TIMEOUT_MS;
|
||||
import static com.android.settings.password.TestUtils.VALID_REMAINING_ATTEMPTS;
|
||||
import static com.android.settings.password.TestUtils.buildConfirmDeviceCredentialBaseActivity;
|
||||
import static com.android.settings.password.TestUtils.createPackageInfoWithService;
|
||||
import static com.android.settings.password.TestUtils.createRemoteLockscreenValidationIntent;
|
||||
import static com.android.settings.password.TestUtils.getConfirmDeviceCredentialBaseFragment;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.KeyguardManager;
|
||||
import android.app.admin.ManagedSubscriptionsPolicy;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.UserHandle;
|
||||
import android.service.remotelockscreenvalidation.IRemoteLockscreenValidationCallback;
|
||||
import android.service.remotelockscreenvalidation.RemoteLockscreenValidationClient;
|
||||
import android.util.FeatureFlagUtils;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockPatternView;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
|
||||
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||
|
||||
import org.junit.After;
|
||||
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 org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowApplicationPackageManager;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
ShadowLockPatternUtils.class,
|
||||
ShadowUtils.class,
|
||||
ShadowDevicePolicyManager.class,
|
||||
ShadowUserManager.class,
|
||||
ShadowApplicationPackageManager.class
|
||||
})
|
||||
public class ConfirmLockPatternTest {
|
||||
|
||||
@Mock
|
||||
CredentialCheckResultTracker mCredentialCheckResultTracker;
|
||||
@Mock
|
||||
RemoteLockscreenValidationClient mRemoteLockscreenValidationClient;
|
||||
@Captor
|
||||
ArgumentCaptor<IRemoteLockscreenValidationCallback> mCallbackCaptor;
|
||||
|
||||
private Context mContext;
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mLockPatternUtils = new LockPatternUtils(mContext);
|
||||
|
||||
ShadowApplicationPackageManager shadowApplicationPackageManager =
|
||||
(ShadowApplicationPackageManager) Shadows.shadowOf(mContext.getPackageManager());
|
||||
shadowApplicationPackageManager.addPackageNoDefaults(
|
||||
createPackageInfoWithService(
|
||||
PACKAGE_NAME,
|
||||
SERVICE_NAME,
|
||||
Manifest.permission.BIND_REMOTE_LOCKSCREEN_VALIDATION_SERVICE));
|
||||
|
||||
final ShadowDevicePolicyManager shadowDpm = ShadowDevicePolicyManager.getShadow();
|
||||
shadowDpm.setManagedSubscriptionsPolicy(
|
||||
new ManagedSubscriptionsPolicy(
|
||||
ManagedSubscriptionsPolicy.TYPE_ALL_PERSONAL_SUBSCRIPTIONS));
|
||||
|
||||
// Set false by default so we can check if lock was set when remote validation succeeds.
|
||||
ShadowLockPatternUtils.setIsSecure(UserHandle.myUserId(), false);
|
||||
|
||||
FeatureFlagUtils.setEnabled(mContext,
|
||||
FeatureFlagUtils.SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, true);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowLockPatternUtils.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_remoteValidation_successfullyStart() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity =
|
||||
buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPattern.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PATTERN, VALID_REMAINING_ATTEMPTS));
|
||||
ConfirmDeviceCredentialBaseFragment fragment =
|
||||
getConfirmDeviceCredentialBaseFragment(activity);
|
||||
|
||||
assertThat(activity.isFinishing()).isFalse();
|
||||
assertThat(fragment.mRemoteValidation).isTrue();
|
||||
LockPatternView lockPatternView = (LockPatternView) activity.findViewById(R.id.lockPattern);
|
||||
assertThat(lockPatternView.isInStealthMode()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPatternDetected_normalFlow_doesNotAttemptRemoteLockscreenValidation() {
|
||||
ConfirmLockPattern activity = Robolectric.buildActivity(
|
||||
ConfirmLockPattern.class, new Intent()).setup().get();
|
||||
ConfirmDeviceCredentialBaseFragment fragment =
|
||||
getConfirmDeviceCredentialBaseFragment(activity);
|
||||
LockPatternView lockPatternView = activity.findViewById(R.id.lockPattern);
|
||||
fragment.mRemoteLockscreenValidationClient = mRemoteLockscreenValidationClient;
|
||||
|
||||
triggerOnPatternDetected(lockPatternView);
|
||||
|
||||
verifyNoInteractions(mRemoteLockscreenValidationClient);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPatternDetected_remoteValidation_guessValid_checkboxChecked() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity =
|
||||
buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPattern.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PATTERN, VALID_REMAINING_ATTEMPTS));
|
||||
ConfirmDeviceCredentialBaseFragment fragment =
|
||||
getConfirmDeviceCredentialBaseFragment(activity);
|
||||
LockPatternView lockPatternView = activity.findViewById(R.id.lockPattern);
|
||||
ReflectionHelpers.setField(fragment,
|
||||
"mCredentialCheckResultTracker", mCredentialCheckResultTracker);
|
||||
fragment.mRemoteLockscreenValidationClient = mRemoteLockscreenValidationClient;
|
||||
|
||||
triggerOnPatternDetected(lockPatternView);
|
||||
verify(mRemoteLockscreenValidationClient)
|
||||
.validateLockscreenGuess(any(), mCallbackCaptor.capture());
|
||||
mCallbackCaptor.getValue().onSuccess(GUESS_VALID_RESULT);
|
||||
|
||||
verify(mCredentialCheckResultTracker).setResult(
|
||||
eq(true), any(), eq(0), eq(fragment.mEffectiveUserId));
|
||||
assertThat(mLockPatternUtils.isSecure(fragment.mEffectiveUserId)).isTrue();
|
||||
assertThat(fragment.mDeviceCredentialGuess).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPatternDetected_remoteValidation_guessValid_checkboxUnchecked() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity =
|
||||
buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPattern.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PATTERN, VALID_REMAINING_ATTEMPTS));
|
||||
ConfirmDeviceCredentialBaseFragment fragment =
|
||||
getConfirmDeviceCredentialBaseFragment(activity);
|
||||
LockPatternView lockPatternView = activity.findViewById(R.id.lockPattern);
|
||||
ReflectionHelpers.setField(fragment,
|
||||
"mCredentialCheckResultTracker", mCredentialCheckResultTracker);
|
||||
fragment.mCheckBox.setChecked(false);
|
||||
fragment.mRemoteLockscreenValidationClient = mRemoteLockscreenValidationClient;
|
||||
|
||||
triggerOnPatternDetected(lockPatternView);
|
||||
verify(mRemoteLockscreenValidationClient)
|
||||
.validateLockscreenGuess(any(), mCallbackCaptor.capture());
|
||||
mCallbackCaptor.getValue().onSuccess(GUESS_VALID_RESULT);
|
||||
|
||||
verify(mCredentialCheckResultTracker).setResult(
|
||||
eq(true), any(), eq(0), eq(fragment.mEffectiveUserId));
|
||||
assertThat(mLockPatternUtils.isSecure(fragment.mEffectiveUserId)).isFalse();
|
||||
assertThat(fragment.mDeviceCredentialGuess).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPatternDetected_remoteValidation_guessInvalid() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity =
|
||||
buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPattern.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PATTERN, VALID_REMAINING_ATTEMPTS));
|
||||
ConfirmDeviceCredentialBaseFragment fragment =
|
||||
getConfirmDeviceCredentialBaseFragment(activity);
|
||||
LockPatternView lockPatternView = activity.findViewById(R.id.lockPattern);
|
||||
ReflectionHelpers.setField(fragment,
|
||||
"mCredentialCheckResultTracker", mCredentialCheckResultTracker);
|
||||
fragment.mRemoteLockscreenValidationClient = mRemoteLockscreenValidationClient;
|
||||
|
||||
triggerOnPatternDetected(lockPatternView);
|
||||
verify(mRemoteLockscreenValidationClient)
|
||||
.validateLockscreenGuess(any(), mCallbackCaptor.capture());
|
||||
mCallbackCaptor.getValue().onSuccess(GUESS_INVALID_RESULT);
|
||||
|
||||
verify(mCredentialCheckResultTracker).setResult(
|
||||
eq(false), any(), eq(0), eq(fragment.mEffectiveUserId));
|
||||
assertThat(mLockPatternUtils.isSecure(fragment.mEffectiveUserId)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPatternDetected_remoteValidation_lockout() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity =
|
||||
buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPattern.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PATTERN, VALID_REMAINING_ATTEMPTS));
|
||||
ConfirmDeviceCredentialBaseFragment fragment =
|
||||
getConfirmDeviceCredentialBaseFragment(activity);
|
||||
LockPatternView lockPatternView = activity.findViewById(R.id.lockPattern);
|
||||
ReflectionHelpers.setField(fragment,
|
||||
"mCredentialCheckResultTracker", mCredentialCheckResultTracker);
|
||||
fragment.mRemoteLockscreenValidationClient = mRemoteLockscreenValidationClient;
|
||||
|
||||
triggerOnPatternDetected(lockPatternView);
|
||||
verify(mRemoteLockscreenValidationClient)
|
||||
.validateLockscreenGuess(any(), mCallbackCaptor.capture());
|
||||
mCallbackCaptor.getValue().onSuccess(LOCKOUT_RESULT);
|
||||
|
||||
verify(mCredentialCheckResultTracker).setResult(
|
||||
eq(false), any(), eq(TIMEOUT_MS), eq(fragment.mEffectiveUserId));
|
||||
assertThat(mLockPatternUtils.isSecure(fragment.mEffectiveUserId)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPatternDetected_noRemainingAttempts_finishActivity() throws Exception {
|
||||
ConfirmDeviceCredentialBaseActivity activity =
|
||||
buildConfirmDeviceCredentialBaseActivity(
|
||||
ConfirmLockPattern.class,
|
||||
createRemoteLockscreenValidationIntent(
|
||||
KeyguardManager.PATTERN, VALID_REMAINING_ATTEMPTS));
|
||||
ConfirmDeviceCredentialBaseFragment fragment =
|
||||
getConfirmDeviceCredentialBaseFragment(activity);
|
||||
LockPatternView lockPatternView = activity.findViewById(R.id.lockPattern);
|
||||
ReflectionHelpers.setField(fragment,
|
||||
"mCredentialCheckResultTracker", mCredentialCheckResultTracker);
|
||||
fragment.mRemoteLockscreenValidationClient = mRemoteLockscreenValidationClient;
|
||||
|
||||
triggerOnPatternDetected(lockPatternView);
|
||||
verify(mRemoteLockscreenValidationClient)
|
||||
.validateLockscreenGuess(any(), mCallbackCaptor.capture());
|
||||
mCallbackCaptor.getValue().onSuccess(NO_REMAINING_ATTEMPTS_RESULT);
|
||||
|
||||
assertThat(activity.isFinishing()).isTrue();
|
||||
verifyNoInteractions(mCredentialCheckResultTracker);
|
||||
assertThat(mLockPatternUtils.isSecure(fragment.mEffectiveUserId)).isFalse();
|
||||
}
|
||||
|
||||
private void triggerOnPatternDetected(LockPatternView lockPatternView) {
|
||||
List<LockPatternView.Cell> pattern = List.of(LockPatternView.Cell.of(0, 0));
|
||||
lockPatternView.setPattern(LockPatternView.DisplayMode.Correct, pattern);
|
||||
ReflectionHelpers.callInstanceMethod(lockPatternView, "notifyPatternDetected");
|
||||
}
|
||||
}
|
107
tests/robotests/src/com/android/settings/password/TestUtils.java
Normal file
107
tests/robotests/src/com/android/settings/password/TestUtils.java
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.settings.password;
|
||||
|
||||
import android.app.KeyguardManager;
|
||||
import android.app.RemoteLockscreenValidationResult;
|
||||
import android.app.StartLockscreenValidationRequest;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
|
||||
import com.android.security.SecureBox;
|
||||
import com.android.settings.R;
|
||||
|
||||
import org.robolectric.Robolectric;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public final class TestUtils {
|
||||
|
||||
public static final String SERVICE_NAME = "SERVICE_NAME";
|
||||
public static final String PACKAGE_NAME = "PACKAGE_NAME";
|
||||
public static final ComponentName COMPONENT_NAME =
|
||||
new ComponentName(PACKAGE_NAME, SERVICE_NAME);
|
||||
public static final int VALID_REMAINING_ATTEMPTS = 5;
|
||||
public static final int NO_MORE_REMAINING_ATTEMPTS = 0;
|
||||
public static final int TIMEOUT_MS = 10000;
|
||||
public static final RemoteLockscreenValidationResult GUESS_VALID_RESULT =
|
||||
new RemoteLockscreenValidationResult.Builder()
|
||||
.setResultCode(RemoteLockscreenValidationResult.RESULT_GUESS_VALID)
|
||||
.build();
|
||||
public static final RemoteLockscreenValidationResult GUESS_INVALID_RESULT =
|
||||
new RemoteLockscreenValidationResult.Builder()
|
||||
.setResultCode(RemoteLockscreenValidationResult.RESULT_GUESS_INVALID)
|
||||
.build();
|
||||
public static final RemoteLockscreenValidationResult LOCKOUT_RESULT =
|
||||
new RemoteLockscreenValidationResult.Builder()
|
||||
.setResultCode(RemoteLockscreenValidationResult.RESULT_LOCKOUT)
|
||||
.setTimeoutMillis(TIMEOUT_MS)
|
||||
.build();
|
||||
public static final RemoteLockscreenValidationResult NO_REMAINING_ATTEMPTS_RESULT =
|
||||
new RemoteLockscreenValidationResult.Builder()
|
||||
.setResultCode(RemoteLockscreenValidationResult.RESULT_NO_REMAINING_ATTEMPTS)
|
||||
.build();
|
||||
|
||||
private TestUtils() {
|
||||
}
|
||||
|
||||
public static PackageInfo createPackageInfoWithService(
|
||||
String packageName, String serviceName, String requiredServicePermission) {
|
||||
ServiceInfo serviceInfo = new ServiceInfo();
|
||||
serviceInfo.name = serviceName;
|
||||
serviceInfo.applicationInfo = new ApplicationInfo();
|
||||
serviceInfo.permission = requiredServicePermission;
|
||||
|
||||
PackageInfo packageInfo = new PackageInfo();
|
||||
packageInfo.packageName = packageName;
|
||||
packageInfo.services = new ServiceInfo[]{serviceInfo};
|
||||
return packageInfo;
|
||||
}
|
||||
|
||||
public static Intent createRemoteLockscreenValidationIntent(
|
||||
int lockscreenType, int remainingAttempts) throws Exception {
|
||||
return new Intent()
|
||||
.putExtra(ConfirmDeviceCredentialBaseFragment.IS_REMOTE_LOCKSCREEN_VALIDATION, true)
|
||||
.putExtra(KeyguardManager.EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST,
|
||||
createStartLockscreenValidationRequest(lockscreenType, remainingAttempts))
|
||||
.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME);
|
||||
}
|
||||
|
||||
public static StartLockscreenValidationRequest createStartLockscreenValidationRequest(
|
||||
int lockscreenType, int remainingAttempts) throws NoSuchAlgorithmException {
|
||||
return new StartLockscreenValidationRequest.Builder()
|
||||
.setLockscreenUiType(lockscreenType)
|
||||
.setRemainingAttempts(remainingAttempts)
|
||||
.setSourcePublicKey(SecureBox.genKeyPair().getPublic().getEncoded())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ConfirmDeviceCredentialBaseActivity buildConfirmDeviceCredentialBaseActivity(
|
||||
Class<? extends ConfirmDeviceCredentialBaseActivity> impl, Intent intent) {
|
||||
return Robolectric.buildActivity(impl, intent).setup().get();
|
||||
}
|
||||
|
||||
public static ConfirmDeviceCredentialBaseFragment getConfirmDeviceCredentialBaseFragment(
|
||||
ConfirmDeviceCredentialBaseActivity activity) {
|
||||
return (ConfirmDeviceCredentialBaseFragment)
|
||||
activity.getSupportFragmentManager().findFragmentById(R.id.main_content);
|
||||
}
|
||||
|
||||
}
|
@@ -8,6 +8,7 @@ import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.admin.DevicePolicyManager.DeviceOwnerType;
|
||||
import android.app.admin.ManagedSubscriptionsPolicy;
|
||||
import android.app.admin.PasswordMetrics;
|
||||
import android.app.admin.PasswordPolicy;
|
||||
import android.content.ComponentName;
|
||||
@@ -29,6 +30,7 @@ public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDev
|
||||
private Map<Integer, CharSequence> mSupportMessagesMap = new HashMap<>();
|
||||
private boolean mIsAdminActiveAsUser = false;
|
||||
private ComponentName mDeviceOwnerComponentName;
|
||||
private ManagedSubscriptionsPolicy mManagedSubscriptionsPolicy;
|
||||
private int mDeviceOwnerUserId = -1;
|
||||
private int mPasswordMinQuality = PASSWORD_QUALITY_UNSPECIFIED;
|
||||
private int mPasswordMinLength = 0;
|
||||
@@ -85,6 +87,10 @@ public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDev
|
||||
mDeviceOwnerTypes.put(admin.getPackageName(), deviceOwnerType);
|
||||
}
|
||||
|
||||
public void setManagedSubscriptionsPolicy(ManagedSubscriptionsPolicy policy) {
|
||||
mManagedSubscriptionsPolicy = policy;
|
||||
}
|
||||
|
||||
@DeviceOwnerType
|
||||
public int getDeviceOwnerType(@NonNull ComponentName admin) {
|
||||
return mDeviceOwnerTypes.getOrDefault(admin.getPackageName(), DEVICE_OWNER_TYPE_DEFAULT);
|
||||
@@ -99,6 +105,11 @@ public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDev
|
||||
return policy.getMinMetrics();
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public ManagedSubscriptionsPolicy getManagedSubscriptionsPolicy() {
|
||||
return mManagedSubscriptionsPolicy;
|
||||
}
|
||||
|
||||
public void setPasswordQuality(int quality) {
|
||||
mPasswordMinQuality = quality;
|
||||
}
|
||||
|
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.testutils.shadow;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.admin.PasswordMetrics;
|
||||
import android.content.ComponentName;
|
||||
@@ -43,6 +45,10 @@ public class ShadowLockPatternUtils {
|
||||
private static Map<Integer, PasswordMetrics> sUserToMetricsMap = new HashMap<>();
|
||||
private static Map<Integer, PasswordMetrics> sUserToProfileMetricsMap = new HashMap<>();
|
||||
private static Map<Integer, Boolean> sUserToIsSecureMap = new HashMap<>();
|
||||
private static Map<Integer, Boolean> sUserToPatternEverChosenMap = new HashMap<>();
|
||||
private static Map<Integer, Boolean> sUserToVisiblePatternEnabledMap = new HashMap<>();
|
||||
private static Map<Integer, Boolean> sUserToBiometricAllowedMap = new HashMap<>();
|
||||
private static Map<Integer, Boolean> sUserToLockPatternEnabledMap = new HashMap<>();
|
||||
|
||||
private static boolean sIsUserOwnsFrpCredential;
|
||||
|
||||
@@ -53,6 +59,10 @@ public class ShadowLockPatternUtils {
|
||||
sUserToMetricsMap.clear();
|
||||
sUserToProfileMetricsMap.clear();
|
||||
sUserToIsSecureMap.clear();
|
||||
sUserToPatternEverChosenMap.clear();
|
||||
sUserToVisiblePatternEnabledMap.clear();
|
||||
sUserToBiometricAllowedMap.clear();
|
||||
sUserToLockPatternEnabledMap.clear();
|
||||
sDeviceEncryptionEnabled = false;
|
||||
sIsUserOwnsFrpCredential = false;
|
||||
}
|
||||
@@ -136,6 +146,56 @@ public class ShadowLockPatternUtils {
|
||||
sIsUserOwnsFrpCredential = isUserOwnsFrpCredential;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public boolean isVisiblePatternEnabled(int userId) {
|
||||
return sUserToVisiblePatternEnabledMap.getOrDefault(userId, false);
|
||||
}
|
||||
|
||||
public static void setIsVisiblePatternEnabled(int userId, boolean isVisiblePatternEnabled) {
|
||||
sUserToVisiblePatternEnabledMap.put(userId, isVisiblePatternEnabled);
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public boolean isPatternEverChosen(int userId) {
|
||||
return sUserToPatternEverChosenMap.getOrDefault(userId, true);
|
||||
}
|
||||
|
||||
public static void setIsPatternEverChosen(int userId, boolean isPatternEverChosen) {
|
||||
sUserToPatternEverChosenMap.put(userId, isPatternEverChosen);
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public boolean isBiometricAllowedForUser(int userId) {
|
||||
return sUserToBiometricAllowedMap.getOrDefault(userId, false);
|
||||
}
|
||||
|
||||
public static void setIsBiometricAllowedForUser(int userId, boolean isBiometricAllowed) {
|
||||
sUserToBiometricAllowedMap.put(userId, isBiometricAllowed);
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public boolean isLockPatternEnabled(int userId) {
|
||||
return sUserToBiometricAllowedMap.getOrDefault(userId, false);
|
||||
}
|
||||
|
||||
public static void setIsLockPatternEnabled(int userId, boolean isLockPatternEnabled) {
|
||||
sUserToLockPatternEnabledMap.put(userId, isLockPatternEnabled);
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public boolean setLockCredential(@NonNull LockscreenCredential newCredential,
|
||||
@NonNull LockscreenCredential savedCredential, int userHandle) {
|
||||
setIsSecure(userHandle, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public boolean checkCredential(@NonNull LockscreenCredential credential, int userId,
|
||||
@Nullable LockPatternUtils.CheckCredentialProgressCallback progressCallback)
|
||||
throws LockPatternUtils.RequestThrottledException {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void setRequiredPasswordComplexity(int userHandle, int complexity) {
|
||||
sUserToComplexityMap.put(userHandle, complexity);
|
||||
}
|
||||
|
Reference in New Issue
Block a user