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 package android.host.multiuser;
17 
18 import com.android.tradefed.build.IBuildInfo;
19 import com.android.tradefed.device.DeviceNotAvailableException;
20 import com.android.tradefed.log.LogUtil.CLog;
21 import com.android.tradefed.testtype.DeviceTestCase;
22 import com.android.tradefed.testtype.IBuildReceiver;
23 
24 import java.util.ArrayList;
25 
26 /**
27  * Base class for multi user tests.
28  */
29 public class BaseMultiUserTest extends DeviceTestCase implements IBuildReceiver {
30     protected static final int USER_SYSTEM = 0; // From the UserHandle class.
31 
32     protected IBuildInfo mBuildInfo;
33 
34     /** Whether multi-user is supported. */
35     protected boolean mSupportsMultiUser;
36     protected boolean mIsSplitSystemUser;
37     protected int mPrimaryUserId;
38     /** Users we shouldn't delete in the tests */
39     private ArrayList<Integer> mFixedUsers;
40 
41     @Override
setBuild(IBuildInfo buildInfo)42     public void setBuild(IBuildInfo buildInfo) {
43         mBuildInfo = buildInfo;
44     }
45 
46     @Override
setUp()47     protected void setUp() throws Exception {
48         super.setUp();
49         assertNotNull(mBuildInfo); // ensure build has been set before test is run.
50 
51         mSupportsMultiUser = getDevice().getMaxNumberOfUsersSupported() > 1;
52         mIsSplitSystemUser = checkIfSplitSystemUser();
53         mPrimaryUserId = getDevice().getPrimaryUserId();
54         mFixedUsers = new ArrayList<>();
55         mFixedUsers.add(mPrimaryUserId);
56         if (mPrimaryUserId != USER_SYSTEM) {
57             mFixedUsers.add(USER_SYSTEM);
58         }
59         getDevice().switchUser(mPrimaryUserId);
60         removeTestUsers();
61     }
62 
63     @Override
tearDown()64     protected void tearDown() throws Exception {
65         if (getDevice().getCurrentUser() != mPrimaryUserId) {
66             CLog.w("User changed during test. Switching back to " + mPrimaryUserId);
67             getDevice().switchUser(mPrimaryUserId);
68         }
69         removeTestUsers();
70         super.tearDown();
71     }
72 
createRestrictedProfile(int userId)73     protected int createRestrictedProfile(int userId)
74             throws DeviceNotAvailableException, IllegalStateException{
75         final String command = "pm create-user --profileOf " + userId + " --restricted "
76                 + "TestUser_" + System.currentTimeMillis();
77         CLog.d("Starting command: " + command);
78         final String output = getDevice().executeShellCommand(command);
79         CLog.d("Output for command " + command + ": " + output);
80 
81         if (output.startsWith("Success")) {
82             try {
83                 return Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim());
84             } catch (NumberFormatException e) {
85                 CLog.e("Failed to parse result: %s", output);
86             }
87         } else {
88             CLog.e("Failed to create restricted profile: %s", output);
89         }
90         throw new IllegalStateException();
91     }
92 
93     /**
94      * @return the userid of the created user
95      */
createUser()96     protected int createUser()
97             throws DeviceNotAvailableException, IllegalStateException {
98         final String command = "pm create-user "
99                 + "TestUser_" + System.currentTimeMillis();
100         CLog.d("Starting command: " + command);
101         final String output = getDevice().executeShellCommand(command);
102         CLog.d("Output for command " + command + ": " + output);
103 
104         if (output.startsWith("Success")) {
105             try {
106                 return Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim());
107             } catch (NumberFormatException e) {
108                 CLog.e("Failed to parse result: %s", output);
109             }
110         } else {
111             CLog.e("Failed to create user: %s", output);
112         }
113         throw new IllegalStateException();
114     }
115 
removeTestUsers()116     private void removeTestUsers() throws Exception {
117         for (int userId : getDevice().listUsers()) {
118             if (!mFixedUsers.contains(userId)) {
119                 getDevice().removeUser(userId);
120             }
121         }
122     }
123 
checkIfSplitSystemUser()124     private boolean checkIfSplitSystemUser() throws DeviceNotAvailableException {
125         final String commandOuput = getDevice().executeShellCommand(
126                 "getprop ro.fw.system_user_split");
127         return "y".equals(commandOuput) || "yes".equals(commandOuput)
128                 || "1".equals(commandOuput) || "true".equals(commandOuput)
129                 || "on".equals(commandOuput);
130     }
131 }