blob: f57b3b2568c01a53078f815346e9516d4f699fcc [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.server.wm.MockImeHelper.createManagedMockImeSession;
import static android.server.wm.UiDeviceUtils.pressBackButton;
import static android.server.wm.app.Components.DISMISS_KEYGUARD_ACTIVITY;
import static android.server.wm.app.Components.DISMISS_KEYGUARD_METHOD_ACTIVITY;
import static android.server.wm.app.Components.PIP_ACTIVITY;
import static android.server.wm.app.Components.PipActivity.ACTION_ENTER_PIP;
import static android.server.wm.app.Components.PipActivity.EXTRA_DISMISS_KEYGUARD;
import static android.server.wm.app.Components.PipActivity.EXTRA_ENTER_PIP;
import static android.server.wm.app.Components.PipActivity.EXTRA_SHOW_OVER_KEYGUARD;
import static android.server.wm.app.Components.SHOW_WHEN_LOCKED_ACTIVITY;
import static android.server.wm.app.Components.SHOW_WHEN_LOCKED_ATTR_IME_ACTIVITY;
import static android.server.wm.app.Components.TURN_SCREEN_ON_ATTR_DISMISS_KEYGUARD_ACTIVITY;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE;
import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import android.app.Activity;
import android.app.KeyguardManager;
import android.content.ComponentName;
import android.os.Bundle;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.widget.EditText;
import android.widget.LinearLayout;
import com.android.cts.mockime.ImeEventStream;
import com.android.cts.mockime.MockImeSession;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
/**
* Build/Install/Run:
* atest CtsWindowManagerDeviceTestCases:KeyguardLockedTests
*/
@Presubmit
@android.server.wm.annotation.Group2
public class KeyguardLockedTests extends KeyguardTestBase {
@Before
@Override
public void setUp() throws Exception {
super.setUp();
assumeTrue(supportsSecureLock());
}
@Test
public void testLockAndUnlock() {
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.setLockCredential().gotoKeyguard();
assertTrue(mKeyguardManager.isKeyguardLocked());
assertTrue(mKeyguardManager.isDeviceLocked());
assertTrue(mKeyguardManager.isDeviceSecure());
assertTrue(mKeyguardManager.isKeyguardSecure());
mWmState.assertKeyguardShowingAndNotOccluded();
lockScreenSession.unlockDevice().enterAndConfirmLockCredential();
mWmState.waitAndAssertKeyguardGone();
assertFalse(mKeyguardManager.isDeviceLocked());
assertFalse(mKeyguardManager.isKeyguardLocked());
}
@Test
public void testDisableKeyguard_thenSettingCredential_reenablesKeyguard_b119322269() {
final KeyguardManager.KeyguardLock keyguardLock = mContext.getSystemService(
KeyguardManager.class).newKeyguardLock("KeyguardLockedTests");
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.gotoKeyguard();
keyguardLock.disableKeyguard();
lockScreenSession.setLockCredential();
mWmState.waitForKeyguardShowingAndNotOccluded();
mWmState.assertKeyguardShowingAndNotOccluded();
} finally {
keyguardLock.reenableKeyguard();
}
}
@Test
public void testDismissKeyguard() {
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.setLockCredential().gotoKeyguard();
mWmState.assertKeyguardShowingAndNotOccluded();
launchActivity(DISMISS_KEYGUARD_ACTIVITY);
lockScreenSession.enterAndConfirmLockCredential();
mWmState.waitAndAssertKeyguardGone();
mWmState.assertVisibility(DISMISS_KEYGUARD_ACTIVITY, true);
}
@Test
public void testDismissKeyguard_whileOccluded() {
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.setLockCredential().gotoKeyguard();
mWmState.assertKeyguardShowingAndNotOccluded();
launchActivity(SHOW_WHEN_LOCKED_ACTIVITY);
mWmState.computeState(SHOW_WHEN_LOCKED_ACTIVITY);
mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true);
launchActivity(DISMISS_KEYGUARD_ACTIVITY);
lockScreenSession.enterAndConfirmLockCredential();
mWmState.waitAndAssertKeyguardGone();
mWmState.computeState(DISMISS_KEYGUARD_ACTIVITY);
final boolean isDismissTranslucent = mWmState
.isActivityTranslucent(DISMISS_KEYGUARD_ACTIVITY);
mWmState.assertVisibility(DISMISS_KEYGUARD_ACTIVITY, true);
mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, isDismissTranslucent);
}
@Test
public void testDismissKeyguard_fromShowWhenLocked_notAllowed() {
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.setLockCredential().gotoKeyguard();
mWmState.assertKeyguardShowingAndNotOccluded();
launchActivity(SHOW_WHEN_LOCKED_ACTIVITY);
mWmState.computeState(SHOW_WHEN_LOCKED_ACTIVITY);
mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true);
mBroadcastActionTrigger.dismissKeyguardByFlag();
lockScreenSession.enterAndConfirmLockCredential();
// Make sure we stay on Keyguard.
mWmState.assertKeyguardShowingAndOccluded();
mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true);
}
@Test
public void testDismissKeyguardActivity_method() {
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.setLockCredential();
separateTestJournal();
lockScreenSession.gotoKeyguard();
mWmState.computeState();
assertTrue(mWmState.getKeyguardControllerState().keyguardShowing);
launchActivity(DISMISS_KEYGUARD_METHOD_ACTIVITY);
lockScreenSession.enterAndConfirmLockCredential();
mWmState.waitForKeyguardGone();
mWmState.computeState(DISMISS_KEYGUARD_METHOD_ACTIVITY);
mWmState.assertVisibility(DISMISS_KEYGUARD_METHOD_ACTIVITY, true);
assertFalse(mWmState.getKeyguardControllerState().keyguardShowing);
assertOnDismissSucceeded(DISMISS_KEYGUARD_METHOD_ACTIVITY);
}
@Test
public void testDismissKeyguardActivity_method_cancelled() {
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.setLockCredential();
separateTestJournal();
lockScreenSession.gotoKeyguard();
mWmState.computeState();
assertTrue(mWmState.getKeyguardControllerState().keyguardShowing);
launchActivity(DISMISS_KEYGUARD_METHOD_ACTIVITY);
pressBackButton();
assertOnDismissCancelled(DISMISS_KEYGUARD_METHOD_ACTIVITY);
mWmState.computeState();
mWmState.assertVisibility(DISMISS_KEYGUARD_METHOD_ACTIVITY, false);
assertTrue(mWmState.getKeyguardControllerState().keyguardShowing);
}
@Test
public void testDismissKeyguardAttrActivity_method_turnScreenOn_withSecureKeyguard() {
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.setLockCredential().sleepDevice();
mWmState.computeState();
assertTrue(mWmState.getKeyguardControllerState().keyguardShowing);
launchActivity(TURN_SCREEN_ON_ATTR_DISMISS_KEYGUARD_ACTIVITY);
mWmState.waitForKeyguardShowingAndNotOccluded();
mWmState.assertVisibility(TURN_SCREEN_ON_ATTR_DISMISS_KEYGUARD_ACTIVITY, false);
assertTrue(mWmState.getKeyguardControllerState().keyguardShowing);
assertTrue(isDisplayOn(DEFAULT_DISPLAY));
}
@Test
public void testEnterPipOverKeyguard() {
assumeTrue(supportsPip());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.setLockCredential();
// Show the PiP activity in fullscreen.
launchActivity(PIP_ACTIVITY, EXTRA_SHOW_OVER_KEYGUARD, "true");
// Lock the screen and ensure that the PiP activity showing over the LockScreen.
lockScreenSession.gotoKeyguard(PIP_ACTIVITY);
mWmState.waitForKeyguardShowingAndOccluded();
mWmState.assertKeyguardShowingAndOccluded();
// Request that the PiP activity enter picture-in-picture mode (ensure it does not).
mBroadcastActionTrigger.doAction(ACTION_ENTER_PIP);
waitForEnterPip(PIP_ACTIVITY);
mWmState.assertDoesNotContainStack("Must not contain pinned stack.",
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
// Enter the credentials and ensure that the activity actually entered picture-in-picture.
lockScreenSession.enterAndConfirmLockCredential();
mWmState.waitAndAssertKeyguardGone();
waitForEnterPip(PIP_ACTIVITY);
mWmState.assertContainsStack("Must contain pinned stack.", WINDOWING_MODE_PINNED,
ACTIVITY_TYPE_STANDARD);
}
@Test
public void testShowWhenLockedActivityAndPipActivity() {
assumeTrue(supportsPip());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.setLockCredential();
// Show an activity in PIP.
launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
waitForEnterPip(PIP_ACTIVITY);
mWmState.assertContainsStack("Must contain pinned stack.", WINDOWING_MODE_PINNED,
ACTIVITY_TYPE_STANDARD);
mWmState.assertVisibility(PIP_ACTIVITY, true);
// Show an activity that will keep above the keyguard.
launchActivity(SHOW_WHEN_LOCKED_ACTIVITY);
mWmState.computeState(SHOW_WHEN_LOCKED_ACTIVITY);
mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true);
// Lock the screen and ensure that the fullscreen activity showing over the lockscreen
// is visible, but not the PiP activity.
lockScreenSession.gotoKeyguard(SHOW_WHEN_LOCKED_ACTIVITY);
mWmState.computeState();
mWmState.assertKeyguardShowingAndOccluded();
mWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true);
mWmState.assertVisibility(PIP_ACTIVITY, false);
}
@Test
public void testShowWhenLockedPipActivity() {
assumeTrue(supportsPip());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.setLockCredential();
// Show an activity in PIP.
launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true", EXTRA_SHOW_OVER_KEYGUARD, "true");
waitForEnterPip(PIP_ACTIVITY);
mWmState.assertContainsStack("Must contain pinned stack.", WINDOWING_MODE_PINNED,
ACTIVITY_TYPE_STANDARD);
mWmState.assertVisibility(PIP_ACTIVITY, true);
// Lock the screen and ensure the PiP activity is not visible on the lockscreen even
// though it's marked as showing over the lockscreen itself.
lockScreenSession.gotoKeyguard();
mWmState.assertKeyguardShowingAndNotOccluded();
mWmState.assertVisibility(PIP_ACTIVITY, false);
}
@Test
public void testDismissKeyguardPipActivity() {
assumeTrue(supportsPip());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
// Show an activity in PIP.
launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true", EXTRA_DISMISS_KEYGUARD, "true");
waitForEnterPip(PIP_ACTIVITY);
mWmState.assertContainsStack("Must contain pinned stack.", WINDOWING_MODE_PINNED,
ACTIVITY_TYPE_STANDARD);
mWmState.assertVisibility(PIP_ACTIVITY, true);
// Lock the screen and ensure the PiP activity is not visible on the lockscreen even
// though it's marked as dismiss keyguard.
lockScreenSession.gotoKeyguard();
mWmState.computeState();
mWmState.assertKeyguardShowingAndNotOccluded();
mWmState.assertVisibility(PIP_ACTIVITY, false);
}
@Test
public void testShowWhenLockedAttrImeActivityAndShowSoftInput() throws Exception {
assumeTrue(MSG_NO_MOCK_IME, supportsInstallableIme());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
final MockImeSession mockImeSession = createManagedMockImeSession(this);
lockScreenSession.setLockCredential().gotoKeyguard();
mWmState.assertKeyguardShowingAndNotOccluded();
launchActivity(SHOW_WHEN_LOCKED_ATTR_IME_ACTIVITY);
mWmState.computeState(SHOW_WHEN_LOCKED_ATTR_IME_ACTIVITY);
mWmState.assertVisibility(SHOW_WHEN_LOCKED_ATTR_IME_ACTIVITY, true);
// Make sure the activity has been called showSoftInput & IME window is visible.
final ImeEventStream stream = mockImeSession.openEventStream();
expectEvent(stream, event -> "showSoftInput".equals(event.getEventName()),
TimeUnit.SECONDS.toMillis(5) /* eventTimeout */);
// Assert the IME is shown on the expected display.
mWmState.waitAndAssertImeWindowShownOnDisplay(DEFAULT_DISPLAY);
}
@Test
public void testShowWhenLockedImeActivityAndShowSoftInput() throws Exception {
assumeTrue(MSG_NO_MOCK_IME, supportsInstallableIme());
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
final MockImeSession mockImeSession = createManagedMockImeSession(this);
final TestActivitySession<ShowWhenLockedImeActivity> imeTestActivitySession =
createManagedTestActivitySession();
lockScreenSession.setLockCredential().gotoKeyguard();
mWmState.assertKeyguardShowingAndNotOccluded();
imeTestActivitySession.launchTestActivityOnDisplaySync(ShowWhenLockedImeActivity.class,
DEFAULT_DISPLAY);
// Make sure the activity has been called showSoftInput & IME window is visible.
final ImeEventStream stream = mockImeSession.openEventStream();
expectEvent(stream, event -> "showSoftInput".equals(event.getEventName()),
TimeUnit.SECONDS.toMillis(5) /* eventTimeout */);
// Assert the IME is shown on the expected display.
mWmState.waitAndAssertImeWindowShownOnDisplay(DEFAULT_DISPLAY);
}
public static class ShowWhenLockedImeActivity extends Activity {
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
final EditText editText = new EditText(this);
// Set private IME option for editorMatcher to identify which TextView received
// onStartInput event.
editText.setPrivateImeOptions(
getClass().getName() + "/" + Long.toString(SystemClock.elapsedRealtimeNanos()));
final LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
layout.addView(editText);
setContentView(layout);
// Set showWhenLocked as true & request focus for showing soft input.
setShowWhenLocked(true);
getWindow().setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_VISIBLE);
editText.requestFocus();
}
}
/**
* Waits until the given activity has entered picture-in-picture mode (allowing for the
* subsequent animation to start).
*/
private void waitForEnterPip(ComponentName activityName) {
mWmState.waitForValidState(new WaitForValidActivityState.Builder(activityName)
.setWindowingMode(WINDOWING_MODE_PINNED)
.setActivityType(ACTIVITY_TYPE_STANDARD)
.build());
}
}