1 /* <lambda>null2 * Copyright (C) 2024 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 com.android.bedstead.multiuser 17 18 import android.os.Build 19 import android.os.Process 20 import android.os.UserHandle 21 import com.android.bedstead.harrier.BedsteadJUnit4 22 import com.android.bedstead.harrier.DeviceState 23 import com.android.bedstead.harrier.annotations.EnsureHasNoSecondaryUser 24 import com.android.bedstead.enterprise.annotations.EnsureHasNoWorkProfile 25 import com.android.bedstead.harrier.annotations.EnsureHasSecondaryUser 26 import com.android.bedstead.enterprise.annotations.EnsureHasWorkProfile 27 import com.android.bedstead.harrier.annotations.RequireHeadlessSystemUserMode 28 import com.android.bedstead.harrier.annotations.RequireRunNotOnSecondaryUser 29 import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser 30 import com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser 31 import com.android.bedstead.enterprise.annotations.EnsureHasNoDeviceOwner 32 import com.android.bedstead.multiuser.annotations.EnsureCanAddUser 33 import com.android.bedstead.nene.TestApis 34 import com.android.bedstead.nene.exceptions.NeneException 35 import com.android.bedstead.nene.types.OptionalBoolean 36 import com.android.bedstead.nene.users.UserReference 37 import com.android.bedstead.nene.users.UserType 38 import com.android.bedstead.nene.utils.Poll 39 import com.google.common.truth.Truth.assertThat 40 import org.junit.Assume 41 import org.junit.ClassRule 42 import org.junit.Ignore 43 import org.junit.Rule 44 import org.junit.Test 45 import org.junit.runner.RunWith 46 import org.testng.Assert.assertThrows 47 48 @RunWith(BedsteadJUnit4::class) 49 class UsersTest { 50 private val mSecondaryUserType = TestApis 51 .users() 52 .supportedType(UserType.SECONDARY_USER_TYPE_NAME) 53 private val mManagedProfileType = TestApis 54 .users() 55 .supportedType(UserType.MANAGED_PROFILE_TYPE_NAME) 56 private val mInstrumentedUser = TestApis 57 .users() 58 .instrumented() 59 60 // We don't want to test the exact list of any specific device, so we check that it returns 61 // some known types which will exist on the emulators (used for presubmit tests). 62 @Test 63 fun supportedTypes_containsManagedProfile() { 64 val managedProfileUserType = TestApis 65 .users() 66 .supportedTypes() 67 .first { ut: UserType -> ut.name() == UserType.MANAGED_PROFILE_TYPE_NAME } 68 69 assertThat( 70 managedProfileUserType.baseType() 71 ).containsExactly(UserType.BaseType.PROFILE) 72 assertThat(managedProfileUserType.enabled()).isTrue() 73 assertThat(managedProfileUserType.maxAllowed()).isEqualTo(MAX_MANAGED_PROFILES) 74 assertThat( 75 managedProfileUserType.maxAllowedPerParent() 76 ).isEqualTo(MAX_MANAGED_PROFILES_PER_PARENT) 77 } 78 79 @Test 80 fun supportedTypes_containsSystemUser() { 81 val systemUserType = TestApis 82 .users() 83 .supportedTypes() 84 .first { ut: UserType -> ut.name() == UserType.SYSTEM_USER_TYPE_NAME } 85 86 assertThat(systemUserType.baseType()) 87 .containsExactly(UserType.BaseType.SYSTEM, UserType.BaseType.FULL) 88 assertThat(systemUserType.enabled()).isTrue() 89 assertThat(systemUserType.maxAllowed()).isEqualTo(MAX_SYSTEM_USERS) 90 assertThat( 91 systemUserType.maxAllowedPerParent() 92 ).isEqualTo(MAX_SYSTEM_USERS_PER_PARENT) 93 } 94 95 @Test 96 fun supportedType_validType_returnsType() { 97 val managedProfileUserType = TestApis 98 .users() 99 .supportedType(UserType.MANAGED_PROFILE_TYPE_NAME) 100 101 assertThat( 102 managedProfileUserType!!.baseType() 103 ).containsExactly(UserType.BaseType.PROFILE) 104 assertThat(managedProfileUserType.enabled()).isTrue() 105 assertThat( 106 managedProfileUserType.maxAllowed() 107 ).isEqualTo(MAX_MANAGED_PROFILES) 108 assertThat(managedProfileUserType.maxAllowedPerParent()) 109 .isEqualTo(MAX_MANAGED_PROFILES_PER_PARENT) 110 } 111 112 @Test 113 fun supportedType_invalidType_returnsNull() { 114 assertThat(TestApis.users().supportedType(INVALID_TYPE_NAME)).isNull() 115 } 116 117 @Test 118 @EnsureCanAddUser 119 fun all_containsCreatedUser() { 120 val user = TestApis.users().createUser().create() 121 122 try { 123 assertThat(TestApis.users().all()).contains(user) 124 } finally { 125 user.remove() 126 } 127 } 128 129 @Test 130 @EnsureCanAddUser(number = 2) 131 fun all_userAddedSinceLastCallToUsers_containsNewUser() { 132 val user = TestApis.users().createUser().create() 133 TestApis.users().all() 134 val user2 = TestApis.users().createUser().create() 135 136 try { 137 assertThat(TestApis.users().all()).contains(user2) 138 } finally { 139 user.remove() 140 user2.remove() 141 } 142 } 143 144 @Test 145 @EnsureCanAddUser 146 fun all_userRemovedSinceLastCallToUsers_doesNotContainRemovedUser() { 147 val user = TestApis.users().createUser().create() 148 149 user.remove() 150 151 assertThat(TestApis.users().all()).doesNotContain(user) 152 } 153 154 @Test 155 @EnsureCanAddUser 156 fun find_userExists_returnsUserReference() { 157 val user = TestApis.users().createUser().create() 158 159 try { 160 assertThat(TestApis.users().find(user.id())).isEqualTo(user) 161 } finally { 162 user.remove() 163 } 164 } 165 166 @Test 167 fun find_userDoesNotExist_returnsUserReference() { 168 assertThat(TestApis.users().find(NON_EXISTING_USER_ID)).isNotNull() 169 } 170 171 @Test 172 fun find_fromUserHandle_referencesCorrectId() { 173 assertThat(TestApis.users().find(UserHandle.of(USER_ID)).id()).isEqualTo(USER_ID) 174 } 175 176 @Test 177 fun find_constructedReferenceReferencesCorrectId() { 178 assertThat(TestApis.users().find(USER_ID).id()).isEqualTo(USER_ID) 179 } 180 181 @Test 182 @EnsureCanAddUser 183 fun createUser_additionalSystemUser_throwsException() { 184 assertThrows(NeneException::class.java) { 185 TestApis.users().createUser() 186 .type(TestApis.users().supportedType(UserType.SYSTEM_USER_TYPE_NAME)) 187 .create() 188 } 189 } 190 191 @Test 192 @EnsureCanAddUser 193 fun createUser_userIsCreated_andIsNotEphemeralOrGuest() { 194 val user = TestApis.users().createUser().create() 195 196 try { 197 assertThat(user.exists()).isTrue() 198 assertThat(user.isEphemeral).isFalse() 199 assertThat(user.isGuest).isFalse() 200 } finally { 201 user.remove() 202 } 203 } 204 205 @Test 206 @EnsureCanAddUser 207 fun createUser_createdUserHasCorrectName() { 208 val userReference = TestApis 209 .users() 210 .createUser() 211 .name(USER_NAME) 212 .create() 213 214 try { 215 assertThat(userReference.name()).isEqualTo(USER_NAME) 216 } finally { 217 userReference.remove() 218 } 219 } 220 221 @Test 222 @EnsureCanAddUser 223 fun createUser_createdUserHasCorrectTypeName() { 224 val userReference = TestApis.users().createUser() 225 .type(mSecondaryUserType) 226 .create() 227 228 try { 229 assertThat(userReference.type()).isEqualTo(mSecondaryUserType) 230 } finally { 231 userReference.remove() 232 } 233 } 234 235 @Test 236 @EnsureCanAddUser 237 fun createUser_specifiesNullStringUserType_throwsException() { 238 val userBuilder = TestApis.users().createUser() 239 240 assertThrows(NullPointerException::class.java) { 241 userBuilder.type(null as String?) 242 } 243 } 244 245 @Test 246 @EnsureCanAddUser 247 fun createUser_specifiesNullUserType_throwsException() { 248 val userBuilder = TestApis.users().createUser() 249 250 assertThrows(NullPointerException::class.java) { 251 userBuilder.type(null as UserType?) 252 } 253 } 254 255 @Test 256 @EnsureCanAddUser 257 fun createUser_specifiesSystemUserType_throwsException() { 258 val type = TestApis.users().supportedType(UserType.SYSTEM_USER_TYPE_NAME) 259 val userBuilder = TestApis.users().createUser() 260 .type(type) 261 262 assertThrows(NeneException::class.java) { userBuilder.create() } 263 } 264 265 @Test 266 @EnsureCanAddUser 267 fun createUser_specifiesSecondaryUserType_createsUser() { 268 val user = TestApis.users().createUser().type(mSecondaryUserType).create() 269 270 try { 271 assertThat(user.exists()).isTrue() 272 } finally { 273 user.remove() 274 } 275 } 276 277 @Test 278 @EnsureHasNoDeviceOwner // Device Owners can disable managed profiles 279 @EnsureHasNoWorkProfile 280 @EnsureCanAddUser 281 fun createUser_specifiesManagedProfileUserType_createsUser() { 282 val personalUser = TestApis.users().instrumented() 283 val user = TestApis.users() 284 .createUser() 285 .type(mManagedProfileType) 286 .parent(personalUser) 287 .create() 288 289 try { 290 assertThat(user.exists()).isTrue() 291 } finally { 292 user.remove() 293 } 294 } 295 296 @Test 297 @EnsureHasNoWorkProfile 298 @EnsureCanAddUser 299 fun createUser_createsProfile_parentIsSet() { 300 val personalUser = TestApis.users().instrumented() 301 val user = TestApis 302 .users() 303 .createUser() 304 .type(mManagedProfileType) 305 .parent(personalUser) 306 .create() 307 308 try { 309 assertThat(user.parent()) 310 .isEqualTo(TestApis.users().instrumented()) 311 } finally { 312 user.remove() 313 } 314 } 315 316 @Test 317 @EnsureCanAddUser 318 fun createUser_specifiesParentOnNonProfileType_throwsException() { 319 val systemUser = TestApis.users().system() 320 val userBuilder = TestApis.users().createUser() 321 .type(mSecondaryUserType).parent(systemUser) 322 323 assertThrows(NeneException::class.java) { userBuilder.create() } 324 } 325 326 @Test 327 @EnsureCanAddUser 328 fun createUser_specifiesProfileTypeWithoutParent_throwsException() { 329 val userBuilder = TestApis.users().createUser().type(mManagedProfileType) 330 331 assertThrows(NeneException::class.java) { userBuilder.create() } 332 } 333 334 @Test 335 @EnsureCanAddUser 336 fun createUser_androidLessThanS_createsManagedProfileNotOnSystemUser_throwsException() { 337 Assume.assumeTrue( 338 "After Android S, managed profiles may be a profile of a non-system user", 339 Build.VERSION.SDK_INT < Build.VERSION_CODES.S 340 ) 341 val nonSystemUser = TestApis.users().createUser().create() 342 try { 343 val userBuilder = TestApis.users().createUser() 344 .type(mManagedProfileType) 345 .parent(nonSystemUser) 346 347 assertThrows(NeneException::class.java) { userBuilder.create() } 348 } finally { 349 nonSystemUser.remove() 350 } 351 } 352 353 @Test 354 @EnsureCanAddUser 355 fun createAndStart_isStarted() { 356 var user: UserReference? = null 357 try { 358 user = TestApis.users().createUser().name(USER_NAME).createAndStart() 359 360 assertThat(user.isUnlocked()).isTrue() 361 } finally { 362 user?.remove() 363 } 364 } 365 366 @Test 367 fun system_hasId0() { 368 assertThat(TestApis.users().system().id()).isEqualTo(0) 369 } 370 371 @Test 372 fun instrumented_hasCurrentProcessId() { 373 assertThat(TestApis.users().instrumented().id()) 374 .isEqualTo(Process.myUserHandle().identifier) 375 } 376 377 @Test 378 @EnsureHasNoSecondaryUser 379 fun findUsersOfType_noMatching_returnsEmptySet() { 380 assertThat(TestApis.users().findUsersOfType(mSecondaryUserType)).isEmpty() 381 } 382 383 @Test 384 fun findUsersOfType_nullType_throwsException() { 385 assertThrows(NullPointerException::class.java) { 386 TestApis.users().findUsersOfType(null) 387 } 388 } 389 390 @Test 391 @EnsureHasSecondaryUser 392 @Ignore( 393 "TODO: Re-enable when harrier .secondaryUser() only" + 394 " returns the harrier-managed secondary user" 395 ) 396 @EnsureCanAddUser 397 fun findUsersOfType_returnsUsers() { 398 TestApis.users().createUser().create().use { additionalUser -> 399 400 assertThat(TestApis.users().findUsersOfType(mSecondaryUserType)) 401 .containsExactly(sDeviceState.secondaryUser(), additionalUser) 402 } 403 } 404 405 @Test 406 fun findUsersOfType_profileType_throwsException() { 407 assertThrows(NeneException::class.java) { 408 TestApis.users().findUsersOfType(mManagedProfileType) 409 } 410 } 411 412 @Test 413 @EnsureHasNoSecondaryUser 414 fun findUserOfType_noMatching_returnsNull() { 415 assertThat(TestApis.users().findUserOfType(mSecondaryUserType)).isNull() 416 } 417 418 @Test 419 fun findUserOfType_nullType_throwsException() { 420 assertThrows(NullPointerException::class.java) { 421 TestApis.users().findUserOfType(null) 422 } 423 } 424 425 @Test 426 @EnsureHasSecondaryUser 427 @EnsureCanAddUser 428 fun findUserOfType_multipleMatchingUsers_throwsException() { 429 TestApis.users().createUser().create().use { _ -> 430 431 assertThrows(NeneException::class.java) { 432 TestApis.users().findUserOfType(mSecondaryUserType) 433 } 434 } 435 } 436 437 @Test 438 @EnsureHasSecondaryUser 439 fun findUserOfType_oneMatchingUser_returnsUser() { 440 val users = TestApis.users().findUsersOfType(mSecondaryUserType) 441 val i: Iterator<UserReference> = users.iterator() 442 i.next() // Skip the first one so we leave one 443 while (i.hasNext()) { 444 i.next().remove() 445 } 446 447 assertThat(TestApis.users().findUserOfType(mSecondaryUserType)).isNotNull() 448 } 449 450 @Test 451 fun findUserOfType_profileType_throwsException() { 452 assertThrows(NeneException::class.java) { 453 TestApis.users().findUserOfType(mManagedProfileType) 454 } 455 } 456 457 @Test 458 @EnsureHasNoWorkProfile 459 fun findProfilesOfType_noMatching_returnsEmptySet() { 460 assertThat( 461 TestApis.users().findProfilesOfType(mManagedProfileType, mInstrumentedUser) 462 ).isEmpty() 463 } 464 465 @Test 466 fun findProfilesOfType_nullType_throwsException() { 467 assertThrows(NullPointerException::class.java) { 468 TestApis.users().findProfilesOfType(null, mInstrumentedUser) 469 } 470 } 471 472 @Test 473 fun findProfilesOfType_nullParent_throwsException() { 474 assertThrows(NullPointerException::class.java) { 475 TestApis.users().findProfilesOfType(mManagedProfileType, null) 476 } 477 } 478 479 // TODO(scottjonathan): Once we have profiles which support more than one instance, test this 480 @Test 481 @EnsureHasNoWorkProfile 482 fun findProfileOfType_noMatching_returnsNull() { 483 assertThat( 484 TestApis.users().findProfileOfType(mManagedProfileType, mInstrumentedUser) 485 ).isNull() 486 } 487 488 @Test 489 fun findProfilesOfType_nonProfileType_throwsException() { 490 assertThrows(NeneException::class.java) { 491 TestApis.users().findProfilesOfType(mSecondaryUserType, mInstrumentedUser) 492 } 493 } 494 495 @Test 496 fun findProfileOfType_nullType_throwsException() { 497 assertThrows(NullPointerException::class.java) { 498 TestApis.users().findProfileOfType(null, mInstrumentedUser) 499 } 500 } 501 502 @Test 503 fun findProfileOfType_nonProfileType_throwsException() { 504 assertThrows(NeneException::class.java) { 505 TestApis.users().findProfileOfType(mSecondaryUserType, mInstrumentedUser) 506 } 507 } 508 509 @Test 510 fun findProfileOfType_nullParent_throwsException() { 511 assertThrows(NullPointerException::class.java) { 512 TestApis.users().findProfileOfType(mManagedProfileType, null) 513 } 514 } 515 516 @Test // TODO(scottjonathan): This should have a way of specifying exactly 1 517 @EnsureHasWorkProfile 518 fun findProfileOfType_oneMatchingUser_returnsUser() { 519 assertThat( 520 TestApis.users().findProfileOfType(mManagedProfileType, mInstrumentedUser) 521 ).isNotNull() 522 } 523 524 @Test 525 fun nonExisting_userDoesNotExist() { 526 val userReference = TestApis.users().nonExisting() 527 528 assertThat(userReference.exists()).isFalse() 529 } 530 531 @Test 532 @EnsureHasSecondaryUser(switchedToUser = OptionalBoolean.TRUE) 533 fun currentUser_secondaryUser_returnsCurrentUser() { 534 assertThat(TestApis.users().current()).isEqualTo(sDeviceState.secondaryUser()) 535 } 536 537 @Test 538 @RequireRunOnPrimaryUser(switchedToUser = OptionalBoolean.TRUE) 539 fun currentUser_primaryUser_returnsCurrentUser() { 540 assertThat(TestApis.users().current()).isEqualTo(sDeviceState.primaryUser()) 541 } 542 543 @Test 544 @RequireRunNotOnSecondaryUser 545 @EnsureHasSecondaryUser 546 @RequireHeadlessSystemUserMode(reason = "stopBgUsersOnSwitch is only for headless") 547 @Throws(Exception::class) 548 fun switch_hasSetStopBgUsersOnSwitch_stopsUser() { 549 try { 550 sDeviceState.secondaryUser().switchTo() 551 TestApis.users().setStopBgUsersOnSwitch(OptionalBoolean.TRUE) 552 TestApis.users().system().switchTo() 553 Poll.forValue("Secondary user running") { 554 sDeviceState.secondaryUser().isRunning() 555 } 556 .toBeEqualTo(false) 557 .errorOnFail() 558 .await() 559 560 assertThat(sDeviceState.secondaryUser().isRunning()).isFalse() 561 } finally { 562 sDeviceState.secondaryUser().start() 563 TestApis.users().setStopBgUsersOnSwitch(OptionalBoolean.ANY) 564 } 565 } 566 567 @Test 568 @RequireRunOnSecondaryUser 569 fun switch_hasSetStopBgUsersOnSwitchFalse_doesNotStopUser() { 570 try { 571 TestApis.users().setStopBgUsersOnSwitch(OptionalBoolean.FALSE) 572 TestApis.users().system().switchTo() 573 assertThat(sDeviceState.secondaryUser().isRunning()).isTrue() 574 } finally { 575 TestApis.users().setStopBgUsersOnSwitch(OptionalBoolean.ANY) 576 sDeviceState.secondaryUser().start() 577 sDeviceState.secondaryUser().switchTo() 578 } 579 } 580 581 @Test 582 @EnsureCanAddUser 583 fun createEphemeralUser() { 584 TestApis.users() 585 .createUser() 586 .ephemeral(true) 587 .create().use { user -> 588 589 assertThat(user.isEphemeral).isTrue() 590 } 591 } 592 593 @Test 594 @EnsureCanAddUser 595 fun createGuestUser() { 596 TestApis.users() 597 .createUser() 598 .type(UserType.USER_TYPE_FULL_GUEST) 599 .create().use { user -> 600 601 assertThat(user.isGuest).isTrue() 602 } 603 } 604 605 companion object { 606 private const val MAX_SYSTEM_USERS = 1 607 private const val MAX_SYSTEM_USERS_PER_PARENT = UserType.UNLIMITED 608 private const val INVALID_TYPE_NAME = "invalidTypeName" 609 private const val MAX_MANAGED_PROFILES = UserType.UNLIMITED 610 private const val MAX_MANAGED_PROFILES_PER_PARENT = 1 611 private const val NON_EXISTING_USER_ID = 10000 612 private const val USER_ID = NON_EXISTING_USER_ID 613 private const val USER_NAME = "userName" 614 615 @ClassRule 616 @Rule 617 @JvmField 618 val sDeviceState = DeviceState() 619 } 620 } 621