diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java index db121e2c637..d3217832794 100644 --- a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java +++ b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java @@ -16,6 +16,7 @@ package com.android.settings.accessibility; import android.accessibilityservice.AccessibilityServiceInfo; +import android.annotation.Nullable; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; @@ -27,6 +28,7 @@ import android.support.v7.preference.Preference; import android.view.accessibility.AccessibilityManager; import android.widget.Switch; +import com.android.internal.accessibility.AccessibilityShortcutController; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.search.BaseSearchIndexProvider; @@ -87,7 +89,7 @@ public class AccessibilityShortcutPreferenceFragment extends ToggleFeaturePrefer super.onInstallSwitchBarToggleSwitch(); mSwitchBar.addOnSwitchChangeListener((Switch switchView, boolean enabled) -> { Context context = getContext(); - if (enabled && (getServiceInfo(context) == null)) { + if (enabled && !shortcutFeatureAvailable(context)) { // If no service is configured, we'll disable the shortcut shortly. Give the // user a chance to select a service. We'll update the preferences when we resume. Settings.Secure.putInt( @@ -110,7 +112,7 @@ public class AccessibilityShortcutPreferenceFragment extends ToggleFeaturePrefer ContentResolver cr = getContentResolver(); Context context = getContext(); mServicePreference.setSummary(getServiceName(context)); - if (getServiceInfo(context) == null) { + if (!shortcutFeatureAvailable(context)) { // If no service is configured, make sure the overall shortcut is turned off Settings.Secure.putInt( getContentResolver(), Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 0); @@ -132,19 +134,38 @@ public class AccessibilityShortcutPreferenceFragment extends ToggleFeaturePrefer * @return The name of the service or a string saying that none is selected. */ public static CharSequence getServiceName(Context context) { + if (!shortcutFeatureAvailable(context)) { + return context.getString(R.string.accessibility_no_service_selected); + } AccessibilityServiceInfo shortcutServiceInfo = getServiceInfo(context); if (shortcutServiceInfo != null) { return shortcutServiceInfo.getResolveInfo().loadLabel(context.getPackageManager()); } - return context.getString(R.string.accessibility_no_service_selected); + return AccessibilityShortcutController.getFrameworkShortcutFeaturesMap() + .get(getShortcutComponent(context)).getLabel(context); } private static AccessibilityServiceInfo getServiceInfo(Context context) { - ComponentName shortcutServiceName = ComponentName.unflattenFromString( - AccessibilityUtils.getShortcutTargetServiceComponentNameString( - context, UserHandle.myUserId())); return AccessibilityManager.getInstance(context) - .getInstalledServiceInfoWithComponentName(shortcutServiceName); + .getInstalledServiceInfoWithComponentName(getShortcutComponent(context)); + } + + private static boolean shortcutFeatureAvailable(Context context) { + ComponentName shortcutFeature = getShortcutComponent(context); + if (shortcutFeature == null) return false; + + if (AccessibilityShortcutController.getFrameworkShortcutFeaturesMap() + .containsKey(shortcutFeature)) { + return true; + } + return getServiceInfo(context) != null; + } + + private static @Nullable ComponentName getShortcutComponent(Context context) { + String componentNameString = AccessibilityUtils.getShortcutTargetServiceComponentNameString( + context, UserHandle.myUserId()); + if (componentNameString == null) return null; + return ComponentName.unflattenFromString(componentNameString); } public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = diff --git a/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java b/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java index 5b0e76d631e..e0c41befa45 100644 --- a/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java +++ b/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java @@ -25,29 +25,40 @@ import android.app.Fragment; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; +import android.content.pm.ApplicationInfo; +import android.content.pm.ComponentInfo; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; +import android.util.IconDrawableFactory; import android.view.accessibility.AccessibilityManager; +import com.android.internal.accessibility.AccessibilityShortcutController; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.internal.accessibility.AccessibilityShortcutController.ToggleableFrameworkFeatureInfo; import com.android.settings.R; import com.android.settings.applications.defaultapps.DefaultAppInfo; import com.android.settings.applications.defaultapps.DefaultAppPickerFragment; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; +import com.android.settings.widget.RadioButtonPickerFragment; import com.android.settings.widget.RadioButtonPreference; +import com.android.settings.wrapper.IPackageManagerWrapper; import com.android.settingslib.accessibility.AccessibilityUtils; +import com.android.settingslib.wrapper.PackageManagerWrapper; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * Fragment for picking accessibility shortcut service */ -public class ShortcutServicePickerFragment extends DefaultAppPickerFragment { +public class ShortcutServicePickerFragment extends RadioButtonPickerFragment { @Override public int getMetricsCategory() { @@ -60,22 +71,29 @@ public class ShortcutServicePickerFragment extends DefaultAppPickerFragment { } @Override - protected List getCandidates() { + protected List getCandidates() { final Context context = getContext(); + final PackageManager pm = context.getPackageManager(); final AccessibilityManager accessibilityManager = context .getSystemService(AccessibilityManager.class); final List installedServices = accessibilityManager.getInstalledAccessibilityServiceList(); final int numInstalledServices = installedServices.size(); + final PackageManagerWrapper pmw = new PackageManagerWrapper(context.getPackageManager()); - List candidates = new ArrayList<>(numInstalledServices); + final List candidates = new ArrayList<>(numInstalledServices); + Map frameworkFeatureInfoMap = + AccessibilityShortcutController.getFrameworkShortcutFeaturesMap(); + for (ComponentName componentName : frameworkFeatureInfoMap.keySet()) { + // Lookup icon + candidates.add(new FrameworkCandidateInfo(frameworkFeatureInfoMap.get(componentName), + R.drawable.empty_icon, componentName.flattenToString())); + } for (int i = 0; i < numInstalledServices; i++) { - AccessibilityServiceInfo installedServiceInfo = installedServices.get(i); - candidates.add(new DefaultAppInfo(context, mPm, - UserHandle.myUserId(), + final AccessibilityServiceInfo installedServiceInfo = installedServices.get(i); + candidates.add(new DefaultAppInfo(context, pmw, UserHandle.myUserId(), installedServiceInfo.getComponentName(), - (String) installedServiceInfo.loadSummary(mPm.getPackageManager()), - true /* enabled */)); + (String) installedServiceInfo.loadSummary(pm), true /* enabled */)); } return candidates; @@ -105,13 +123,21 @@ public class ShortcutServicePickerFragment extends DefaultAppPickerFragment { public void onRadioButtonClicked(RadioButtonPreference selected) { final String selectedKey = selected.getKey(); - final Activity activity = getActivity(); if (TextUtils.isEmpty(selectedKey)) { super.onRadioButtonClicked(selected); - } else if (activity != null) { - final DialogFragment fragment = ConfirmationDialogFragment.newInstance( - this, selectedKey); - fragment.show(activity.getFragmentManager(), ConfirmationDialogFragment.TAG); + } else { + final ComponentName selectedComponent = ComponentName.unflattenFromString(selectedKey); + if (AccessibilityShortcutController.getFrameworkShortcutFeaturesMap() + .containsKey(selectedComponent)) { + // This is a framework feature. It doesn't need to be confirmed. + onRadioButtonConfirmed(selectedKey); + } else { + final Activity activity = getActivity(); + if (activity != null) { + ConfirmationDialogFragment.newInstance(this, selectedKey) + .show(activity.getFragmentManager(), ConfirmationDialogFragment.TAG); + } + } } } @@ -156,11 +182,40 @@ public class ShortcutServicePickerFragment extends DefaultAppPickerFragment { @Override public void onClick(DialogInterface dialog, int which) { final Fragment fragment = getTargetFragment(); - if ((which == BUTTON_POSITIVE) && (fragment instanceof DefaultAppPickerFragment)) { + if ((which == BUTTON_POSITIVE) && (fragment instanceof ShortcutServicePickerFragment)) { final Bundle bundle = getArguments(); ((ShortcutServicePickerFragment) fragment).onServiceConfirmed( bundle.getString(EXTRA_KEY)); } } } + + private class FrameworkCandidateInfo extends CandidateInfo { + ToggleableFrameworkFeatureInfo mToggleableFrameworkFeatureInfo; + int mIconResId; + String mKey; + + public FrameworkCandidateInfo( + ToggleableFrameworkFeatureInfo frameworkFeatureInfo, int iconResId, String key) { + super(true /* enabled */); + mToggleableFrameworkFeatureInfo = frameworkFeatureInfo; + mIconResId = iconResId; + mKey = key; + } + + @Override + public CharSequence loadLabel() { + return mToggleableFrameworkFeatureInfo.getLabel(getContext()); + } + + @Override + public Drawable loadIcon() { + return getContext().getDrawable(mIconResId); + } + + @Override + public String getKey() { + return mKey; + } + } }