1 /*
2  * Copyright (C) 2019 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 com.android.test.stress;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertTrue;
21 import static org.junit.Assert.fail;
22 
23 import com.android.tradefed.log.LogUtil.CLog;
24 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
25 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
26 
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 
30 import java.util.concurrent.TimeUnit;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33 
34 /**
35  * A test to exercise Android Framework parts related to creating, starting, stopping, and deleting
36  * a managed profile as much as possible. The aim is to catch any issues in this code before it
37  * affects managed profile CTS tests.
38  */
39 @RunWith(DeviceJUnit4ClassRunner.class)
40 public class ManagedProfileLifecycleStressTest extends BaseHostJUnit4Test {
41     // Stop the test once this time limit has been reached. 25 minutes used as a limit to make total
42     // test time less than 30 minutes, so that it can be put into presubmit.
43     private static final int TIME_LIMIT_MINUTES = 25;
44 
45     private static final String DUMMY_DPC_APK = "DummyDPC.apk";
46     private static final String DUMMY_DPC_COMPONENT =
47             "com.android.dummydpc/com.android.dummydpc.DummyDeviceAdminReceiver";
48     private static final Pattern CREATE_USER_OUTPUT_REGEX =
49             Pattern.compile("Success: created user id (\\d+)");
50 
51     /**
52      * Create, start, and kill managed profiles in a loop.
53      */
54     @Test
testCreateStartDelete()55     public void testCreateStartDelete() throws Exception {
56         // Disable package verifier for ADB installs.
57         getDevice().executeShellCommand("settings put global verifier_verify_adb_installs 0");
58         int iteration = 0;
59         final long deadline = System.nanoTime() + TimeUnit.MINUTES.toNanos(TIME_LIMIT_MINUTES);
60         while (System.nanoTime() < deadline) {
61             iteration++;
62             CLog.w("Iteration N" + iteration);
63             final int userId = createManagedProfile();
64             startUser(userId);
65             installPackageAsUser(DUMMY_DPC_APK, true /* grantPermissions */, userId, "-t");
66             setProfileOwner(DUMMY_DPC_COMPONENT, userId);
67             removeUser(userId);
68         }
69         CLog.w("Completed " + iteration + " iterations.");
70     }
71 
createManagedProfile()72     private int createManagedProfile() throws Exception {
73         final String output = getDevice().executeShellCommand(
74                 "pm create-user --profileOf 0 --managed TestProfile");
75         final Matcher matcher = CREATE_USER_OUTPUT_REGEX.matcher(output.trim());
76         if (!matcher.matches() || matcher.groupCount() != 1) {
77             fail("user creation failed, output: " + output);
78         }
79         return Integer.parseInt(matcher.group(1));
80     }
81 
setProfileOwner(String componentName, int userId)82     private void setProfileOwner(String componentName, int userId) throws Exception {
83         String command = "dpm set-profile-owner --user " + userId + " '" + componentName + "'";
84         String commandOutput = getDevice().executeShellCommand(command);
85         assertTrue("Unexpected dpm output: " + commandOutput, commandOutput.startsWith("Success:"));
86     }
87 
removeUser(int userId)88     private void removeUser(int userId) throws Exception {
89         final String output = getDevice().executeShellCommand("pm remove-user " + userId).trim();
90         assertEquals("Unexpected pm output: " + output, "Success: removed user", output);
91     }
92 
startUser(int userId)93     private void startUser(int userId) throws Exception {
94         final String output = getDevice().executeShellCommand("am start-user -w " + userId).trim();
95         assertEquals("Unexpected am output: " + output, "Success: user started", output);
96     }
97 }
98