summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java4
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java38
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java8
3 files changed, 44 insertions, 6 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index ef500ff7fbda..fdb28ba9103e 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -4006,8 +4006,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
@Override
public boolean registerProxyForDisplay(IAccessibilityServiceClient client, int displayId)
throws RemoteException {
- mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
+ mSecurityPolicy.checkForAccessibilityPermissionOrRole();
if (client == null) {
return false;
}
@@ -4043,8 +4043,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
@Override
public boolean unregisterProxyForDisplay(int displayId) {
- mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
+ mSecurityPolicy.checkForAccessibilityPermissionOrRole();
final long identity = Binder.clearCallingIdentity();
try {
return mProxyManager.unregisterProxy(displayId);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java b/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
index 93356263b897..f45fa921c4a2 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
@@ -18,6 +18,7 @@ package com.android.server.accessibility;
import static android.accessibilityservice.AccessibilityService.SoftKeyboardController.ENABLE_IME_FAIL_BY_ADMIN;
import static android.accessibilityservice.AccessibilityService.SoftKeyboardController.ENABLE_IME_SUCCESS;
+import static android.companion.AssociationRequest.DEVICE_PROFILE_APP_STREAMING;
import android.Manifest;
import android.accessibilityservice.AccessibilityService;
@@ -25,6 +26,7 @@ import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
+import android.app.role.RoleManager;
import android.appwidget.AppWidgetManagerInternal;
import android.content.ComponentName;
import android.content.Context;
@@ -675,6 +677,42 @@ public class AccessibilitySecurityPolicy {
}
/**
+ * Throws a SecurityException if the caller has neither the MANAGE_ACCESSIBILITY permission nor
+ * the COMPANION_DEVICE_APP_STREAMING role.
+ */
+ public void checkForAccessibilityPermissionOrRole() {
+ final boolean canManageAccessibility =
+ mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
+ == PackageManager.PERMISSION_GRANTED;
+ if (canManageAccessibility) {
+ return;
+ }
+ final int callingUid = Binder.getCallingUid();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final RoleManager roleManager = mContext.getSystemService(RoleManager.class);
+ if (roleManager != null) {
+ final List<String> holders = roleManager.getRoleHoldersAsUser(
+ DEVICE_PROFILE_APP_STREAMING, UserHandle.getUserHandleForUid(callingUid));
+ final String[] packageNames = mPackageManager.getPackagesForUid(callingUid);
+ if (packageNames != null) {
+ for (String packageName : packageNames) {
+ if (holders.contains(packageName)) {
+ return;
+ }
+ }
+ }
+ }
+ throw new SecurityException(
+ "Cannot register a proxy for a device without the "
+ + "android.app.role.COMPANION_DEVICE_APP_STREAMING role or the"
+ + " MANAGE_ACCESSIBILITY permission.");
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
* Called after a service was bound or unbound. Checks the current bound accessibility
* services and updates alarms.
*
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index f2ec81bb5a73..7e638a869682 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -290,9 +290,9 @@ public class AccessibilityManagerServiceTest {
@SmallTest
@Test
- public void testRegisterProxyWithoutA11yPermission() throws Exception {
+ public void testRegisterProxyWithoutA11yPermissionOrRole() throws Exception {
doThrow(SecurityException.class).when(mMockSecurityPolicy)
- .enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
+ .checkForAccessibilityPermissionOrRole();
assertThrows(SecurityException.class,
() -> mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY));
@@ -342,9 +342,9 @@ public class AccessibilityManagerServiceTest {
@SmallTest
@Test
- public void testUnRegisterProxyWithoutA11yPermission() {
+ public void testUnRegisterProxyWithoutA11yPermissionOrRole() {
doThrow(SecurityException.class).when(mMockSecurityPolicy)
- .enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
+ .checkForAccessibilityPermissionOrRole();
assertThrows(SecurityException.class,
() -> mA11yms.unregisterProxyForDisplay(TEST_DISPLAY));