/* * 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; import static android.support.test.InstrumentationRegistry.getInstrumentation; import static android.support.test.InstrumentationRegistry.getTargetContext; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertTrue; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager.AppTask; import android.app.KeyguardManager; import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.Intent; import android.support.test.filters.MediumTest; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry; import android.support.test.runner.lifecycle.Stage; import android.support.test.uiautomator.UiDevice; import android.support.test.uiautomator.UiObject; import android.support.test.uiautomator.UiSelector; import android.text.format.DateUtils; import com.android.internal.widget.LockPatternUtils; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import java.util.Collection; import java.util.List; /** * Tests for {@link ChooseLockGenericTest} * * m SettingsTests && * adb install \ * -r -g ${ANDROID_PRODUCT_OUT}/data/app/SettingsTests/SettingsTests.apk && * adb shell am instrument -e class com.android.settings.ChooseLockGenericTest \ * -w com.android.settings.tests/android.support.test.runner.AndroidJUnitRunner */ @RunWith(AndroidJUnit4.class) @MediumTest public class ChooseLockGenericTest { private static final long TIMEOUT = 5 * DateUtils.SECOND_IN_MILLIS; private static final Intent PHISHING_ATTACK_INTENT = new Intent() .putExtra("confirm_credentials", false) .putExtra("password_confirmed", true); private UiDevice mDevice; private Context mTargetContext; private String mSettingPackage; @Rule public ActivityTestRule mChooseLockGenericActivityRule = new ActivityTestRule<>( ChooseLockGeneric.class, true /* enable touch at launch */, false /* don't launch at every test */); @Before public void setUp() throws Exception { mDevice = UiDevice.getInstance(getInstrumentation()); mTargetContext = getInstrumentation().getTargetContext(); mSettingPackage = mTargetContext.getPackageName(); } @Test public void testConfirmLockPasswordShown_deviceWithPassword() throws Throwable { setPassword(); try { // GIVEN a PIN password is set on this device at set up. // WHEN ChooseLockGeneric is launched with no extras. mChooseLockGenericActivityRule.launchActivity(null /* No extras */); // THEN ConfirmLockPassword.InternalActivity is shown. assertThat(getCurrentActivity()) .isInstanceOf(ConfirmLockPassword.InternalActivity.class); } finally { finishAllAppTasks(); mDevice.waitForIdle(); clearPassword(); } } @Test public void testConfirmLockPasswordShown_deviceWithPassword_phishingAttack() throws Throwable { setPassword(); try { // GIVEN a PIN password is set on this device at set up. // WHEN ChooseLockGeneric is launched with extras to by-pass lock password confirmation. mChooseLockGenericActivityRule.launchActivity(PHISHING_ATTACK_INTENT); // THEN ConfirmLockPassword.InternalActivity is still shown. assertThat(getCurrentActivity()) .isInstanceOf(ConfirmLockPassword.InternalActivity.class); } finally { finishAllAppTasks(); mDevice.waitForIdle(); clearPassword(); } } @Test public void testForFingerprint_inflateLayout() { mChooseLockGenericActivityRule.launchActivity(new Intent() .putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true)); assertThat(mChooseLockGenericActivityRule.getActivity().isResumed()).isTrue(); } private Activity getCurrentActivity() throws Throwable { getInstrumentation().waitForIdleSync(); final Activity[] activity = new Activity[1]; getInstrumentation().runOnMainSync(() -> { Collection activities = ActivityLifecycleMonitorRegistry.getInstance() .getActivitiesInStage(Stage.RESUMED); activity[0] = activities.iterator().next(); }); return activity[0]; } /** Sets a PIN password, 12345, for testing. */ private void setPassword() throws Exception { Intent newPasswordIntent = new Intent(getTargetContext(), ChooseLockGeneric.class) .putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) .putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, "12345") .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); getInstrumentation().getContext().startActivity(newPasswordIntent); mDevice.waitForIdle(); // Ignore any interstitial options UiObject view = new UiObject(new UiSelector() .resourceId(mSettingPackage + ":id/encrypt_dont_require_password")); if (view.waitForExists(TIMEOUT)) { view.click(); mDevice.waitForIdle(); } // Set our PIN view = new UiObject(new UiSelector() .resourceId(mSettingPackage + ":id/password_entry")); assertTrue("password_entry", view.waitForExists(TIMEOUT)); // Enter it twice to confirm enterTestPin(view); enterTestPin(view); mDevice.pressBack(); assertThat(getTargetContext().getSystemService(KeyguardManager.class).isDeviceSecure()) .isTrue(); } /** Clears the previous set PIN password. */ private void clearPassword() throws Exception { Intent newPasswordIntent = new Intent(getTargetContext(), ChooseLockGeneric.class) .putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); getInstrumentation().getContext().startActivity(newPasswordIntent); mDevice.waitForIdle(); // Enter current PIN UiObject view = new UiObject( new UiSelector().resourceId(mSettingPackage + ":id/password_entry")); if (!view.waitForExists(TIMEOUT)) { // Odd, maybe there is a crash dialog showing; try dismissing it mDevice.pressBack(); mDevice.waitForIdle(); assertTrue("password_entry", view.waitForExists(TIMEOUT)); } enterTestPin(view); mDevice.pressBack(); assertThat(getTargetContext().getSystemService(KeyguardManager.class).isDeviceSecure()) .isFalse(); } private void finishAllAppTasks() { final ActivityManager activityManager = getTargetContext().getSystemService(ActivityManager.class); final List appTasks = activityManager.getAppTasks(); for (ActivityManager.AppTask task : appTasks) { task.finishAndRemoveTask(); } } private void enterTestPin(UiObject view) throws Exception { mDevice.waitForIdle(); view.setText("12345"); mDevice.pressEnter(); mDevice.waitForIdle(); } }