1 /* 2 * Copyright (C) 2019 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.server.accessibility; 18 19 import static junit.framework.Assert.assertFalse; 20 import static junit.framework.TestCase.assertNull; 21 import static junit.framework.TestCase.assertTrue; 22 23 import static org.hamcrest.Matchers.containsInAnyOrder; 24 import static org.hamcrest.Matchers.emptyArray; 25 import static org.hamcrest.Matchers.hasSize; 26 import static org.junit.Assert.assertEquals; 27 import static org.junit.Assert.assertThat; 28 import static org.mockito.AdditionalAnswers.returnsFirstArg; 29 import static org.mockito.ArgumentMatchers.any; 30 import static org.mockito.ArgumentMatchers.anyInt; 31 import static org.mockito.ArgumentMatchers.eq; 32 import static org.mockito.Mockito.doReturn; 33 import static org.mockito.Mockito.verify; 34 import static org.mockito.Mockito.when; 35 36 import android.Manifest; 37 import android.accessibilityservice.AccessibilityServiceInfo; 38 import android.app.AppOpsManager; 39 import android.appwidget.AppWidgetManagerInternal; 40 import android.content.ComponentName; 41 import android.content.Context; 42 import android.content.pm.ApplicationInfo; 43 import android.content.pm.PackageManager; 44 import android.content.pm.ResolveInfo; 45 import android.content.pm.ServiceInfo; 46 import android.os.Process; 47 import android.os.UserHandle; 48 import android.os.UserManager; 49 import android.testing.DexmakerShareClassLoaderRule; 50 import android.util.ArraySet; 51 import android.view.accessibility.AccessibilityEvent; 52 import android.view.accessibility.AccessibilityWindowInfo; 53 54 import com.android.server.LocalServices; 55 import com.android.server.wm.ActivityTaskManagerInternal; 56 57 import org.junit.Before; 58 import org.junit.Rule; 59 import org.junit.Test; 60 import org.mockito.Mock; 61 import org.mockito.Mockito; 62 import org.mockito.MockitoAnnotations; 63 64 import java.util.Arrays; 65 import java.util.List; 66 67 /** 68 * Tests for the AccessibilitySecurityPolicy 69 */ 70 public class AccessibilitySecurityPolicyTest { 71 private static final String PACKAGE_NAME = "com.android.server.accessibility"; 72 private static final String PACKAGE_NAME2 = "com.android.server.accessibility2"; 73 private static final int WINDOWID = 0x000a; 74 private static final int WINDOWID2 = 0x000b; 75 private static final int APP_UID = 10400; 76 private static final int APP_PID = 2000; 77 private static final int SYSTEM_PID = 558; 78 79 private static final String PERMISSION = "test-permission"; 80 private static final String FUNCTION = "test-function-name"; 81 82 private static final int[] ALWAYS_DISPATCH_EVENTS = { 83 AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, 84 AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED, 85 AccessibilityEvent.TYPE_ANNOUNCEMENT, 86 AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START, 87 AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END, 88 AccessibilityEvent.TYPE_GESTURE_DETECTION_START, 89 AccessibilityEvent.TYPE_GESTURE_DETECTION_END, 90 AccessibilityEvent.TYPE_TOUCH_INTERACTION_START, 91 AccessibilityEvent.TYPE_TOUCH_INTERACTION_END, 92 AccessibilityEvent.TYPE_VIEW_HOVER_ENTER, 93 AccessibilityEvent.TYPE_VIEW_HOVER_EXIT, 94 AccessibilityEvent.TYPE_ASSIST_READING_CONTEXT, 95 AccessibilityEvent.TYPE_WINDOWS_CHANGED, 96 }; 97 private static final int[] OTHER_EVENTS = { 98 AccessibilityEvent.TYPE_VIEW_CLICKED, 99 AccessibilityEvent.TYPE_VIEW_LONG_CLICKED, 100 AccessibilityEvent.TYPE_VIEW_SELECTED, 101 AccessibilityEvent.TYPE_VIEW_FOCUSED, 102 AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED, 103 AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED, 104 AccessibilityEvent.TYPE_VIEW_SCROLLED, 105 AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED, 106 AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED, 107 AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED, 108 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY, 109 AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED, 110 }; 111 112 private AccessibilitySecurityPolicy mA11ySecurityPolicy; 113 114 // To mock package-private class 115 @Rule public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule = 116 new DexmakerShareClassLoaderRule(); 117 118 @Mock private Context mMockContext; 119 @Mock private PackageManager mMockPackageManager; 120 @Mock private UserManager mMockUserManager; 121 @Mock private AppOpsManager mMockAppOpsManager; 122 @Mock private AccessibilityServiceConnection mMockA11yServiceConnection; 123 @Mock private AccessibilityWindowManager mMockA11yWindowManager; 124 @Mock private AppWidgetManagerInternal mMockAppWidgetManager; 125 @Mock private AccessibilitySecurityPolicy.AccessibilityUserManager mMockA11yUserManager; 126 @Mock private ActivityTaskManagerInternal mMockActivityTaskManagerInternal; 127 128 @Before setUp()129 public void setUp() { 130 MockitoAnnotations.initMocks(this); 131 when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); 132 when(mMockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager); 133 when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mMockAppOpsManager); 134 135 LocalServices.removeServiceForTest(ActivityTaskManagerInternal.class); 136 LocalServices.addService( 137 ActivityTaskManagerInternal.class, mMockActivityTaskManagerInternal); 138 139 mA11ySecurityPolicy = new AccessibilitySecurityPolicy(mMockContext, mMockA11yUserManager); 140 mA11ySecurityPolicy.setAccessibilityWindowManager(mMockA11yWindowManager); 141 mA11ySecurityPolicy.setAppWidgetManager(mMockAppWidgetManager); 142 143 when(mMockA11yWindowManager.resolveParentWindowIdLocked(anyInt())).then(returnsFirstArg()); 144 } 145 146 @Test canDispatchAccessibilityEvent_alwaysDispatchEvents_returnTrue()147 public void canDispatchAccessibilityEvent_alwaysDispatchEvents_returnTrue() { 148 for (int i = 0; i < ALWAYS_DISPATCH_EVENTS.length; i++) { 149 final AccessibilityEvent event = AccessibilityEvent.obtain(ALWAYS_DISPATCH_EVENTS[i]); 150 assertTrue("Should dispatch [" + event + "]", 151 mA11ySecurityPolicy.canDispatchAccessibilityEventLocked( 152 UserHandle.USER_SYSTEM, 153 event)); 154 } 155 } 156 157 @Test canDispatchAccessibilityEvent_otherEvents_invalidWindowId_returnFalse()158 public void canDispatchAccessibilityEvent_otherEvents_invalidWindowId_returnFalse() { 159 final int invalidWindowId = WINDOWID; 160 for (int i = 0; i < OTHER_EVENTS.length; i++) { 161 final AccessibilityEvent event = AccessibilityEvent.obtain(OTHER_EVENTS[i]); 162 event.setWindowId(invalidWindowId); 163 assertFalse("Shouldn't dispatch [" + event + "]", 164 mA11ySecurityPolicy.canDispatchAccessibilityEventLocked( 165 UserHandle.USER_SYSTEM, 166 event)); 167 } 168 } 169 170 @Test canDispatchAccessibilityEvent_otherEvents_windowIdIsActive_returnTrue()171 public void canDispatchAccessibilityEvent_otherEvents_windowIdIsActive_returnTrue() { 172 when(mMockA11yWindowManager.getActiveWindowId(UserHandle.USER_SYSTEM)) 173 .thenReturn(WINDOWID); 174 for (int i = 0; i < OTHER_EVENTS.length; i++) { 175 final AccessibilityEvent event = AccessibilityEvent.obtain(OTHER_EVENTS[i]); 176 event.setWindowId(WINDOWID); 177 assertTrue("Should dispatch [" + event + "]", 178 mA11ySecurityPolicy.canDispatchAccessibilityEventLocked( 179 UserHandle.USER_SYSTEM, 180 event)); 181 } 182 } 183 184 @Test canDispatchAccessibilityEvent_otherEvents_windowIdExist_returnTrue()185 public void canDispatchAccessibilityEvent_otherEvents_windowIdExist_returnTrue() { 186 when(mMockA11yWindowManager.getActiveWindowId(UserHandle.USER_SYSTEM)) 187 .thenReturn(WINDOWID2); 188 when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(WINDOWID)) 189 .thenReturn(AccessibilityWindowInfo.obtain()); 190 for (int i = 0; i < OTHER_EVENTS.length; i++) { 191 final AccessibilityEvent event = AccessibilityEvent.obtain(OTHER_EVENTS[i]); 192 event.setWindowId(WINDOWID); 193 assertTrue("Should dispatch [" + event + "]", 194 mA11ySecurityPolicy.canDispatchAccessibilityEventLocked( 195 UserHandle.USER_SYSTEM, 196 event)); 197 } 198 } 199 200 @Test resolveValidReportedPackage_nullPkgName_returnNull()201 public void resolveValidReportedPackage_nullPkgName_returnNull() { 202 assertNull(mA11ySecurityPolicy.resolveValidReportedPackageLocked( 203 null, Process.SYSTEM_UID, UserHandle.USER_SYSTEM, SYSTEM_PID)); 204 } 205 206 @Test resolveValidReportedPackage_uidIsSystem_returnPkgName()207 public void resolveValidReportedPackage_uidIsSystem_returnPkgName() { 208 assertEquals(mA11ySecurityPolicy.resolveValidReportedPackageLocked( 209 PACKAGE_NAME, Process.SYSTEM_UID, UserHandle.USER_SYSTEM, SYSTEM_PID), 210 PACKAGE_NAME); 211 } 212 213 @Test resolveValidReportedPackage_uidAndPkgNameMatched_returnPkgName()214 public void resolveValidReportedPackage_uidAndPkgNameMatched_returnPkgName() 215 throws PackageManager.NameNotFoundException { 216 when(mMockPackageManager.getPackageUidAsUser(PACKAGE_NAME, UserHandle.USER_SYSTEM)) 217 .thenReturn(APP_UID); 218 219 assertEquals(mA11ySecurityPolicy.resolveValidReportedPackageLocked( 220 PACKAGE_NAME, APP_UID, UserHandle.USER_SYSTEM, APP_PID), 221 PACKAGE_NAME); 222 } 223 224 @Test resolveValidReportedPackage_uidIsWidgetHost_pkgNameIsAppWidget_returnPkgName()225 public void resolveValidReportedPackage_uidIsWidgetHost_pkgNameIsAppWidget_returnPkgName() 226 throws PackageManager.NameNotFoundException { 227 final int widgetHostUid = APP_UID; 228 final int widgetHostPid = APP_PID; 229 final String hostPackageName = PACKAGE_NAME; 230 final String widgetPackageName = PACKAGE_NAME2; 231 final ArraySet<String> widgetPackages = new ArraySet<>(); 232 widgetPackages.add(widgetPackageName); 233 234 when(mMockAppWidgetManager.getHostedWidgetPackages(widgetHostUid)) 235 .thenReturn(widgetPackages); 236 when(mMockPackageManager.getPackageUidAsUser(hostPackageName, UserHandle.USER_SYSTEM)) 237 .thenReturn(widgetHostUid); 238 239 assertEquals(mA11ySecurityPolicy.resolveValidReportedPackageLocked( 240 widgetPackageName, widgetHostUid, UserHandle.USER_SYSTEM, widgetHostPid), 241 widgetPackageName); 242 } 243 244 @Test resolveValidReportedPackage_pkgNameIsInvalid_returnFirstCorrectPkgName()245 public void resolveValidReportedPackage_pkgNameIsInvalid_returnFirstCorrectPkgName() 246 throws PackageManager.NameNotFoundException { 247 final String invalidPackageName = "x"; 248 final String[] uidPackages = {PACKAGE_NAME, PACKAGE_NAME2}; 249 when(mMockPackageManager.getPackagesForUid(APP_UID)) 250 .thenReturn(uidPackages); 251 when(mMockPackageManager.getPackageUidAsUser(invalidPackageName, UserHandle.USER_SYSTEM)) 252 .thenThrow(PackageManager.NameNotFoundException.class); 253 when(mMockAppWidgetManager.getHostedWidgetPackages(APP_UID)) 254 .thenReturn(new ArraySet<>()); 255 when(mMockContext.checkPermission( 256 eq(Manifest.permission.ACT_AS_PACKAGE_FOR_ACCESSIBILITY), anyInt(), eq(APP_UID))) 257 .thenReturn(PackageManager.PERMISSION_DENIED); 258 259 assertEquals(PACKAGE_NAME, mA11ySecurityPolicy.resolveValidReportedPackageLocked( 260 invalidPackageName, APP_UID, UserHandle.USER_SYSTEM, APP_PID)); 261 } 262 263 @Test resolveValidReportedPackage_anotherPkgNameWithActAsPkgPermission_returnPkg()264 public void resolveValidReportedPackage_anotherPkgNameWithActAsPkgPermission_returnPkg() 265 throws PackageManager.NameNotFoundException { 266 final String wantedPackageName = PACKAGE_NAME2; 267 final int wantedUid = APP_UID + 1; 268 final String[] uidPackages = {PACKAGE_NAME}; 269 when(mMockPackageManager.getPackagesForUid(APP_UID)) 270 .thenReturn(uidPackages); 271 when(mMockPackageManager.getPackageUidAsUser(wantedPackageName, UserHandle.USER_SYSTEM)) 272 .thenReturn(wantedUid); 273 when(mMockAppWidgetManager.getHostedWidgetPackages(APP_UID)) 274 .thenReturn(new ArraySet<>()); 275 when(mMockContext.checkPermission( 276 eq(Manifest.permission.ACT_AS_PACKAGE_FOR_ACCESSIBILITY), anyInt(), eq(APP_UID))) 277 .thenReturn(PackageManager.PERMISSION_GRANTED); 278 279 assertEquals(wantedPackageName, mA11ySecurityPolicy.resolveValidReportedPackageLocked( 280 wantedPackageName, APP_UID, UserHandle.USER_SYSTEM, APP_PID)); 281 } 282 283 @Test resolveValidReportedPackage_anotherPkgNameWithoutActAsPkgPermission_returnUidPkg()284 public void resolveValidReportedPackage_anotherPkgNameWithoutActAsPkgPermission_returnUidPkg() 285 throws PackageManager.NameNotFoundException { 286 final String wantedPackageName = PACKAGE_NAME2; 287 final int wantedUid = APP_UID + 1; 288 final String[] uidPackages = {PACKAGE_NAME}; 289 when(mMockPackageManager.getPackagesForUid(APP_UID)) 290 .thenReturn(uidPackages); 291 when(mMockPackageManager.getPackageUidAsUser(wantedPackageName, UserHandle.USER_SYSTEM)) 292 .thenReturn(wantedUid); 293 when(mMockAppWidgetManager.getHostedWidgetPackages(APP_UID)) 294 .thenReturn(new ArraySet<>()); 295 when(mMockContext.checkPermission( 296 eq(Manifest.permission.ACT_AS_PACKAGE_FOR_ACCESSIBILITY), anyInt(), eq(APP_UID))) 297 .thenReturn(PackageManager.PERMISSION_DENIED); 298 299 assertEquals(PACKAGE_NAME, mA11ySecurityPolicy.resolveValidReportedPackageLocked( 300 wantedPackageName, APP_UID, UserHandle.USER_SYSTEM, APP_PID)); 301 } 302 303 @Test computeValidReportedPackages_uidIsSystem_returnEmptyArray()304 public void computeValidReportedPackages_uidIsSystem_returnEmptyArray() { 305 assertThat(mA11ySecurityPolicy.computeValidReportedPackages( 306 PACKAGE_NAME, Process.SYSTEM_UID), emptyArray()); 307 } 308 309 @Test computeValidReportedPackages_uidIsAppWidgetHost_returnTargetAndWidgetName()310 public void computeValidReportedPackages_uidIsAppWidgetHost_returnTargetAndWidgetName() { 311 final int widgetHostUid = APP_UID; 312 final String targetPackageName = PACKAGE_NAME; 313 final String widgetPackageName = PACKAGE_NAME2; 314 final ArraySet<String> widgetPackages = new ArraySet<>(); 315 widgetPackages.add(widgetPackageName); 316 when(mMockAppWidgetManager.getHostedWidgetPackages(widgetHostUid)) 317 .thenReturn(widgetPackages); 318 319 List<String> packages = Arrays.asList(mA11ySecurityPolicy.computeValidReportedPackages( 320 targetPackageName, widgetHostUid)); 321 assertThat(packages, hasSize(2)); 322 assertThat(packages, containsInAnyOrder(targetPackageName, widgetPackageName)); 323 } 324 325 @Test canGetAccessibilityNodeInfo_windowIdNotExist_returnFalse()326 public void canGetAccessibilityNodeInfo_windowIdNotExist_returnFalse() { 327 final int invalidWindowId = WINDOWID; 328 when(mMockA11yServiceConnection.getCapabilities()) 329 .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT); 330 331 assertFalse(mA11ySecurityPolicy.canGetAccessibilityNodeInfoLocked(UserHandle.USER_SYSTEM, 332 mMockA11yServiceConnection, invalidWindowId)); 333 } 334 335 @Test canGetAccessibilityNodeInfo_hasCapAndWindowIsActive_returnTrue()336 public void canGetAccessibilityNodeInfo_hasCapAndWindowIsActive_returnTrue() { 337 when(mMockA11yServiceConnection.getCapabilities()) 338 .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT); 339 when(mMockA11yWindowManager.getActiveWindowId(UserHandle.USER_SYSTEM)) 340 .thenReturn(WINDOWID); 341 342 assertTrue(mA11ySecurityPolicy.canGetAccessibilityNodeInfoLocked(UserHandle.USER_SYSTEM, 343 mMockA11yServiceConnection, WINDOWID)); 344 } 345 346 @Test canGetAccessibilityNodeInfo_hasCapAndWindowExist_returnTrue()347 public void canGetAccessibilityNodeInfo_hasCapAndWindowExist_returnTrue() { 348 when(mMockA11yServiceConnection.getCapabilities()) 349 .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT); 350 when(mMockA11yWindowManager.getActiveWindowId(UserHandle.USER_SYSTEM)) 351 .thenReturn(WINDOWID2); 352 when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(WINDOWID)) 353 .thenReturn(AccessibilityWindowInfo.obtain()); 354 355 assertTrue(mA11ySecurityPolicy.canGetAccessibilityNodeInfoLocked(UserHandle.USER_SYSTEM, 356 mMockA11yServiceConnection, WINDOWID)); 357 } 358 359 @Test canRetrieveWindows_retrieveWindowsFlagIsFalse_returnFalse()360 public void canRetrieveWindows_retrieveWindowsFlagIsFalse_returnFalse() { 361 when(mMockA11yServiceConnection.getCapabilities()) 362 .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT); 363 364 assertFalse(mA11ySecurityPolicy.canRetrieveWindowsLocked(mMockA11yServiceConnection)); 365 } 366 367 @Test canRetrieveWindows_hasCapabilityAndRetrieveWindowsFlag_returnTrue()368 public void canRetrieveWindows_hasCapabilityAndRetrieveWindowsFlag_returnTrue() { 369 when(mMockA11yServiceConnection.getCapabilities()) 370 .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT); 371 mMockA11yServiceConnection.mRetrieveInteractiveWindows = true; 372 373 assertTrue(mA11ySecurityPolicy.canRetrieveWindowsLocked(mMockA11yServiceConnection)); 374 } 375 376 @Test canRetrieveWindowContent_hasCapability_returnTrue()377 public void canRetrieveWindowContent_hasCapability_returnTrue() { 378 when(mMockA11yServiceConnection.getCapabilities()) 379 .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT); 380 381 assertTrue(mA11ySecurityPolicy.canRetrieveWindowContentLocked(mMockA11yServiceConnection)); 382 } 383 384 @Test canControlMagnification_hasCapability_returnTrue()385 public void canControlMagnification_hasCapability_returnTrue() { 386 when(mMockA11yServiceConnection.getCapabilities()) 387 .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_CONTROL_MAGNIFICATION); 388 389 assertTrue(mA11ySecurityPolicy.canControlMagnification(mMockA11yServiceConnection)); 390 } 391 392 @Test canPerformGestures_hasCapability_returnTrue()393 public void canPerformGestures_hasCapability_returnTrue() { 394 assertFalse(mA11ySecurityPolicy.canPerformGestures(mMockA11yServiceConnection)); 395 when(mMockA11yServiceConnection.getCapabilities()) 396 .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES); 397 398 assertTrue(mA11ySecurityPolicy.canPerformGestures(mMockA11yServiceConnection)); 399 } 400 401 @Test canCaptureFingerprintGestures_hasCapability_returnTrue()402 public void canCaptureFingerprintGestures_hasCapability_returnTrue() { 403 assertFalse(mA11ySecurityPolicy.canCaptureFingerprintGestures(mMockA11yServiceConnection)); 404 when(mMockA11yServiceConnection.getCapabilities()) 405 .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES); 406 407 assertTrue(mA11ySecurityPolicy.canCaptureFingerprintGestures(mMockA11yServiceConnection)); 408 } 409 410 @Test canTakeScreenshot_hasCapability_returnTrue()411 public void canTakeScreenshot_hasCapability_returnTrue() { 412 when(mMockA11yServiceConnection.getCapabilities()) 413 .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_TAKE_SCREENSHOT); 414 415 assertTrue(mA11ySecurityPolicy.canTakeScreenshotLocked(mMockA11yServiceConnection)); 416 } 417 418 @Test resolveProfileParent_userIdIsCurrentUser_returnCurrentUser()419 public void resolveProfileParent_userIdIsCurrentUser_returnCurrentUser() { 420 final int currentUserId = 10; 421 final int userId = currentUserId; 422 when(mMockA11yUserManager.getCurrentUserIdLocked()) 423 .thenReturn(currentUserId); 424 425 assertEquals(mA11ySecurityPolicy.resolveProfileParentLocked(userId), 426 currentUserId); 427 } 428 429 @Test resolveProfileParent_userIdNotCurrentUser_shouldGetProfileParent()430 public void resolveProfileParent_userIdNotCurrentUser_shouldGetProfileParent() { 431 final int userId = 15; 432 final int currentUserId = 20; 433 when(mMockA11yUserManager.getCurrentUserIdLocked()).thenReturn(currentUserId); 434 435 mA11ySecurityPolicy.resolveProfileParentLocked(userId); 436 verify(mMockUserManager).getProfileParent(userId); 437 } 438 439 @Test resolveCallingUserId_userIdIsCallingUser_shouldResolveProfileParent()440 public void resolveCallingUserId_userIdIsCallingUser_shouldResolveProfileParent() { 441 final AccessibilitySecurityPolicy spySecurityPolicy = Mockito.spy(mA11ySecurityPolicy); 442 final int callingUserId = UserHandle.getUserId(Process.myUid()); 443 final int userId = callingUserId; 444 445 spySecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(userId); 446 verify(spySecurityPolicy).resolveProfileParentLocked(userId); 447 } 448 449 @Test resolveCallingUserId_callingParentIsCurrentUser_returnCurrentUser()450 public void resolveCallingUserId_callingParentIsCurrentUser_returnCurrentUser() { 451 final AccessibilitySecurityPolicy spySecurityPolicy = Mockito.spy(mA11ySecurityPolicy); 452 final int callingUserId = UserHandle.getUserId(Process.myUid()); 453 final int callingParentId = 20; 454 final int currentUserId = callingParentId; 455 when(mMockA11yUserManager.getCurrentUserIdLocked()) 456 .thenReturn(currentUserId); 457 doReturn(callingParentId).when(spySecurityPolicy).resolveProfileParentLocked( 458 callingUserId); 459 460 assertEquals(spySecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked( 461 UserHandle.USER_CURRENT_OR_SELF), currentUserId); 462 463 } 464 465 @Test(expected = SecurityException.class) resolveCallingUserId_callingParentNotCurrentUserAndNoPerm_shouldException()466 public void resolveCallingUserId_callingParentNotCurrentUserAndNoPerm_shouldException() { 467 final AccessibilitySecurityPolicy spySecurityPolicy = Mockito.spy(mA11ySecurityPolicy); 468 final int callingUserId = UserHandle.getUserId(Process.myUid()); 469 final int callingParentId = 20; 470 final int currentUserId = 30; 471 when(mMockA11yUserManager.getCurrentUserIdLocked()) 472 .thenReturn(currentUserId); 473 doReturn(callingParentId).when(spySecurityPolicy).resolveProfileParentLocked( 474 callingUserId); 475 when(mMockContext.checkCallingPermission(any())) 476 .thenReturn(PackageManager.PERMISSION_DENIED); 477 478 spySecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked( 479 UserHandle.USER_CURRENT_OR_SELF); 480 } 481 482 @Test resolveCallingUserId_anotherUserIdWithCrossUserPermission_returnUserId()483 public void resolveCallingUserId_anotherUserIdWithCrossUserPermission_returnUserId() { 484 final AccessibilitySecurityPolicy spySecurityPolicy = Mockito.spy(mA11ySecurityPolicy); 485 final int callingUserId = UserHandle.getUserId(Process.myUid()); 486 final int callingParentId = 20; 487 final int currentUserId = 30; 488 final int wantedUserId = 40; 489 when(mMockA11yUserManager.getCurrentUserIdLocked()) 490 .thenReturn(currentUserId); 491 doReturn(callingParentId).when(spySecurityPolicy).resolveProfileParentLocked( 492 callingUserId); 493 when(mMockContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS)) 494 .thenReturn(PackageManager.PERMISSION_GRANTED); 495 496 assertEquals(wantedUserId, 497 spySecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(wantedUserId)); 498 } 499 500 @Test resolveCallingUserId_anotherUserIdWithCrossUserFullPermission_returnUserId()501 public void resolveCallingUserId_anotherUserIdWithCrossUserFullPermission_returnUserId() { 502 final AccessibilitySecurityPolicy spySecurityPolicy = Mockito.spy(mA11ySecurityPolicy); 503 final int callingUserId = UserHandle.getUserId(Process.myUid()); 504 final int callingParentId = 20; 505 final int currentUserId = 30; 506 final int wantedUserId = 40; 507 when(mMockA11yUserManager.getCurrentUserIdLocked()) 508 .thenReturn(currentUserId); 509 doReturn(callingParentId).when(spySecurityPolicy).resolveProfileParentLocked( 510 callingUserId); 511 when(mMockContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) 512 .thenReturn(PackageManager.PERMISSION_GRANTED); 513 514 assertEquals(wantedUserId, 515 spySecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(wantedUserId)); 516 } 517 518 @Test(expected = SecurityException.class) resolveCallingUserId_anotherUserIdWithoutCrossUserPermission_shouldException()519 public void resolveCallingUserId_anotherUserIdWithoutCrossUserPermission_shouldException() { 520 final AccessibilitySecurityPolicy spySecurityPolicy = Mockito.spy(mA11ySecurityPolicy); 521 final int callingUserId = UserHandle.getUserId(Process.myUid()); 522 final int callingParentId = 20; 523 final int currentUserId = 30; 524 final int wantedUserId = 40; 525 when(mMockA11yUserManager.getCurrentUserIdLocked()) 526 .thenReturn(currentUserId); 527 doReturn(callingParentId).when(spySecurityPolicy).resolveProfileParentLocked( 528 callingUserId); 529 when(mMockContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS)) 530 .thenReturn(PackageManager.PERMISSION_DENIED); 531 when(mMockContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) 532 .thenReturn(PackageManager.PERMISSION_DENIED); 533 534 spySecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(wantedUserId); 535 } 536 537 @Test canRegisterService_shouldCheckAppOps()538 public void canRegisterService_shouldCheckAppOps() { 539 final ServiceInfo serviceInfo = new ServiceInfo(); 540 serviceInfo.applicationInfo = new ApplicationInfo(); 541 serviceInfo.packageName = PACKAGE_NAME; 542 serviceInfo.name = AccessibilitySecurityPolicyTest.class.getSimpleName(); 543 544 assertFalse(mA11ySecurityPolicy.canRegisterService(serviceInfo)); 545 serviceInfo.permission = android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE; 546 mA11ySecurityPolicy.canRegisterService(serviceInfo); 547 verify(mMockAppOpsManager).noteOpNoThrow(AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE, 548 serviceInfo.applicationInfo.uid, serviceInfo.packageName); 549 } 550 551 @Test checkAccessibilityAccess_shouldCheckAppOps()552 public void checkAccessibilityAccess_shouldCheckAppOps() { 553 final AccessibilityServiceInfo mockServiceInfo = Mockito.mock( 554 AccessibilityServiceInfo.class); 555 final ResolveInfo mockResolveInfo = Mockito.mock( 556 ResolveInfo.class); 557 final ServiceInfo serviceInfo = new ServiceInfo(); 558 serviceInfo.applicationInfo = new ApplicationInfo(); 559 serviceInfo.applicationInfo.uid = APP_UID; 560 mockResolveInfo.serviceInfo = serviceInfo; 561 562 when(mMockA11yServiceConnection.getServiceInfo()).thenReturn(mockServiceInfo); 563 when(mockServiceInfo.getResolveInfo()).thenReturn(mockResolveInfo); 564 when(mMockA11yServiceConnection.getComponentName()) 565 .thenReturn(new ComponentName( 566 PACKAGE_NAME, AccessibilitySecurityPolicyTest.class.getSimpleName())); 567 568 mA11ySecurityPolicy.checkAccessibilityAccess(mMockA11yServiceConnection); 569 verify(mMockAppOpsManager).noteOpNoThrow(AppOpsManager.OPSTR_ACCESS_ACCESSIBILITY, 570 APP_UID, PACKAGE_NAME); 571 } 572 573 @Test testEnforceCallerIsRecentsOrHasPermission()574 public void testEnforceCallerIsRecentsOrHasPermission() { 575 mA11ySecurityPolicy.enforceCallerIsRecentsOrHasPermission(PERMISSION, FUNCTION); 576 verify(mMockActivityTaskManagerInternal).enforceCallerIsRecentsOrHasPermission( 577 PERMISSION, FUNCTION); 578 } 579 } 580