• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.device.CollectingOutputReceiver;
24 import com.android.tradefed.log.LogUtil.CLog;
25 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
26 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
27 
28 import org.junit.Test;
29 import org.junit.runner.RunWith;
30 
31 import java.util.concurrent.TimeUnit;
32 import java.util.regex.Matcher;
33 import java.util.regex.Pattern;
34 
35 /**
36  * A test to exercise Android Framework parts related to creating, starting, stopping, and deleting
37  * a managed profile as much as possible. The aim is to catch any issues in this code before it
38  * affects managed profile CTS tests.
39  */
40 @RunWith(DeviceJUnit4ClassRunner.class)
41 public class ManagedProfileLifecycleStressTest extends BaseHostJUnit4Test {
42     // Stop the test once this time limit has been reached. 25 minutes used as a limit to make total
43     // test time less than 30 minutes, so that it can be put into presubmit.
44     private static final int TIME_LIMIT_MINUTES = 25;
45 
46     private static final String DUMMY_DPC_APK = "DummyDPC.apk";
47     private static final String DUMMY_DPC_COMPONENT =
48             "com.android.dummydpc/com.android.dummydpc.DummyDeviceAdminReceiver";
49     private static final Pattern CREATE_USER_OUTPUT_REGEX =
50             Pattern.compile("Success: created user id (\\d+)");
51 
52     /**
53      * Create, start, and kill managed profiles in a loop.
54      */
55     @Test
testCreateStartDelete()56     public void testCreateStartDelete() throws Exception {
57         // Disable package verifier for ADB installs.
58         getDevice().executeShellCommand("settings put global verifier_verify_adb_installs 0");
59         int iteration = 0;
60         final long deadline = System.nanoTime() + TimeUnit.MINUTES.toNanos(TIME_LIMIT_MINUTES);
61         while (System.nanoTime() < deadline) {
62             iteration++;
63             CLog.w("Iteration N" + iteration);
64             final int userId = createManagedProfile();
65             startUser(userId);
66             installPackageAsUser(
67                     DUMMY_DPC_APK, /* grantPermissions= */true, userId, /* options= */"-t");
68             setProfileOwner(DUMMY_DPC_COMPONENT, userId);
69             removeUser(userId);
70         }
71         CLog.w("Completed " + iteration + " iterations.");
72     }
73 
74     /**
75      * Create, start, and kill managed profiles in a loop with waitForBroadcastIdle after each user
76      * operation.
77      */
78     @Test
testCreateStartDeleteStable()79     public void testCreateStartDeleteStable() throws Exception {
80         // Disable package verifier for ADB installs.
81         getDevice().executeShellCommand("settings put global verifier_verify_adb_installs 0");
82         int iteration = 0;
83         final long deadline = System.nanoTime() + TimeUnit.MINUTES.toNanos(TIME_LIMIT_MINUTES);
84         while (System.nanoTime() < deadline) {
85             iteration++;
86             CLog.w("Iteration N" + iteration);
87             final int userId = createManagedProfile();
88             waitForBroadcastIdle();
89 
90             startUser(userId);
91             waitForBroadcastIdle();
92 
93             installPackageAsUser(
94                     DUMMY_DPC_APK, /* grantPermissions= */true, userId, /* options= */"-t");
95 
96             setProfileOwner(DUMMY_DPC_COMPONENT, userId);
97 
98             removeUser(userId);
99             waitForBroadcastIdle();
100         }
101         CLog.w("Completed " + iteration + " iterations.");
102     }
103 
waitForBroadcastIdle()104     private void waitForBroadcastIdle() throws Exception {
105         final CollectingOutputReceiver receiver = new CollectingOutputReceiver();
106         // We allow 8min for the command to complete and 4min for the command to start to
107         // output something.
108         getDevice().executeShellCommand(
109                 "am wait-for-broadcast-idle",
110                 receiver,
111                 /* maxTimeoutForCommand= */8,
112                 /* maxTimeoutToOutputShellResponse= */4,
113                 TimeUnit.MINUTES,
114                 /* retryAttempts= */0);
115         final String output = receiver.getOutput();
116         if (!output.contains("All broadcast queues are idle!")) {
117             CLog.e("Output from 'am wait-for-broadcast-idle': %s", output);
118             fail("'am wait-for-broadcase-idle' did not complete.");
119         }
120     }
121 
createManagedProfile()122     private int createManagedProfile() throws Exception {
123         final String output = getDevice().executeShellCommand(
124                 "pm create-user --profileOf 0 --managed TestProfile");
125         final Matcher matcher = CREATE_USER_OUTPUT_REGEX.matcher(output.trim());
126         if (!matcher.matches() || matcher.groupCount() != 1) {
127             fail("user creation failed, output: " + output);
128         }
129         return Integer.parseInt(matcher.group(1));
130     }
131 
setProfileOwner(String componentName, int userId)132     private void setProfileOwner(String componentName, int userId) throws Exception {
133         String command = "dpm set-profile-owner --user " + userId + " '" + componentName + "'";
134         String commandOutput = getDevice().executeShellCommand(command);
135         assertTrue("Unexpected dpm output: " + commandOutput, commandOutput.startsWith("Success:"));
136     }
137 
removeUser(int userId)138     private void removeUser(int userId) throws Exception {
139         final String output = getDevice().executeShellCommand("pm remove-user " + userId).trim();
140         assertEquals("Unexpected pm output: " + output, "Success: removed user", output);
141     }
142 
startUser(int userId)143     private void startUser(int userId) throws Exception {
144         final String output = getDevice().executeShellCommand("am start-user -w " + userId).trim();
145         assertEquals("Unexpected am output: " + output, "Success: user started", output);
146     }
147 }
148