diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4be267fec4a..e971356192f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4095,8 +4095,14 @@
When magnification is turned on, use the Accessibility button at the bottom of the screen to quickly magnify.\n\nTo zoom, tap the Accessibility button, then tap anywhere on the screen.\n- Drag 2 or more fingers to scroll
\n- Pinch 2 or more fingers to adjust zoom
\n\nTo zoom temporarily, tap the Accessibility button, then touch & hold anywhere on the screen.\n- Drag to move around the screen
\n- Lift finger to zoom out
\n\nYou can’t zoom in on the keyboard or navigation bar.
The Accessibility button is set to %1$s. To use magnification, touch & hold the Accessibility button, then select magnification.
-
+
Accessibility shortcut
+
+ Shortcut service
+
+ Allow from lock screen
+
+ When the shortcut is on, you can press both volume buttons for 3 seconds to start an accessibility feature.
High contrast text
@@ -4280,6 +4286,9 @@
No services installed
+
+ No service selected
+
No description provided.
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index 065ead127e1..48e11afe336 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -18,8 +18,9 @@
android:title="@string/accessibility_settings"
android:persistent="true">
-
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/com/android/settings/accessibility/AccessibilityServiceWarning.java b/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
index 3a84d742c0f..71cafbad651 100644
--- a/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
+++ b/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
@@ -78,9 +78,16 @@ public class AccessibilityServiceWarning {
return StorageManager.isNonDefaultBlockEncrypted();
}
- private static View createEnableDialogContentView(Activity parentActivity,
+ /**
+ * Get a content View for a dialog to confirm that they want to enable a service.
+ *
+ * @param context A valid context
+ * @param info The info about a service
+ * @return A content view suitable for viewing
+ */
+ private static View createEnableDialogContentView(Context context,
AccessibilityServiceInfo info) {
- LayoutInflater inflater = (LayoutInflater) parentActivity.getSystemService(
+ LayoutInflater inflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
View content = inflater.inflate(R.layout.enable_accessibility_service_dialog_content,
@@ -89,8 +96,8 @@ public class AccessibilityServiceWarning {
TextView encryptionWarningView = (TextView) content.findViewById(
R.id.encryption_warning);
if (isFullDiskEncrypted()) {
- String text = parentActivity.getString(R.string.enable_service_encryption_warning,
- info.getResolveInfo().loadLabel(parentActivity.getPackageManager()));
+ String text = context.getString(R.string.enable_service_encryption_warning,
+ info.getResolveInfo().loadLabel(context.getPackageManager()));
encryptionWarningView.setText(text);
encryptionWarningView.setVisibility(View.VISIBLE);
} else {
@@ -99,8 +106,8 @@ public class AccessibilityServiceWarning {
TextView capabilitiesHeaderView = (TextView) content.findViewById(
R.id.capabilities_header);
- capabilitiesHeaderView.setText(parentActivity.getString(R.string.capabilities_list_title,
- info.getResolveInfo().loadLabel(parentActivity.getPackageManager())));
+ capabilitiesHeaderView.setText(context.getString(R.string.capabilities_list_title,
+ info.getResolveInfo().loadLabel(context.getPackageManager())));
LinearLayout capabilitiesView = (LinearLayout) content.findViewById(R.id.capabilities);
@@ -110,21 +117,21 @@ public class AccessibilityServiceWarning {
ImageView imageView = (ImageView) capabilityView.findViewById(
com.android.internal.R.id.perm_icon);
- imageView.setImageDrawable(parentActivity.getDrawable(
+ imageView.setImageDrawable(context.getDrawable(
com.android.internal.R.drawable.ic_text_dot));
TextView labelView = (TextView) capabilityView.findViewById(
com.android.internal.R.id.permission_group);
- labelView.setText(parentActivity.getString(
+ labelView.setText(context.getString(
R.string.capability_title_receiveAccessibilityEvents));
TextView descriptionView = (TextView) capabilityView.findViewById(
com.android.internal.R.id.permission_list);
descriptionView.setText(
- parentActivity.getString(R.string.capability_desc_receiveAccessibilityEvents));
+ context.getString(R.string.capability_desc_receiveAccessibilityEvents));
List capabilities =
- info.getCapabilityInfos(parentActivity);
+ info.getCapabilityInfos(context);
capabilitiesView.addView(capabilityView);
@@ -138,16 +145,16 @@ public class AccessibilityServiceWarning {
imageView = (ImageView) capabilityView.findViewById(
com.android.internal.R.id.perm_icon);
- imageView.setImageDrawable(parentActivity.getDrawable(
+ imageView.setImageDrawable(context.getDrawable(
com.android.internal.R.drawable.ic_text_dot));
labelView = (TextView) capabilityView.findViewById(
com.android.internal.R.id.permission_group);
- labelView.setText(parentActivity.getString(capability.titleResId));
+ labelView.setText(context.getString(capability.titleResId));
descriptionView = (TextView) capabilityView.findViewById(
com.android.internal.R.id.permission_list);
- descriptionView.setText(parentActivity.getString(capability.descResId));
+ descriptionView.setText(context.getString(capability.descResId));
capabilitiesView.addView(capabilityView);
}
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index 9b2c85327bb..5e791ae6b9f 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -17,11 +17,9 @@
package com.android.settings.accessibility;
import android.accessibilityservice.AccessibilityServiceInfo;
-import android.app.Dialog;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
@@ -130,9 +128,6 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
// presentation.
private static final long DELAY_UPDATE_SERVICES_MILLIS = 1000;
- // ID for dialog that confirms shortcut capabilities
- private static final int DIALOG_ID_ADD_SHORTCUT_WARNING = 1;
-
private final Map mLongPressTimeoutValueToTitleMap = new HashMap<>();
private final Handler mHandler = new Handler();
@@ -205,7 +200,7 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
private Preference mDisplayMagnificationPreferenceScreen;
private Preference mFontSizePreferenceScreen;
private Preference mAutoclickPreferenceScreen;
- private ListPreference mAccessibilityShortcutPreference;
+ private Preference mAccessibilityShortcutPreferenceScreen;
private Preference mDisplayDaltonizerPreferenceScreen;
private SwitchPreference mToggleInversionPreference;
@@ -264,9 +259,6 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
} else if (mToggleInversionPreference == preference) {
handleToggleInversionPreferenceChange((Boolean) newValue);
return true;
- } else if (mAccessibilityShortcutPreference == preference) {
- handleAccessibilityShortcutPreferenceChange((String) newValue);
- return true;
}
return false;
}
@@ -283,58 +275,6 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, (checked ? 1 : 0));
}
- private void handleAccessibilityShortcutPreferenceChange(String serviceComponentName) {
- // When assigning a service to the shortcut the user must explicitly agree to the same
- // capabilities that are present if the service were being enabled.
- // No need if clearing the setting or the service is already enabled.
- if (TextUtils.isEmpty(serviceComponentName)
- || AccessibilityUtils.getEnabledServicesFromSettings(getActivity())
- .contains(ComponentName.unflattenFromString(serviceComponentName))) {
- Settings.Secure.putString(getContentResolver(),
- Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, serviceComponentName);
- updateAccessibilityShortcut();
- return;
- }
- if (!serviceComponentName.equals(mAccessibilityShortcutPreference.getValue())) {
- showDialog(DIALOG_ID_ADD_SHORTCUT_WARNING);
- }
- }
-
- @Override
- public Dialog onCreateDialog(int dialogId) {
- switch (dialogId) {
- case DIALOG_ID_ADD_SHORTCUT_WARNING: {
- DialogInterface.OnClickListener listener =
- (DialogInterface dialogInterface, int buttonId) -> {
- if (buttonId == DialogInterface.BUTTON_POSITIVE) {
- Settings.Secure.putString(getContentResolver(),
- Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
- mAccessibilityShortcutPreference.getValue());
- }
- updateAccessibilityShortcut();
- };
- AccessibilityServiceInfo info = AccessibilityManager.getInstance(getActivity())
- .getInstalledServiceInfoWithComponentName(
- ComponentName.unflattenFromString(
- mAccessibilityShortcutPreference.getValue()));
- if (info == null) {
- return null;
- }
- return AccessibilityServiceWarning
- .createCapabilitiesDialog(getActivity(), info, listener);
- }
- default: {
- throw new IllegalArgumentException();
- }
- }
- }
-
- @Override
- public int getDialogMetricsCategory(int dialogId) {
- // The only dialog is the one that confirms the properties for the accessibility shortcut
- return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE;
- }
-
@Override
public boolean onPreferenceTreeClick(Preference preference) {
if (mToggleHighTextContrastPreference == preference) {
@@ -458,9 +398,7 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
mDisplayDaltonizerPreferenceScreen = findPreference(DISPLAY_DALTONIZER_PREFERENCE_SCREEN);
// Accessibility shortcut
- mAccessibilityShortcutPreference =
- (ListPreference) findPreference(ACCESSIBILITY_SHORTCUT_PREFERENCE);
- mAccessibilityShortcutPreference.setOnPreferenceChangeListener(this);
+ mAccessibilityShortcutPreferenceScreen = findPreference(ACCESSIBILITY_SHORTCUT_PREFERENCE);
}
private void updateAllPreferences() {
@@ -651,7 +589,7 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
updateAutoclickSummary(mAutoclickPreferenceScreen);
- updateAccessibilityShortcut();
+ updateAccessibilityShortcut(mAccessibilityShortcutPreferenceScreen);
}
private void updateFeatureSummary(String prefKey, Preference pref) {
@@ -700,35 +638,21 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
mToggleMasterMonoPreference.setChecked(masterMono);
}
- private void updateAccessibilityShortcut() {
- String currentShortcutNameString =
- AccessibilityUtils.getShortcutTargetServiceComponentNameString(getActivity(),
- UserHandle.myUserId());
- final PackageManager pm = getPackageManager();
- final AccessibilityManager accessibilityManager = getActivity()
- .getSystemService(AccessibilityManager.class);
- final List installedServices =
- accessibilityManager.getInstalledAccessibilityServiceList();
- final int numInstalledServices = installedServices.size();
-
- CharSequence[] entries = new CharSequence[numInstalledServices + 1];
- CharSequence[] entryValues = new CharSequence[numInstalledServices + 1];
- int currentSettingIndex = numInstalledServices;
- for (int i = 0; i < numInstalledServices; i++) {
- AccessibilityServiceInfo installedService = installedServices.get(i);
- entries[i] = installedService.getResolveInfo().loadLabel(pm);
- entryValues[i] = installedService.getComponentName().flattenToShortString();
- if (installedService.getId().equals(currentShortcutNameString)) {
- currentSettingIndex = i;
- }
+ private void updateAccessibilityShortcut(Preference preference) {
+ if (AccessibilityManager.getInstance(getActivity())
+ .getInstalledAccessibilityServiceList().isEmpty()) {
+ mAccessibilityShortcutPreferenceScreen
+ .setSummary(getString(R.string.accessibility_no_services_installed));
+ mAccessibilityShortcutPreferenceScreen.setEnabled(false);
+ } else {
+ mAccessibilityShortcutPreferenceScreen.setEnabled(true);
+ boolean shortcutEnabled =
+ AccessibilityUtils.isShortcutEnabled(getContext(), UserHandle.myUserId());
+ CharSequence summary = shortcutEnabled
+ ? AccessibilityShortcutPreferenceFragment.getServiceName(getContext())
+ : getString(R.string.accessibility_feature_state_off);
+ mAccessibilityShortcutPreferenceScreen.setSummary(summary);
}
- entries[numInstalledServices] =
- getString(com.android.internal.R.string.disable_accessibility_shortcut);
- entryValues[numInstalledServices] = "";
- mAccessibilityShortcutPreference.setEntryValues(entryValues);
- mAccessibilityShortcutPreference.setEntries(entries);
- mAccessibilityShortcutPreference.setSummary(entries[currentSettingIndex]);
- mAccessibilityShortcutPreference.setValueIndex(currentSettingIndex);
}
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
new file mode 100644
index 00000000000..6ed06da768f
--- /dev/null
+++ b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.accessibility;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.text.TextUtils;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.Switch;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settingslib.accessibility.AccessibilityUtils;
+
+/**
+ * Settings page for accessibility shortcut
+ */
+public class AccessibilityShortcutPreferenceFragment extends ToggleFeaturePreferenceFragment
+ implements Indexable {
+
+ public static final String SHORTCUT_SERVICE_KEY = "accessibility_shortcut_service";
+ public static final String ON_LOCK_SCREEN_KEY = "accessibility_shortcut_on_lock_screen";
+ // ID for dialog that confirms shortcut capabilities
+ private static final int DIALOG_ID_ADD_SHORTCUT_WARNING = 1;
+
+ private Preference mServicePreference;
+ private SwitchPreference mOnLockScreenSwitchPreference;
+ private String mSelectedServiceComponentNameString;
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.accessibility_shortcut_settings);
+ mServicePreference = findPreference(SHORTCUT_SERVICE_KEY);
+ mOnLockScreenSwitchPreference = (SwitchPreference) findPreference(ON_LOCK_SCREEN_KEY);
+ mOnLockScreenSwitchPreference.setOnPreferenceChangeListener((Preference p, Object o) -> {
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN,
+ ((Boolean) o) ? 1 : 0);
+ return true;
+ });
+ mFooterPreferenceMixin.createFooterPreference()
+ .setTitle(R.string.accessibility_shortcut_description);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updatePreferences();
+ }
+
+ @Override
+ protected void onInstallSwitchBarToggleSwitch() {
+ super.onInstallSwitchBarToggleSwitch();
+ mSwitchBar.addOnSwitchChangeListener((Switch switchView, boolean enabled) -> {
+ onPreferenceToggled(Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, enabled);
+ });
+ }
+
+ @Override
+ protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
+ Settings.Secure.putInt(getContentResolver(), preferenceKey, enabled ? 1 : 0);
+ }
+
+ private void updatePreferences() {
+ ContentResolver cr = getContentResolver();
+ boolean isEnabled = Settings.Secure
+ .getInt(cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 1) == 1;
+ mToggleSwitch.setChecked(isEnabled);
+ CharSequence serviceName = getServiceName(getContext());
+ mServicePreference.setSummary(serviceName);
+ mOnLockScreenSwitchPreference.setChecked(Settings.Secure.getInt(
+ cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, 1) == 1);
+ if (TextUtils.equals(serviceName, getString(R.string.accessibility_no_service_selected))) {
+ // If there's no service configured, enabling the shortcut will have no effect
+ // It should already be disabled, but force the switch to off just in case
+ mToggleSwitch.setChecked(false);
+ mToggleSwitch.setEnabled(false);
+ mSwitchBar.setEnabled(false);
+ } else {
+ mToggleSwitch.setEnabled(true);
+ mSwitchBar.setEnabled(true);
+ }
+ }
+
+ /**
+ * Get the user-visible name of the service currently selected for the shortcut.
+ *
+ * @param context The current context
+ * @return The name of the service or a string saying that none is selected.
+ */
+ public static CharSequence getServiceName(Context context) {
+ ComponentName shortcutServiceName = ComponentName.unflattenFromString(
+ AccessibilityUtils.getShortcutTargetServiceComponentNameString(
+ context, UserHandle.myUserId()));
+ AccessibilityServiceInfo shortcutServiceInfo = AccessibilityManager.getInstance(context)
+ .getInstalledServiceInfoWithComponentName(shortcutServiceName);
+ if (shortcutServiceInfo != null) {
+ return shortcutServiceInfo.getResolveInfo().loadLabel(context.getPackageManager());
+ }
+ return context.getString(R.string.accessibility_no_service_selected);
+ }
+
+ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ // This fragment is for details of the shortcut. Only the shortcut itself needs
+ // to be indexed.
+ protected boolean isPageSearchEnabled(Context context) {
+ return false;
+ }
+ };
+}
diff --git a/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java b/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java
new file mode 100644
index 00000000000..8b6d52a5677
--- /dev/null
+++ b/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.accessibility;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.content.ComponentName;
+import android.content.DialogInterface;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.text.TextUtils;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.DialogCreatable;
+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.RadioButtonPreference;
+import com.android.settingslib.accessibility.AccessibilityUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Fragment for picking accessibility shortcut service
+ */
+public class ShortcutServicePickerFragment extends DefaultAppPickerFragment {
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE;
+ }
+
+ @Override
+ protected List extends DefaultAppInfo> getCandidates() {
+ final AccessibilityManager accessibilityManager = getContext()
+ .getSystemService(AccessibilityManager.class);
+ final List installedServices =
+ accessibilityManager.getInstalledAccessibilityServiceList();
+ final int numInstalledServices = installedServices.size();
+
+ List candidates = new ArrayList<>(numInstalledServices);
+ for (int i = 0; i < numInstalledServices; i++) {
+ AccessibilityServiceInfo installedServiceInfo = installedServices.get(i);
+ candidates.add(new DefaultAppInfo(mPm,
+ UserHandle.myUserId(),
+ installedServiceInfo.getComponentName(),
+ installedServiceInfo.loadSummary(mPm.getPackageManager()),
+ true /* enabled */));
+ }
+
+ return candidates;
+ }
+
+ @Override
+ protected String getDefaultKey() {
+ String shortcutServiceString = AccessibilityUtils
+ .getShortcutTargetServiceComponentNameString(getContext(), UserHandle.myUserId());
+ if (shortcutServiceString != null) {
+ ComponentName shortcutName = ComponentName.unflattenFromString(shortcutServiceString);
+ if (shortcutName != null) {
+ return shortcutName.flattenToString();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected boolean setDefaultKey(String key) {
+ Settings.Secure.putString(getContext().getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, key);
+ return true;
+ }
+
+ @Override
+ 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);
+ }
+ }
+
+ private void onServiceConfirmed(String serviceKey) {
+ onRadioButtonConfirmed(serviceKey);
+ }
+
+ public static class ConfirmationDialogFragment extends InstrumentedDialogFragment
+ implements DialogInterface.OnClickListener {
+ private static final String EXTRA_KEY = "extra_key";
+ private static final String TAG = "ConfirmationDialogFragment";
+
+ public static ConfirmationDialogFragment newInstance(ShortcutServicePickerFragment parent,
+ String key) {
+ final ConfirmationDialogFragment fragment = new ConfirmationDialogFragment();
+ final Bundle argument = new Bundle();
+ argument.putString(EXTRA_KEY, key);
+ fragment.setArguments(argument);
+ fragment.setTargetFragment(parent, 0);
+ return fragment;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Bundle bundle = getArguments();
+ final String key = bundle.getString(EXTRA_KEY);
+ final ComponentName serviceComponentName = ComponentName.unflattenFromString(key);
+ final AccessibilityManager accessibilityManager = getActivity()
+ .getSystemService(AccessibilityManager.class);
+ AccessibilityServiceInfo info = accessibilityManager
+ .getInstalledServiceInfoWithComponentName(serviceComponentName);
+ return AccessibilityServiceWarning.createCapabilitiesDialog(getActivity(), info, this);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ final Fragment fragment = getTargetFragment();
+ if (fragment instanceof DefaultAppPickerFragment) {
+ final Bundle bundle = getArguments();
+ ((ShortcutServicePickerFragment) fragment).onServiceConfirmed(
+ bundle.getString(EXTRA_KEY));
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/applications/defaultapps/DefaultAppInfo.java b/src/com/android/settings/applications/defaultapps/DefaultAppInfo.java
index e99b106dfab..b40943ff54a 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultAppInfo.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultAppInfo.java
@@ -20,6 +20,7 @@ import android.app.AppGlobals;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
@@ -76,16 +77,15 @@ public class DefaultAppInfo extends RadioButtonPickerFragment.CandidateInfo {
public CharSequence loadLabel() {
if (componentName != null) {
try {
- final ActivityInfo actInfo = AppGlobals.getPackageManager().getActivityInfo(
- componentName, 0, userId);
- if (actInfo != null) {
- return actInfo.loadLabel(mPm.getPackageManager());
+ final ComponentInfo componentInfo = getComponentInfo();
+ if (componentInfo != null) {
+ return componentInfo.loadLabel(mPm.getPackageManager());
} else {
final ApplicationInfo appInfo = mPm.getApplicationInfoAsUser(
componentName.getPackageName(), 0, userId);
return appInfo.loadLabel(mPm.getPackageManager());
}
- } catch (RemoteException | PackageManager.NameNotFoundException e) {
+ } catch (PackageManager.NameNotFoundException e) {
return null;
}
} else if (packageItemInfo != null) {
@@ -100,16 +100,15 @@ public class DefaultAppInfo extends RadioButtonPickerFragment.CandidateInfo {
public Drawable loadIcon() {
if (componentName != null) {
try {
- final ActivityInfo actInfo = AppGlobals.getPackageManager().getActivityInfo(
- componentName, 0, userId);
- if (actInfo != null) {
- return actInfo.loadIcon(mPm.getPackageManager());
+ final ComponentInfo componentInfo = getComponentInfo();
+ if (componentInfo != null) {
+ return componentInfo.loadIcon(mPm.getPackageManager());
} else {
final ApplicationInfo appInfo = mPm.getApplicationInfoAsUser(
componentName.getPackageName(), 0, userId);
return appInfo.loadIcon(mPm.getPackageManager());
}
- } catch (RemoteException | PackageManager.NameNotFoundException e) {
+ } catch (PackageManager.NameNotFoundException e) {
return null;
}
}
@@ -130,4 +129,18 @@ public class DefaultAppInfo extends RadioButtonPickerFragment.CandidateInfo {
return null;
}
}
+
+ private ComponentInfo getComponentInfo() {
+ try {
+ ComponentInfo componentInfo = AppGlobals.getPackageManager().getActivityInfo(
+ componentName, 0, userId);
+ if (componentInfo == null) {
+ componentInfo = AppGlobals.getPackageManager().getServiceInfo(
+ componentName, 0, userId);
+ }
+ return componentInfo;
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
}
diff --git a/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java b/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java
index d08ac992b35..98557ee86e2 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java
@@ -61,7 +61,6 @@ public abstract class DefaultAppPickerFragment extends RadioButtonPickerFragment
}
}
-
@Override
public void bindPreferenceExtra(RadioButtonPreference pref,
String key, CandidateInfo info, String defaultKey, String systemDefaultKey) {
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 8b1983434d0..aca6a157cb1 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -30,6 +30,7 @@ import com.android.settings.R;
import com.android.settings.ScreenPinningSettings;
import com.android.settings.SecuritySettings;
import com.android.settings.accessibility.AccessibilitySettings;
+import com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment;
import com.android.settings.accessibility.MagnificationPreferenceFragment;
import com.android.settings.accounts.UserAndAccountDashboardFragment;
import com.android.settings.applications.AdvancedAppSettings;
@@ -176,6 +177,8 @@ public final class SearchIndexableResources {
R.drawable.ic_settings_security);
addIndex(MagnificationPreferenceFragment.class, NO_DATA_RES_ID,
R.drawable.ic_settings_accessibility);
+ addIndex(AccessibilityShortcutPreferenceFragment.class, NO_DATA_RES_ID,
+ R.drawable.ic_settings_accessibility);
}
private SearchIndexableResources() {
diff --git a/tests/robotests/src/com/android/settings/accessibility/ShortcutServicePickerFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ShortcutServicePickerFragmentTest.java
new file mode 100644
index 00000000000..9161f06e9e8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/ShortcutServicePickerFragmentTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.UserManager;
+
+import android.test.mock.MockContentResolver;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.applications.PackageManagerWrapper;
+import com.android.settings.testutils.FakeFeatureFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ShortcutServicePickerFragmentTest {
+
+ private static final String TEST_SERVICE_KEY_1 = "abc/123";
+ private static final String TEST_SERVICE_KEY_2 = "abcd/1234";
+
+ private static final String SUMMARY_1 = "summary1";
+ private static final String SUMMARY_2 = "summary2";
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Activity mActivity;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private PackageManagerWrapper mPackageManager;
+
+ private ShortcutServicePickerFragment mFragment;
+ private MockContentResolver mContentResolver;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ FakeFeatureFactory.setupForTest(mActivity);
+ when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+
+ mFragment = spy(new ShortcutServicePickerFragment());
+ mFragment.onAttach((Context) mActivity);
+
+ doReturn(RuntimeEnvironment.application).when(mFragment).getContext();
+ }
+
+ @Test
+ public void setAndGetDefaultAppKey_shouldUpdateDefaultAppKey() {
+ assertThat(mFragment.setDefaultKey(TEST_SERVICE_KEY_1)).isTrue();
+ assertThat(mFragment.getDefaultKey()).isEqualTo(TEST_SERVICE_KEY_1);
+ }
+}
+