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