1 /* 2 * Copyright (C) 2022 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 com.android.permissioncontroller.permissionui.ui.handheld 18 19 import android.Manifest.permission.ACCESS_COARSE_LOCATION 20 import android.content.Intent 21 import android.content.pm.PackageManager 22 import android.permission.cts.PermissionUtils.grantPermission 23 import android.permission.cts.PermissionUtils.install 24 import android.permission.cts.PermissionUtils.revokePermission 25 import android.permission.cts.PermissionUtils.uninstallApp 26 import android.util.Log 27 import androidx.test.ext.junit.runners.AndroidJUnit4 28 import androidx.test.uiautomator.By 29 import com.android.compatibility.common.util.SystemUtil.eventually 30 import com.android.compatibility.common.util.SystemUtil.getEventually 31 import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity 32 import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObjectOrNull 33 import com.android.permissioncontroller.permissionui.getUsageCountsFromUi 34 import com.android.permissioncontroller.permissionui.wakeUpScreen 35 import com.google.common.truth.Truth.assertThat 36 import org.junit.After 37 import org.junit.Before 38 import org.junit.Test 39 import org.junit.runner.RunWith 40 41 /** Simple tests for {@link ManageStandardPermissionsFragment} */ 42 @RunWith(AndroidJUnit4::class) 43 class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() { 44 @Before setupnull45 fun setup() { 46 wakeUpScreen() 47 48 runWithShellPermissionIdentity { 49 removePackageIfInstalled() 50 instrumentationContext.startActivity( 51 Intent(Intent.ACTION_MANAGE_PERMISSIONS).apply { 52 addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) 53 } 54 ) 55 } 56 } 57 58 @After tearDownnull59 fun tearDown() { 60 uninstallApp(LOCATION_USER_PKG) 61 uninstallApp(ADDITIONAL_DEFINER_PKG) 62 uninstallApp(ADDITIONAL_USER_PKG) 63 uiDevice.pressBack() 64 } 65 66 /** 67 * The test packages are not expected to be installed already, remove them if they are already 68 * installed (i.e. leftover from another test) when a test starts. 69 */ removePackageIfInstallednull70 private fun removePackageIfInstalled() { 71 val packageNames = listOf(LOCATION_USER_PKG, ADDITIONAL_DEFINER_PKG, ADDITIONAL_USER_PKG) 72 for (packageName in packageNames) { 73 try { 74 val packageInfo = 75 instrumentationContext.packageManager.getPackageInfo(packageName, 0) 76 if (packageInfo != null) { 77 Log.w(LOG_TAG, "package $packageName not expected to be installed.") 78 uninstallApp(packageName) 79 Thread.sleep(1000) 80 } 81 } catch (e: PackageManager.NameNotFoundException) { 82 // ignore 83 } 84 } 85 } 86 87 /** 88 * Read the number of additional permissions from the Ui. 89 * 90 * @return number of additional permissions 91 */ getAdditionalPermissionCountnull92 private fun getAdditionalPermissionCount(): Int { 93 waitFindObjectOrNull(By.textContains(ADDITIONAL_PERMISSIONS_LABEL)) ?: return 0 94 // Sometimes the entire preference disappears while it's searching for the app count 95 // (during uninstalling). Hence also return the count as 0 if count doesn't exist 96 val additionalPermissionsSummary = 97 waitFindObjectOrNull(By.textContains(ADDITIONAL_PERMISSIONS_SUMMARY)) ?: return 0 98 val additionalPermissionsSummaryText = additionalPermissionsSummary.getText() 99 100 // Matches a single number out of the summary line, i.e. "...3..." -> "3" 101 return getEventually { 102 Regex("^[^\\d]*(\\d+)[^\\d]*\$") 103 .find(additionalPermissionsSummaryText)!! 104 .groupValues[1] 105 .toInt() 106 } 107 } 108 109 @Test groupSummaryGetsUpdatedWhenAppGetsInstallednull110 fun groupSummaryGetsUpdatedWhenAppGetsInstalled() { 111 val original = getUsageCountsFromUi(LOCATION_GROUP_LABEL) 112 113 install(LOCATION_USER_APK) 114 eventually( 115 { 116 val afterInstall = getUsageCountsFromUi(LOCATION_GROUP_LABEL) 117 assertThat(afterInstall.granted).isEqualTo(original.granted) 118 assertThat(afterInstall.total).isEqualTo(original.total + 1) 119 }, 120 TIMEOUT 121 ) 122 } 123 124 @Test groupSummaryGetsUpdatedWhenAppGetsUninstallednull125 fun groupSummaryGetsUpdatedWhenAppGetsUninstalled() { 126 val original = getUsageCountsFromUi(LOCATION_GROUP_LABEL) 127 install(LOCATION_USER_APK) 128 eventually( 129 { assertThat(getUsageCountsFromUi(LOCATION_GROUP_LABEL)).isNotEqualTo(original) }, 130 TIMEOUT 131 ) 132 133 uninstallApp(LOCATION_USER_PKG) 134 eventually( 135 { assertThat(getUsageCountsFromUi(LOCATION_GROUP_LABEL)).isEqualTo(original) }, 136 TIMEOUT 137 ) 138 } 139 140 @Test groupSummaryGetsUpdatedWhenPermissionGetsGrantednull141 fun groupSummaryGetsUpdatedWhenPermissionGetsGranted() { 142 val original = getUsageCountsFromUi(LOCATION_GROUP_LABEL) 143 144 install(LOCATION_USER_APK) 145 eventually( 146 { 147 assertThat(getUsageCountsFromUi(LOCATION_GROUP_LABEL).total) 148 .isEqualTo(original.total + 1) 149 }, 150 TIMEOUT 151 ) 152 153 grantPermission(LOCATION_USER_PKG, ACCESS_COARSE_LOCATION) 154 eventually { 155 assertThat(getUsageCountsFromUi(LOCATION_GROUP_LABEL).granted) 156 .isEqualTo(original.granted + 1) 157 } 158 } 159 160 @Test groupSummaryGetsUpdatedWhenPermissionGetsRevokednull161 fun groupSummaryGetsUpdatedWhenPermissionGetsRevoked() { 162 val original = getUsageCountsFromUi(LOCATION_GROUP_LABEL) 163 164 install(LOCATION_USER_APK) 165 grantPermission(LOCATION_USER_PKG, ACCESS_COARSE_LOCATION) 166 eventually( 167 { 168 assertThat(getUsageCountsFromUi(LOCATION_GROUP_LABEL).total) 169 .isNotEqualTo(original.total) 170 assertThat(getUsageCountsFromUi(LOCATION_GROUP_LABEL).granted) 171 .isNotEqualTo(original.granted) 172 }, 173 TIMEOUT 174 ) 175 176 revokePermission(LOCATION_USER_PKG, ACCESS_COARSE_LOCATION) 177 eventually { 178 assertThat(getUsageCountsFromUi(LOCATION_GROUP_LABEL).granted) 179 .isEqualTo(original.granted) 180 } 181 } 182 183 @Test additionalPermissionSummaryGetUpdateWhenAppGetsInstallednull184 fun additionalPermissionSummaryGetUpdateWhenAppGetsInstalled() { 185 val additionalPermissionBefore = getAdditionalPermissionCount() 186 187 install(ADDITIONAL_DEFINER_APK) 188 install(ADDITIONAL_USER_APK) 189 eventually( 190 { 191 assertThat(getAdditionalPermissionCount()).isEqualTo(additionalPermissionBefore + 1) 192 }, 193 TIMEOUT 194 ) 195 } 196 197 @Test additionalPermissionSummaryGetUpdateWhenUserGetsUninstallednull198 fun additionalPermissionSummaryGetUpdateWhenUserGetsUninstalled() { 199 val additionalPermissionBefore = getAdditionalPermissionCount() 200 201 install(ADDITIONAL_DEFINER_APK) 202 install(ADDITIONAL_USER_APK) 203 eventually( 204 { assertThat(getAdditionalPermissionCount()).isNotEqualTo(additionalPermissionBefore) }, 205 TIMEOUT 206 ) 207 208 uninstallApp(ADDITIONAL_USER_PKG) 209 eventually( 210 { assertThat(getAdditionalPermissionCount()).isEqualTo(additionalPermissionBefore) }, 211 TIMEOUT 212 ) 213 } 214 215 @Test additionalPermissionSummaryGetUpdateWhenDefinerGetsUninstallednull216 fun additionalPermissionSummaryGetUpdateWhenDefinerGetsUninstalled() { 217 val additionalPermissionBefore = getAdditionalPermissionCount() 218 219 install(ADDITIONAL_DEFINER_APK) 220 install(ADDITIONAL_USER_APK) 221 eventually( 222 { assertThat(getAdditionalPermissionCount()).isNotEqualTo(additionalPermissionBefore) }, 223 TIMEOUT 224 ) 225 226 uninstallApp(ADDITIONAL_DEFINER_PKG) 227 eventually( 228 { assertThat(getAdditionalPermissionCount()).isEqualTo(additionalPermissionBefore) }, 229 TIMEOUT 230 ) 231 } 232 233 companion object { 234 private val LOG_TAG = ManageStandardPermissionsFragmentTest::class.java.simpleName 235 236 private const val LOCATION_USER_APK = 237 "/data/local/tmp/pc-permissionui/AppThatRequestsLocation.apk" 238 private const val ADDITIONAL_DEFINER_APK = 239 "/data/local/tmp/pc-permissionui/" + "PermissionUiDefineAdditionalPermissionApp.apk" 240 private const val ADDITIONAL_USER_APK = 241 "/data/local/tmp/pc-permissionui/" + "PermissionUiUseAdditionalPermissionApp.apk" 242 private const val LOCATION_USER_PKG = "android.permission.cts.appthatrequestpermission" 243 private const val ADDITIONAL_DEFINER_PKG = 244 "com.android.permissioncontroller.tests.appthatdefinespermission" 245 private const val ADDITIONAL_USER_PKG = 246 "com.android.permissioncontroller.tests.appthatrequestpermission" 247 private const val ADDITIONAL_PERMISSIONS_LABEL = "Additional permissions" 248 private const val ADDITIONAL_PERMISSIONS_SUMMARY = "more" 249 private const val LOCATION_GROUP_LABEL = "Location" 250 251 // Package Added/Removed broadcast are pretty slow on cf devices, we may want to increase 252 // this in future if the test still fails. 253 private const val TIMEOUT = 30000L 254 } 255 } 256