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.appsecurity.cts; 18 19 import com.android.tradefed.util.RunUtil; 20 import static android.appsecurity.cts.Utils.waitForBootCompleted; 21 22 import static com.android.compatibility.common.util.PropertyUtil.getFirstApiLevel; 23 import static com.android.compatibility.common.util.PropertyUtil.getVendorApiLevel; 24 25 import static org.junit.Assert.assertNotNull; 26 import static org.junit.Assert.assertTrue; 27 import static org.junit.Assume.assumeFalse; 28 import static org.junit.Assume.assumeTrue; 29 30 import com.android.tradefed.device.DeviceNotAvailableException; 31 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 32 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 33 34 import org.junit.After; 35 import org.junit.Before; 36 import org.junit.Test; 37 import org.junit.runner.RunWith; 38 39 /** 40 * Set of tests that verify behavior of direct boot, if supported. 41 * <p> 42 * Note that these tests drive PIN setup manually instead of relying on device 43 * administrators, which are not supported by all devices. 44 */ 45 @RunWith(DeviceJUnit4ClassRunner.class) 46 public class DirectBootHostTest extends BaseHostJUnit4Test { 47 private static final String TAG = "DirectBootHostTest"; 48 49 private static final String PKG = "com.android.cts.encryptionapp"; 50 private static final String CLASS = PKG + ".EncryptionAppTest"; 51 private static final String APK = "CtsEncryptionApp.apk"; 52 53 private static final String OTHER_APK = "CtsSplitApp.apk"; 54 private static final String OTHER_PKG = "com.android.cts.splitapp"; 55 56 private static final String FEATURE_DEVICE_ADMIN = "feature:android.software.device_admin"; 57 private static final String FEATURE_SECURE_LOCK_SCREEN = 58 "feature:android.software.secure_lock_screen"; 59 private static final String FEATURE_AUTOMOTIVE = "feature:android.hardware.type.automotive"; 60 private static final String FEATURE_SECURITY_MODEL_COMPATIBLE = 61 "feature:android.hardware.security.model.compatible"; 62 63 @Before setUp()64 public void setUp() throws Exception { 65 Utils.prepareSingleUser(getDevice()); 66 assertNotNull(getAbi()); 67 assertNotNull(getBuild()); 68 69 getDevice().uninstallPackage(PKG); 70 getDevice().uninstallPackage(OTHER_PKG); 71 } 72 73 @After tearDown()74 public void tearDown() throws Exception { 75 getDevice().uninstallPackage(PKG); 76 getDevice().uninstallPackage(OTHER_PKG); 77 } 78 79 /** 80 * Automotive devices MUST use FBE. 81 */ 82 @Test testAutomotiveFbe()83 public void testAutomotiveFbe() throws Exception { 84 assumeSupportedDevice(); 85 assumeTrue("Device not automotive; skipping test", isAutomotiveDevice()); 86 assertTrue("Automotive devices must use FBE", fbeEnabled()); 87 } 88 89 /** 90 * If device uses FBE, verify the direct boot lifecycle. 91 */ 92 @Test testDirectBoot()93 public void testDirectBoot() throws Exception { 94 assumeSupportedDevice(); 95 assumeTrue("Device doesn't use FBE; skipping test", fbeEnabled()); 96 doDirectBootTest(true); 97 } 98 99 /** 100 * If device doesn't use FBE, verify the legacy lifecycle. 101 */ 102 @Test testNoDirectBoot()103 public void testNoDirectBoot() throws Exception { 104 assumeSupportedDevice(); 105 assumeFalse("Device uses FBE; skipping test", fbeEnabled()); 106 doDirectBootTest(false); 107 } 108 doDirectBootTest(boolean fbeEnabled)109 public void doDirectBootTest(boolean fbeEnabled) throws Exception { 110 try { 111 // Set up test app and secure lock screens 112 new InstallMultiple().addFile(APK).run(); 113 new InstallMultiple().addFile(OTHER_APK).run(); 114 115 // To receive boot broadcasts, kick our other app out of stopped state 116 getDevice().executeShellCommand("am start -a android.intent.action.MAIN" 117 + " --user current" 118 + " -c android.intent.category.LAUNCHER com.android.cts.splitapp/.MyActivity"); 119 120 // Give enough time for PackageManager to persist stopped state 121 RunUtil.getDefault().sleep(15000); 122 123 runDeviceTestsAsCurrentUser(PKG, CLASS, "testSetUp"); 124 125 // Give enough time for vold to update keys 126 RunUtil.getDefault().sleep(15000); 127 128 // Reboot system into known state with keys ejected 129 getDevice().rebootUntilOnline(); 130 waitForBootCompleted(getDevice()); 131 132 if (fbeEnabled) { 133 runDeviceTestsAsCurrentUser(PKG, CLASS, "testVerifyLockedAndDismiss"); 134 } else { 135 runDeviceTestsAsCurrentUser(PKG, CLASS, "testVerifyUnlockedAndDismiss"); 136 } 137 138 } finally { 139 try { 140 // Remove secure lock screens and tear down test app 141 runDeviceTestsAsCurrentUser(PKG, CLASS, "testTearDown"); 142 } finally { 143 getDevice().uninstallPackage(PKG); 144 145 // Get ourselves back into a known-good state 146 getDevice().rebootUntilOnline(); 147 getDevice().waitForDeviceAvailable(); 148 } 149 } 150 } 151 runDeviceTestsAsCurrentUser( String packageName, String testClassName, String testMethodName)152 private void runDeviceTestsAsCurrentUser( 153 String packageName, String testClassName, String testMethodName) 154 throws DeviceNotAvailableException { 155 Utils.runDeviceTestsAsCurrentUser(getDevice(), packageName, testClassName, testMethodName); 156 } 157 fbeEnabled()158 private boolean fbeEnabled() throws Exception { 159 return "file".equals(getDevice().getProperty("ro.crypto.type")); 160 } 161 assumeSupportedDevice()162 private void assumeSupportedDevice() throws Exception { 163 assumeTrue("Skipping test: FEATURE_DEVICE_ADMIN missing.", 164 getDevice().hasFeature(FEATURE_DEVICE_ADMIN)); 165 assumeTrue("Skipping test: FEATURE_SECURE_LOCK_SCREEN missing.", 166 getDevice().hasFeature(FEATURE_SECURE_LOCK_SCREEN)); 167 // This feature name check only applies to devices that first shipped with 168 // SC or later. 169 final int firstApiLevel = 170 Math.min(getFirstApiLevel(getDevice()), getVendorApiLevel(getDevice())); 171 if (firstApiLevel >= 31) { 172 assumeTrue("Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.", 173 getDevice().hasFeature("feature:android.hardware.security.model.compatible")); 174 } 175 } 176 isAutomotiveDevice()177 private boolean isAutomotiveDevice() throws Exception { 178 return getDevice().hasFeature(FEATURE_AUTOMOTIVE); 179 } 180 181 private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> { InstallMultiple()182 public InstallMultiple() { 183 super(getDevice(), getBuild(), getAbi()); 184 addArg("--force-queryable"); 185 } 186 } 187 } 188