Home | History | Annotate | Download | only in password
      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