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 17 package android.app.role.cts 18 19 import android.app.role.RoleManager 20 import android.os.Build 21 import android.os.UserHandle 22 import androidx.test.InstrumentationRegistry 23 import androidx.test.filters.SdkSuppress 24 import androidx.test.runner.AndroidJUnit4 25 import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity 26 import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow 27 import com.google.common.truth.Truth.assertThat 28 import org.junit.After 29 import org.junit.Assert.assertThrows 30 import org.junit.Before 31 import org.junit.Test 32 import org.junit.runner.RunWith 33 34 /** 35 * Tests role shell commands. 36 */ 37 @RunWith(AndroidJUnit4::class) 38 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S") 39 class RoleShellCommandTest { 40 private val instrumentation = InstrumentationRegistry.getInstrumentation() 41 private val context = instrumentation.context 42 private val roleManager = context.getSystemService(RoleManager::class.java)!! 43 private val userId = UserHandle.myUserId() 44 45 private var roleHolder: String? = null 46 private var wasBypassingRoleQualification: Boolean = false 47 48 @Before saveRoleHoldernull49 fun saveRoleHolder() { 50 roleHolder = getRoleHolders().firstOrNull() 51 if (roleHolder == APP_PACKAGE_NAME) { 52 removeRoleHolder() 53 roleHolder = null 54 } 55 } 56 57 @Before saveBypassingRoleQualificationnull58 fun saveBypassingRoleQualification() { 59 wasBypassingRoleQualification = isBypassingRoleQualification() 60 } 61 62 @After restoreRoleHoldernull63 fun restoreRoleHolder() { 64 removeRoleHolder() 65 roleHolder?.let { addRoleHolder(it) } 66 assertIsRoleHolder(false) 67 } 68 69 @After restoreBypassingRoleQualificationnull70 fun restoreBypassingRoleQualification() { 71 setBypassingRoleQualification(wasBypassingRoleQualification) 72 } 73 74 @Before installAppnull75 fun installApp() { 76 installPackage(APP_APK_PATH) 77 } 78 79 @After uninstallAppnull80 fun uninstallApp() { 81 uninstallPackage(APP_PACKAGE_NAME) 82 } 83 84 @Test helpPrintsNonEmptynull85 fun helpPrintsNonEmpty() { 86 assertThat(runShellCommandOrThrow("cmd role help")).isNotEmpty() 87 } 88 89 @Test dontAddRoleHolderThenIsNotRoleHoldernull90 fun dontAddRoleHolderThenIsNotRoleHolder() { 91 assertIsRoleHolder(false) 92 } 93 94 @Test addRoleHolderThenIsRoleHoldernull95 fun addRoleHolderThenIsRoleHolder() { 96 addRoleHolder() 97 98 assertIsRoleHolder(true) 99 } 100 101 @Test addAndRemoveRoleHolderThenIsNotRoleHoldernull102 fun addAndRemoveRoleHolderThenIsNotRoleHolder() { 103 addRoleHolder() 104 removeRoleHolder() 105 106 assertIsRoleHolder(false) 107 } 108 109 @Test addAndClearRoleHolderThenIsNotRoleHoldernull110 fun addAndClearRoleHolderThenIsNotRoleHolder() { 111 addRoleHolder() 112 clearRoleHolders() 113 114 assertIsRoleHolder(false) 115 } 116 117 @Test addInvalidRoleHolderThenFailsnull118 fun addInvalidRoleHolderThenFails() { 119 assertThrows(AssertionError::class.java) { 120 runShellCommandOrThrow("cmd role add-role-holder --user $userId $ROLE_NAME invalid") 121 } 122 } 123 124 @Test addRoleHolderThenAppearsInDumpsysnull125 fun addRoleHolderThenAppearsInDumpsys() { 126 addRoleHolder() 127 128 assertThat(runShellCommandOrThrow("dumpsys role")).contains(APP_PACKAGE_NAME) 129 } 130 131 @Test setBypassingRoleQualificationToTrueThenSetsToTruenull132 fun setBypassingRoleQualificationToTrueThenSetsToTrue() { 133 setBypassingRoleQualification(false) 134 135 runShellCommandOrThrow("cmd role set-bypassing-role-qualification true") 136 137 assertThat(isBypassingRoleQualification()).isTrue() 138 } 139 140 @Test setBypassingRoleQualificationToFalseThenSetsToFalsenull141 fun setBypassingRoleQualificationToFalseThenSetsToFalse() { 142 setBypassingRoleQualification(true) 143 144 runShellCommandOrThrow("cmd role set-bypassing-role-qualification false") 145 146 assertThat(isBypassingRoleQualification()).isFalse() 147 } 148 addRoleHoldernull149 private fun addRoleHolder(packageName: String = APP_PACKAGE_NAME) { 150 runShellCommandOrThrow("cmd role add-role-holder --user $userId $ROLE_NAME $packageName") 151 } 152 removeRoleHoldernull153 private fun removeRoleHolder(packageName: String = APP_PACKAGE_NAME) { 154 runShellCommandOrThrow("cmd role remove-role-holder --user $userId $ROLE_NAME $packageName") 155 } 156 clearRoleHoldersnull157 private fun clearRoleHolders() { 158 runShellCommandOrThrow("cmd role clear-role-holders --user $userId $ROLE_NAME") 159 } 160 getRoleHoldersnull161 private fun getRoleHolders(): List<String> = 162 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { 163 runShellCommandOrThrow("cmd role get-role-holders --user $userId $ROLE_NAME") 164 .trim().let { if (it.isNotEmpty()) it.split(";") else emptyList() } 165 } else { <lambda>null166 callWithShellPermissionIdentity { roleManager.getRoleHolders(ROLE_NAME) } 167 } 168 assertIsRoleHoldernull169 private fun assertIsRoleHolder(shouldBeRoleHolder: Boolean) { 170 val packageNames = getRoleHolders() 171 if (shouldBeRoleHolder) { 172 assertThat(packageNames).contains(APP_PACKAGE_NAME) 173 } else { 174 assertThat(packageNames).doesNotContain(APP_PACKAGE_NAME) 175 } 176 } 177 installPackagenull178 private fun installPackage(apkPath: String) { 179 assertThat(runShellCommandOrThrow("pm install -r --user $userId $apkPath").trim()) 180 .isEqualTo("Success") 181 } 182 uninstallPackagenull183 private fun uninstallPackage(packageName: String) { 184 assertThat(runShellCommandOrThrow("pm uninstall --user $userId $packageName").trim()) 185 .isEqualTo("Success") 186 } 187 isBypassingRoleQualificationnull188 private fun isBypassingRoleQualification(): Boolean = 189 callWithShellPermissionIdentity { roleManager.isBypassingRoleQualification() } 190 setBypassingRoleQualificationnull191 private fun setBypassingRoleQualification(value: Boolean) { 192 callWithShellPermissionIdentity { 193 roleManager.setBypassingRoleQualification(value) 194 } 195 } 196 197 companion object { 198 private const val ROLE_NAME = RoleManager.ROLE_BROWSER 199 private const val APP_APK_PATH = "/data/local/tmp/cts/role/CtsRoleTestApp.apk" 200 private const val APP_PACKAGE_NAME = "android.app.role.cts.app" 201 } 202 } 203