1 /* 2 * Copyright (C) 2016 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 android.server.wm.keyguard; 18 19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 20 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 21 import static android.server.wm.CliIntentExtra.extraString; 22 import static android.server.wm.MockImeHelper.createManagedMockImeSession; 23 import static android.server.wm.UiDeviceUtils.pressBackButton; 24 import static android.server.wm.app.Components.DISMISS_KEYGUARD_ACTIVITY; 25 import static android.server.wm.app.Components.DISMISS_KEYGUARD_METHOD_ACTIVITY; 26 import static android.server.wm.app.Components.PIP_ACTIVITY; 27 import static android.server.wm.app.Components.PipActivity.ACTION_ENTER_PIP; 28 import static android.server.wm.app.Components.PipActivity.EXTRA_DISMISS_KEYGUARD; 29 import static android.server.wm.app.Components.PipActivity.EXTRA_ENTER_PIP; 30 import static android.server.wm.app.Components.PipActivity.EXTRA_SHOW_OVER_KEYGUARD; 31 import static android.server.wm.app.Components.SHOW_WHEN_LOCKED_ACTIVITY; 32 import static android.server.wm.app.Components.SHOW_WHEN_LOCKED_ATTR_IME_ACTIVITY; 33 import static android.server.wm.app.Components.TURN_SCREEN_ON_ATTR_DISMISS_KEYGUARD_ACTIVITY; 34 import static android.view.Display.DEFAULT_DISPLAY; 35 import static android.view.WindowInsets.Type.ime; 36 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE; 37 38 import static androidx.test.InstrumentationRegistry.getInstrumentation; 39 40 import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent; 41 42 import static org.junit.Assert.assertFalse; 43 import static org.junit.Assert.assertTrue; 44 import static org.junit.Assume.assumeFalse; 45 import static org.junit.Assume.assumeTrue; 46 47 import android.app.Activity; 48 import android.app.KeyguardManager; 49 import android.os.Bundle; 50 import android.os.SystemClock; 51 import android.platform.test.annotations.Presubmit; 52 import android.server.wm.ActivityManagerTestBase; 53 import android.server.wm.KeyguardTestBase; 54 import android.server.wm.LockScreenSession; 55 import android.view.View; 56 import android.widget.EditText; 57 import android.widget.LinearLayout; 58 59 import androidx.test.InstrumentationRegistry; 60 import androidx.test.filters.FlakyTest; 61 62 import com.android.compatibility.common.util.CtsTouchUtils; 63 import com.android.compatibility.common.util.PollingCheck; 64 import com.android.cts.mockime.ImeEventStream; 65 import com.android.cts.mockime.MockImeSession; 66 67 import org.junit.Before; 68 import org.junit.Test; 69 70 import java.util.concurrent.TimeUnit; 71 72 /** 73 * Build/Install/Run: 74 * atest CtsWindowManagerDeviceKeyguard:KeyguardLockedTests 75 */ 76 @Presubmit 77 @android.server.wm.annotation.Group2 78 public class KeyguardLockedTests extends KeyguardTestBase { 79 80 private static final long TIMEOUT_IME = TimeUnit.SECONDS.toMillis(5); 81 82 private final CtsTouchUtils mCtsTouchUtils = 83 new CtsTouchUtils(InstrumentationRegistry.getTargetContext()); 84 85 @Before 86 @Override setUp()87 public void setUp() throws Exception { 88 super.setUp(); 89 assumeTrue(supportsSecureLock()); 90 } 91 92 @Test testLockAndUnlock()93 public void testLockAndUnlock() { 94 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 95 lockScreenSession.setLockCredential().gotoKeyguard(); 96 97 assertTrue(mKeyguardManager.isKeyguardLocked()); 98 assertTrue(mKeyguardManager.isDeviceLocked()); 99 assertTrue(mKeyguardManager.isDeviceSecure()); 100 assertTrue(mKeyguardManager.isKeyguardSecure()); 101 mWmState.assertKeyguardShowingAndNotOccluded(); 102 103 lockScreenSession.unlockDevice().enterAndConfirmLockCredential(); 104 105 mWmState.waitAndAssertKeyguardGone(); 106 assertFalse(mKeyguardManager.isDeviceLocked()); 107 assertFalse(mKeyguardManager.isKeyguardLocked()); 108 } 109 110 @Test testDisableKeyguard_thenSettingCredential_reenablesKeyguard_b119322269()111 public void testDisableKeyguard_thenSettingCredential_reenablesKeyguard_b119322269() { 112 final KeyguardManager.KeyguardLock keyguardLock = mContext.getSystemService( 113 KeyguardManager.class).newKeyguardLock("KeyguardLockedTests"); 114 115 try (LockScreenSession lockScreenSession = 116 new LockScreenSession(mInstrumentation, mWmState)) { 117 lockScreenSession.gotoKeyguard(); 118 keyguardLock.disableKeyguard(); 119 120 lockScreenSession.setLockCredential(); 121 lockScreenSession.gotoKeyguard(); 122 123 mWmState.waitForKeyguardShowingAndNotOccluded(); 124 mWmState.assertKeyguardShowingAndNotOccluded(); 125 assertTrue(mKeyguardManager.isKeyguardLocked()); 126 assertTrue(mKeyguardManager.isDeviceLocked()); 127 assertTrue(mKeyguardManager.isDeviceSecure()); 128 assertTrue(mKeyguardManager.isKeyguardSecure()); 129 } finally { 130 keyguardLock.reenableKeyguard(); 131 } 132 } 133 134 @Test testDismissKeyguard()135 public void testDismissKeyguard() { 136 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 137 lockScreenSession.setLockCredential().gotoKeyguard(); 138 139 mWmState.assertKeyguardShowingAndNotOccluded(); 140 launchActivity(DISMISS_KEYGUARD_ACTIVITY); 141 lockScreenSession.enterAndConfirmLockCredential(); 142 143 mWmState.waitAndAssertKeyguardGone(); 144 mWmState.assertVisibility(DISMISS_KEYGUARD_ACTIVITY, true); 145 } 146 147 @Test testDismissKeyguard_whileOccluded()148 public void testDismissKeyguard_whileOccluded() { 149 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 150 lockScreenSession.setLockCredential().gotoKeyguard(); 151 152 mWmState.assertKeyguardShowingAndNotOccluded(); 153 launchActivity(SHOW_WHEN_LOCKED_ACTIVITY); 154 mWmState.computeState(SHOW_WHEN_LOCKED_ACTIVITY); 155 mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true); 156 157 launchActivity(DISMISS_KEYGUARD_ACTIVITY); 158 lockScreenSession.enterAndConfirmLockCredential(); 159 mWmState.waitAndAssertKeyguardGone(); 160 mWmState.computeState(DISMISS_KEYGUARD_ACTIVITY); 161 162 final boolean isDismissTranslucent = mWmState 163 .isActivityTranslucent(DISMISS_KEYGUARD_ACTIVITY); 164 mWmState.assertVisibility(DISMISS_KEYGUARD_ACTIVITY, true); 165 mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, isDismissTranslucent); 166 } 167 168 @Test testDismissKeyguard_fromShowWhenLocked_notAllowed()169 public void testDismissKeyguard_fromShowWhenLocked_notAllowed() { 170 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 171 lockScreenSession.setLockCredential().gotoKeyguard(); 172 173 mWmState.assertKeyguardShowingAndNotOccluded(); 174 launchActivity(SHOW_WHEN_LOCKED_ACTIVITY); 175 mWmState.computeState(SHOW_WHEN_LOCKED_ACTIVITY); 176 mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true); 177 mBroadcastActionTrigger.dismissKeyguardByFlag(); 178 lockScreenSession.enterAndConfirmLockCredential(); 179 180 // Make sure we stay on Keyguard. 181 mWmState.assertKeyguardShowingAndOccluded(); 182 mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true); 183 } 184 185 @Test testDismissKeyguardIfInsecure_notAllowed()186 public void testDismissKeyguardIfInsecure_notAllowed() { 187 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 188 lockScreenSession.setLockCredential().gotoKeyguard(); 189 190 mWmState.assertKeyguardShowingAndNotOccluded(); 191 launchActivityWithDismissKeyguardIfInsecure(SHOW_WHEN_LOCKED_ACTIVITY); 192 mWmState.computeState(SHOW_WHEN_LOCKED_ACTIVITY); 193 mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true); 194 195 // Make sure we stay on Keyguard. 196 mWmState.assertKeyguardShowingAndOccluded(); 197 } 198 199 @Test testDismissKeyguardActivity_method()200 public void testDismissKeyguardActivity_method() { 201 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 202 lockScreenSession.setLockCredential(); 203 separateTestJournal(); 204 205 lockScreenSession.gotoKeyguard(); 206 mWmState.computeState(); 207 assertTrue(mWmState.getKeyguardControllerState().isKeyguardShowing()); 208 209 launchActivity(DISMISS_KEYGUARD_METHOD_ACTIVITY); 210 lockScreenSession.enterAndConfirmLockCredential(); 211 mWmState.waitForKeyguardGone(); 212 mWmState.computeState(DISMISS_KEYGUARD_METHOD_ACTIVITY); 213 mWmState.assertVisibility(DISMISS_KEYGUARD_METHOD_ACTIVITY, true); 214 assertFalse(mWmState.getKeyguardControllerState().isKeyguardShowing()); 215 assertOnDismissSucceeded(DISMISS_KEYGUARD_METHOD_ACTIVITY); 216 } 217 218 @Test testDismissKeyguardActivity_method_cancelled()219 public void testDismissKeyguardActivity_method_cancelled() { 220 // Pressing the back button does not cancel Keyguard in AAOS. 221 assumeFalse(isCar()); 222 223 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 224 lockScreenSession.setLockCredential(); 225 separateTestJournal(); 226 227 lockScreenSession.gotoKeyguard(); 228 mWmState.computeState(); 229 assertTrue(mWmState.getKeyguardControllerState().isKeyguardShowing()); 230 231 launchActivity(DISMISS_KEYGUARD_METHOD_ACTIVITY); 232 pressBackButton(); 233 assertOnDismissCancelled(DISMISS_KEYGUARD_METHOD_ACTIVITY); 234 mWmState.computeState(); 235 mWmState.assertVisibility(DISMISS_KEYGUARD_METHOD_ACTIVITY, false); 236 assertTrue(mWmState.getKeyguardControllerState().isKeyguardShowing()); 237 } 238 239 @Test testDismissKeyguardAttrActivity_method_turnScreenOn_withSecureKeyguard()240 public void testDismissKeyguardAttrActivity_method_turnScreenOn_withSecureKeyguard() { 241 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 242 lockScreenSession.setLockCredential().sleepDevice(); 243 mWmState.computeState(); 244 assertTrue(mWmState.getKeyguardControllerState().isKeyguardShowing()); 245 246 launchActivity(TURN_SCREEN_ON_ATTR_DISMISS_KEYGUARD_ACTIVITY); 247 mWmState.waitForKeyguardShowingAndNotOccluded(); 248 mWmState.assertVisibility(TURN_SCREEN_ON_ATTR_DISMISS_KEYGUARD_ACTIVITY, false); 249 assertTrue(mWmState.getKeyguardControllerState().isKeyguardShowing()); 250 assertTrue(ActivityManagerTestBase.isDisplayOn(DEFAULT_DISPLAY)); 251 } 252 253 @Test testEnterPipOverKeyguard()254 public void testEnterPipOverKeyguard() { 255 assumeTrue(supportsPip()); 256 257 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 258 lockScreenSession.setLockCredential(); 259 260 // Show the PiP activity in fullscreen. 261 launchActivity(PIP_ACTIVITY, extraString(EXTRA_SHOW_OVER_KEYGUARD, "true")); 262 263 // Lock the screen and ensure that the PiP activity showing over the LockScreen. 264 lockScreenSession.gotoKeyguard(PIP_ACTIVITY); 265 mWmState.waitForKeyguardShowingAndOccluded(); 266 mWmState.assertKeyguardShowingAndOccluded(); 267 268 // Request that the PiP activity enter picture-in-picture mode (ensure it does not). 269 mBroadcastActionTrigger.doAction(ACTION_ENTER_PIP); 270 waitForEnterPip(PIP_ACTIVITY); 271 mWmState.assertDoesNotContainStack("Must not contain pinned stack.", 272 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD); 273 274 // Enter the credentials and ensure that the activity actually entered picture-in-picture. 275 lockScreenSession.enterAndConfirmLockCredential(); 276 mWmState.waitAndAssertKeyguardGone(); 277 waitForEnterPip(PIP_ACTIVITY); 278 mWmState.assertContainsStack("Must contain pinned stack.", WINDOWING_MODE_PINNED, 279 ACTIVITY_TYPE_STANDARD); 280 } 281 282 @Test testShowWhenLockedActivityAndPipActivity()283 public void testShowWhenLockedActivityAndPipActivity() { 284 assumeTrue(supportsPip()); 285 286 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 287 lockScreenSession.setLockCredential(); 288 289 // Show an activity in PIP. 290 launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true")); 291 waitForEnterPip(PIP_ACTIVITY); 292 mWmState.assertContainsStack("Must contain pinned stack.", WINDOWING_MODE_PINNED, 293 ACTIVITY_TYPE_STANDARD); 294 mWmState.assertVisibility(PIP_ACTIVITY, true); 295 296 // Show an activity that will keep above the keyguard. 297 launchActivity(SHOW_WHEN_LOCKED_ACTIVITY); 298 mWmState.computeState(SHOW_WHEN_LOCKED_ACTIVITY); 299 mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true); 300 301 // Lock the screen and ensure that the fullscreen activity showing over the lockscreen 302 // is visible, but not the PiP activity. 303 lockScreenSession.gotoKeyguard(SHOW_WHEN_LOCKED_ACTIVITY); 304 mWmState.computeState(); 305 mWmState.assertKeyguardShowingAndOccluded(); 306 mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true); 307 mWmState.assertVisibility(PIP_ACTIVITY, false); 308 } 309 310 @Test testShowWhenLockedPipActivity()311 public void testShowWhenLockedPipActivity() { 312 assumeTrue(supportsPip()); 313 314 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 315 lockScreenSession.setLockCredential(); 316 317 // Show an activity in PIP. 318 launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true"), 319 extraString(EXTRA_SHOW_OVER_KEYGUARD, "true")); 320 waitForEnterPip(PIP_ACTIVITY); 321 mWmState.assertContainsStack("Must contain pinned stack.", WINDOWING_MODE_PINNED, 322 ACTIVITY_TYPE_STANDARD); 323 mWmState.assertVisibility(PIP_ACTIVITY, true); 324 325 // Lock the screen and ensure the PiP activity is not visible on the lockscreen even 326 // though it's marked as showing over the lockscreen itself. 327 lockScreenSession.gotoKeyguard(); 328 mWmState.assertKeyguardShowingAndNotOccluded(); 329 mWmState.assertVisibility(PIP_ACTIVITY, false); 330 } 331 332 @Test testDismissKeyguardPipActivity()333 public void testDismissKeyguardPipActivity() { 334 assumeTrue(supportsPip()); 335 336 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 337 // Show an activity in PIP. 338 launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true"), 339 extraString(EXTRA_DISMISS_KEYGUARD, "true")); 340 waitForEnterPip(PIP_ACTIVITY); 341 mWmState.assertContainsStack("Must contain pinned stack.", WINDOWING_MODE_PINNED, 342 ACTIVITY_TYPE_STANDARD); 343 mWmState.assertVisibility(PIP_ACTIVITY, true); 344 345 // Lock the screen and ensure the PiP activity is not visible on the lockscreen even 346 // though it's marked as dismiss keyguard. 347 lockScreenSession.gotoKeyguard(); 348 mWmState.computeState(); 349 mWmState.assertKeyguardShowingAndNotOccluded(); 350 mWmState.assertVisibility(PIP_ACTIVITY, false); 351 } 352 353 @Test testShowWhenLockedAttrImeActivityAndShowSoftInput()354 public void testShowWhenLockedAttrImeActivityAndShowSoftInput() throws Exception { 355 assumeTrue(MSG_NO_MOCK_IME, supportsInstallableIme()); 356 357 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 358 final MockImeSession mockImeSession = createManagedMockImeSession(this); 359 360 lockScreenSession.setLockCredential().gotoKeyguard(); 361 mWmState.assertKeyguardShowingAndNotOccluded(); 362 launchActivity(SHOW_WHEN_LOCKED_ATTR_IME_ACTIVITY); 363 mWmState.computeState(SHOW_WHEN_LOCKED_ATTR_IME_ACTIVITY); 364 mWmState.assertVisibility(SHOW_WHEN_LOCKED_ATTR_IME_ACTIVITY, true); 365 366 // Make sure the activity has been called showSoftInput & IME window is visible. 367 final ImeEventStream stream = mockImeSession.openEventStream(); 368 expectEvent(stream, event -> "showSoftInput".equals(event.getEventName()), 369 TIMEOUT_IME); 370 // Assert the IME is shown on the expected display. 371 mWmState.waitAndAssertImeWindowShownOnDisplay(DEFAULT_DISPLAY); 372 } 373 374 @Test testShowWhenLockedImeActivityAndShowSoftInput()375 public void testShowWhenLockedImeActivityAndShowSoftInput() throws Exception { 376 assumeTrue(MSG_NO_MOCK_IME, supportsInstallableIme()); 377 378 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 379 final MockImeSession mockImeSession = createManagedMockImeSession(this); 380 final TestActivitySession<ShowWhenLockedImeActivity> imeTestActivitySession = 381 createManagedTestActivitySession(); 382 383 lockScreenSession.setLockCredential().gotoKeyguard(); 384 mWmState.assertKeyguardShowingAndNotOccluded(); 385 imeTestActivitySession.launchTestActivityOnDisplaySync(ShowWhenLockedImeActivity.class, 386 DEFAULT_DISPLAY); 387 388 // Make sure the activity has been called showSoftInput & IME window is visible. 389 final ImeEventStream stream = mockImeSession.openEventStream(); 390 expectEvent(stream, event -> "showSoftInput".equals(event.getEventName()), 391 TIMEOUT_IME); 392 // Assert the IME is shown on the expected display. 393 mWmState.waitAndAssertImeWindowShownOnDisplay(DEFAULT_DISPLAY); 394 395 } 396 397 @Test 398 @FlakyTest(bugId = 297247946) testImeShowsAfterLockScreenOnEditorTap()399 public void testImeShowsAfterLockScreenOnEditorTap() throws Exception { 400 assumeTrue(MSG_NO_MOCK_IME, supportsInstallableIme()); 401 402 final MockImeSession mockImeSession = createManagedMockImeSession(this); 403 final LockScreenSession lockScreenSession = createManagedLockScreenSession(); 404 final TestActivitySession<ShowImeAfterLockscreenActivity> imeTestActivitySession = 405 createManagedTestActivitySession(); 406 imeTestActivitySession.launchTestActivityOnDisplaySync(ShowImeAfterLockscreenActivity.class, 407 DEFAULT_DISPLAY); 408 409 final ShowImeAfterLockscreenActivity activity = imeTestActivitySession.getActivity(); 410 final View rootView = activity.getWindow().getDecorView(); 411 412 mCtsTouchUtils.emulateTapOnViewCenter(getInstrumentation(), null, activity.mEditor); 413 PollingCheck.waitFor( 414 TIMEOUT_IME, 415 () -> rootView.getRootWindowInsets().isVisible(ime())); 416 417 lockScreenSession.setLockCredential().gotoKeyguard(); 418 assertTrue( 419 "Keyguard is showing", mWmState.getKeyguardControllerState().isKeyguardShowing()); 420 lockScreenSession.unlockDevice().enterAndConfirmLockCredential(); 421 mWmState.waitAndAssertKeyguardGone(); 422 423 final ImeEventStream stream = mockImeSession.openEventStream(); 424 425 mCtsTouchUtils.emulateTapOnViewCenter(getInstrumentation(), null, activity.mEditor); 426 427 // Make sure the activity has been called showSoftInput & IME window is visible. 428 expectEvent(stream, event -> "showSoftInput".equals(event.getEventName()), 429 TimeUnit.SECONDS.toMillis(5) /* eventTimeout */); 430 // Assert the IME is shown event on the expected display. 431 mWmState.waitAndAssertImeWindowShownOnDisplay(DEFAULT_DISPLAY); 432 // Check if IME is actually visible. 433 PollingCheck.waitFor( 434 TIMEOUT_IME, 435 () -> rootView.getRootWindowInsets().isVisible(ime())); 436 } 437 438 public static class ShowImeAfterLockscreenActivity extends Activity { 439 440 EditText mEditor; 441 442 @Override onCreate(Bundle icicle)443 protected void onCreate(Bundle icicle) { 444 super.onCreate(icicle); 445 mEditor = createViews(this, false /* showWhenLocked */); 446 } 447 } 448 449 public static class ShowWhenLockedImeActivity extends Activity { 450 451 @Override onCreate(Bundle icicle)452 protected void onCreate(Bundle icicle) { 453 super.onCreate(icicle); 454 createViews(this, true /* showWhenLocked */); 455 } 456 } 457 createViews( Activity activity, boolean showWhenLocked )458 private static EditText createViews( 459 Activity activity, boolean showWhenLocked /* showWhenLocked */) { 460 EditText editor = new EditText(activity); 461 // Set private IME option for editorMatcher to identify which TextView received 462 // onStartInput event. 463 editor.setPrivateImeOptions( 464 activity.getClass().getName() 465 + "/" + Long.toString(SystemClock.elapsedRealtimeNanos())); 466 final LinearLayout layout = new LinearLayout(activity); 467 layout.setOrientation(LinearLayout.VERTICAL); 468 layout.addView(editor); 469 activity.setContentView(layout); 470 471 if (showWhenLocked) { 472 // Set showWhenLocked as true & request focus for showing soft input. 473 activity.setShowWhenLocked(true); 474 activity.getWindow().setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_VISIBLE); 475 } 476 editor.requestFocus(); 477 return editor; 478 } 479 } 480