From f2063cff30bfff1b8e08e4ff8bced9c20b6224ee Mon Sep 17 00:00:00 2001 From: Maurice Lam Date: Wed, 6 Sep 2017 20:52:22 -0700 Subject: [PATCH] Don't default to PIN on non FBE devices. DO NOT MERGE So that EncryptionInterstitial is shown as part of the flow Test: cd tests/robotests && mma Bug: 65192141 Change-Id: I13e8b9059aae39cef2a8509f9f0eee1cd0808220 --- .../SetupFingerprintEnrollIntroduction.java | 14 ++- .../password/StorageManagerWrapper.java | 29 +++++ ...etupFingerprintEnrollIntroductionTest.java | 55 ++++++++++ .../shadow/ShadowFingerprintManager.java | 102 ++++++++++++++++++ 4 files changed, 195 insertions(+), 5 deletions(-) create mode 100644 src/com/android/settings/password/StorageManagerWrapper.java create mode 100644 tests/robotests/src/com/android/settings/testutils/shadow/ShadowFingerprintManager.java diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java index 59907cf493b..5656a27d540 100644 --- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java +++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java @@ -32,6 +32,7 @@ import com.android.settings.SetupWizardUtils; import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment; import com.android.settings.password.SetupChooseLockGeneric; import com.android.settings.password.SetupSkipDialog; +import com.android.settings.password.StorageManagerWrapper; public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction { private static final String KEY_LOCK_SCREEN_PRESENT = "wasLockScreenPresent"; @@ -56,11 +57,14 @@ public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntrodu @Override protected Intent getChooseLockIntent() { - Intent intent = new Intent(this, SetupChooseLockGeneric.class) - .putExtra( - LockPatternUtils.PASSWORD_TYPE_KEY, - DevicePolicyManager.PASSWORD_QUALITY_NUMERIC); - intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true); + Intent intent = new Intent(this, SetupChooseLockGeneric.class); + + if (StorageManagerWrapper.isFileEncryptedNativeOrEmulated()) { + intent.putExtra( + LockPatternUtils.PASSWORD_TYPE_KEY, + DevicePolicyManager.PASSWORD_QUALITY_NUMERIC); + intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true); + } SetupWizardUtils.copySetupExtras(getIntent(), intent); return intent; } diff --git a/src/com/android/settings/password/StorageManagerWrapper.java b/src/com/android/settings/password/StorageManagerWrapper.java new file mode 100644 index 00000000000..5adfaf2e51c --- /dev/null +++ b/src/com/android/settings/password/StorageManagerWrapper.java @@ -0,0 +1,29 @@ +/* + * 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 android.os.storage.StorageManager; + +/** + * Wrapper class to allow Robolectric to shadow methods introduced in newer API + */ +public class StorageManagerWrapper { + + public static boolean isFileEncryptedNativeOrEmulated() { + return StorageManager.isFileEncryptedNativeOrEmulated(); + } +} diff --git a/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java index 801ee5dbfb2..f5859acf52d 100644 --- a/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java +++ b/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java @@ -23,28 +23,38 @@ import static org.robolectric.RuntimeEnvironment.application; import android.app.KeyguardManager; import android.content.Intent; +import android.content.pm.PackageManager; 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.fingerprint.SetupFingerprintEnrollIntroductionTest + .ShadowStorageManagerWrapper; import com.android.settings.password.SetupChooseLockGeneric.SetupChooseLockGenericFragment; import com.android.settings.password.SetupSkipDialog; +import com.android.settings.password.StorageManagerWrapper; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.ShadowEventLogWriter; +import com.android.settings.testutils.shadow.ShadowFingerprintManager; import com.android.settings.testutils.shadow.ShadowLockPatternUtils; import com.android.settings.testutils.shadow.ShadowUserManager; +import org.junit.After; 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.RuntimeEnvironment; import org.robolectric.Shadows; import org.robolectric.annotation.Config; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; import org.robolectric.shadows.ShadowActivity; +import org.robolectric.shadows.ShadowActivity.IntentForResult; import org.robolectric.shadows.ShadowKeyguardManager; import org.robolectric.util.ActivityController; @@ -54,7 +64,9 @@ import org.robolectric.util.ActivityController; sdk = TestConfig.SDK_VERSION, shadows = { ShadowEventLogWriter.class, + ShadowFingerprintManager.class, ShadowLockPatternUtils.class, + ShadowStorageManagerWrapper.class, ShadowUserManager.class }) public class SetupFingerprintEnrollIntroductionTest { @@ -68,12 +80,22 @@ public class SetupFingerprintEnrollIntroductionTest { public void setUp() { MockitoAnnotations.initMocks(this); + RuntimeEnvironment.getRobolectricPackageManager() + .setSystemFeature(PackageManager.FEATURE_FINGERPRINT, true); + ShadowFingerprintManager.addToServiceMap(); + final Intent intent = new Intent(); mController = Robolectric.buildActivity(SetupFingerprintEnrollIntroduction.class, intent); ShadowUserManager.getShadow().setUserInfo(0, mUserInfo); } + @After + public void tearDown() { + ShadowStorageManagerWrapper.reset(); + ShadowFingerprintManager.reset(); + } + @Test public void testKeyguardNotSecure_shouldFinishWithSetupSkipDialogResultSkip() { getShadowKeyguardManager().setIsKeyguardSecure(false); @@ -188,8 +210,41 @@ public class SetupFingerprintEnrollIntroductionTest { assertThat(Shadows.shadowOf(activity).getResultIntent()).isNull(); } + @Test + public void testLockPattern() { + ShadowStorageManagerWrapper.sIsFileEncrypted = false; + + mController.create().postCreate(null).resume(); + + SetupFingerprintEnrollIntroduction activity = mController.get(); + + final Button nextButton = activity.findViewById(R.id.fingerprint_next_button); + nextButton.performClick(); + + ShadowActivity shadowActivity = Shadows.shadowOf(activity); + IntentForResult startedActivity = shadowActivity.getNextStartedActivityForResult(); + assertThat(startedActivity).isNotNull(); + assertThat(startedActivity.intent.hasExtra( + SetupChooseLockGenericFragment.EXTRA_PASSWORD_QUALITY)).isFalse(); + } + private ShadowKeyguardManager getShadowKeyguardManager() { return Shadows.shadowOf(application.getSystemService(KeyguardManager.class)); } + + @Implements(StorageManagerWrapper.class) + public static class ShadowStorageManagerWrapper { + + private static boolean sIsFileEncrypted = true; + + public static void reset() { + sIsFileEncrypted = true; + } + + @Implementation + public static boolean isFileEncryptedNativeOrEmulated() { + return sIsFileEncrypted; + } + } } diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowFingerprintManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowFingerprintManager.java new file mode 100644 index 00000000000..b84cf42ed14 --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowFingerprintManager.java @@ -0,0 +1,102 @@ +/* + * 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.testutils.shadow; + +import android.content.Context; +import android.hardware.fingerprint.Fingerprint; +import android.hardware.fingerprint.FingerprintManager; +import android.support.annotation.NonNull; + +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.annotation.Resetter; +import org.robolectric.internal.ShadowExtractor; +import org.robolectric.shadows.ShadowContextImpl; +import org.robolectric.util.ReflectionHelpers; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; + +@Implements(FingerprintManager.class) +public class ShadowFingerprintManager { + + private static Map getSystemServiceMap() { + return ReflectionHelpers.getStaticField(ShadowContextImpl.class, "SYSTEM_SERVICE_MAP"); + } + + /** + * Call this in @Before of a test to add FingerprintManager to Robolectric's system service + * map. Otherwise getSystemService(FINGERPRINT_SERVICE) will return null. + */ + public static void addToServiceMap() { + getSystemServiceMap().put(Context.FINGERPRINT_SERVICE, FingerprintManager.class.getName()); + } + + @Resetter + public static void reset() { + getSystemServiceMap().remove(Context.FINGERPRINT_SERVICE); + } + + public boolean hardwareDetected = true; + + @NonNull + private List mFingerprints = Collections.emptyList(); + + @Implementation + public boolean isHardwareDetected() { + return hardwareDetected; + } + + @Implementation + public boolean hasEnrolledFingerprints() { + return !mFingerprints.isEmpty(); + } + + @Implementation + public List getEnrolledFingerprints() { + return mFingerprints; + } + + @Implementation + public List getEnrolledFingerprints(int userId) { + return mFingerprints; + } + + public void setEnrolledFingerprints(Fingerprint... fingerprints) { + mFingerprints = Arrays.asList(fingerprints); + } + + public void setDefaultFingerprints(int num) { + setEnrolledFingerprints( + IntStream.range(0, num) + .mapToObj(i -> new Fingerprint( + "Fingerprint " + i, + 0, /* groupId */ + i, /* fingerId */ + 0 /* deviceId */)) + .toArray(Fingerprint[]::new)); + } + + public static ShadowFingerprintManager get() { + return (ShadowFingerprintManager) ShadowExtractor.extract( + RuntimeEnvironment.application.getSystemService(FingerprintManager.class)); + } +}