blob: 13a3c64bb6a6ff01f1b8b1144e145ab35b827ed4 [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.appsecurity.cts;
import com.android.tradefed.util.RunUtil;
import static android.appsecurity.cts.Utils.waitForBootCompleted;
import static com.android.compatibility.common.util.PropertyUtil.getFirstApiLevel;
import static com.android.compatibility.common.util.PropertyUtil.getVendorApiLevel;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Set of tests that verify behavior of direct boot, if supported.
* <p>
* Note that these tests drive PIN setup manually instead of relying on device
* administrators, which are not supported by all devices.
*/
@RunWith(DeviceJUnit4ClassRunner.class)
public class DirectBootHostTest extends BaseHostJUnit4Test {
private static final String TAG = "DirectBootHostTest";
private static final String PKG = "com.android.cts.encryptionapp";
private static final String CLASS = PKG + ".EncryptionAppTest";
private static final String APK = "CtsEncryptionApp.apk";
private static final String OTHER_APK = "CtsSplitApp.apk";
private static final String OTHER_PKG = "com.android.cts.splitapp";
private static final String FEATURE_DEVICE_ADMIN = "feature:android.software.device_admin";
private static final String FEATURE_SECURE_LOCK_SCREEN =
"feature:android.software.secure_lock_screen";
private static final String FEATURE_AUTOMOTIVE = "feature:android.hardware.type.automotive";
private static final String FEATURE_SECURITY_MODEL_COMPATIBLE =
"feature:android.hardware.security.model.compatible";
@Before
public void setUp() throws Exception {
Utils.prepareSingleUser(getDevice());
assertNotNull(getAbi());
assertNotNull(getBuild());
getDevice().uninstallPackage(PKG);
getDevice().uninstallPackage(OTHER_PKG);
}
@After
public void tearDown() throws Exception {
getDevice().uninstallPackage(PKG);
getDevice().uninstallPackage(OTHER_PKG);
}
/**
* Automotive devices MUST use FBE.
*/
@Test
public void testAutomotiveFbe() throws Exception {
assumeSupportedDevice();
assumeTrue("Device not automotive; skipping test", isAutomotiveDevice());
assertTrue("Automotive devices must use FBE", fbeEnabled());
}
/**
* If device uses FBE, verify the direct boot lifecycle.
*/
@Test
public void testDirectBoot() throws Exception {
assumeSupportedDevice();
assumeTrue("Device doesn't use FBE; skipping test", fbeEnabled());
doDirectBootTest(true);
}
/**
* If device doesn't use FBE, verify the legacy lifecycle.
*/
@Test
public void testNoDirectBoot() throws Exception {
assumeSupportedDevice();
assumeFalse("Device uses FBE; skipping test", fbeEnabled());
doDirectBootTest(false);
}
public void doDirectBootTest(boolean fbeEnabled) throws Exception {
try {
// Set up test app and secure lock screens
new InstallMultiple().addFile(APK).run();
new InstallMultiple().addFile(OTHER_APK).run();
// To receive boot broadcasts, kick our other app out of stopped state
getDevice().executeShellCommand("am start -a android.intent.action.MAIN"
+ " --user current"
+ " -c android.intent.category.LAUNCHER com.android.cts.splitapp/.MyActivity");
// Give enough time for PackageManager to persist stopped state
RunUtil.getDefault().sleep(15000);
runDeviceTestsAsCurrentUser(PKG, CLASS, "testSetUp");
// Give enough time for vold to update keys
RunUtil.getDefault().sleep(15000);
// Reboot system into known state with keys ejected
getDevice().rebootUntilOnline();
waitForBootCompleted(getDevice());
if (fbeEnabled) {
runDeviceTestsAsCurrentUser(PKG, CLASS, "testVerifyLockedAndDismiss");
} else {
runDeviceTestsAsCurrentUser(PKG, CLASS, "testVerifyUnlockedAndDismiss");
}
} finally {
try {
// Remove secure lock screens and tear down test app
runDeviceTestsAsCurrentUser(PKG, CLASS, "testTearDown");
} finally {
getDevice().uninstallPackage(PKG);
// Get ourselves back into a known-good state
getDevice().rebootUntilOnline();
getDevice().waitForDeviceAvailable();
}
}
}
private void runDeviceTestsAsCurrentUser(
String packageName, String testClassName, String testMethodName)
throws DeviceNotAvailableException {
Utils.runDeviceTestsAsCurrentUser(getDevice(), packageName, testClassName, testMethodName);
}
private boolean fbeEnabled() throws Exception {
return "file".equals(getDevice().getProperty("ro.crypto.type"));
}
private void assumeSupportedDevice() throws Exception {
assumeTrue("Skipping test: FEATURE_DEVICE_ADMIN missing.",
getDevice().hasFeature(FEATURE_DEVICE_ADMIN));
assumeTrue("Skipping test: FEATURE_SECURE_LOCK_SCREEN missing.",
getDevice().hasFeature(FEATURE_SECURE_LOCK_SCREEN));
// This feature name check only applies to devices that first shipped with
// SC or later.
final int firstApiLevel =
Math.min(getFirstApiLevel(getDevice()), getVendorApiLevel(getDevice()));
if (firstApiLevel >= 31) {
assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.",
getDevice().hasFeature("feature:android.hardware.security.model.compatible"));
}
}
private boolean isAutomotiveDevice() throws Exception {
return getDevice().hasFeature(FEATURE_AUTOMOTIVE);
}
private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
public InstallMultiple() {
super(getDevice(), getBuild(), getAbi());
addArg("--force-queryable");
}
}
}