xref: /aosp_15_r20/cts/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
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