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 callWithShellPermissionIdentity { roleManager.getRoleHolders(ROLE_NAME) } 163 assertIsRoleHoldernull164 private fun assertIsRoleHolder(shouldBeRoleHolder: Boolean) { 165 val packageNames = getRoleHolders() 166 if (shouldBeRoleHolder) { 167 assertThat(packageNames).contains(APP_PACKAGE_NAME) 168 } else { 169 assertThat(packageNames).doesNotContain(APP_PACKAGE_NAME) 170 } 171 } 172 installPackagenull173 private fun installPackage(apkPath: String) { 174 assertThat(runShellCommandOrThrow("pm install -r --user $userId $apkPath").trim()) 175 .isEqualTo("Success") 176 } 177 uninstallPackagenull178 private fun uninstallPackage(packageName: String) { 179 assertThat(runShellCommandOrThrow("pm uninstall --user $userId $packageName").trim()) 180 .isEqualTo("Success") 181 } 182 isBypassingRoleQualificationnull183 private fun isBypassingRoleQualification(): Boolean = 184 callWithShellPermissionIdentity { roleManager.isBypassingRoleQualification() } 185 setBypassingRoleQualificationnull186 private fun setBypassingRoleQualification(value: Boolean) { 187 callWithShellPermissionIdentity { 188 roleManager.setBypassingRoleQualification(value) 189 } 190 } 191 192 companion object { 193 private const val ROLE_NAME = RoleManager.ROLE_BROWSER 194 private const val APP_APK_PATH = "/data/local/tmp/cts/role/CtsRoleTestApp.apk" 195 private const val APP_PACKAGE_NAME = "android.app.role.cts.app" 196 } 197 } 198