Merge "Checks that prebundled categories contain only preinstalled contents." into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
914643da7d
@@ -20,6 +20,16 @@ flag {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flag {
|
||||||
|
name: "check_prebundled_is_preinstalled"
|
||||||
|
namespace: "accessibility"
|
||||||
|
description: "Checks that all 'prebundled' components, used for grouping, are also preinstalled"
|
||||||
|
bug: "353888087"
|
||||||
|
metadata {
|
||||||
|
purpose: PURPOSE_BUGFIX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
flag {
|
flag {
|
||||||
name: "edit_shortcuts_in_full_screen"
|
name: "edit_shortcuts_in_full_screen"
|
||||||
namespace: "accessibility"
|
namespace: "accessibility"
|
||||||
|
@@ -75,7 +75,8 @@ public class AccessibilitySettings extends DashboardFragment implements
|
|||||||
private static final String CATEGORY_AUDIO = "audio_category";
|
private static final String CATEGORY_AUDIO = "audio_category";
|
||||||
private static final String CATEGORY_SPEECH = "speech_category";
|
private static final String CATEGORY_SPEECH = "speech_category";
|
||||||
private static final String CATEGORY_DISPLAY = "display_category";
|
private static final String CATEGORY_DISPLAY = "display_category";
|
||||||
private static final String CATEGORY_DOWNLOADED_SERVICES = "user_installed_services_category";
|
@VisibleForTesting
|
||||||
|
static final String CATEGORY_DOWNLOADED_SERVICES = "user_installed_services_category";
|
||||||
private static final String CATEGORY_KEYBOARD_OPTIONS = "physical_keyboard_options_category";
|
private static final String CATEGORY_KEYBOARD_OPTIONS = "physical_keyboard_options_category";
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final String CATEGORY_INTERACTION_CONTROL = "interaction_control_category";
|
static final String CATEGORY_INTERACTION_CONTROL = "interaction_control_category";
|
||||||
@@ -380,6 +381,7 @@ public class AccessibilitySettings extends DashboardFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void updateServicePreferences() {
|
protected void updateServicePreferences() {
|
||||||
|
final AccessibilityManager a11yManager = AccessibilityManager.getInstance(getPrefContext());
|
||||||
// Since services category is auto generated we have to do a pass
|
// Since services category is auto generated we have to do a pass
|
||||||
// to generate it since services can come and go and then based on
|
// to generate it since services can come and go and then based on
|
||||||
// the global accessibility state to decided whether it is enabled.
|
// the global accessibility state to decided whether it is enabled.
|
||||||
@@ -410,8 +412,18 @@ public class AccessibilitySettings extends DashboardFragment implements
|
|||||||
AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM,
|
AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM,
|
||||||
mCategoryToPrefCategoryMap.get(CATEGORY_INTERACTION_CONTROL));
|
mCategoryToPrefCategoryMap.get(CATEGORY_INTERACTION_CONTROL));
|
||||||
|
|
||||||
final List<RestrictedPreference> preferenceList = getInstalledAccessibilityList(
|
final List<AccessibilityShortcutInfo> installedShortcutList =
|
||||||
getPrefContext());
|
a11yManager.getInstalledAccessibilityShortcutListAsUser(getPrefContext(),
|
||||||
|
UserHandle.myUserId());
|
||||||
|
final List<AccessibilityServiceInfo> modifiableInstalledServiceList =
|
||||||
|
new ArrayList<>(a11yManager.getInstalledAccessibilityServiceList());
|
||||||
|
final List<RestrictedPreference> preferenceList = getInstalledAccessibilityPreferences(
|
||||||
|
getPrefContext(), installedShortcutList, modifiableInstalledServiceList);
|
||||||
|
|
||||||
|
if (Flags.checkPrebundledIsPreinstalled()) {
|
||||||
|
removeNonPreinstalledComponents(mPreBundledServiceComponentToCategoryMap,
|
||||||
|
installedShortcutList, modifiableInstalledServiceList);
|
||||||
|
}
|
||||||
|
|
||||||
final PreferenceCategory downloadedServicesCategory =
|
final PreferenceCategory downloadedServicesCategory =
|
||||||
mCategoryToPrefCategoryMap.get(CATEGORY_DOWNLOADED_SERVICES);
|
mCategoryToPrefCategoryMap.get(CATEGORY_DOWNLOADED_SERVICES);
|
||||||
@@ -456,13 +468,21 @@ public class AccessibilitySettings extends DashboardFragment implements
|
|||||||
updatePreferenceCategoryVisibility(CATEGORY_KEYBOARD_OPTIONS);
|
updatePreferenceCategoryVisibility(CATEGORY_KEYBOARD_OPTIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<RestrictedPreference> getInstalledAccessibilityList(Context context) {
|
/**
|
||||||
final AccessibilityManager a11yManager = AccessibilityManager.getInstance(context);
|
* Gets a list of {@link RestrictedPreference}s for the provided a11y shortcuts and services.
|
||||||
|
*
|
||||||
|
* <p>{@code modifiableInstalledServiceList} may be modified to remove any entries with
|
||||||
|
* matching package name and label as an entry in {@code installedShortcutList}.
|
||||||
|
*
|
||||||
|
* @param installedShortcutList A list of installed {@link AccessibilityShortcutInfo}s.
|
||||||
|
* @param modifiableInstalledServiceList A modifiable list of installed
|
||||||
|
* {@link AccessibilityServiceInfo}s.
|
||||||
|
*/
|
||||||
|
private List<RestrictedPreference> getInstalledAccessibilityPreferences(Context context,
|
||||||
|
List<AccessibilityShortcutInfo> installedShortcutList,
|
||||||
|
List<AccessibilityServiceInfo> modifiableInstalledServiceList) {
|
||||||
final RestrictedPreferenceHelper preferenceHelper = new RestrictedPreferenceHelper(context);
|
final RestrictedPreferenceHelper preferenceHelper = new RestrictedPreferenceHelper(context);
|
||||||
|
|
||||||
final List<AccessibilityShortcutInfo> installedShortcutList =
|
|
||||||
a11yManager.getInstalledAccessibilityShortcutListAsUser(context,
|
|
||||||
UserHandle.myUserId());
|
|
||||||
final List<AccessibilityActivityPreference> activityList =
|
final List<AccessibilityActivityPreference> activityList =
|
||||||
preferenceHelper.createAccessibilityActivityPreferenceList(installedShortcutList);
|
preferenceHelper.createAccessibilityActivityPreferenceList(installedShortcutList);
|
||||||
final Set<Pair<String, CharSequence>> packageLabelPairs =
|
final Set<Pair<String, CharSequence>> packageLabelPairs =
|
||||||
@@ -471,16 +491,14 @@ public class AccessibilitySettings extends DashboardFragment implements
|
|||||||
a11yActivityPref.getPackageName(), a11yActivityPref.getLabel())
|
a11yActivityPref.getPackageName(), a11yActivityPref.getLabel())
|
||||||
).collect(Collectors.toSet());
|
).collect(Collectors.toSet());
|
||||||
|
|
||||||
// Remove duplicate item here, new a ArrayList to copy unmodifiable list result
|
// Remove duplicate A11yServices that are already shown as A11yActivities.
|
||||||
// (getInstalledAccessibilityServiceList).
|
|
||||||
final List<AccessibilityServiceInfo> installedServiceList = new ArrayList<>(
|
|
||||||
a11yManager.getInstalledAccessibilityServiceList());
|
|
||||||
if (!packageLabelPairs.isEmpty()) {
|
if (!packageLabelPairs.isEmpty()) {
|
||||||
installedServiceList.removeIf(
|
modifiableInstalledServiceList.removeIf(
|
||||||
target -> containsPackageAndLabelInList(packageLabelPairs, target));
|
target -> containsPackageAndLabelInList(packageLabelPairs, target));
|
||||||
}
|
}
|
||||||
final List<RestrictedPreference> serviceList =
|
final List<RestrictedPreference> serviceList =
|
||||||
preferenceHelper.createAccessibilityServicePreferenceList(installedServiceList);
|
preferenceHelper.createAccessibilityServicePreferenceList(
|
||||||
|
modifiableInstalledServiceList);
|
||||||
|
|
||||||
final List<RestrictedPreference> preferenceList = new ArrayList<>();
|
final List<RestrictedPreference> preferenceList = new ArrayList<>();
|
||||||
preferenceList.addAll(activityList);
|
preferenceList.addAll(activityList);
|
||||||
@@ -489,6 +507,22 @@ public class AccessibilitySettings extends DashboardFragment implements
|
|||||||
return preferenceList;
|
return preferenceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void removeNonPreinstalledComponents(
|
||||||
|
Map<ComponentName, PreferenceCategory> componentToCategory,
|
||||||
|
List<AccessibilityShortcutInfo> shortcutInfos,
|
||||||
|
List<AccessibilityServiceInfo> serviceInfos) {
|
||||||
|
for (AccessibilityShortcutInfo info : shortcutInfos) {
|
||||||
|
if (!info.getActivityInfo().applicationInfo.isSystemApp()) {
|
||||||
|
componentToCategory.remove(info.getComponentName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (AccessibilityServiceInfo info : serviceInfos) {
|
||||||
|
if (!info.getResolveInfo().serviceInfo.applicationInfo.isSystemApp()) {
|
||||||
|
componentToCategory.remove(info.getComponentName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean containsPackageAndLabelInList(
|
private boolean containsPackageAndLabelInList(
|
||||||
Set<Pair<String, CharSequence>> packageLabelPairs,
|
Set<Pair<String, CharSequence>> packageLabelPairs,
|
||||||
AccessibilityServiceInfo targetServiceInfo) {
|
AccessibilityServiceInfo targetServiceInfo) {
|
||||||
|
@@ -26,11 +26,9 @@ import static org.robolectric.Shadows.shadowOf;
|
|||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
|
|
||||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||||
import android.accessibilityservice.AccessibilityShortcutInfo;
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ActivityInfo;
|
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.content.pm.ServiceInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
@@ -110,9 +108,7 @@ public class AccessibilitySettingsTest {
|
|||||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||||
@Spy
|
@Spy
|
||||||
private final AccessibilityServiceInfo mServiceInfo = getMockAccessibilityServiceInfo(
|
private final AccessibilityServiceInfo mServiceInfo = getMockAccessibilityServiceInfo(
|
||||||
PACKAGE_NAME, CLASS_NAME);
|
new ComponentName(PACKAGE_NAME, CLASS_NAME));
|
||||||
@Mock
|
|
||||||
private AccessibilityShortcutInfo mShortcutInfo;
|
|
||||||
private ShadowAccessibilityManager mShadowAccessibilityManager;
|
private ShadowAccessibilityManager mShadowAccessibilityManager;
|
||||||
@Mock
|
@Mock
|
||||||
private LocalBluetoothManager mLocalBluetoothManager;
|
private LocalBluetoothManager mLocalBluetoothManager;
|
||||||
@@ -125,7 +121,6 @@ public class AccessibilitySettingsTest {
|
|||||||
mShadowAccessibilityManager.setInstalledAccessibilityServiceList(new ArrayList<>());
|
mShadowAccessibilityManager.setInstalledAccessibilityServiceList(new ArrayList<>());
|
||||||
mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat);
|
mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat);
|
||||||
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
|
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
|
||||||
setMockAccessibilityShortcutInfo(mShortcutInfo);
|
|
||||||
|
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT,
|
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT,
|
||||||
@@ -398,14 +393,25 @@ public class AccessibilitySettingsTest {
|
|||||||
public void testAccessibilityMenuInSystem_IncludedInInteractionControl() {
|
public void testAccessibilityMenuInSystem_IncludedInInteractionControl() {
|
||||||
mShadowAccessibilityManager.setInstalledAccessibilityServiceList(
|
mShadowAccessibilityManager.setInstalledAccessibilityServiceList(
|
||||||
List.of(getMockAccessibilityServiceInfo(
|
List.of(getMockAccessibilityServiceInfo(
|
||||||
AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM)));
|
AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM,
|
||||||
|
/*isSystemApp=*/true)));
|
||||||
setupFragment();
|
setupFragment();
|
||||||
|
|
||||||
final RestrictedPreference pref = mFragment.getPreferenceScreen().findPreference(
|
assertThat(getPreferenceCategory(AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM))
|
||||||
AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM.flattenToString());
|
.isEqualTo(AccessibilitySettings.CATEGORY_INTERACTION_CONTROL);
|
||||||
final String prefCategory = mFragment.mServicePreferenceToPreferenceCategoryMap.get(
|
}
|
||||||
pref).getKey();
|
|
||||||
assertThat(prefCategory).isEqualTo(AccessibilitySettings.CATEGORY_INTERACTION_CONTROL);
|
@Test
|
||||||
|
@EnableFlags(com.android.settings.accessibility.Flags.FLAG_CHECK_PREBUNDLED_IS_PREINSTALLED)
|
||||||
|
public void testNonPreinstalledApp_IncludedInDownloadedCategory() {
|
||||||
|
mShadowAccessibilityManager.setInstalledAccessibilityServiceList(
|
||||||
|
List.of(getMockAccessibilityServiceInfo(
|
||||||
|
AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM,
|
||||||
|
/*isSystemApp=*/false)));
|
||||||
|
setupFragment();
|
||||||
|
|
||||||
|
assertThat(getPreferenceCategory(AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM))
|
||||||
|
.isEqualTo(AccessibilitySettings.CATEGORY_DOWNLOADED_SERVICES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -418,13 +424,20 @@ public class AccessibilitySettingsTest {
|
|||||||
assertThat(pref).isNull();
|
assertThat(pref).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccessibilityServiceInfo getMockAccessibilityServiceInfo(String packageName,
|
private String getPreferenceCategory(ComponentName componentName) {
|
||||||
String className) {
|
return mFragment.mServicePreferenceToPreferenceCategoryMap.get(
|
||||||
return getMockAccessibilityServiceInfo(new ComponentName(packageName, className));
|
mFragment.getPreferenceScreen().findPreference(
|
||||||
|
componentName.flattenToString())).getKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccessibilityServiceInfo getMockAccessibilityServiceInfo(ComponentName componentName) {
|
private AccessibilityServiceInfo getMockAccessibilityServiceInfo(ComponentName componentName) {
|
||||||
final ApplicationInfo applicationInfo = new ApplicationInfo();
|
return getMockAccessibilityServiceInfo(componentName, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AccessibilityServiceInfo getMockAccessibilityServiceInfo(ComponentName componentName,
|
||||||
|
boolean isSystemApp) {
|
||||||
|
final ApplicationInfo applicationInfo = Mockito.mock(ApplicationInfo.class);
|
||||||
|
when(applicationInfo.isSystemApp()).thenReturn(isSystemApp);
|
||||||
final ServiceInfo serviceInfo = new ServiceInfo();
|
final ServiceInfo serviceInfo = new ServiceInfo();
|
||||||
applicationInfo.packageName = componentName.getPackageName();
|
applicationInfo.packageName = componentName.getPackageName();
|
||||||
serviceInfo.packageName = componentName.getPackageName();
|
serviceInfo.packageName = componentName.getPackageName();
|
||||||
@@ -445,16 +458,6 @@ public class AccessibilitySettingsTest {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setMockAccessibilityShortcutInfo(AccessibilityShortcutInfo mockInfo) {
|
|
||||||
final ActivityInfo activityInfo = Mockito.mock(ActivityInfo.class);
|
|
||||||
activityInfo.applicationInfo = new ApplicationInfo();
|
|
||||||
when(mockInfo.getActivityInfo()).thenReturn(activityInfo);
|
|
||||||
when(activityInfo.loadLabel(any())).thenReturn(DEFAULT_LABEL);
|
|
||||||
when(mockInfo.loadSummary(any())).thenReturn(DEFAULT_SUMMARY);
|
|
||||||
when(mockInfo.loadDescription(any())).thenReturn(DEFAULT_DESCRIPTION);
|
|
||||||
when(mockInfo.getComponentName()).thenReturn(COMPONENT_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setInvisibleToggleFragmentType(AccessibilityServiceInfo info) {
|
private void setInvisibleToggleFragmentType(AccessibilityServiceInfo info) {
|
||||||
info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
|
info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
|
||||||
info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
|
info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
|
||||||
|
Reference in New Issue
Block a user