1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.password; 18 19 import static android.support.test.InstrumentationRegistry.getInstrumentation; 20 import static android.support.test.InstrumentationRegistry.getTargetContext; 21 import static com.google.common.truth.Truth.assertThat; 22 import static org.junit.Assert.assertTrue; 23 24 import android.app.Activity; 25 import android.app.ActivityManager; 26 import android.app.ActivityManager.AppTask; 27 import android.app.KeyguardManager; 28 import android.app.admin.DevicePolicyManager; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.support.test.filters.MediumTest; 32 import android.support.test.rule.ActivityTestRule; 33 import android.support.test.runner.AndroidJUnit4; 34 import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry; 35 import android.support.test.runner.lifecycle.Stage; 36 import android.support.test.uiautomator.UiDevice; 37 import android.support.test.uiautomator.UiObject; 38 import android.support.test.uiautomator.UiSelector; 39 import android.text.format.DateUtils; 40 import android.view.WindowManager; 41 42 import com.android.internal.widget.LockPatternUtils; 43 44 import org.junit.Before; 45 import org.junit.Rule; 46 import org.junit.Test; 47 import org.junit.runner.RunWith; 48 49 import java.util.Collection; 50 import java.util.List; 51 52 /** 53 * Tests for {@link ChooseLockGenericTest} 54 * 55 * m SettingsTests && 56 * adb install \ 57 * -r -g ${ANDROID_PRODUCT_OUT}/data/app/SettingsTests/SettingsTests.apk && 58 * adb shell am instrument -e class com.android.settings.password.ChooseLockGenericTest \ 59 * -w com.android.settings.tests/android.support.test.runner.AndroidJUnitRunner 60 */ 61 @RunWith(AndroidJUnit4.class) 62 @MediumTest 63 public class ChooseLockGenericTest { 64 private static final long TIMEOUT = 5 * DateUtils.SECOND_IN_MILLIS; 65 private static final Intent PHISHING_ATTACK_INTENT = new Intent() 66 .putExtra("confirm_credentials", false) 67 .putExtra("password_confirmed", true); 68 69 private UiDevice mDevice; 70 private Context mTargetContext; 71 private String mSettingPackage; 72 73 @Rule 74 public ActivityTestRule<ChooseLockGeneric> mChooseLockGenericActivityRule = 75 new ActivityTestRule<>( 76 ChooseLockGeneric.class, 77 true /* enable touch at launch */, 78 false /* don't launch at every test */); 79 80 @Before 81 public void setUp() throws Exception { 82 mDevice = UiDevice.getInstance(getInstrumentation()); 83 mTargetContext = getInstrumentation().getTargetContext(); 84 mSettingPackage = mTargetContext.getPackageName(); 85 } 86 87 @Test 88 public void testConfirmLockPasswordShown_deviceWithPassword() throws Throwable { 89 setPassword(); 90 try { 91 // GIVEN a PIN password is set on this device at set up. 92 // WHEN ChooseLockGeneric is launched with no extras. 93 mChooseLockGenericActivityRule.launchActivity(null /* No extras */); 94 // THEN ConfirmLockPassword.InternalActivity is shown. 95 final Activity activity = getCurrentActivity(); 96 assertThat(isSecureWindow(activity)).isTrue(); 97 assertThat(activity) 98 .isInstanceOf(ConfirmLockPassword.InternalActivity.class); 99 } finally { 100 finishAllAppTasks(); 101 mDevice.waitForIdle(); 102 clearPassword(); 103 } 104 } 105 106 @Test 107 public void testConfirmLockPasswordShown_deviceWithPassword_phishingAttack() throws Throwable { 108 setPassword(); 109 try { 110 // GIVEN a PIN password is set on this device at set up. 111 // WHEN ChooseLockGeneric is launched with extras to by-pass lock password confirmation. 112 mChooseLockGenericActivityRule.launchActivity(PHISHING_ATTACK_INTENT); 113 // THEN ConfirmLockPassword.InternalActivity is still shown. 114 final Activity activity = getCurrentActivity(); 115 assertThat(isSecureWindow(activity)).isTrue(); 116 assertThat(activity) 117 .isInstanceOf(ConfirmLockPassword.InternalActivity.class); 118 } finally { 119 finishAllAppTasks(); 120 mDevice.waitForIdle(); 121 clearPassword(); 122 } 123 } 124 125 @Test 126 public void testForFingerprint_inflateLayout() { 127 mChooseLockGenericActivityRule.launchActivity(new Intent() 128 .putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true)); 129 130 assertThat(mChooseLockGenericActivityRule.getActivity().isResumed()).isTrue(); 131 } 132 133 private Activity getCurrentActivity() throws Throwable { 134 getInstrumentation().waitForIdleSync(); 135 final Activity[] activity = new Activity[1]; 136 getInstrumentation().runOnMainSync(() -> { 137 Collection<Activity> activities = ActivityLifecycleMonitorRegistry.getInstance() 138 .getActivitiesInStage(Stage.RESUMED); 139 activity[0] = activities.iterator().next(); 140 }); 141 return activity[0]; 142 } 143 144 /** Sets a PIN password, 12345, for testing. */ 145 private void setPassword() throws Exception { 146 Intent newPasswordIntent = new Intent(getTargetContext(), ChooseLockGeneric.class) 147 .putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, 148 DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) 149 .putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, 150 "12345") 151 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 152 getInstrumentation().getContext().startActivity(newPasswordIntent); 153 mDevice.waitForIdle(); 154 155 156 // Ignore any interstitial options 157 UiObject view = new UiObject(new UiSelector() 158 .resourceId(mSettingPackage + ":id/encrypt_dont_require_password")); 159 if (view.waitForExists(TIMEOUT)) { 160 view.click(); 161 mDevice.waitForIdle(); 162 } 163 164 // Set our PIN 165 view = new UiObject(new UiSelector() 166 .resourceId(mSettingPackage + ":id/password_entry")); 167 assertTrue("password_entry", view.waitForExists(TIMEOUT)); 168 169 // Enter it twice to confirm 170 enterTestPin(view); 171 enterTestPin(view); 172 173 mDevice.pressBack(); 174 175 assertThat(getTargetContext().getSystemService(KeyguardManager.class).isDeviceSecure()) 176 .isTrue(); 177 } 178 179 /** Clears the previous set PIN password. */ 180 private void clearPassword() throws Exception { 181 Intent newPasswordIntent = new Intent(getTargetContext(), ChooseLockGeneric.class) 182 .putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, 183 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) 184 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 185 | Intent.FLAG_ACTIVITY_CLEAR_TASK); 186 getInstrumentation().getContext().startActivity(newPasswordIntent); 187 mDevice.waitForIdle(); 188 189 // Enter current PIN 190 UiObject view = new UiObject( 191 new UiSelector().resourceId(mSettingPackage + ":id/password_entry")); 192 if (!view.waitForExists(TIMEOUT)) { 193 // Odd, maybe there is a crash dialog showing; try dismissing it 194 mDevice.pressBack(); 195 mDevice.waitForIdle(); 196 197 assertTrue("password_entry", view.waitForExists(TIMEOUT)); 198 } 199 200 enterTestPin(view); 201 202 mDevice.pressBack(); 203 204 assertThat(getTargetContext().getSystemService(KeyguardManager.class).isDeviceSecure()) 205 .isFalse(); 206 } 207 208 private void finishAllAppTasks() { 209 final ActivityManager activityManager = 210 getTargetContext().getSystemService(ActivityManager.class); 211 final List<AppTask> appTasks = activityManager.getAppTasks(); 212 for (ActivityManager.AppTask task : appTasks) { 213 task.finishAndRemoveTask(); 214 } 215 } 216 217 private void enterTestPin(UiObject view) throws Exception { 218 mDevice.waitForIdle(); 219 view.setText("12345"); 220 mDevice.pressEnter(); 221 mDevice.waitForIdle(); 222 } 223 224 private boolean isSecureWindow(Activity activity) { 225 return (activity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_SECURE) 226 != 0; 227 } 228 } 229