1 /* 2 * Copyright (C) 2021 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.os; 17 18 import android.annotation.NonNull; 19 import android.annotation.Nullable; 20 import android.annotation.SuppressLint; 21 import android.annotation.SystemApi; 22 import android.content.pm.UserInfo; 23 import android.graphics.Bitmap; 24 import android.text.TextUtils; 25 26 /** 27 * Contains necessary information to create user using 28 * {@link UserManager#createUser(NewUserRequest)}. 29 * 30 * @hide 31 */ 32 @SystemApi 33 @SuppressLint("PackageLayering") 34 public final class NewUserRequest { 35 @Nullable 36 private final String mName; 37 private final boolean mAdmin; 38 private final boolean mEphemeral; 39 @NonNull 40 private final String mUserType; 41 private final Bitmap mUserIcon; 42 private final String mAccountName; 43 private final String mAccountType; 44 private final PersistableBundle mAccountOptions; 45 NewUserRequest(Builder builder)46 private NewUserRequest(Builder builder) { 47 mName = builder.mName; 48 mAdmin = builder.mAdmin; 49 mEphemeral = builder.mEphemeral; 50 mUserType = builder.mUserType; 51 mUserIcon = builder.mUserIcon; 52 mAccountName = builder.mAccountName; 53 mAccountType = builder.mAccountType; 54 mAccountOptions = builder.mAccountOptions; 55 } 56 57 /** 58 * Returns the name of the user. 59 */ 60 @Nullable getName()61 public String getName() { 62 return mName; 63 } 64 65 /** 66 * Returns whether the user is ephemeral. 67 * 68 * <p> Ephemeral user will be removed after leaving the foreground. 69 */ isEphemeral()70 public boolean isEphemeral() { 71 return mEphemeral; 72 } 73 74 /** 75 * Returns whether the user is an admin. 76 * 77 * <p> Admin user is with administrative privileges and such user can create and 78 * delete users. 79 */ isAdmin()80 public boolean isAdmin() { 81 return mAdmin; 82 } 83 84 /** 85 * Returns the calculated flags for user creation. 86 */ getFlags()87 int getFlags() { 88 int flags = 0; 89 if (isAdmin()) flags |= UserInfo.FLAG_ADMIN; 90 if (isEphemeral()) flags |= UserInfo.FLAG_EPHEMERAL; 91 return flags; 92 } 93 94 /** 95 * Returns the user type. 96 * 97 * <p> Default value is {@link UserManager#USER_TYPE_FULL_SECONDARY} 98 */ 99 @NonNull getUserType()100 public String getUserType() { 101 return mUserType; 102 } 103 104 /** 105 * Returns the user icon. 106 */ 107 @Nullable getUserIcon()108 public Bitmap getUserIcon() { 109 return mUserIcon; 110 } 111 112 /** 113 * Returns the account name. 114 */ 115 @Nullable getAccountName()116 public String getAccountName() { 117 return mAccountName; 118 } 119 120 /** 121 * Returns the account type. 122 */ 123 @Nullable getAccountType()124 public String getAccountType() { 125 return mAccountType; 126 } 127 128 /** 129 * Returns the account options. 130 */ 131 @SuppressLint("NullableCollection") 132 @Nullable getAccountOptions()133 public PersistableBundle getAccountOptions() { 134 return mAccountOptions; 135 } 136 137 @Override toString()138 public String toString() { 139 return "NewUserRequest{" 140 + "mName='" + mName + '\'' 141 + ", mAdmin=" + mAdmin 142 + ", mEphemeral=" + mEphemeral 143 + ", mUserType='" + mUserType + '\'' 144 + ", mAccountName='" + mAccountName + '\'' 145 + ", mAccountType='" + mAccountType + '\'' 146 + ", mAccountOptions=" + mAccountOptions 147 + '}'; 148 } 149 150 /** 151 * Builder for building {@link NewUserRequest} 152 */ 153 @SuppressLint("PackageLayering") 154 public static final class Builder { 155 156 private String mName; 157 private boolean mAdmin; 158 private boolean mEphemeral; 159 private String mUserType = UserManager.USER_TYPE_FULL_SECONDARY; 160 private Bitmap mUserIcon; 161 private String mAccountName; 162 private String mAccountType; 163 private PersistableBundle mAccountOptions; 164 165 /** 166 * Sets user name. 167 * 168 * @return This object for method chaining. 169 */ 170 @NonNull setName(@ullable String name)171 public Builder setName(@Nullable String name) { 172 mName = name; 173 return this; 174 } 175 176 /** 177 * Sets user as admin. 178 * 179 * <p> Admin user is with administrative privileges and such user can create 180 * and delete users. 181 * 182 * @return This object for method chaining. 183 */ 184 @NonNull setAdmin()185 public Builder setAdmin() { 186 mAdmin = true; 187 return this; 188 } 189 190 /** 191 * Sets user as ephemeral. 192 * 193 * <p> Ephemeral user will be removed after leaving the foreground. 194 * 195 * @return This object for method chaining. 196 */ 197 @NonNull setEphemeral()198 public Builder setEphemeral() { 199 mEphemeral = true; 200 return this; 201 } 202 203 /** 204 * Sets user type. 205 * 206 * <p> Default value is {link UserManager#USER_TYPE_FULL_SECONDARY}. 207 * 208 * @return This object for method chaining. 209 */ 210 @NonNull setUserType(@onNull String type)211 public Builder setUserType(@NonNull String type) { 212 mUserType = type; 213 return this; 214 } 215 216 /** 217 * Sets user icon. 218 * 219 * @return This object for method chaining. 220 */ 221 @NonNull setUserIcon(@ullable Bitmap userIcon)222 public Builder setUserIcon(@Nullable Bitmap userIcon) { 223 mUserIcon = userIcon; 224 return this; 225 } 226 227 /** 228 * Sets account name that will be used by the setup wizard to initialize the user. 229 * 230 * @see android.accounts.Account 231 * @return This object for method chaining. 232 */ 233 @NonNull setAccountName(@ullable String accountName)234 public Builder setAccountName(@Nullable String accountName) { 235 mAccountName = accountName; 236 return this; 237 } 238 239 /** 240 * Sets account type for the account to be created. This is required if the account name 241 * is not null. This will be used by the setup wizard to initialize the user. 242 * 243 * @see android.accounts.Account 244 * @return This object for method chaining. 245 */ 246 @NonNull setAccountType(@ullable String accountType)247 public Builder setAccountType(@Nullable String accountType) { 248 mAccountType = accountType; 249 return this; 250 } 251 252 /** 253 * Sets account options that can contain account-specific extra information 254 * to be used by setup wizard to initialize the account for the user. 255 * 256 * @return This object for method chaining. 257 */ 258 @NonNull setAccountOptions(@ullable PersistableBundle accountOptions)259 public Builder setAccountOptions(@Nullable PersistableBundle accountOptions) { 260 mAccountOptions = accountOptions; 261 return this; 262 } 263 264 /** 265 * Builds {@link NewUserRequest} 266 * 267 * @throws IllegalStateException if builder is configured with incompatible properties and 268 * it is not possible to create such user. For example - a guest admin user. 269 */ 270 @NonNull build()271 public NewUserRequest build() { 272 checkIfPropertiesAreCompatible(); 273 return new NewUserRequest(this); 274 } 275 checkIfPropertiesAreCompatible()276 private void checkIfPropertiesAreCompatible() { 277 if (mUserType == null) { 278 throw new IllegalStateException("Usertype cannot be null"); 279 } 280 281 // Admin user can only be USER_TYPE_FULL_SECONDARY 282 if (mAdmin && !mUserType.equals(UserManager.USER_TYPE_FULL_SECONDARY)) { 283 throw new IllegalStateException("Admin user can't be of type: " + mUserType); 284 } 285 286 if (TextUtils.isEmpty(mAccountName) != TextUtils.isEmpty(mAccountType)) { 287 throw new IllegalStateException( 288 "Account name and account type should be provided together."); 289 } 290 } 291 } 292 } 293