1 /* 2 * 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 17 package android.devicepolicy.cts 18 19 import android.accounts.Account 20 import android.accounts.AccountManager 21 import android.accounts.RemoteAccountManager 22 import android.app.admin.flags.Flags.FLAG_SPLIT_CREATE_MANAGED_PROFILE_ENABLED 23 import android.os.UserHandle 24 import com.android.bedstead.accounts.accounts 25 import com.android.bedstead.accounts.annotations.EnsureHasAccountAuthenticator 26 import com.android.bedstead.enterprise.annotations.EnsureHasDevicePolicyManagerRoleHolder 27 import com.android.bedstead.enterprise.dpmRoleHolder 28 import com.android.bedstead.flags.annotations.RequireFlagsEnabled 29 import com.android.bedstead.harrier.BedsteadJUnit4 30 import com.android.bedstead.harrier.DeviceState 31 import com.android.bedstead.harrier.UserType 32 import com.android.bedstead.harrier.annotations.Postsubmit 33 import com.android.bedstead.multiuser.annotations.EnsureHasSecondaryUser 34 import com.android.bedstead.multiuser.secondaryUser 35 import com.android.bedstead.nene.TestApis 36 import com.android.bedstead.permissions.CommonPermissions.COPY_ACCOUNTS 37 import com.android.bedstead.permissions.annotations.EnsureDoesNotHavePermission 38 import com.android.bedstead.remoteaccountauthenticator.RemoteAccountAuthenticator 39 import com.android.compatibility.common.util.ApiTest 40 import com.google.common.truth.Truth.assertThat 41 import org.junit.Assert.assertThrows 42 import org.junit.ClassRule 43 import org.junit.Rule 44 import org.junit.Test 45 import org.junit.runner.RunWith 46 47 @RunWith(BedsteadJUnit4::class) 48 @RequireFlagsEnabled(FLAG_SPLIT_CREATE_MANAGED_PROFILE_ENABLED) 49 @EnsureHasAccountAuthenticator 50 class AccountMigrationTest { 51 52 @Test 53 @EnsureHasDevicePolicyManagerRoleHolder 54 @Postsubmit(reason = "new test") 55 @ApiTest(apis = ["android.accounts.AccountManager#removeAccount"]) removeAccount_hasRemoveAccountsPermission_removesAccountnull56 fun removeAccount_hasRemoveAccountsPermission_removesAccount() { 57 val previousNumberOfAccounts = sDeviceState.accounts().allAccounts().size 58 val account = addAccount() 59 60 val result = sDeviceState.dpmRoleHolder().accountManager().removeAccount( 61 account, 62 null, 63 null, 64 null 65 ).result 66 67 assertThat(result).isNotNull() 68 assertThat(result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT)).isTrue() 69 assertThat(sDeviceState.accounts().allAccounts().size).isEqualTo(previousNumberOfAccounts) 70 } 71 72 @Test 73 @EnsureHasDevicePolicyManagerRoleHolder 74 @EnsureHasSecondaryUser 75 @EnsureHasAccountAuthenticator(onUser = UserType.SECONDARY_USER) 76 @ApiTest(apis = ["android.accounts.AccountManager#copyAccountToUser"]) copyAccountToUser_hasCopyAccountsPermission_copiesAccountToOtherUsernull77 fun copyAccountToUser_hasCopyAccountsPermission_copiesAccountToOtherUser() { 78 val account = addAccount() 79 80 val result = sDeviceState.dpmRoleHolder().accountManager().copyAccountToUser( 81 account, 82 sDeviceState.initialUser().userHandle(), 83 sDeviceState.secondaryUser().userHandle(), 84 null, 85 null 86 ).result 87 88 assertThat(result).isTrue() 89 assertThat( 90 sDeviceState.accounts(sDeviceState.secondaryUser()) 91 .containsAccount(account) 92 ).isTrue() 93 } 94 95 @Test 96 @EnsureDoesNotHavePermission(COPY_ACCOUNTS) 97 @EnsureHasSecondaryUser 98 @EnsureHasAccountAuthenticator(onUser = UserType.SECONDARY_USER) 99 @Postsubmit(reason = "new test") 100 @ApiTest(apis = ["android.accounts.AccountManager#copyAccountToUser"]) copyAccountToUser_noPermission_throwsSecurityExceptionnull101 fun copyAccountToUser_noPermission_throwsSecurityException() { 102 val account = addAccount() 103 104 assertThrows(SecurityException::class.java) { 105 sLocalAccountManager.copyAccountToUser( 106 account, 107 sDeviceState.initialUser().userHandle(), 108 sDeviceState.secondaryUser().userHandle(), 109 null, 110 null 111 ).result 112 } 113 } 114 115 @Test 116 @EnsureHasDevicePolicyManagerRoleHolder 117 @EnsureHasSecondaryUser 118 @EnsureHasAccountAuthenticator(onUser = UserType.SECONDARY_USER) migrateAccount_hasCopyAccountsAndRemoveAccountsPermission_migratesAccountToOtherUsernull119 fun migrateAccount_hasCopyAccountsAndRemoveAccountsPermission_migratesAccountToOtherUser() { 120 val previousNumberOfAccounts = sDeviceState.accounts().allAccounts().size 121 val account = addAccount() 122 123 sDeviceState.dpmRoleHolder().accountManager().migrateAccount( 124 account, 125 sDeviceState.secondaryUser().userHandle() 126 ) 127 128 assertThat(sDeviceState.accounts().allAccounts().size).isEqualTo(previousNumberOfAccounts) 129 assertThat( 130 sDeviceState.accounts(sDeviceState.secondaryUser()) 131 .containsAccount(account) 132 ).isTrue() 133 } 134 RemoteAccountManagernull135 private fun RemoteAccountManager.migrateAccount(account: Account, userHandle: UserHandle) { 136 copyAccountToUser( 137 account, 138 sDeviceState.initialUser().userHandle(), 139 userHandle, 140 null, 141 null 142 ).result 143 removeAccount(account, null, null, null).result 144 } 145 containsAccountnull146 private fun RemoteAccountAuthenticator.containsAccount(account: Account): Boolean { 147 for (accountReference in allAccounts()) { 148 if (accountReference.account() == account) { 149 return true 150 } 151 } 152 return false 153 } 154 addAccountnull155 private fun addAccount() = sDeviceState.accounts().addAccount().add().account() 156 157 companion object { 158 @ClassRule 159 @Rule 160 @JvmField 161 val sDeviceState = DeviceState() 162 private val sLocalAccountManager = TestApis 163 .context().instrumentedContext() 164 .getSystemService(AccountManager::class.java)!! 165 } 166 } 167