blob: 0d11e0a9831ddb777e4dacdbc7364c377c474909 [file] [log] [blame]
/*
* Copyright (C) 2019 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 com.android.cts.devicepolicy;
import static com.android.cts.devicepolicy.metrics.DevicePolicyEventLogVerifier.assertMetricsLogged;
import android.platform.test.annotations.FlakyTest;
import android.platform.test.annotations.LargeTest;
import android.stats.devicepolicy.EventId;
import com.android.cts.devicepolicy.annotations.LockSettingsTest;
import com.android.cts.devicepolicy.metrics.DevicePolicyEventWrapper;
import com.android.tradefed.device.DeviceNotAvailableException;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
public class ManagedProfilePasswordTest extends BaseManagedProfileTest {
private static final String USER_STATE_LOCKED = "RUNNING_LOCKED";
private static final long TIMEOUT_USER_LOCKED_MILLIS = TimeUnit.MINUTES.toMillis(3);
// Password needs to be in sync with ResetPasswordWithTokenTest.PASSWORD1
private static final String RESET_PASSWORD_TEST_DEFAULT_PASSWORD = "123456";
@FlakyTest
@Test
public void testLockNowWithKeyEviction() throws Exception {
assumeHasFileBasedEncryptionAndSecureLockScreenFeatures();
changeUserCredential(TEST_PASSWORD, null, mProfileUserId);
lockProfile();
}
@FlakyTest
@Test
public void testResetPasswordWithTokenBeforeUnlock() throws Exception {
assumeHasFileBasedEncryptionAndSecureLockScreenFeatures();
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ResetPasswordWithTokenTest",
"testSetupWorkProfile", mProfileUserId);
lockProfile();
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ResetPasswordWithTokenTest",
"testResetPasswordBeforeUnlock", mProfileUserId);
// Password needs to be in sync with ResetPasswordWithTokenTest.PASSWORD1
verifyUserCredential(RESET_PASSWORD_TEST_DEFAULT_PASSWORD, mProfileUserId);
}
@FlakyTest
@Test
public void testClearPasswordWithTokenBeforeUnlock() throws Exception {
assumeHasFileBasedEncryptionAndSecureLockScreenFeatures();
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ResetPasswordWithTokenTest",
"testSetupWorkProfile", mProfileUserId);
lockProfile();
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ResetPasswordWithTokenTest",
"testClearPasswordBeforeUnlock", mProfileUserId);
// Make sure profile has no password
verifyUserCredential("", mProfileUserId);
}
/**
* Test password reset token is still functional after the primary user clears and
* re-adds back its device lock. This is to detect a regression where the work profile
* undergoes an untrusted credential reset (causing synthetic password to change, invalidating
* existing password reset token) if it has unified work challenge and the primary user clears
* the device lock.
*/
@FlakyTest
@Test
public void testResetPasswordTokenUsableAfterClearingLock() throws Exception {
assumeHasFileBasedEncryptionAndSecureLockScreenFeatures();
final String devicePassword = TEST_PASSWORD;
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ResetPasswordWithTokenTest",
"testSetResetPasswordToken", mProfileUserId);
try {
changeUserCredential(devicePassword, null, mParentUserId);
changeUserCredential(null, devicePassword, mParentUserId);
changeUserCredential(devicePassword, null, mParentUserId);
lockProfile();
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ResetPasswordWithTokenTest",
"testResetPasswordBeforeUnlock", mProfileUserId);
verifyUserCredential(RESET_PASSWORD_TEST_DEFAULT_PASSWORD, mProfileUserId);
} finally {
changeUserCredential(null, devicePassword, mParentUserId);
// Cycle the device screen to flush stale password information from keyguard,
// otherwise it will still ask for the non-existent password.
// return screen to be on for cts test runs
executeShellCommand("input keyevent KEYCODE_WAKEUP");
executeShellCommand("input keyevent KEYCODE_SLEEP");
executeShellCommand("input keyevent KEYCODE_WAKEUP");
}
}
@LockSettingsTest
@Test
public void testIsUsingUnifiedPassword() throws Exception {
assumeHasSecureLockScreenFeature();
// Freshly created profile has no separate challenge.
verifyUnifiedPassword(true);
// Set separate challenge and verify that the API reports it correctly.
changeUserCredential(
TEST_PASSWORD /* newCredential */, null /* oldCredential */, mProfileUserId);
verifyUnifiedPassword(false);
}
@FlakyTest
@LargeTest
@LockSettingsTest
@Test
public void testUnlockWorkProfile_deviceWidePassword() throws Exception {
assumeHasFileBasedEncryptionAndSecureLockScreenFeatures();
try {
// Add a device password after the work profile has been created.
changeUserCredential(TEST_PASSWORD, /* oldCredential= */ null, mPrimaryUserId);
// Lock the profile with key eviction.
lockProfile();
// Turn on work profile, by unlocking the profile with the device password.
verifyUserCredential(TEST_PASSWORD, mPrimaryUserId);
// Verify profile user is running unlocked by running a basic test on the work profile.
installAppAsUser(SIMPLE_APP_APK, mProfileUserId);
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".BasicTest", mProfileUserId);
} finally {
// Clean up
changeUserCredential(/* newCredential= */ null, TEST_PASSWORD, mPrimaryUserId);
}
}
@FlakyTest
@LargeTest
@LockSettingsTest
@Test
public void testRebootDevice_unifiedPassword() throws Exception {
assumeHasSecureLockScreenFeature();
// Waiting before rebooting prevents flakiness.
waitForBroadcastIdle();
changeUserCredential(TEST_PASSWORD, /* oldCredential= */ null, mPrimaryUserId);
try {
rebootAndWaitUntilReady();
verifyUserCredential(TEST_PASSWORD, mPrimaryUserId);
waitForUserUnlock(mProfileUserId);
installAppAsUser(SIMPLE_APP_APK, mProfileUserId);
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".BasicTest", mProfileUserId);
} finally {
changeUserCredential(/* newCredential= */ null, TEST_PASSWORD, mPrimaryUserId);
// Work-around for http://b/113866275 - password prompt being erroneously shown at the
// end.
pressPowerButton();
}
}
@LargeTest
@LockSettingsTest
@Test
public void testRebootDevice_separatePasswords() throws Exception {
assumeHasSecureLockScreenFeature();
// Waiting before rebooting prevents flakiness.
waitForBroadcastIdle();
final String profilePassword = "profile";
final String primaryPassword = TEST_PASSWORD;
int managedProfileUserId = getFirstManagedProfileUserId();
changeUserCredential(
profilePassword, /* oldCredential= */ null, managedProfileUserId);
changeUserCredential(primaryPassword, /* oldCredential= */ null, mPrimaryUserId);
try {
rebootAndWaitUntilReady();
verifyUserCredential(profilePassword, managedProfileUserId);
verifyUserCredential(primaryPassword, mPrimaryUserId);
installAppAsUser(SIMPLE_APP_APK, mProfileUserId);
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".BasicTest", mProfileUserId);
} finally {
changeUserCredential(
/* newCredential= */ null, profilePassword, managedProfileUserId);
changeUserCredential(/* newCredential= */ null, primaryPassword, mPrimaryUserId);
// Work-around for http://b/113866275 - password prompt being erroneously shown at the
// end.
pressPowerButton();
}
}
@Test
public void testCreateSeparateChallengeChangedLogged() throws Exception {
assumeHasSecureLockScreenFeature();
assertMetricsLogged(getDevice(), () -> {
changeUserCredential(
TEST_PASSWORD /* newCredential */, null /* oldCredential */, mProfileUserId);
}, new DevicePolicyEventWrapper.Builder(EventId.SEPARATE_PROFILE_CHALLENGE_CHANGED_VALUE)
.setBoolean(true)
.build());
}
@Test
public void testActivePasswordSufficientForDeviceRequirement() throws Exception {
assumeHasSecureLockScreenFeature();
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ActivePasswordSufficientForDeviceTest",
mProfileUserId);
}
private void verifyUnifiedPassword(boolean unified) throws DeviceNotAvailableException {
final String testMethod =
unified ? "testUsingUnifiedPassword" : "testNotUsingUnifiedPassword";
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".IsUsingUnifiedPasswordTest",
testMethod, mProfileUserId);
}
private void lockProfile() throws Exception {
final String cmd = "am broadcast --receiver-foreground --user " + mProfileUserId
+ " -a com.android.cts.managedprofile.LOCK_PROFILE"
+ " com.android.cts.managedprofile/.LockProfileReceiver";
getDevice().executeShellCommand(cmd);
waitUntilProfileLocked();
}
private void waitUntilProfileLocked() throws Exception {
final String cmd = String.format("am get-started-user-state %d", mProfileUserId);
tryWaitForSuccess(
() -> getDevice().executeShellCommand(cmd).startsWith(USER_STATE_LOCKED),
"The managed profile has not been locked after calling "
+ "lockNow(FLAG_SECURE_USER_DATA)",
TIMEOUT_USER_LOCKED_MILLIS);
}
}