1 /*
2  * Copyright (C) 2020 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.car.test.util;
17 
18 import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
19 
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.UserIdInt;
23 import android.content.pm.UserInfo;
24 import android.content.pm.UserInfo.UserInfoFlag;
25 import android.os.UserManager;
26 
27 import com.android.internal.util.Preconditions;
28 
29 import java.util.Arrays;
30 import java.util.List;
31 import java.util.stream.Collectors;
32 
33 /**
34  * Provides utilities for Android User related tasks.
35  */
36 public final class UserTestingHelper {
37 
38     /**
39      * Creates a simple {@link UserInfo}, containing just the given {@code userId}.
40      */
41     @NonNull
newUser(@serIdInt int userId)42     public static UserInfo newUser(@UserIdInt int userId) {
43         return new UserInfoBuilder(userId).build();
44     }
45 
46     /**
47      * Creates a list of {@link UserInfo UserInfos}, each containing just the given user ids.
48      */
49     @NonNull
newUsers(@serIdInt int... userIds)50     public static List<UserInfo> newUsers(@UserIdInt int... userIds) {
51         return Arrays.stream(userIds)
52                 .mapToObj(id -> newUser(id))
53                 .collect(Collectors.toList());
54     }
55 
56     /**
57      * Creates a {@link UserInfo} with the type explicitly set and with the given {@code userId}.
58      */
59     @NonNull
newSecondaryUser(@serIdInt int userId)60     public static UserInfo newSecondaryUser(@UserIdInt int userId) {
61         return new UserInfoBuilder(userId).setType(UserManager.USER_TYPE_FULL_SECONDARY).build();
62     }
63 
64     /**
65      * Creates a new guest with the given {@code userId} and proper flags and types set.
66      */
67     @NonNull
newGuestUser(@serIdInt int userId, boolean ephemeral)68     public static UserInfo newGuestUser(@UserIdInt int userId, boolean ephemeral) {
69         return new UserInfoBuilder(userId).setGuest(true).setEphemeral(ephemeral).build();
70     }
71 
72     /**
73      * Creates a new guest with the given {@code userId} and without any flag..
74      */
75     @NonNull
newGuestUser(@serIdInt int userId)76     public static UserInfo newGuestUser(@UserIdInt int userId) {
77         return new UserInfoBuilder(userId).setGuest(true).build();
78     }
79 
80     /**
81      * Gets the default {@link UserInfo#userType} for a guest / regular user.
82      */
83     @NonNull
getDefaultUserType(boolean isGuest)84     public static String getDefaultUserType(boolean isGuest) {
85         return isGuest ? UserManager.USER_TYPE_FULL_GUEST : UserManager.USER_TYPE_FULL_SECONDARY;
86     }
87 
88     /**
89      * Sets the property that defines the maximum number of uses allowed in the device.
90      */
setMaxSupportedUsers(int max)91     public static void setMaxSupportedUsers(int max) {
92         runShellCommand("setprop fw.max_users %d", max);
93     }
94 
95     /**
96      * Configures the user to use PIN credentials.
97      */
setUserLockCredentials(@serIdInt int userId, int pin)98     public static void setUserLockCredentials(@UserIdInt int userId, int pin) {
99         runShellCommand("locksettings set-pin %s --user %d ", pin, userId);
100     }
101 
102     /**
103      * Clears the user credentials using current PIN.
104      */
clearUserLockCredentials(@serIdInt int userId, int pin)105     public static void clearUserLockCredentials(@UserIdInt int userId, int pin) {
106         runShellCommand("locksettings clear --old %d --user %d ", pin, userId);
107     }
108 
109     /**
110      * Builder for {@link UserInfo} objects.
111      */
112     public static final class UserInfoBuilder {
113 
114         @UserIdInt
115         private final int mUserId;
116 
117         @UserInfoFlag
118         private int mFlags;
119 
120         @Nullable
121         private String mName;
122 
123         @Nullable
124         private String mType;
125 
126         private boolean mGuest;
127         private boolean mEphemeral;
128         private boolean mAdmin;
129         private boolean mPreCreated;
130         private boolean mInitialized;
131 
132         /**
133          * Default constructor.
134          */
UserInfoBuilder(@serIdInt int userId)135         public UserInfoBuilder(@UserIdInt int userId) {
136             mUserId = userId;
137         }
138 
139         /**
140          * Sets the user name.
141          */
142         @NonNull
setName(@ullable String name)143         public UserInfoBuilder setName(@Nullable String name) {
144             mName = name;
145             return this;
146         }
147 
148         /**
149          * Sets the user type.
150          */
151         @NonNull
setType(@ullable String type)152         public UserInfoBuilder setType(@Nullable String type) {
153             Preconditions.checkState(!mGuest, "cannot set type (" + mType + ") after setting it as "
154                     + "guest");
155             mType = type;
156             return this;
157         }
158 
159         /**
160          * Sets whether the user is a guest.
161          */
162         @NonNull
setGuest(boolean guest)163         public UserInfoBuilder setGuest(boolean guest) {
164             Preconditions.checkState(mType == null, "cannot set guest after setting type (" + mType
165                     + ")");
166             mGuest = guest;
167             return this;
168         }
169 
170         /**
171          * Sets the user flags
172          */
173         @NonNull
setFlags(@serInfoFlag int flags)174         public UserInfoBuilder setFlags(@UserInfoFlag int flags) {
175             mFlags = flags;
176             return this;
177         }
178 
179         /**
180          * Sets whether the user is ephemeral.
181          */
182         @NonNull
setEphemeral(boolean ephemeral)183         public UserInfoBuilder setEphemeral(boolean ephemeral) {
184             mEphemeral = ephemeral;
185             return this;
186         }
187 
188         /**
189          * Sets whether the user is an admin.
190          */
191         @NonNull
setAdmin(boolean admin)192         public UserInfoBuilder setAdmin(boolean admin) {
193             mAdmin = admin;
194             return this;
195         }
196 
197         /**
198          * Sets whether the user is an pre-created.
199          */
200         @NonNull
setPreCreated(boolean preCreated)201         public UserInfoBuilder setPreCreated(boolean preCreated) {
202             mPreCreated = preCreated;
203             return this;
204         }
205 
206         /**
207          * Sets whether the user is initialized.
208          */
209         @NonNull
setInitialized(boolean initialized)210         public UserInfoBuilder setInitialized(boolean initialized) {
211             mInitialized = initialized;
212             return this;
213         }
214 
215         /**
216          * Creates a new {@link UserInfo}.
217          */
218         @NonNull
build()219         public UserInfo build() {
220             int flags = mFlags;
221             if (mEphemeral) {
222                 flags |= UserInfo.FLAG_EPHEMERAL;
223             }
224             if (mAdmin) {
225                 flags |= UserInfo.FLAG_ADMIN;
226             }
227             if (mInitialized) {
228                 flags |= UserInfo.FLAG_INITIALIZED;
229             }
230             if (mGuest) {
231                 mType = UserManager.USER_TYPE_FULL_GUEST;
232             }
233             UserInfo info = new UserInfo(mUserId, mName, /* iconPath= */ null, flags, mType);
234             info.preCreated = mPreCreated;
235             return info;
236         }
237     }
238 
UserTestingHelper()239     private UserTestingHelper() {
240         throw new UnsupportedOperationException("contains only static methods");
241     }
242 }
243