Merge "Adds install source checks for accessibility service" into sc-dev
This commit is contained in:
@@ -4892,4 +4892,7 @@
|
||||
<bool name="config_supportsMicToggle">false</bool>
|
||||
<!-- Whether this device is supporting the camera toggle -->
|
||||
<bool name="config_supportsCamToggle">false</bool>
|
||||
|
||||
<!-- List containing the allowed install sources for accessibility service. -->
|
||||
<string-array name="config_accessibility_allowed_install_source" translatable="false"/>
|
||||
</resources>
|
||||
|
||||
@@ -4357,6 +4357,8 @@
|
||||
<java-symbol type="drawable" name="ic_accessibility_24dp" />
|
||||
<java-symbol type="string" name="view_and_control_notification_title" />
|
||||
<java-symbol type="string" name="view_and_control_notification_content" />
|
||||
<java-symbol type="array" name="config_accessibility_allowed_install_source" />
|
||||
|
||||
<!-- Translation -->
|
||||
<java-symbol type="string" name="ui_translation_accessibility_translated_text" />
|
||||
<java-symbol type="string" name="ui_translation_accessibility_translation_finished" />
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.accessibility;
|
||||
|
||||
import static android.content.pm.PackageManagerInternal.PACKAGE_INSTALLER;
|
||||
|
||||
import android.Manifest;
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.annotation.NonNull;
|
||||
@@ -24,7 +26,9 @@ import android.app.AppOpsManager;
|
||||
import android.appwidget.AppWidgetManagerInternal;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.InstallSourceInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
@@ -33,11 +37,13 @@ import android.os.IBinder;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Slog;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
import libcore.util.EmptyArray;
|
||||
|
||||
@@ -666,13 +672,66 @@ public class AccessibilitySecurityPolicy {
|
||||
|
||||
/**
|
||||
* Identifies whether the accessibility service is true and designed for accessibility. An
|
||||
* accessibility service is considered as accessibility category if
|
||||
* {@link AccessibilityServiceInfo#isAccessibilityTool} is true.
|
||||
* accessibility service is considered as accessibility category if meets all conditions below:
|
||||
* <ul>
|
||||
* <li> {@link AccessibilityServiceInfo#isAccessibilityTool} is true</li>
|
||||
* <li> is installed from the trusted install source</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param serviceInfo The accessibility service's serviceInfo.
|
||||
* @return Returns true if it is a true accessibility service.
|
||||
*/
|
||||
public boolean isA11yCategoryService(AccessibilityServiceInfo serviceInfo) {
|
||||
return serviceInfo.isAccessibilityTool();
|
||||
if (!serviceInfo.isAccessibilityTool()) {
|
||||
return false;
|
||||
}
|
||||
if (!serviceInfo.getResolveInfo().serviceInfo.applicationInfo.isSystemApp()) {
|
||||
return hasTrustedSystemInstallSource(
|
||||
serviceInfo.getResolveInfo().serviceInfo.packageName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Returns true if the {@code installedPackage} is installed from the trusted install source.
|
||||
*/
|
||||
private boolean hasTrustedSystemInstallSource(String installedPackage) {
|
||||
try {
|
||||
InstallSourceInfo installSourceInfo = mPackageManager.getInstallSourceInfo(
|
||||
installedPackage);
|
||||
if (installSourceInfo == null) {
|
||||
return false;
|
||||
}
|
||||
final String installSourcePackageName = installSourceInfo.getInitiatingPackageName();
|
||||
if (installSourcePackageName == null || !mPackageManager.getPackageInfo(
|
||||
installSourcePackageName,
|
||||
0).applicationInfo.isSystemApp()) {
|
||||
return false;
|
||||
}
|
||||
return isTrustedInstallSource(installSourcePackageName);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Slog.w(LOG_TAG, "can't find the package's install source:" + installedPackage);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns true if the {@code installerPackage} is a trusted install source. */
|
||||
private boolean isTrustedInstallSource(String installerPackage) {
|
||||
final String[] allowedInstallingSources = mContext.getResources().getStringArray(
|
||||
com.android.internal.R.array
|
||||
.config_accessibility_allowed_install_source);
|
||||
|
||||
if (allowedInstallingSources.length == 0) {
|
||||
//Filters unwanted default installers if no allowed install sources.
|
||||
String defaultInstaller = ArrayUtils.firstOrNull(LocalServices.getService(
|
||||
PackageManagerInternal.class).getKnownPackageNames(PACKAGE_INSTALLER,
|
||||
mCurrentUserId));
|
||||
return !TextUtils.equals(defaultInstaller, installerPackage);
|
||||
}
|
||||
for (int i = 0; i < allowedInstallingSources.length; i++) {
|
||||
if (TextUtils.equals(allowedInstallingSources[i], installerPackage)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,9 +43,12 @@ import android.appwidget.AppWidgetManagerInternal;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.InstallSourceInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.pm.SigningInfo;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
@@ -81,8 +84,10 @@ public class AccessibilitySecurityPolicyTest {
|
||||
private static final int APP_PID = 2000;
|
||||
private static final int SYSTEM_PID = 558;
|
||||
private static final int TEST_USER_ID = UserHandle.USER_SYSTEM;
|
||||
private static final String TEST_PACKAGE_NAME = "com.android.server.accessibility";
|
||||
private static final ComponentName TEST_COMPONENT_NAME = new ComponentName(
|
||||
"com.android.server.accessibility", "AccessibilitySecurityPolicyTest");
|
||||
TEST_PACKAGE_NAME, "AccessibilitySecurityPolicyTest");
|
||||
private static final String ALLOWED_INSTALL_PACKAGE_NAME = "com.allowed.install.package";
|
||||
|
||||
private static final int[] ALWAYS_DISPATCH_EVENTS = {
|
||||
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
|
||||
@@ -142,19 +147,40 @@ public class AccessibilitySecurityPolicyTest {
|
||||
@Mock
|
||||
private AccessibilityServiceInfo mMockA11yServiceInfo;
|
||||
@Mock
|
||||
private ResolveInfo mMockResolveInfo;
|
||||
@Mock
|
||||
private ServiceInfo mMockServiceInfo;
|
||||
@Mock
|
||||
private ApplicationInfo mMockApplicationInfo;
|
||||
@Mock
|
||||
private ApplicationInfo mMockSourceApplicationInfo;
|
||||
@Mock
|
||||
private PackageInfo mMockSourcePackageInfo;
|
||||
@Mock
|
||||
private PolicyWarningUIController mPolicyWarningUIController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
public void setUp() throws PackageManager.NameNotFoundException {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext.setMockPackageManager(mMockPackageManager);
|
||||
mContext.addMockSystemService(Context.USER_SERVICE, mMockUserManager);
|
||||
mContext.addMockSystemService(Context.APP_OPS_SERVICE, mMockAppOpsManager);
|
||||
mContext.getOrCreateTestableResources().addOverride(
|
||||
R.dimen.accessibility_focus_highlight_stroke_width, 1);
|
||||
mContext.getOrCreateTestableResources().addOverride(R.array
|
||||
.config_accessibility_allowed_install_source,
|
||||
new String[]{ALLOWED_INSTALL_PACKAGE_NAME});
|
||||
|
||||
when(mMockA11yServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo);
|
||||
when(mMockA11yServiceInfo.getComponentName()).thenReturn(TEST_COMPONENT_NAME);
|
||||
when(mMockA11yServiceConnection.getServiceInfo()).thenReturn(mMockA11yServiceInfo);
|
||||
when(mMockPackageManager.getPackageInfo(ALLOWED_INSTALL_PACKAGE_NAME, 0)).thenReturn(
|
||||
mMockSourcePackageInfo);
|
||||
|
||||
mMockResolveInfo.serviceInfo = mMockServiceInfo;
|
||||
mMockServiceInfo.applicationInfo = mMockApplicationInfo;
|
||||
mMockServiceInfo.packageName = TEST_PACKAGE_NAME;
|
||||
mMockSourcePackageInfo.applicationInfo = mMockSourceApplicationInfo;
|
||||
|
||||
mA11ySecurityPolicy = new AccessibilitySecurityPolicy(
|
||||
mPolicyWarningUIController, mContext, mMockA11yUserManager);
|
||||
@@ -595,28 +621,7 @@ public class AccessibilitySecurityPolicyTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBoundServicesChanged_bindA11yCategoryService_noUIControllerAction() {
|
||||
final ArrayList<AccessibilityServiceConnection> boundServices = new ArrayList<>();
|
||||
boundServices.add(mMockA11yServiceConnection);
|
||||
when(mMockA11yServiceInfo.isAccessibilityTool()).thenReturn(true);
|
||||
|
||||
mA11ySecurityPolicy.onBoundServicesChangedLocked(TEST_USER_ID, boundServices);
|
||||
|
||||
verify(mPolicyWarningUIController, never()).onNonA11yCategoryServiceBound(anyInt(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBoundServicesChanged_unbindA11yCategoryService_noUIControllerAction() {
|
||||
onBoundServicesChanged_bindA11yCategoryService_noUIControllerAction();
|
||||
|
||||
mA11ySecurityPolicy.onBoundServicesChangedLocked(TEST_USER_ID, new ArrayList<>());
|
||||
|
||||
verify(mPolicyWarningUIController, never()).onNonA11yCategoryServiceUnbound(anyInt(),
|
||||
any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBoundServicesChanged_bindNonA11yCategoryService_activateUIControllerAction() {
|
||||
public void onBoundServicesChanged_bindNonA11yToolService_activateUIControllerAction() {
|
||||
final ArrayList<AccessibilityServiceConnection> boundServices = new ArrayList<>();
|
||||
boundServices.add(mMockA11yServiceConnection);
|
||||
when(mMockA11yServiceInfo.isAccessibilityTool()).thenReturn(false);
|
||||
@@ -628,8 +633,8 @@ public class AccessibilitySecurityPolicyTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBoundServicesChanged_unbindNonA11yCategoryService_activateUIControllerAction() {
|
||||
onBoundServicesChanged_bindNonA11yCategoryService_activateUIControllerAction();
|
||||
public void onBoundServicesChanged_unbindNonA11yToolService_activateUIControllerAction() {
|
||||
onBoundServicesChanged_bindNonA11yToolService_activateUIControllerAction();
|
||||
|
||||
mA11ySecurityPolicy.onBoundServicesChangedLocked(TEST_USER_ID, new ArrayList<>());
|
||||
|
||||
@@ -637,9 +642,66 @@ public class AccessibilitySecurityPolicyTest {
|
||||
eq(TEST_COMPONENT_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBoundServicesChanged_bindSystemA11yToolService_noUIControllerAction() {
|
||||
final ArrayList<AccessibilityServiceConnection> boundServices = new ArrayList<>();
|
||||
boundServices.add(mMockA11yServiceConnection);
|
||||
when(mMockApplicationInfo.isSystemApp()).thenReturn(true);
|
||||
when(mMockA11yServiceInfo.isAccessibilityTool()).thenReturn(true);
|
||||
|
||||
mA11ySecurityPolicy.onBoundServicesChangedLocked(TEST_USER_ID, boundServices);
|
||||
|
||||
verify(mPolicyWarningUIController, never()).onNonA11yCategoryServiceBound(anyInt(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBoundServicesChanged_unbindSystemA11yToolService_noUIControllerAction() {
|
||||
onBoundServicesChanged_bindSystemA11yToolService_noUIControllerAction();
|
||||
|
||||
mA11ySecurityPolicy.onBoundServicesChangedLocked(TEST_USER_ID, new ArrayList<>());
|
||||
|
||||
verify(mPolicyWarningUIController, never()).onNonA11yCategoryServiceUnbound(anyInt(),
|
||||
any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBoundServicesChanged_bindAllowedSourceA11yToolService_noUIControllerAction()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
final ArrayList<AccessibilityServiceConnection> boundServices = new ArrayList<>();
|
||||
boundServices.add(mMockA11yServiceConnection);
|
||||
when(mMockApplicationInfo.isSystemApp()).thenReturn(false);
|
||||
final InstallSourceInfo installSourceInfo = new InstallSourceInfo(
|
||||
ALLOWED_INSTALL_PACKAGE_NAME, new SigningInfo(), null,
|
||||
ALLOWED_INSTALL_PACKAGE_NAME);
|
||||
when(mMockPackageManager.getInstallSourceInfo(TEST_PACKAGE_NAME)).thenReturn(
|
||||
installSourceInfo);
|
||||
when(mMockSourceApplicationInfo.isSystemApp()).thenReturn(true);
|
||||
when(mMockA11yServiceInfo.isAccessibilityTool()).thenReturn(true);
|
||||
|
||||
mA11ySecurityPolicy.onBoundServicesChangedLocked(TEST_USER_ID, boundServices);
|
||||
|
||||
verify(mPolicyWarningUIController, never()).onNonA11yCategoryServiceBound(anyInt(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBoundServicesChanged_bindUnknownSourceA11yToolService_activateUIControllerAction()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
final ArrayList<AccessibilityServiceConnection> boundServices = new ArrayList<>();
|
||||
boundServices.add(mMockA11yServiceConnection);
|
||||
when(mMockA11yServiceInfo.isAccessibilityTool()).thenReturn(true);
|
||||
final InstallSourceInfo installSourceInfo = new InstallSourceInfo(null, null, null, null);
|
||||
when(mMockPackageManager.getInstallSourceInfo(TEST_PACKAGE_NAME)).thenReturn(
|
||||
installSourceInfo);
|
||||
|
||||
mA11ySecurityPolicy.onBoundServicesChangedLocked(TEST_USER_ID, boundServices);
|
||||
|
||||
verify(mPolicyWarningUIController).onNonA11yCategoryServiceBound(eq(TEST_USER_ID),
|
||||
eq(TEST_COMPONENT_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onSwitchUser_differentUser_activateUIControllerAction() {
|
||||
onBoundServicesChanged_bindNonA11yCategoryService_activateUIControllerAction();
|
||||
onBoundServicesChanged_bindNonA11yToolService_activateUIControllerAction();
|
||||
|
||||
mA11ySecurityPolicy.onSwitchUserLocked(2, new HashSet<>());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user