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 android.permission.cts 18 19 import android.accessibility.cts.common.InstrumentedAccessibilityService 20 import android.accessibility.cts.common.InstrumentedAccessibilityServiceTestRule 21 import android.app.ActivityOptions 22 import android.app.Instrumentation 23 import android.app.UiAutomation 24 import android.content.ComponentName 25 import android.content.Context 26 import android.os.Build 27 import android.permission.cts.CtsNotificationListenerServiceUtils.assertEmptyNotification 28 import android.permission.cts.CtsNotificationListenerServiceUtils.assertNotificationExist 29 import android.permission.cts.CtsNotificationListenerServiceUtils.cancelNotification 30 import android.permission.cts.CtsNotificationListenerServiceUtils.cancelNotifications 31 import android.permission.cts.CtsNotificationListenerServiceUtils.getNotification 32 import android.permission.cts.SafetyCenterUtils.assertSafetyCenterIssueDoesNotExist 33 import android.permission.cts.SafetyCenterUtils.assertSafetyCenterIssueExist 34 import android.permission.cts.SafetyCenterUtils.assertSafetyCenterStarted 35 import android.permission.cts.SafetyCenterUtils.deleteDeviceConfigPrivacyProperty 36 import android.permission.cts.SafetyCenterUtils.deviceSupportsSafetyCenter 37 import android.permission.cts.SafetyCenterUtils.setDeviceConfigPrivacyProperty 38 import android.platform.test.annotations.AppModeFull 39 import android.platform.test.rule.ScreenRecordRule 40 import android.provider.DeviceConfig 41 import android.safetycenter.SafetyCenterManager 42 import androidx.test.filters.FlakyTest 43 import androidx.test.filters.SdkSuppress 44 import androidx.test.platform.app.InstrumentationRegistry 45 import androidx.test.runner.AndroidJUnit4 46 import com.android.compatibility.common.util.DeviceConfigStateChangerRule 47 import com.android.compatibility.common.util.SystemUtil.runShellCommand 48 import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity 49 import com.android.modules.utils.build.SdkLevel 50 import org.junit.After 51 import org.junit.Assert 52 import org.junit.Assume 53 import org.junit.Before 54 import org.junit.ClassRule 55 import org.junit.Rule 56 import org.junit.Test 57 import org.junit.runner.RunWith 58 59 @RunWith(AndroidJUnit4::class) 60 @AppModeFull( 61 reason = 62 "Cannot set system settings as instant app. Also we never show an accessibility " + 63 "notification for instant apps." 64 ) 65 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu") 66 @ScreenRecordRule.ScreenRecord 67 @FlakyTest 68 class AccessibilityPrivacySourceTest { 69 70 private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() 71 private val context: Context = instrumentation.targetContext 72 private val permissionControllerPackage = context.packageManager.permissionControllerPackageName 73 private val accessibilityTestService = 74 ComponentName(context, AccessibilityTestService::class.java).flattenToString() 75 private val safetyCenterIssueId = "accessibility_$accessibilityTestService" 76 private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java) 77 78 @get:Rule val screenRecordRule = ScreenRecordRule(false, false) 79 80 @get:Rule 81 val mAccessibilityServiceRule = 82 InstrumentedAccessibilityServiceTestRule(AccessibilityTestService::class.java, false) 83 84 @get:Rule 85 val deviceConfigSafetyCenterEnabled = 86 DeviceConfigStateChangerRule( 87 context, 88 DeviceConfig.NAMESPACE_PRIVACY, 89 SAFETY_CENTER_ENABLED, 90 true.toString() 91 ) 92 93 @get:Rule 94 val deviceConfigA11yListenerDisabled = 95 DeviceConfigStateChangerRule( 96 context, 97 DeviceConfig.NAMESPACE_PRIVACY, 98 ACCESSIBILITY_LISTENER_ENABLED, 99 false.toString() 100 ) 101 102 @Before setupnull103 fun setup() { 104 Assume.assumeTrue(deviceSupportsSafetyCenter(context)) 105 InstrumentedAccessibilityService.disableAllServices() 106 runShellCommand("input keyevent KEYCODE_WAKEUP") 107 resetPermissionController() 108 cancelNotifications(permissionControllerPackage) 109 assertEmptyNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID) 110 runWithShellPermissionIdentity { safetyCenterManager?.clearAllSafetySourceDataForTests() } 111 assertSafetyCenterIssueDoesNotExist( 112 SC_ACCESSIBILITY_SOURCE_ID, 113 safetyCenterIssueId, 114 SC_ACCESSIBILITY_ISSUE_TYPE_ID 115 ) 116 } 117 118 @After cleanupnull119 fun cleanup() { 120 cancelNotifications(permissionControllerPackage) 121 runWithShellPermissionIdentity { safetyCenterManager?.clearAllSafetySourceDataForTests() } 122 } 123 124 @Test testJobSendsNotificationnull125 fun testJobSendsNotification() { 126 mAccessibilityServiceRule.enableService() 127 runJobAndWaitUntilCompleted() 128 assertNotificationExist(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID) 129 } 130 131 @Test testJobSendsNotificationOnEnablenull132 fun testJobSendsNotificationOnEnable() { 133 mAccessibilityServiceRule.enableService() 134 runJobAndWaitUntilCompleted() 135 assertNotificationExist(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID) 136 137 setDeviceConfigPrivacyProperty(ACCESSIBILITY_LISTENER_ENABLED, true.toString()) 138 cancelNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID) 139 InstrumentedAccessibilityService.disableAllServices() 140 setDeviceConfigPrivacyProperty(ACCESSIBILITY_LISTENER_ENABLED, false.toString()) 141 setDeviceConfigPrivacyProperty(ACCESSIBILITY_JOB_INTERVAL_MILLIS, "0") 142 143 // enable service again and verify a notification 144 try { 145 mAccessibilityServiceRule.enableService() 146 runJobAndWaitUntilCompleted() 147 assertNotificationExist(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID) 148 } finally { 149 deleteDeviceConfigPrivacyProperty(ACCESSIBILITY_JOB_INTERVAL_MILLIS) 150 } 151 } 152 153 @Test testJobSendsIssuesToSafetyCenternull154 fun testJobSendsIssuesToSafetyCenter() { 155 mAccessibilityServiceRule.enableService() 156 runJobAndWaitUntilCompleted() 157 assertSafetyCenterIssueExist( 158 SC_ACCESSIBILITY_SOURCE_ID, 159 safetyCenterIssueId, 160 SC_ACCESSIBILITY_ISSUE_TYPE_ID 161 ) 162 } 163 164 @Test testJobDoesNotSendNotificationInSecondRunForSameServicenull165 fun testJobDoesNotSendNotificationInSecondRunForSameService() { 166 mAccessibilityServiceRule.enableService() 167 runJobAndWaitUntilCompleted() 168 assertNotificationExist(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID) 169 170 cancelNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID) 171 172 runJobAndWaitUntilCompleted() 173 assertEmptyNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID) 174 } 175 176 @Test testAccessibilityListenerSendsIssueToSafetyCenternull177 fun testAccessibilityListenerSendsIssueToSafetyCenter() { 178 setDeviceConfigPrivacyProperty(ACCESSIBILITY_LISTENER_ENABLED, true.toString()) 179 try { 180 val automation = getAutomation() 181 mAccessibilityServiceRule.enableService() 182 TestUtils.eventually( 183 { 184 assertSafetyCenterIssueExist( 185 SC_ACCESSIBILITY_SOURCE_ID, 186 safetyCenterIssueId, 187 SC_ACCESSIBILITY_ISSUE_TYPE_ID, 188 automation 189 ) 190 }, 191 TIMEOUT_MILLIS 192 ) 193 automation.destroy() 194 } finally { 195 setDeviceConfigPrivacyProperty(ACCESSIBILITY_LISTENER_ENABLED, false.toString()) 196 } 197 } 198 199 @Test testJobWithDisabledServiceDoesNotSendNotificationnull200 fun testJobWithDisabledServiceDoesNotSendNotification() { 201 runJobAndWaitUntilCompleted() 202 assertEmptyNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID) 203 } 204 205 @Test testJobWithDisabledServiceDoesNotSendIssueToSafetyCenternull206 fun testJobWithDisabledServiceDoesNotSendIssueToSafetyCenter() { 207 runJobAndWaitUntilCompleted() 208 assertSafetyCenterIssueDoesNotExist( 209 SC_ACCESSIBILITY_SOURCE_ID, 210 safetyCenterIssueId, 211 SC_ACCESSIBILITY_ISSUE_TYPE_ID 212 ) 213 } 214 215 @Test testJobWithSafetyCenterDisabledDoesNotSendNotificationnull216 fun testJobWithSafetyCenterDisabledDoesNotSendNotification() { 217 setDeviceConfigPrivacyProperty(SAFETY_CENTER_ENABLED, false.toString()) 218 mAccessibilityServiceRule.enableService() 219 runJobAndWaitUntilCompleted() 220 assertEmptyNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID) 221 } 222 223 @Test testJobWithSafetyCenterDisabledDoesNotSendIssueToSafetyCenternull224 fun testJobWithSafetyCenterDisabledDoesNotSendIssueToSafetyCenter() { 225 setDeviceConfigPrivacyProperty(SAFETY_CENTER_ENABLED, false.toString()) 226 mAccessibilityServiceRule.enableService() 227 runJobAndWaitUntilCompleted() 228 assertSafetyCenterIssueDoesNotExist( 229 SC_ACCESSIBILITY_SOURCE_ID, 230 safetyCenterIssueId, 231 SC_ACCESSIBILITY_ISSUE_TYPE_ID 232 ) 233 } 234 235 @Test testNotificationClickOpenSafetyCenternull236 fun testNotificationClickOpenSafetyCenter() { 237 mAccessibilityServiceRule.enableService() 238 runJobAndWaitUntilCompleted() 239 assertNotificationExist(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID) 240 val statusBarNotification = 241 getNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID) 242 Assert.assertNotNull(statusBarNotification) 243 val contentIntent = statusBarNotification!!.notification.contentIntent 244 if (SdkLevel.isAtLeastU()) { 245 val options = 246 ActivityOptions.makeBasic() 247 .setPendingIntentBackgroundActivityStartMode( 248 ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED 249 ) 250 contentIntent.send( 251 /* context = */ null, 252 /* code = */ 0, 253 /* intent = */ null, 254 /* onFinished = */ null, 255 /* handler = */ null, 256 /* requiredPermission = */ null, 257 /* options = */ options.toBundle() 258 ) 259 } else { 260 contentIntent.send() 261 } 262 assertSafetyCenterStarted() 263 } 264 getAutomationnull265 private fun getAutomation(): UiAutomation { 266 return instrumentation.getUiAutomation( 267 UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES 268 ) 269 } 270 runJobAndWaitUntilCompletednull271 private fun runJobAndWaitUntilCompleted() { 272 TestUtils.runJobAndWaitUntilCompleted( 273 permissionControllerPackage, 274 ACCESSIBILITY_JOB_ID, 275 TIMEOUT_MILLIS, 276 getAutomation() 277 ) 278 } 279 280 /** Reset the permission controllers state. */ 281 @Throws(Throwable::class) resetPermissionControllernull282 private fun resetPermissionController() { 283 PermissionUtils.resetPermissionControllerJob( 284 getAutomation(), 285 permissionControllerPackage, 286 ACCESSIBILITY_JOB_ID, 287 45000, 288 ACTION_SET_UP_ACCESSIBILITY_CHECK, 289 AccessibilityOnBootReceiver 290 ) 291 } 292 293 companion object { 294 private const val SC_ACCESSIBILITY_SOURCE_ID = "AndroidAccessibility" 295 private const val SAFETY_CENTER_ENABLED = "safety_center_is_enabled" 296 private const val ACCESSIBILITY_LISTENER_ENABLED = "sc_accessibility_listener_enabled" 297 private const val ACCESSIBILITY_JOB_INTERVAL_MILLIS = "sc_accessibility_job_interval_millis" 298 299 private const val ACCESSIBILITY_JOB_ID = 6 300 private const val ACCESSIBILITY_NOTIFICATION_ID = 4 301 private const val TIMEOUT_MILLIS: Long = 10000 302 303 private const val SC_ACCESSIBILITY_ISSUE_TYPE_ID = "accessibility_privacy_issue" 304 305 private const val AccessibilityOnBootReceiver = 306 "com.android.permissioncontroller.privacysources.AccessibilityOnBootReceiver" 307 private const val ACTION_SET_UP_ACCESSIBILITY_CHECK = 308 "com.android.permissioncontroller.action.SET_UP_ACCESSIBILITY_CHECK" 309 310 @get:ClassRule 311 @JvmStatic 312 val ctsNotificationListenerHelper = 313 CtsNotificationListenerHelperRule( 314 InstrumentationRegistry.getInstrumentation().targetContext 315 ) 316 } 317 } 318