From 4c930fc2d5bf3a3ea3caf5df6e5eddb6c9a90a60 Mon Sep 17 00:00:00 2001 From: Maurice Lam Date: Fri, 2 Jun 2017 19:22:53 -0700 Subject: [PATCH] Allow skipping PIN setup screen So that setup wizard can show PIN option by default. Test: Added Robolectric and instrumentation tests Bug: 38509560 Change-Id: Id72744dd444b9b026ca5f28f230bae3bec254b2f (cherry picked from commit 0f897d79f698920f1c0e0c102a7985704ffa196e) --- .../SetupFingerprintEnrollIntroduction.java | 7 +- .../settings/password/ChooseLockPassword.java | 2 +- .../settings/password/SetupChooseLockGeneric.java | 1 - .../settings/password/SetupChooseLockPassword.java | 9 ++ .../{fingerprint => password}/SetupSkipDialog.java | 5 +- .../password/SetupChooseLockPasswordAppTest.java | 61 +++++++++++ .../SetupFingerprintEnrollIntroductionTest.java | 111 +++++++++++++++++++++ .../testutils/shadow/ShadowLockPatternUtils.java | 7 ++ .../testutils/shadow/ShadowUserManager.java | 34 +++++++ .../SetupFingerprintEnrollIntroductionTest.java | 109 -------------------- 10 files changed, 228 insertions(+), 118 deletions(-) rename src/com/android/settings/{fingerprint => password}/SetupSkipDialog.java (94%) create mode 100644 tests/app/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java create mode 100644 tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java delete mode 100644 tests/unit/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java index 26b3427396..e6688127f8 100644 --- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java +++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java @@ -28,9 +28,9 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.widget.LockPatternUtils; import com.android.settings.R; import com.android.settings.SetupWizardUtils; -import com.android.settings.password.ChooseLockGeneric; import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment; import com.android.settings.password.SetupChooseLockGeneric; +import com.android.settings.password.SetupSkipDialog; public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction { @@ -98,9 +98,8 @@ public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntrodu setResult(RESULT_SKIP); finish(); } else { - SetupSkipDialog dialog = SetupSkipDialog.newInstance( - getIntent().getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false)); - dialog.show(getFragmentManager()); + setResult(SetupSkipDialog.RESULT_SKIP); + finish(); } } diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java index d4bc076408..b41a40f3c6 100644 --- a/src/com/android/settings/password/ChooseLockPassword.java +++ b/src/com/android/settings/password/ChooseLockPassword.java @@ -201,7 +201,7 @@ public class ChooseLockPassword extends SettingsActivity { private String mFirstPin; private RecyclerView mPasswordRestrictionView; protected boolean mIsAlphaMode; - private Button mCancelButton; + protected Button mCancelButton; private Button mNextButton; private TextChangedHandler mTextChangedHandler; diff --git a/src/com/android/settings/password/SetupChooseLockGeneric.java b/src/com/android/settings/password/SetupChooseLockGeneric.java index 4e73b87d45..179bd797cb 100644 --- a/src/com/android/settings/password/SetupChooseLockGeneric.java +++ b/src/com/android/settings/password/SetupChooseLockGeneric.java @@ -35,7 +35,6 @@ import com.android.settings.R; import com.android.settings.SetupEncryptionInterstitial; import com.android.settings.SetupWizardUtils; import com.android.settings.fingerprint.SetupFingerprintEnrollFindSensor; -import com.android.settings.fingerprint.SetupSkipDialog; import com.android.settings.utils.SettingsDividerItemDecoration; import com.android.setupwizardlib.GlifPreferenceLayout; diff --git a/src/com/android/settings/password/SetupChooseLockPassword.java b/src/com/android/settings/password/SetupChooseLockPassword.java index 0c62c7c1f6..bd935a21eb 100644 --- a/src/com/android/settings/password/SetupChooseLockPassword.java +++ b/src/com/android/settings/password/SetupChooseLockPassword.java @@ -84,6 +84,9 @@ public class SetupChooseLockPassword extends ChooseLockPassword { @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + + mCancelButton.setText(R.string.skip_label); + boolean showOptionsButton = getActivity().getIntent().getBooleanExtra( ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, false); if (showOptionsButton) { @@ -99,6 +102,12 @@ public class SetupChooseLockPassword extends ChooseLockPassword { case R.id.screen_lock_options: launchChooseLockGeneric(); break; + case R.id.cancel_button: + SetupSkipDialog dialog = SetupSkipDialog.newInstance( + getActivity().getIntent() + .getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false)); + dialog.show(getFragmentManager()); + break; default: super.onClick(v); } diff --git a/src/com/android/settings/fingerprint/SetupSkipDialog.java b/src/com/android/settings/password/SetupSkipDialog.java similarity index 94% rename from src/com/android/settings/fingerprint/SetupSkipDialog.java rename to src/com/android/settings/password/SetupSkipDialog.java index 842e69c3c7..36646b7552 100644 --- a/src/com/android/settings/fingerprint/SetupSkipDialog.java +++ b/src/com/android/settings/password/SetupSkipDialog.java @@ -14,12 +14,11 @@ * limitations under the License */ -package com.android.settings.fingerprint; +package com.android.settings.password; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; -import android.app.DialogFragment; import android.app.FragmentManager; import android.content.DialogInterface; import android.os.Bundle; @@ -36,7 +35,7 @@ public class SetupSkipDialog extends InstrumentedDialogFragment private static final String ARG_FRP_SUPPORTED = "frp_supported"; private static final String TAG_SKIP_DIALOG = "skip_dialog"; - private static final int RESULT_SKIP = Activity.RESULT_FIRST_USER + 10; + public static final int RESULT_SKIP = Activity.RESULT_FIRST_USER + 10; public static SetupSkipDialog newInstance(boolean isFrpSupported) { SetupSkipDialog dialog = new SetupSkipDialog(); diff --git a/tests/app/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java b/tests/app/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java new file mode 100644 index 0000000000..78acc3e741 --- /dev/null +++ b/tests/app/src/com/android/settings/password/SetupChooseLockPasswordAppTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2017 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 android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; + +import static com.google.common.truth.Truth.assertThat; + +import android.support.test.filters.MediumTest; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; + +import com.android.settings.R; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@MediumTest +public class SetupChooseLockPasswordAppTest { + + @Rule + public ActivityTestRule mActivityTestRule = + new ActivityTestRule<>( + SetupChooseLockPassword.class, + true /* enable touch at launch */, + false /* don't launch at every test */); + + @Test + public void testSkipDialogIsShown() throws Throwable { + SetupChooseLockPassword activity = mActivityTestRule.launchActivity(null); + + onView(withId(R.id.cancel_button)) + .check(matches(withText(R.string.skip_label))) + .check(matches(isDisplayed())) + .perform(click()); + onView(withId(android.R.id.button1)).check(matches(isDisplayed())).perform(click()); + + assertThat(activity.isFinishing()).named("Is finishing").isTrue(); + } +} diff --git a/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java new file mode 100644 index 0000000000..9ee53efdaf --- /dev/null +++ b/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2017 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.fingerprint; + + +import static com.google.common.truth.Truth.assertThat; + +import static org.robolectric.RuntimeEnvironment.application; + +import android.app.KeyguardManager; +import android.content.Intent; +import android.content.pm.UserInfo; +import android.view.View; +import android.widget.Button; + +import com.android.settings.R; +import com.android.settings.TestConfig; +import com.android.settings.password.SetupSkipDialog; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.ShadowEventLogWriter; +import com.android.settings.testutils.shadow.ShadowLockPatternUtils; +import com.android.settings.testutils.shadow.ShadowUserManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; +import org.robolectric.Shadows; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowActivity; +import org.robolectric.shadows.ShadowKeyguardManager; +import org.robolectric.util.ActivityController; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config( + manifest = TestConfig.MANIFEST_PATH, + sdk = TestConfig.SDK_VERSION, + shadows = { + ShadowEventLogWriter.class, + ShadowLockPatternUtils.class, + ShadowUserManager.class + }) +public class SetupFingerprintEnrollIntroductionTest { + + @Mock + private UserInfo mUserInfo; + + private ActivityController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + final Intent intent = new Intent(); + mController = Robolectric.buildActivity(SetupFingerprintEnrollIntroduction.class, intent); + + ShadowUserManager.getShadow().setUserInfo(0, mUserInfo); + } + + @Test + public void testKeyguardNotSecure_shouldFinishWithSetupSkipDialogResultSkip() { + getShadowKeyguardManager().setIsKeyguardSecure(false); + + mController.create().resume(); + + final Button skipButton = mController.get().findViewById(R.id.fingerprint_cancel_button); + assertThat(skipButton.getVisibility()).named("Skip visible").isEqualTo(View.VISIBLE); + skipButton.performClick(); + + ShadowActivity shadowActivity = Shadows.shadowOf(mController.get()); + assertThat(mController.get().isFinishing()).named("Is finishing").isTrue(); + assertThat(shadowActivity.getResultCode()).named("Result code") + .isEqualTo(SetupSkipDialog.RESULT_SKIP); + } + + @Test + public void testKeyguardSecure_shouldFinishWithFingerprintResultSkip() { + getShadowKeyguardManager().setIsKeyguardSecure(true); + + mController.create().resume(); + + final Button skipButton = mController.get().findViewById(R.id.fingerprint_cancel_button); + assertThat(skipButton.getVisibility()).named("Skip visible").isEqualTo(View.VISIBLE); + skipButton.performClick(); + + ShadowActivity shadowActivity = Shadows.shadowOf(mController.get()); + assertThat(mController.get().isFinishing()).named("Is finishing").isTrue(); + assertThat(shadowActivity.getResultCode()).named("Result code") + .isEqualTo(FingerprintEnrollBase.RESULT_SKIP); + } + + private ShadowKeyguardManager getShadowKeyguardManager() { + return Shadows.shadowOf(application.getSystemService(KeyguardManager.class)); + } +} diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java index b1419ba8e3..7c56dc6ba8 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java @@ -16,6 +16,8 @@ package com.android.settings.testutils.shadow; +import android.app.admin.DevicePolicyManager; + import com.android.internal.widget.LockPatternUtils; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; @@ -27,4 +29,9 @@ public class ShadowLockPatternUtils { public boolean isSecure(int id) { return true; } + + @Implementation + public int getActivePasswordQuality(int userId) { + return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; + } } diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java index c67ad36f93..61346bc371 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java @@ -16,11 +16,19 @@ package com.android.settings.testutils.shadow; +import android.annotation.UserIdInt; import android.content.Context; +import android.content.pm.UserInfo; import android.os.UserManager; +import android.util.SparseArray; +import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; +import org.robolectric.internal.ShadowExtractor; + +import java.util.Collections; +import java.util.List; /** * This class provides the API 24 implementation of UserManager.get(Context). @@ -28,8 +36,34 @@ import org.robolectric.annotation.Implements; @Implements(UserManager.class) public class ShadowUserManager { + private SparseArray mUserInfos = new SparseArray<>(); + + public void setUserInfo(int userHandle, UserInfo userInfo) { + mUserInfos.put(userHandle, userInfo); + } + + @Implementation + public UserInfo getUserInfo(int userHandle) { + return mUserInfos.get(userHandle); + } + + @Implementation + public List getProfiles(@UserIdInt int userHandle) { + return Collections.emptyList(); + } + + @Implementation + public int getCredentialOwnerProfile(@UserIdInt int userHandle) { + return userHandle; + } + @Implementation public static UserManager get(Context context) { return (UserManager) context.getSystemService(Context.USER_SERVICE); } + + public static ShadowUserManager getShadow() { + return (ShadowUserManager) ShadowExtractor.extract( + RuntimeEnvironment.application.getSystemService(UserManager.class)); + } } diff --git a/tests/unit/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java b/tests/unit/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java deleted file mode 100644 index 8afed185cb..0000000000 --- a/tests/unit/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2017 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.fingerprint; - - -import static org.mockito.Mockito.doReturn; - -import android.app.KeyguardManager; -import android.content.Context; -import android.content.ContextWrapper; -import android.content.Intent; -import android.test.ActivityUnitTestCase; -import android.view.View; -import android.widget.Button; - -import com.android.settings.R; - -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -public class SetupFingerprintEnrollIntroductionTest - extends ActivityUnitTestCase { - - private TestContext mContext; - - @Mock - private KeyguardManager mKeyguardManager; - - private SetupFingerprintEnrollIntroduction mActivity; - - public SetupFingerprintEnrollIntroductionTest() { - super(SetupFingerprintEnrollIntroduction.class); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - MockitoAnnotations.initMocks(this); - mContext = new TestContext(getInstrumentation().getTargetContext()); - setActivityContext(mContext); - - getInstrumentation().runOnMainSync(() -> { - final Intent intent = new Intent(); - mActivity = startActivity(intent, - null /* savedInstanceState */, null /* lastNonConfigurationInstance */); - }); - } - - public void testKeyguardNotSecure_shouldShowSkipDialog() { - doReturn(false).when(mKeyguardManager).isKeyguardSecure(); - - getInstrumentation().runOnMainSync(() -> { - getInstrumentation().callActivityOnCreate(mActivity, null); - getInstrumentation().callActivityOnResume(mActivity); - - final Button skipButton = - (Button) mActivity.findViewById(R.id.fingerprint_cancel_button); - assertEquals(View.VISIBLE, skipButton.getVisibility()); - skipButton.performClick(); - }); - - assertFalse(isFinishCalled()); - } - - public void testKeyguardSecure_shouldNotShowSkipDialog() { - doReturn(true).when(mKeyguardManager).isKeyguardSecure(); - - getInstrumentation().runOnMainSync(() -> { - getInstrumentation().callActivityOnCreate(mActivity, null); - getInstrumentation().callActivityOnResume(mActivity); - - final Button skipButton = - (Button) mActivity.findViewById(R.id.fingerprint_cancel_button); - assertEquals(View.VISIBLE, skipButton.getVisibility()); - skipButton.performClick(); - }); - - assertTrue(isFinishCalled()); - } - - public class TestContext extends ContextWrapper { - - public TestContext(Context base) { - super(base); - } - - @Override - public Object getSystemService(String name) { - if (Context.KEYGUARD_SERVICE.equals(name)) { - return mKeyguardManager; - } - return super.getSystemService(name); - } - } -} -- 2.11.0