Avoid A11y features blocked by IT admin can be allowed to bind at the system level

Root cause: Address A11y features blocked by IT admin by adjusting the UI, which seems like a good idea but might not cover all cases
Solution: Avoid A11y features blocked by IT admin can be allowed to bind at the system level

Bug: 254223085
Test: atest CtsAccessibilityServiceTestCases
Test: `adb shell settings put secure enabled_accessibility_service` disallowed service & verify the service would not be bound by `adb shell dumpsys accessibility`
Change-Id: I6ce326c82d063923d8737d637aa5f7f570cfc950
This commit is contained in:
menghanli
2023-03-13 21:20:49 +08:00
parent 6b02ff5740
commit 125d1d9bc0
2 changed files with 47 additions and 40 deletions

View File

@@ -2263,6 +2263,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
if (userState.mEnabledServices.contains(componentName)
&& !mUiAutomationManager.suppressingAccessibilityServicesLocked()) {
// Skip the enabling service disallowed by device admin policy.
if (!isAccessibilityTargetAllowed(componentName.getPackageName(),
installedService.getResolveInfo().serviceInfo.applicationInfo.uid,
userState.mUserId)) {
Slog.d(LOG_TAG, "Skipping enabling service disallowed by device admin policy: "
+ componentName);
disableAccessibilityServiceLocked(componentName, userState.mUserId);
continue;
}
if (service == null) {
service = new AccessibilityServiceConnection(userState, mContext, componentName,
installedService, sIdCounter++, mMainHandler, mLock, mSecurityPolicy,
@@ -3875,32 +3884,29 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
}
@Override
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.QUERY_ADMIN_POLICY})
public boolean isAccessibilityTargetAllowed(String packageName, int uid, int userId) {
final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
final List<String> permittedServices = dpm.getPermittedAccessibilityServices(userId);
final long identity = Binder.clearCallingIdentity();
try {
final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
final List<String> permittedServices = dpm.getPermittedAccessibilityServices(userId);
// permittedServices null means all accessibility services are allowed.
boolean allowed = permittedServices == null || permittedServices.contains(packageName);
if (allowed) {
final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
final int mode = appOps.noteOpNoThrow(
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
uid, packageName, /* attributionTag= */ null, /* message= */ null);
final boolean ecmEnabled = mContext.getResources().getBoolean(
R.bool.config_enhancedConfirmationModeEnabled);
return !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED;
// permittedServices null means all accessibility services are allowed.
boolean allowed = permittedServices == null || permittedServices.contains(packageName);
if (allowed) {
final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
final int mode = appOps.noteOpNoThrow(
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
uid, packageName, /* attributionTag= */ null, /* message= */ null);
final boolean ecmEnabled = mContext.getResources().getBoolean(
R.bool.config_enhancedConfirmationModeEnabled);
return !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED;
}
return false;
} finally {
Binder.restoreCallingIdentity(identity);
}
return false;
}
@Override
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.QUERY_ADMIN_POLICY})
public boolean sendRestrictedDialogIntent(String packageName, int uid, int userId) {
// The accessibility service is allowed. Don't show the restricted dialog.
if (isAccessibilityTargetAllowed(packageName, uid, userId)) {

View File

@@ -11776,6 +11776,20 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(canManageUsers(caller) || canQueryAdminPolicy(caller));
// Move AccessibilityManager out of lock to prevent potential deadlock
final List<AccessibilityServiceInfo> installedServices;
long id = mInjector.binderClearCallingIdentity();
try {
UserInfo user = getUserInfo(userId);
if (user.isManagedProfile()) {
userId = user.profileGroupId;
}
installedServices = withAccessibilityManager(userId,
AccessibilityManager::getInstalledAccessibilityServiceList);
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
synchronized (getLockObject()) {
List<String> result = null;
// If we have multiple profiles we return the intersection of the
@@ -11802,27 +11816,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// If we have a permitted list add all system accessibility services.
if (result != null) {
long id = mInjector.binderClearCallingIdentity();
try {
UserInfo user = getUserInfo(userId);
if (user.isManagedProfile()) {
userId = user.profileGroupId;
}
final List<AccessibilityServiceInfo> installedServices =
withAccessibilityManager(userId,
AccessibilityManager::getInstalledAccessibilityServiceList);
if (installedServices != null) {
for (AccessibilityServiceInfo service : installedServices) {
ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo;
ApplicationInfo applicationInfo = serviceInfo.applicationInfo;
if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
result.add(serviceInfo.packageName);
}
if (installedServices != null) {
for (AccessibilityServiceInfo service : installedServices) {
ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo;
ApplicationInfo applicationInfo = serviceInfo.applicationInfo;
if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
result.add(serviceInfo.packageName);
}
}
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
}