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