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.permission.cts.PermissionUtils.grantPermission 22 import android.permission.cts.PermissionUtils.install 23 import android.permission.cts.PermissionUtils.revokePermission 24 import android.permission.cts.PermissionUtils.uninstallApp 25 import androidx.test.uiautomator.By 26 import androidx.test.ext.junit.runners.AndroidJUnit4 27 import com.android.compatibility.common.util.SystemUtil.eventually 28 import com.android.compatibility.common.util.SystemUtil.getEventually 29 import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity 30 import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObjectOrNull 31 import com.android.permissioncontroller.permissionui.getUsageCountsFromUi 32 import com.android.permissioncontroller.permissionui.wakeUpScreen 33 import com.google.common.truth.Truth.assertThat 34 import org.junit.After 35 import org.junit.Before 36 import org.junit.Test 37 import org.junit.runner.RunWith 38 39 /** 40 * Simple tests for {@link ManageStandardPermissionsFragment} 41 */ 42 @RunWith(AndroidJUnit4::class) 43 class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() { 44 private val LOCATION_USER_APK = 45 "/data/local/tmp/permissioncontroller/tests/permissionui/AppThatRequestsLocation.apk" 46 private val ADDITIONAL_DEFINER_APK = 47 "/data/local/tmp/permissioncontroller/tests/permissionui/" + 48 "PermissionUiDefineAdditionalPermissionApp.apk" 49 private val ADDITIONAL_USER_APK = 50 "/data/local/tmp/permissioncontroller/tests/permissionui/" + 51 "PermissionUiUseAdditionalPermissionApp.apk" 52 private val LOCATION_USER_PKG = "android.permission.cts.appthatrequestpermission" 53 private val ADDITIONAL_DEFINER_PKG = 54 "com.android.permissioncontroller.tests.appthatdefinespermission" 55 private val ADDITIONAL_USER_PKG = 56 "com.android.permissioncontroller.tests.appthatrequestpermission" 57 private val ADDITIONAL_PERMISSIONS_LABEL = "Additional permissions" 58 private val ADDITIONAL_PERMISSIONS_SUMMARY = "more" 59 60 private val locationGroupLabel = "Location" 61 62 /** 63 * Read the number of additional permissions from the Ui. 64 * 65 * @return number of additional permissions 66 */ getAdditionalPermissionCountnull67 private fun getAdditionalPermissionCount(): Int { 68 waitFindObjectOrNull(By.textContains(ADDITIONAL_PERMISSIONS_LABEL)) ?: return 0 69 // Sometimes the entire preference disappears while it's searching for the app count 70 // (during uninstalling). Hence also return the count as 0 if count doesn't exist 71 val additionalPermissionsSummary = waitFindObjectOrNull( 72 By.textContains(ADDITIONAL_PERMISSIONS_SUMMARY)) ?: return 0 73 val additionalPermissionsSummaryText = additionalPermissionsSummary.getText() 74 75 // Matches a single number out of the summary line, i.e. "...3..." -> "3" 76 return getEventually { 77 Regex("^[^\\d]*(\\d+)[^\\d]*\$") 78 .find(additionalPermissionsSummaryText)!!.groupValues[1] 79 .toInt() 80 } 81 } 82 83 @Before setupnull84 fun setup() { 85 wakeUpScreen() 86 87 runWithShellPermissionIdentity { 88 instrumentationContext.startActivity(Intent(Intent.ACTION_MANAGE_PERMISSIONS).apply { 89 addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 90 }) 91 } 92 93 reuninstallApp(LOCATION_USER_APK, LOCATION_USER_PKG) 94 95 // Sleep before each test for 1 second for getUsageCountsFromUi to get the correct counts 96 Thread.sleep(1000) 97 } 98 99 @Test groupSummaryGetsUpdatedWhenAppGetsInstallednull100 fun groupSummaryGetsUpdatedWhenAppGetsInstalled() { 101 val original = getUsageCountsFromUi(locationGroupLabel) 102 103 install(LOCATION_USER_APK) 104 eventually { 105 val afterInstall = getUsageCountsFromUi(locationGroupLabel) 106 assertThat(afterInstall.granted).isEqualTo(original.granted) 107 assertThat(afterInstall.total).isEqualTo(original.total + 1) 108 } 109 } 110 111 @Test groupSummaryGetsUpdatedWhenAppGetsUninstallednull112 fun groupSummaryGetsUpdatedWhenAppGetsUninstalled() { 113 reuninstallApp(LOCATION_USER_APK, LOCATION_USER_PKG) 114 val original = getUsageCountsFromUi(locationGroupLabel) 115 116 install(LOCATION_USER_APK) 117 eventually { 118 assertThat(getUsageCountsFromUi(locationGroupLabel)).isNotEqualTo(original) 119 } 120 121 uninstallApp(LOCATION_USER_PKG) 122 reuninstallApp(LOCATION_USER_APK, LOCATION_USER_PKG) 123 eventually { 124 assertThat(getUsageCountsFromUi(locationGroupLabel)).isEqualTo(original) 125 } 126 } 127 128 @Test groupSummaryGetsUpdatedWhenPermissionGetsGrantednull129 fun groupSummaryGetsUpdatedWhenPermissionGetsGranted() { 130 val original = getUsageCountsFromUi(locationGroupLabel) 131 132 install(LOCATION_USER_APK) 133 eventually { 134 assertThat(getUsageCountsFromUi(locationGroupLabel).total) 135 .isEqualTo(original.total + 1) 136 } 137 138 grantPermission(LOCATION_USER_PKG, ACCESS_COARSE_LOCATION) 139 eventually { 140 assertThat(getUsageCountsFromUi(locationGroupLabel).granted) 141 .isEqualTo(original.granted + 1) 142 } 143 } 144 145 @Test groupSummaryGetsUpdatedWhenPermissionGetsRevokednull146 fun groupSummaryGetsUpdatedWhenPermissionGetsRevoked() { 147 val original = getUsageCountsFromUi(locationGroupLabel) 148 149 install(LOCATION_USER_APK) 150 grantPermission(LOCATION_USER_PKG, ACCESS_COARSE_LOCATION) 151 eventually { 152 assertThat(getUsageCountsFromUi(locationGroupLabel).total) 153 .isNotEqualTo(original.total) 154 assertThat(getUsageCountsFromUi(locationGroupLabel).granted) 155 .isNotEqualTo(original.granted) 156 } 157 158 revokePermission(LOCATION_USER_PKG, ACCESS_COARSE_LOCATION) 159 eventually { 160 assertThat(getUsageCountsFromUi(locationGroupLabel).granted) 161 .isEqualTo(original.granted) 162 } 163 } 164 165 @Test additionalPermissionSummaryGetUpdateWhenAppGetsInstallednull166 fun additionalPermissionSummaryGetUpdateWhenAppGetsInstalled() { 167 val additionalPermissionBefore = getAdditionalPermissionCount() 168 169 install(ADDITIONAL_DEFINER_APK) 170 install(ADDITIONAL_USER_APK) 171 eventually { 172 assertThat(getAdditionalPermissionCount()) 173 .isEqualTo(additionalPermissionBefore + 1) 174 } 175 } 176 177 @Test additionalPermissionSummaryGetUpdateWhenUserGetsUninstallednull178 fun additionalPermissionSummaryGetUpdateWhenUserGetsUninstalled() { 179 val additionalPermissionBefore = getAdditionalPermissionCount() 180 181 install(ADDITIONAL_DEFINER_APK) 182 install(ADDITIONAL_USER_APK) 183 eventually { 184 assertThat(getAdditionalPermissionCount()) 185 .isNotEqualTo(additionalPermissionBefore) 186 } 187 188 uninstallApp(ADDITIONAL_USER_PKG) 189 eventually { 190 assertThat(getAdditionalPermissionCount()).isEqualTo(additionalPermissionBefore) 191 } 192 } 193 194 @Test additionalPermissionSummaryGetUpdateWhenDefinerGetsUninstallednull195 fun additionalPermissionSummaryGetUpdateWhenDefinerGetsUninstalled() { 196 val additionalPermissionBefore = getAdditionalPermissionCount() 197 198 install(ADDITIONAL_DEFINER_APK) 199 install(ADDITIONAL_USER_APK) 200 eventually { 201 assertThat(getAdditionalPermissionCount()) 202 .isNotEqualTo(additionalPermissionBefore) 203 } 204 205 uninstallApp(ADDITIONAL_DEFINER_PKG) 206 eventually { 207 assertThat(getAdditionalPermissionCount()).isEqualTo(additionalPermissionBefore) 208 } 209 } 210 reuninstallAppnull211 fun reuninstallApp(apk: String, pkg: String) { 212 // b/275752754: sometimes this test is flaky because inside @After it didn't uninstall the 213 // packages correctly. This caused the permission manager screen to still show the package 214 // as requesting the permission and caused the original usage count to be incorrect. 215 // Installing/uninstalling the packages again to ensure the package is correctly uninstalled 216 install(apk) 217 uninstallApp(pkg) 218 } 219 220 @After tearDownnull221 fun tearDown() { 222 uninstallApp(LOCATION_USER_PKG) 223 uninstallApp(ADDITIONAL_DEFINER_PKG) 224 uninstallApp(ADDITIONAL_USER_PKG) 225 226 uiDevice.pressBack() 227 } 228 } 229